-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathhelpers.ts
123 lines (107 loc) · 3.65 KB
/
helpers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import getPort from 'get-port'
import { getDeployStore } from '@netlify/blobs'
import { BlobsServer } from '@netlify/blobs/server'
import type { NetlifyPluginUtils } from '@netlify/build'
import { Buffer } from 'node:buffer'
import { mkdtemp } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { assert, vi } from 'vitest'
import { BLOB_TOKEN } from './constants.mjs'
import { type FixtureTestContext } from './contexts'
import { createBlobContext } from './lambda-helpers.mjs'
/**
* Generates a 24char deploy ID (this is validated in the blob storage so we cant use a uuidv4)
* @returns
*/
export const generateRandomObjectID = () => {
const characters = 'abcdef0123456789'
let objectId = ''
for (let i = 0; i < 24; i++) {
objectId += characters[Math.floor(Math.random() * characters.length)]
}
return objectId
}
/**
* Starts a new mock blob storage
* @param ctx
*/
export const startMockBlobStore = async (ctx: FixtureTestContext) => {
const port = await getPort()
// create new blob store server
ctx.blobServer = new BlobsServer({
port,
token: BLOB_TOKEN,
directory: await mkdtemp(join(tmpdir(), 'opennextjs-netlify-blob-')),
})
await ctx.blobServer.start()
ctx.blobServerGetSpy = vi.spyOn(ctx.blobServer, 'get')
ctx.blobStoreHost = `localhost:${port}`
ctx.blobStorePort = port
vi.stubEnv('NETLIFY_BLOBS_CONTEXT', createBlobContext(ctx))
ctx.blobStore = getDeployStore({
apiURL: `http://${ctx.blobStoreHost}`,
deployID: ctx.deployID,
siteID: ctx.siteID,
token: BLOB_TOKEN,
})
}
/**
* Retrieves an array of blob store entries
*/
export const getBlobEntries = async (ctx: FixtureTestContext) => {
ctx.blobStore = ctx.blobStore
? ctx.blobStore
: getDeployStore({
apiURL: `http://${ctx.blobStoreHost}`,
deployID: ctx.deployID,
siteID: ctx.siteID,
token: BLOB_TOKEN,
})
const { blobs } = await ctx.blobStore.list()
return blobs
}
export function getBlobServerGets(ctx: FixtureTestContext, predicate?: (key: string) => boolean) {
const isString = (arg: unknown): arg is string => typeof arg === 'string'
return ctx.blobServerGetSpy.mock.calls
.map(([request]) => {
if (typeof request.url !== 'string') {
return undefined
}
let urlSegments = request.url.split('/').slice(1)
// ignore region url component when using `experimentalRegion`
const REGION_PREFIX = 'region:'
if (urlSegments[0].startsWith(REGION_PREFIX)) {
urlSegments = urlSegments.slice(1)
}
const [_siteID, _deployID, key] = urlSegments
return key && decodeBlobKey(key)
})
.filter(isString)
.filter((key) => !predicate || predicate(key))
}
export function countOfBlobServerGetsForKey(ctx: FixtureTestContext, key: string) {
return getBlobServerGets(ctx).reduce((acc, curr) => (curr === key ? acc + 1 : acc), 0)
}
/**
* Converts a string to base64 blob key
*/
export const encodeBlobKey = (key: string) => Buffer.from(key).toString('base64url')
/**
* Converts a base64 blob key to a string
*/
export const decodeBlobKey = (key: string) => Buffer.from(key, 'base64url').toString('utf-8')
/**
* Fake build utils that are passed to a build plugin execution
*/
export const mockBuildUtils = {
failBuild: (message: string, options: { error?: Error }) => {
assert.fail(`${message}: ${options?.error || ''}`)
},
failPlugin: (message: string, options: { error?: Error }) => {
assert.fail(`${message}: ${options?.error || ''}`)
},
cancelBuild: (message: string, options: { error?: Error }) => {
assert.fail(`${message}: ${options?.error || ''}`)
},
} as unknown as NetlifyPluginUtils