{
  "version": 3,
  "sources": ["../../../../src/workers/kv/sites.worker.ts", "../../../../src/workers/kv/constants.ts", "../../../../src/workers/kv/validator.worker.ts"],
  "sourcesContent": ["import { base64Decode, base64Encode, SharedBindings } from \"miniflare:shared\";\nimport {\n\tdecodeSitesKey,\n\tdeserialiseSiteRegExps,\n\tencodeSitesKey,\n\tKVLimits,\n\tKVParams,\n\tSiteBindings,\n\ttestSiteRegExps,\n} from \"./constants\";\nimport { decodeListOptions, validateListOptions } from \"./validator.worker\";\nimport type {\n\tSerialisableSiteMatcherRegExps,\n\tSiteMatcherRegExps,\n} from \"./constants\";\n\ninterface Env {\n\t[SharedBindings.MAYBE_SERVICE_BLOBS]: Fetcher;\n\t[SiteBindings.JSON_SITE_FILTER]: SerialisableSiteMatcherRegExps;\n}\n\nconst siteRegExpsCache = new WeakMap<Env, SiteMatcherRegExps>();\nfunction getSiteRegExps(env: Env): SiteMatcherRegExps {\n\tlet regExps = siteRegExpsCache.get(env);\n\tif (regExps !== undefined) return regExps;\n\tregExps = deserialiseSiteRegExps(env[SiteBindings.JSON_SITE_FILTER]);\n\tsiteRegExpsCache.set(env, regExps);\n\treturn regExps;\n}\n\n// https://github.com/cloudflare/workerd/blob/81d97010e44f848bb95d0083e2677bca8d1658b7/src/workerd/server/server.c%2B%2B#L860-L874\ninterface DirectoryEntry {\n\tname: string;\n\ttype:\n\t\t| \"file\"\n\t\t| \"directory\"\n\t\t| \"symlink\"\n\t\t| \"blockDevice\"\n\t\t| \"characterDevice\"\n\t\t| \"namedPipe\"\n\t\t| \"socket\"\n\t\t| \"other\";\n}\n\nasync function* walkDirectory(\n\tblobsService: Fetcher,\n\tpath = \"\"\n): AsyncGenerator<string> {\n\tconst res = await blobsService.fetch(`http://placeholder/${path}`);\n\tconst contentType = (res.headers.get(\"Content-Type\") ?? \"\").toLowerCase();\n\tconst isDirectory = contentType.startsWith(\"application/json\");\n\tif (!isDirectory) {\n\t\t// We should only call this function with directories, but in case this\n\t\t// `path` suddenly became a regular file, just return it as a path\n\t\tawait res.body?.pipeTo(new WritableStream());\n\t\tyield path;\n\t\treturn;\n\t}\n\n\tconst entries = await res.json<DirectoryEntry[]>();\n\tfor (const { name, type } of entries) {\n\t\tconst entryPath = `${path}${path === \"\" ? \"\" : \"/\"}${name}`;\n\t\tif (type === \"directory\") {\n\t\t\tyield* walkDirectory(blobsService, entryPath);\n\t\t} else {\n\t\t\tyield entryPath;\n\t\t}\n\t}\n}\n\nconst encoder = new TextEncoder();\nfunction arrayCompare(\n\ta: Uint8Array = new Uint8Array(),\n\tb: Uint8Array = new Uint8Array()\n): number {\n\tconst minLength = Math.min(a.length, b.length);\n\tfor (let i = 0; i < minLength; i++) {\n\t\tconst aElement = a[i];\n\t\tconst bElement = b[i];\n\t\tif (aElement < bElement) return -1;\n\t\tif (aElement > bElement) return 1;\n\t}\n\treturn a.length - b.length;\n}\n\nasync function handleListRequest(\n\turl: URL,\n\tblobsService: Fetcher,\n\tsiteRegExps: SiteMatcherRegExps\n) {\n\tconst options = decodeListOptions(url);\n\tvalidateListOptions(options);\n\tconst { limit = KVLimits.MAX_LIST_KEYS, prefix, cursor } = options;\n\n\t// Get sorted array of all keys matching prefix. Note KV uses\n\t// lexicographic ordering in the UTF-8 collation. To do this, we encode all\n\t// names using a `TextEncoder`, and then compare those arrays. We store the\n\t// encoded name with the name to avoid encoding on each comparison. For\n\t// reference, `String#localeCompare` and `Intl.Collator#compare` are not\n\t// lexicographic (https://github.com/cloudflare/miniflare/issues/235), and\n\t// `<` doesn't use the UTF-8 collation\n\t// (https://github.com/cloudflare/miniflare/issues/380).\n\tlet keys: { name: string; encodedName?: Uint8Array }[] = [];\n\tfor await (let name of walkDirectory(blobsService)) {\n\t\tif (!testSiteRegExps(siteRegExps, name)) continue;\n\t\tname = encodeSitesKey(name);\n\t\tif (prefix !== undefined && !name.startsWith(prefix)) continue;\n\t\tkeys.push({ name, encodedName: encoder.encode(name) });\n\t}\n\tkeys.sort((a, b) => arrayCompare(a.encodedName, b.encodedName));\n\t// Remove `encodedName`s, so they don't get returned\n\tfor (const key of keys) delete key.encodedName;\n\n\t// Apply cursor\n\tconst startAfter = cursor === undefined ? \"\" : base64Decode(cursor);\n\tlet startIndex = 0;\n\tif (startAfter !== \"\") {\n\t\t// We could do a binary search here, but listing Workers Sites namespaces\n\t\t// is an incredibly unlikely operation, so doesn't need to be optimised\n\t\tstartIndex = keys.findIndex(({ name }) => name === startAfter);\n\t\t// If we couldn't find where to start, return nothing\n\t\tif (startIndex === -1) startIndex = keys.length;\n\t\t// Since we want to start AFTER this index, add 1 to it\n\t\tstartIndex++;\n\t}\n\n\t// Apply limit\n\tconst endIndex = startIndex + limit;\n\tconst nextCursor =\n\t\tendIndex < keys.length ? base64Encode(keys[endIndex - 1].name) : undefined;\n\tkeys = keys.slice(startIndex, endIndex);\n\n\tif (nextCursor === undefined) {\n\t\treturn Response.json({ keys, list_complete: true });\n\t} else {\n\t\treturn Response.json({ keys, list_complete: false, cursor: nextCursor });\n\t}\n}\n\nexport default <ExportedHandler<Env>>{\n\tasync fetch(request, env) {\n\t\t// Only permit reads\n\t\tif (request.method !== \"GET\") {\n\t\t\tconst message = `Cannot ${request.method.toLowerCase()}() with Workers Sites namespace`;\n\t\t\treturn new Response(message, { status: 405, statusText: message });\n\t\t}\n\n\t\t// Decode key (empty if listing)\n\t\tconst url = new URL(request.url);\n\t\tlet key = url.pathname.substring(1); // Strip leading \"/\"\n\t\tif (url.searchParams.get(KVParams.URL_ENCODED)?.toLowerCase() === \"true\") {\n\t\t\tkey = decodeURIComponent(key);\n\t\t}\n\n\t\t// Strip SITES_NO_CACHE_PREFIX\n\t\tkey = decodeSitesKey(key);\n\n\t\t// If not listing keys, check key is included, returning not found if not\n\t\tconst siteRegExps = getSiteRegExps(env);\n\t\tif (key !== \"\" && !testSiteRegExps(siteRegExps, key)) {\n\t\t\treturn new Response(\"Not Found\", {\n\t\t\t\tstatus: 404,\n\t\t\t\tstatusText: \"Not Found\",\n\t\t\t});\n\t\t}\n\n\t\tconst blobsService = env[SharedBindings.MAYBE_SERVICE_BLOBS];\n\t\tif (key === \"\") {\n\t\t\treturn handleListRequest(url, blobsService, siteRegExps);\n\t\t} else {\n\t\t\treturn blobsService.fetch(new URL(key, \"http://placeholder\"));\n\t\t}\n\t},\n};\n", "import { testRegExps } from \"miniflare:shared\";\nimport type { MatcherRegExps } from \"miniflare:shared\";\n\nexport const KVLimits = {\n\tMIN_CACHE_TTL_SECONDS: 30,\n\tMIN_EXPIRATION_TTL_SECONDS: 60,\n\tMAX_LIST_KEYS: 1000,\n\tMAX_KEY_SIZE_BYTES: 512,\n\tMAX_VALUE_SIZE_BYTES: 25 * 1024 * 1024 /* 25MiB */,\n\tMAX_VALUE_SIZE_TEST_BYTES: 1024 /* 1KiB */,\n\tMAX_METADATA_SIZE_BYTES: 1024 /* 1KiB */,\n\tMAX_BULK_SIZE_BYTES: 25 * 1024 * 1024 /* 25MiB */,\n} as const;\n\nexport const KVParams = {\n\tURL_ENCODED: \"urlencoded\",\n\tCACHE_TTL: \"cache_ttl\",\n\tEXPIRATION: \"expiration\",\n\tEXPIRATION_TTL: \"expiration_ttl\",\n\tLIST_LIMIT: \"key_count_limit\",\n\tLIST_PREFIX: \"prefix\",\n\tLIST_CURSOR: \"cursor\",\n} as const;\n\nexport const KVHeaders = {\n\tEXPIRATION: \"CF-Expiration\",\n\tMETADATA: \"CF-KV-Metadata\",\n} as const;\n\nexport const SiteBindings = {\n\tKV_NAMESPACE_SITE: \"__STATIC_CONTENT\",\n\tJSON_SITE_MANIFEST: \"__STATIC_CONTENT_MANIFEST\",\n\tJSON_SITE_FILTER: \"MINIFLARE_SITE_FILTER\",\n} as const;\n\n// Magic prefix: if a URLs pathname starts with this, it shouldn't be cached.\n// This ensures edge caching of Workers Sites files is disabled, and the latest\n// local version is always served.\nexport const SITES_NO_CACHE_PREFIX = \"$__MINIFLARE_SITES__$/\";\nexport const MAX_BULK_GET_KEYS = 100;\n\nexport function encodeSitesKey(key: string): string {\n\t// `encodeURIComponent()` ensures `ETag`s used by `@cloudflare/kv-asset-handler`\n\t// are always byte strings.\n\treturn SITES_NO_CACHE_PREFIX + encodeURIComponent(key);\n}\nexport function decodeSitesKey(key: string): string {\n\treturn key.startsWith(SITES_NO_CACHE_PREFIX)\n\t\t? decodeURIComponent(key.substring(SITES_NO_CACHE_PREFIX.length))\n\t\t: key;\n}\n\nexport function isSitesRequest(request: { url: string }) {\n\tconst url = new URL(request.url);\n\treturn url.pathname.startsWith(`/${SITES_NO_CACHE_PREFIX}`);\n}\n\nexport interface SiteMatcherRegExps {\n\tinclude?: MatcherRegExps;\n\texclude?: MatcherRegExps;\n}\n\nexport interface SerialisableMatcherRegExps {\n\tinclude: string[];\n\texclude: string[];\n}\n\nexport interface SerialisableSiteMatcherRegExps {\n\tinclude?: SerialisableMatcherRegExps;\n\texclude?: SerialisableMatcherRegExps;\n}\n\nfunction serialiseRegExp(regExp: RegExp): string {\n\tconst str = regExp.toString();\n\treturn str.substring(str.indexOf(\"/\") + 1, str.lastIndexOf(\"/\"));\n}\n\nexport function serialiseRegExps(\n\tmatcher: MatcherRegExps\n): SerialisableMatcherRegExps {\n\treturn {\n\t\tinclude: matcher.include.map(serialiseRegExp),\n\t\texclude: matcher.exclude.map(serialiseRegExp),\n\t};\n}\n\nexport function deserialiseRegExps(\n\tmatcher: SerialisableMatcherRegExps\n): MatcherRegExps {\n\treturn {\n\t\tinclude: matcher.include.map((regExp) => new RegExp(regExp)),\n\t\texclude: matcher.exclude.map((regExp) => new RegExp(regExp)),\n\t};\n}\n\nexport function serialiseSiteRegExps(\n\tsiteRegExps: SiteMatcherRegExps\n): SerialisableSiteMatcherRegExps {\n\treturn {\n\t\tinclude: siteRegExps.include && serialiseRegExps(siteRegExps.include),\n\t\texclude: siteRegExps.exclude && serialiseRegExps(siteRegExps.exclude),\n\t};\n}\n\nexport function deserialiseSiteRegExps(\n\tsiteRegExps: SerialisableSiteMatcherRegExps\n): SiteMatcherRegExps {\n\treturn {\n\t\tinclude: siteRegExps.include && deserialiseRegExps(siteRegExps.include),\n\t\texclude: siteRegExps.exclude && deserialiseRegExps(siteRegExps.exclude),\n\t};\n}\n\nexport function testSiteRegExps(\n\tregExps: SiteMatcherRegExps,\n\tkey: string\n): boolean {\n\t// Either include globs undefined, or name matches them\n\tif (regExps.include !== undefined) return testRegExps(regExps.include, key);\n\t// Either exclude globs undefined, or name doesn't match them\n\tif (regExps.exclude !== undefined) return !testRegExps(regExps.exclude, key);\n\treturn true;\n}\n\nexport function getAssetsBindingsNames(\n\t// __STATIC_CONTENT and __STATIC_CONTENT_MANIFEST binding names are\n\t// reserved for Workers Sites. Since we want to allow both sites and\n\t// assets to work side by side, we cannot use the same binding name\n\t// for assets. Therefore deferring to a different default naming here.\n\tassetsKVBindingName = \"__STATIC_ASSETS_CONTENT\",\n\tassetsManifestBindingName = \"__STATIC_ASSETS_CONTENT_MANIFEST\"\n) {\n\treturn {\n\t\tASSETS_KV_NAMESPACE: assetsKVBindingName,\n\t\tASSETS_MANIFEST: assetsManifestBindingName,\n\t} as const;\n}\n", "import { Buffer } from \"node:buffer\";\nimport { HttpError } from \"miniflare:shared\";\nimport { KVLimits, KVParams } from \"./constants\";\n\nexport function decodeKey({ key }: { key: string }, query: URLSearchParams) {\n\tif (query.get(KVParams.URL_ENCODED)?.toLowerCase() !== \"true\") return key;\n\ttry {\n\t\treturn decodeURIComponent(key);\n\t} catch (e: any) {\n\t\tif (e instanceof URIError) {\n\t\t\tthrow new HttpError(400, \"Could not URL-decode key name\");\n\t\t} else {\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\nexport function validateKey(key: string): void {\n\tif (key === \"\") {\n\t\tthrow new HttpError(400, \"Key names must not be empty\");\n\t}\n\tif (key === \".\" || key === \"..\") {\n\t\tthrow new HttpError(\n\t\t\t400,\n\t\t\t`Illegal key name \"${key}\". Please use a different name.`\n\t\t);\n\t}\n\tvalidateKeyLength(key);\n}\n\nexport function validateKeyLength(key: string): void {\n\tconst keyLength = Buffer.byteLength(key);\n\tif (keyLength > KVLimits.MAX_KEY_SIZE_BYTES) {\n\t\tthrow new HttpError(\n\t\t\t414,\n\t\t\t`UTF-8 encoded length of ${keyLength} exceeds key length limit of ${KVLimits.MAX_KEY_SIZE_BYTES}.`\n\t\t);\n\t}\n}\n\nexport function validateGetOptions(\n\tkey: string,\n\toptions?: Omit<KVNamespaceGetOptions<never>, \"type\">\n): void {\n\tvalidateKey(key);\n\t// Validate cacheTtl, but ignore it as there's only one \"edge location\":\n\t// the user's computer\n\tconst cacheTtl = options?.cacheTtl;\n\tif (\n\t\tcacheTtl !== undefined &&\n\t\t(isNaN(cacheTtl) || cacheTtl < KVLimits.MIN_CACHE_TTL_SECONDS)\n\t) {\n\t\tthrow new HttpError(\n\t\t\t400,\n\t\t\t`Invalid ${KVParams.CACHE_TTL} of ${cacheTtl}. Cache TTL must be at least ${KVLimits.MIN_CACHE_TTL_SECONDS}.`\n\t\t);\n\t}\n}\n\nexport function validatePutOptions(\n\tkey: string,\n\toptions: {\n\t\tnow: number /* seconds */;\n\t\trawExpiration: string /* seconds */ | null;\n\t\trawExpirationTtl: string /* seconds */ | null;\n\t\trawMetadata: string /* JSON */ | null;\n\t}\n): { expiration?: number /* seconds */; metadata?: unknown } {\n\tconst { now, rawExpiration, rawExpirationTtl, rawMetadata } = options;\n\n\tvalidateKey(key);\n\n\t// Validate expiration\n\tlet expiration: number | undefined;\n\tif (rawExpirationTtl !== null) {\n\t\tconst expirationTtl = parseInt(rawExpirationTtl);\n\t\tif (Number.isNaN(expirationTtl) || expirationTtl <= 0) {\n\t\t\tthrow new HttpError(\n\t\t\t\t400,\n\t\t\t\t`Invalid ${KVParams.EXPIRATION_TTL} of ${rawExpirationTtl}. Please specify integer greater than 0.`\n\t\t\t);\n\t\t}\n\t\tif (expirationTtl < KVLimits.MIN_EXPIRATION_TTL_SECONDS) {\n\t\t\tthrow new HttpError(\n\t\t\t\t400,\n\t\t\t\t`Invalid ${KVParams.EXPIRATION_TTL} of ${rawExpirationTtl}. Expiration TTL must be at least ${KVLimits.MIN_EXPIRATION_TTL_SECONDS}.`\n\t\t\t);\n\t\t}\n\t\texpiration = now + expirationTtl;\n\t} else if (rawExpiration !== null) {\n\t\texpiration = parseInt(rawExpiration);\n\t\tif (Number.isNaN(expiration) || expiration <= now) {\n\t\t\tthrow new HttpError(\n\t\t\t\t400,\n\t\t\t\t`Invalid ${KVParams.EXPIRATION} of ${rawExpiration}. Please specify integer greater than the current number of seconds since the UNIX epoch.`\n\t\t\t);\n\t\t}\n\t\tif (expiration < now + KVLimits.MIN_EXPIRATION_TTL_SECONDS) {\n\t\t\tthrow new HttpError(\n\t\t\t\t400,\n\t\t\t\t`Invalid ${KVParams.EXPIRATION} of ${rawExpiration}. Expiration times must be at least ${KVLimits.MIN_EXPIRATION_TTL_SECONDS} seconds in the future.`\n\t\t\t);\n\t\t}\n\t}\n\n\t// Validate metadata size\n\tlet metadata: unknown | undefined;\n\tif (rawMetadata !== null) {\n\t\tconst metadataLength = Buffer.byteLength(rawMetadata);\n\t\tif (metadataLength > KVLimits.MAX_METADATA_SIZE_BYTES) {\n\t\t\tthrow new HttpError(\n\t\t\t\t413,\n\t\t\t\t`Metadata length of ${metadataLength} exceeds limit of ${KVLimits.MAX_METADATA_SIZE_BYTES}.`\n\t\t\t);\n\t\t}\n\t\tmetadata = JSON.parse(rawMetadata);\n\t}\n\n\treturn { expiration, metadata };\n}\n\nexport function decodeListOptions(url: URL) {\n\tconst limitParam = url.searchParams.get(KVParams.LIST_LIMIT);\n\tconst limit =\n\t\tlimitParam === null ? KVLimits.MAX_LIST_KEYS : parseInt(limitParam);\n\tconst prefix = url.searchParams.get(KVParams.LIST_PREFIX) ?? undefined;\n\tconst cursor = url.searchParams.get(KVParams.LIST_CURSOR) ?? undefined;\n\treturn { limit, prefix, cursor };\n}\n\nexport function validateListOptions(options: KVNamespaceListOptions): void {\n\t// Validate key limit\n\tconst limit = options.limit;\n\tif (limit !== undefined) {\n\t\tif (isNaN(limit) || limit < 1) {\n\t\t\tthrow new HttpError(\n\t\t\t\t400,\n\t\t\t\t`Invalid ${KVParams.LIST_LIMIT} of ${limit}. Please specify an integer greater than 0.`\n\t\t\t);\n\t\t}\n\t\tif (limit > KVLimits.MAX_LIST_KEYS) {\n\t\t\tthrow new HttpError(\n\t\t\t\t400,\n\t\t\t\t`Invalid ${KVParams.LIST_LIMIT} of ${limit}. Please specify an integer less than ${KVLimits.MAX_LIST_KEYS}.`\n\t\t\t);\n\t\t}\n\t}\n\n\t// Validate key prefix\n\tconst prefix = options.prefix;\n\tif (prefix != null) validateKeyLength(prefix);\n}\n"],
  "mappings": "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",
  "names": []
}
