UNPKG

cross-cf

Version:

Cross-environment DO and KV access

1 lines 84 kB
{"version":3,"file":"cross-cf.cjs","sources":["../node_modules/ignore/index.js","../node_modules/kleur/colors.js","../node_modules/@miniflare/shared/dist/src/index.js","../node_modules/@miniflare/storage-memory/dist/src/index.js","../cross-cf.js"],"sourcesContent":["// A simple implementation of make-array\nfunction makeArray (subject) {\n return Array.isArray(subject)\n ? subject\n : [subject]\n}\n\nconst EMPTY = ''\nconst SPACE = ' '\nconst ESCAPE = '\\\\'\nconst REGEX_TEST_BLANK_LINE = /^\\s+$/\nconst REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\\\!/\nconst REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\\\#/\nconst REGEX_SPLITALL_CRLF = /\\r?\\n/g\n// /foo,\n// ./foo,\n// ../foo,\n// .\n// ..\nconst REGEX_TEST_INVALID_PATH = /^\\.*\\/|^\\.+$/\n\nconst SLASH = '/'\nconst KEY_IGNORE = typeof Symbol !== 'undefined'\n ? Symbol.for('node-ignore')\n /* istanbul ignore next */\n : 'node-ignore'\n\nconst define = (object, key, value) =>\n Object.defineProperty(object, key, {value})\n\nconst REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g\n\nconst RETURN_FALSE = () => false\n\n// Sanitize the range of a regular expression\n// The cases are complicated, see test cases for details\nconst sanitizeRange = range => range.replace(\n REGEX_REGEXP_RANGE,\n (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)\n ? match\n // Invalid range (out of order) which is ok for gitignore rules but\n // fatal for JavaScript regular expression, so eliminate it.\n : EMPTY\n)\n\n// See fixtures #59\nconst cleanRangeBackSlash = slashes => {\n const {length} = slashes\n return slashes.slice(0, length - length % 2)\n}\n\n// > If the pattern ends with a slash,\n// > it is removed for the purpose of the following description,\n// > but it would only find a match with a directory.\n// > In other words, foo/ will match a directory foo and paths underneath it,\n// > but will not match a regular file or a symbolic link foo\n// > (this is consistent with the way how pathspec works in general in Git).\n// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'\n// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call\n// you could use option `mark: true` with `glob`\n\n// '`foo/`' should not continue with the '`..`'\nconst REPLACERS = [\n\n // > Trailing spaces are ignored unless they are quoted with backslash (\"\\\")\n [\n // (a\\ ) -> (a )\n // (a ) -> (a)\n // (a \\ ) -> (a )\n /\\\\?\\s+$/,\n match => match.indexOf('\\\\') === 0\n ? SPACE\n : EMPTY\n ],\n\n // replace (\\ ) with ' '\n [\n /\\\\\\s/g,\n () => SPACE\n ],\n\n // Escape metacharacters\n // which is written down by users but means special for regular expressions.\n\n // > There are 12 characters with special meanings:\n // > - the backslash \\,\n // > - the caret ^,\n // > - the dollar sign $,\n // > - the period or dot .,\n // > - the vertical bar or pipe symbol |,\n // > - the question mark ?,\n // > - the asterisk or star *,\n // > - the plus sign +,\n // > - the opening parenthesis (,\n // > - the closing parenthesis ),\n // > - and the opening square bracket [,\n // > - the opening curly brace {,\n // > These special characters are often called \"metacharacters\".\n [\n /[\\\\$.|*+(){^]/g,\n match => `\\\\${match}`\n ],\n\n [\n // > a question mark (?) matches a single character\n /(?!\\\\)\\?/g,\n () => '[^/]'\n ],\n\n // leading slash\n [\n\n // > A leading slash matches the beginning of the pathname.\n // > For example, \"/*.c\" matches \"cat-file.c\" but not \"mozilla-sha1/sha1.c\".\n // A leading slash matches the beginning of the pathname\n /^\\//,\n () => '^'\n ],\n\n // replace special metacharacter slash after the leading slash\n [\n /\\//g,\n () => '\\\\/'\n ],\n\n [\n // > A leading \"**\" followed by a slash means match in all directories.\n // > For example, \"**/foo\" matches file or directory \"foo\" anywhere,\n // > the same as pattern \"foo\".\n // > \"**/foo/bar\" matches file or directory \"bar\" anywhere that is directly\n // > under directory \"foo\".\n // Notice that the '*'s have been replaced as '\\\\*'\n /^\\^*\\\\\\*\\\\\\*\\\\\\//,\n\n // '**/foo' <-> 'foo'\n () => '^(?:.*\\\\/)?'\n ],\n\n // starting\n [\n // there will be no leading '/'\n // (which has been replaced by section \"leading slash\")\n // If starts with '**', adding a '^' to the regular expression also works\n /^(?=[^^])/,\n function startingReplacer () {\n // If has a slash `/` at the beginning or middle\n return !/\\/(?!$)/.test(this)\n // > Prior to 2.22.1\n // > If the pattern does not contain a slash /,\n // > Git treats it as a shell glob pattern\n // Actually, if there is only a trailing slash,\n // git also treats it as a shell glob pattern\n\n // After 2.22.1 (compatible but clearer)\n // > If there is a separator at the beginning or middle (or both)\n // > of the pattern, then the pattern is relative to the directory\n // > level of the particular .gitignore file itself.\n // > Otherwise the pattern may also match at any level below\n // > the .gitignore level.\n ? '(?:^|\\\\/)'\n\n // > Otherwise, Git treats the pattern as a shell glob suitable for\n // > consumption by fnmatch(3)\n : '^'\n }\n ],\n\n // two globstars\n [\n // Use lookahead assertions so that we could match more than one `'/**'`\n /\\\\\\/\\\\\\*\\\\\\*(?=\\\\\\/|$)/g,\n\n // Zero, one or several directories\n // should not use '*', or it will be replaced by the next replacer\n\n // Check if it is not the last `'/**'`\n (_, index, str) => index + 6 < str.length\n\n // case: /**/\n // > A slash followed by two consecutive asterisks then a slash matches\n // > zero or more directories.\n // > For example, \"a/**/b\" matches \"a/b\", \"a/x/b\", \"a/x/y/b\" and so on.\n // '/**/'\n ? '(?:\\\\/[^\\\\/]+)*'\n\n // case: /**\n // > A trailing `\"/**\"` matches everything inside.\n\n // #21: everything inside but it should not include the current folder\n : '\\\\/.+'\n ],\n\n // intermediate wildcards\n [\n // Never replace escaped '*'\n // ignore rule '\\*' will match the path '*'\n\n // 'abc.*/' -> go\n // 'abc.*' -> skip this rule\n /(^|[^\\\\]+)\\\\\\*(?=.+)/g,\n\n // '*.js' matches '.js'\n // '*.js' doesn't match 'abc'\n (_, p1) => `${p1}[^\\\\/]*`\n ],\n\n [\n // unescape, revert step 3 except for back slash\n // For example, if a user escape a '\\\\*',\n // after step 3, the result will be '\\\\\\\\\\\\*'\n /\\\\\\\\\\\\(?=[$.|*+(){^])/g,\n () => ESCAPE\n ],\n\n [\n // '\\\\\\\\' -> '\\\\'\n /\\\\\\\\/g,\n () => ESCAPE\n ],\n\n [\n // > The range notation, e.g. [a-zA-Z],\n // > can be used to match one of the characters in a range.\n\n // `\\` is escaped by step 3\n /(\\\\)?\\[([^\\]/]*?)(\\\\*)($|\\])/g,\n (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE\n // '\\\\[bar]' -> '\\\\\\\\[bar\\\\]'\n ? `\\\\[${range}${cleanRangeBackSlash(endEscape)}${close}`\n : close === ']'\n ? endEscape.length % 2 === 0\n // A normal case, and it is a range notation\n // '[bar]'\n // '[bar\\\\\\\\]'\n ? `[${sanitizeRange(range)}${endEscape}]`\n // Invalid range notaton\n // '[bar\\\\]' -> '[bar\\\\\\\\]'\n : '[]'\n : '[]'\n ],\n\n // ending\n [\n // 'js' will not match 'js.'\n // 'ab' will not match 'abc'\n /(?:[^*])$/,\n\n // WTF!\n // https://git-scm.com/docs/gitignore\n // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)\n // which re-fixes #24, #38\n\n // > If there is a separator at the end of the pattern then the pattern\n // > will only match directories, otherwise the pattern can match both\n // > files and directories.\n\n // 'js*' will not match 'a.js'\n // 'js/' will not match 'a.js'\n // 'js' will match 'a.js' and 'a.js/'\n match => /\\/$/.test(match)\n // foo/ will not match 'foo'\n ? `${match}$`\n // foo matches 'foo' and 'foo/'\n : `${match}(?=$|\\\\/$)`\n ],\n\n // trailing wildcard\n [\n /(\\^|\\\\\\/)?\\\\\\*$/,\n (_, p1) => {\n const prefix = p1\n // '\\^':\n // '/*' does not match EMPTY\n // '/*' does not match everything\n\n // '\\\\\\/':\n // 'abc/*' does not match 'abc/'\n ? `${p1}[^/]+`\n\n // 'a*' matches 'a'\n // 'a*' matches 'aa'\n : '[^/]*'\n\n return `${prefix}(?=$|\\\\/$)`\n }\n ],\n]\n\n// A simple cache, because an ignore rule only has only one certain meaning\nconst regexCache = Object.create(null)\n\n// @param {pattern}\nconst makeRegex = (pattern, ignoreCase) => {\n let source = regexCache[pattern]\n\n if (!source) {\n source = REPLACERS.reduce(\n (prev, current) => prev.replace(current[0], current[1].bind(pattern)),\n pattern\n )\n regexCache[pattern] = source\n }\n\n return ignoreCase\n ? new RegExp(source, 'i')\n : new RegExp(source)\n}\n\nconst isString = subject => typeof subject === 'string'\n\n// > A blank line matches no files, so it can serve as a separator for readability.\nconst checkPattern = pattern => pattern\n && isString(pattern)\n && !REGEX_TEST_BLANK_LINE.test(pattern)\n\n // > A line starting with # serves as a comment.\n && pattern.indexOf('#') !== 0\n\nconst splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF)\n\nclass IgnoreRule {\n constructor (\n origin,\n pattern,\n negative,\n regex\n ) {\n this.origin = origin\n this.pattern = pattern\n this.negative = negative\n this.regex = regex\n }\n}\n\nconst createRule = (pattern, ignoreCase) => {\n const origin = pattern\n let negative = false\n\n // > An optional prefix \"!\" which negates the pattern;\n if (pattern.indexOf('!') === 0) {\n negative = true\n pattern = pattern.substr(1)\n }\n\n pattern = pattern\n // > Put a backslash (\"\\\") in front of the first \"!\" for patterns that\n // > begin with a literal \"!\", for example, `\"\\!important!.txt\"`.\n .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')\n // > Put a backslash (\"\\\") in front of the first hash for patterns that\n // > begin with a hash.\n .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#')\n\n const regex = makeRegex(pattern, ignoreCase)\n\n return new IgnoreRule(\n origin,\n pattern,\n negative,\n regex\n )\n}\n\nconst throwError = (message, Ctor) => {\n throw new Ctor(message)\n}\n\nconst checkPath = (path, originalPath, doThrow) => {\n if (!isString(path)) {\n return doThrow(\n `path must be a string, but got \\`${originalPath}\\``,\n TypeError\n )\n }\n\n // We don't know if we should ignore EMPTY, so throw\n if (!path) {\n return doThrow(`path must not be empty`, TypeError)\n }\n\n // Check if it is a relative path\n if (checkPath.isNotRelative(path)) {\n const r = '`path.relative()`d'\n return doThrow(\n `path should be a ${r} string, but got \"${originalPath}\"`,\n RangeError\n )\n }\n\n return true\n}\n\nconst isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path)\n\ncheckPath.isNotRelative = isNotRelative\ncheckPath.convert = p => p\n\nclass Ignore {\n constructor ({\n ignorecase = true,\n ignoreCase = ignorecase,\n allowRelativePaths = false\n } = {}) {\n define(this, KEY_IGNORE, true)\n\n this._rules = []\n this._ignoreCase = ignoreCase\n this._allowRelativePaths = allowRelativePaths\n this._initCache()\n }\n\n _initCache () {\n this._ignoreCache = Object.create(null)\n this._testCache = Object.create(null)\n }\n\n _addPattern (pattern) {\n // #32\n if (pattern && pattern[KEY_IGNORE]) {\n this._rules = this._rules.concat(pattern._rules)\n this._added = true\n return\n }\n\n if (checkPattern(pattern)) {\n const rule = createRule(pattern, this._ignoreCase)\n this._added = true\n this._rules.push(rule)\n }\n }\n\n // @param {Array<string> | string | Ignore} pattern\n add (pattern) {\n this._added = false\n\n makeArray(\n isString(pattern)\n ? splitPattern(pattern)\n : pattern\n ).forEach(this._addPattern, this)\n\n // Some rules have just added to the ignore,\n // making the behavior changed.\n if (this._added) {\n this._initCache()\n }\n\n return this\n }\n\n // legacy\n addPattern (pattern) {\n return this.add(pattern)\n }\n\n // | ignored : unignored\n // negative | 0:0 | 0:1 | 1:0 | 1:1\n // -------- | ------- | ------- | ------- | --------\n // 0 | TEST | TEST | SKIP | X\n // 1 | TESTIF | SKIP | TEST | X\n\n // - SKIP: always skip\n // - TEST: always test\n // - TESTIF: only test if checkUnignored\n // - X: that never happen\n\n // @param {boolean} whether should check if the path is unignored,\n // setting `checkUnignored` to `false` could reduce additional\n // path matching.\n\n // @returns {TestResult} true if a file is ignored\n _testOne (path, checkUnignored) {\n let ignored = false\n let unignored = false\n\n this._rules.forEach(rule => {\n const {negative} = rule\n if (\n unignored === negative && ignored !== unignored\n || negative && !ignored && !unignored && !checkUnignored\n ) {\n return\n }\n\n const matched = rule.regex.test(path)\n\n if (matched) {\n ignored = !negative\n unignored = negative\n }\n })\n\n return {\n ignored,\n unignored\n }\n }\n\n // @returns {TestResult}\n _test (originalPath, cache, checkUnignored, slices) {\n const path = originalPath\n // Supports nullable path\n && checkPath.convert(originalPath)\n\n checkPath(\n path,\n originalPath,\n this._allowRelativePaths\n ? RETURN_FALSE\n : throwError\n )\n\n return this._t(path, cache, checkUnignored, slices)\n }\n\n _t (path, cache, checkUnignored, slices) {\n if (path in cache) {\n return cache[path]\n }\n\n if (!slices) {\n // path/to/a.js\n // ['path', 'to', 'a.js']\n slices = path.split(SLASH)\n }\n\n slices.pop()\n\n // If the path has no parent directory, just test it\n if (!slices.length) {\n return cache[path] = this._testOne(path, checkUnignored)\n }\n\n const parent = this._t(\n slices.join(SLASH) + SLASH,\n cache,\n checkUnignored,\n slices\n )\n\n // If the path contains a parent directory, check the parent first\n return cache[path] = parent.ignored\n // > It is not possible to re-include a file if a parent directory of\n // > that file is excluded.\n ? parent\n : this._testOne(path, checkUnignored)\n }\n\n ignores (path) {\n return this._test(path, this._ignoreCache, false).ignored\n }\n\n createFilter () {\n return path => !this.ignores(path)\n }\n\n filter (paths) {\n return makeArray(paths).filter(this.createFilter())\n }\n\n // @returns {TestResult}\n test (path) {\n return this._test(path, this._testCache, true)\n }\n}\n\nconst factory = options => new Ignore(options)\n\nconst isPathValid = path =>\n checkPath(path && checkPath.convert(path), path, RETURN_FALSE)\n\nfactory.isPathValid = isPathValid\n\n// Fixes typescript\nfactory.default = factory\n\nmodule.exports = factory\n\n// Windows\n// --------------------------------------------------------------\n/* istanbul ignore if */\nif (\n // Detect `process` so that it can run in browsers.\n typeof process !== 'undefined'\n && (\n process.env && process.env.IGNORE_TEST_WIN32\n || process.platform === 'win32'\n )\n) {\n /* eslint no-control-regex: \"off\" */\n const makePosix = str => /^\\\\\\\\\\?\\\\/.test(str)\n || /[\"<>|\\u0000-\\u001F]+/u.test(str)\n ? str\n : str.replace(/\\\\/g, '/')\n\n checkPath.convert = makePosix\n\n // 'C:\\\\foo' <- 'C:\\\\foo' has been converted to 'C:/'\n // 'd:\\\\foo'\n const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\\//i\n checkPath.isNotRelative = path =>\n REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path)\n || isNotRelative(path)\n}\n","let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;\nif (typeof process !== 'undefined') {\n\t({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env);\n\tisTTY = process.stdout && process.stdout.isTTY;\n}\n\nconst $ = exports.$ = {\n\tenabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (\n\t\tFORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY\n\t)\n}\n\nfunction init(x, y) {\n\tlet rgx = new RegExp(`\\\\x1b\\\\[${y}m`, 'g');\n\tlet open = `\\x1b[${x}m`, close = `\\x1b[${y}m`;\n\n\treturn function (txt) {\n\t\tif (!$.enabled || txt == null) return txt;\n\t\treturn open + (!!~(''+txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;\n\t};\n}\n\n// modifiers\nexports.reset = init(0, 0);\nexports.bold = init(1, 22);\nexports.dim = init(2, 22);\nexports.italic = init(3, 23);\nexports.underline = init(4, 24);\nexports.inverse = init(7, 27);\nexports.hidden = init(8, 28);\nexports.strikethrough = init(9, 29);\n\n// colors\nexports.black = init(30, 39);\nexports.red = init(31, 39);\nexports.green = init(32, 39);\nexports.yellow = init(33, 39);\nexports.blue = init(34, 39);\nexports.magenta = init(35, 39);\nexports.cyan = init(36, 39);\nexports.white = init(37, 39);\nexports.gray = init(90, 39);\nexports.grey = init(90, 39);\n\n// background colors\nexports.bgBlack = init(40, 49);\nexports.bgRed = init(41, 49);\nexports.bgGreen = init(42, 49);\nexports.bgYellow = init(43, 49);\nexports.bgBlue = init(44, 49);\nexports.bgMagenta = init(45, 49);\nexports.bgCyan = init(46, 49);\nexports.bgWhite = init(47, 49);\n","var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __markAsModule = (target) => __defProp(target, \"__esModule\", { value: true });\nvar __export = (target, all) => {\n __markAsModule(target);\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __reExport = (target, module2, desc) => {\n if (module2 && typeof module2 === \"object\" || typeof module2 === \"function\") {\n for (let key of __getOwnPropNames(module2))\n if (!__hasOwnProp.call(target, key) && key !== \"default\")\n __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });\n }\n return target;\n};\nvar __toModule = (module2) => {\n return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, \"default\", module2 && module2.__esModule && \"default\" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);\n};\n\n// packages/shared/src/index.ts\n__export(exports, {\n Compatibility: () => Compatibility,\n InputGate: () => InputGate,\n InputGatedEventTarget: () => InputGatedEventTarget,\n Log: () => Log,\n LogLevel: () => LogLevel,\n MiniflareError: () => MiniflareError,\n Mutex: () => Mutex,\n NoOpLog: () => NoOpLog,\n Option: () => Option,\n OptionType: () => OptionType,\n OutputGate: () => OutputGate,\n Plugin: () => Plugin,\n RequestContext: () => RequestContext,\n STRING_SCRIPT_PATH: () => STRING_SCRIPT_PATH,\n Storage: () => Storage,\n ThrowingEventTarget: () => ThrowingEventTarget,\n TypedEventTarget: () => TypedEventTarget,\n addAll: () => addAll,\n assertInRequest: () => assertInRequest,\n base64Decode: () => base64Decode,\n base64Encode: () => base64Encode,\n defaultClock: () => defaultClock,\n getRequestContext: () => getRequestContext,\n globsToMatcher: () => globsToMatcher,\n kWrapListener: () => kWrapListener,\n kebabCase: () => kebabCase,\n logOptions: () => logOptions,\n millisToSeconds: () => millisToSeconds,\n nonCircularClone: () => nonCircularClone,\n prefixError: () => prefixError,\n randomHex: () => randomHex,\n resolveStoragePersist: () => resolveStoragePersist,\n runWithInputGateClosed: () => runWithInputGateClosed,\n sanitisePath: () => sanitisePath,\n spaceCase: () => spaceCase,\n titleCase: () => titleCase,\n viewToArray: () => viewToArray,\n viewToBuffer: () => viewToBuffer,\n waitForOpenInputGate: () => waitForOpenInputGate,\n waitForOpenOutputGate: () => waitForOpenOutputGate,\n waitUntilOnOutputGate: () => waitUntilOnOutputGate\n});\n\n// packages/shared/src/compat.ts\nvar FEATURES = [\n {\n defaultAsOf: \"2021-11-10\",\n enableFlag: \"durable_object_fetch_requires_full_url\",\n disableFlag: \"durable_object_fetch_allows_relative_url\"\n },\n {\n defaultAsOf: \"2021-11-10\",\n enableFlag: \"fetch_refuses_unknown_protocols\",\n disableFlag: \"fetch_treats_unknown_protocols_as_http\"\n },\n {\n defaultAsOf: \"2021-11-03\",\n enableFlag: \"formdata_parser_supports_files\",\n disableFlag: \"formdata_parser_converts_files_to_strings\"\n },\n {\n enableFlag: \"html_rewriter_treats_esi_include_as_void_tag\"\n }\n];\nvar collator = new Intl.Collator(void 0, { numeric: true });\nvar Compatibility = class {\n constructor(compatibilityDate = \"1970-01-01\", compatibilityFlags = []) {\n this.compatibilityDate = compatibilityDate;\n this.compatibilityFlags = compatibilityFlags;\n this.#rebuildEnabled();\n }\n #enabled = new Set();\n #rebuildEnabled() {\n this.#enabled.clear();\n const flags = new Set(this.compatibilityFlags);\n for (const { defaultAsOf, enableFlag, disableFlag } of FEATURES) {\n const disabledExplicitly = disableFlag && flags.has(disableFlag);\n if (disabledExplicitly)\n continue;\n const enabledExplicitly = flags.has(enableFlag);\n const enabledAutomatically = defaultAsOf && collator.compare(defaultAsOf, this.compatibilityDate) <= 0;\n if (enabledExplicitly || enabledAutomatically) {\n this.#enabled.add(enableFlag);\n }\n }\n }\n isEnabled(flag) {\n return this.#enabled.has(flag);\n }\n update(compatibilityDate = \"1970-01-01\", compatibilityFlags = []) {\n if (this.compatibilityDate === compatibilityDate && this.compatibilityFlags.length === compatibilityFlags.length && this.compatibilityFlags.every((flag, i) => compatibilityFlags[i] === flag)) {\n return false;\n }\n this.compatibilityDate = compatibilityDate;\n this.compatibilityFlags = compatibilityFlags;\n this.#rebuildEnabled();\n return true;\n }\n get enabled() {\n return [...this.#enabled];\n }\n};\n\n// packages/shared/src/context.ts\nvar import_assert = __toModule(require(\"assert\"));\nvar import_async_hooks = __toModule(require(\"async_hooks\"));\nvar subrequestLimit = parseInt(process.env.MINIFLARE_SUBREQUEST_LIMIT);\nvar MAX_SUBREQUESTS = isNaN(subrequestLimit) ? 50 : subrequestLimit;\nvar MAX_REQUEST_DEPTH = 16;\nvar MAX_PIPELINE_DEPTH = 32;\nvar depthError = \"Subrequest depth limit exceeded. This request recursed through Workers too many times. This can happen e.g. if you have a Worker or Durable Object that calls other Workers or objects recursively.\";\nvar requestContextStorage = new import_async_hooks.AsyncLocalStorage();\nfunction getRequestContext() {\n return requestContextStorage.getStore();\n}\nfunction assertInRequest() {\n if (!getRequestContext()) {\n throw new Error(\"Some functionality, such as asynchronous I/O (fetch, Cache API, KV), timeouts (setTimeout, setInterval), and generating random values (crypto.getRandomValues, crypto.subtle.generateKey), can only be performed while handling a request.\");\n }\n}\nvar RequestContext = class {\n requestDepth;\n pipelineDepth;\n durableObject;\n constructor({\n requestDepth = 1,\n pipelineDepth = 1,\n durableObject = false\n } = {}) {\n (0, import_assert.default)(requestDepth >= 1);\n (0, import_assert.default)(pipelineDepth >= 1);\n if (requestDepth > MAX_REQUEST_DEPTH) {\n throw new Error(`${depthError}\nWorkers and objects can recurse up to ${MAX_REQUEST_DEPTH} times.\nIf you're trying to fetch from an origin server, make sure you've set the \\`upstream\\` option.`);\n }\n if (pipelineDepth > MAX_PIPELINE_DEPTH) {\n throw new Error(`${depthError}\nService bindings can recurse up to ${MAX_PIPELINE_DEPTH} times.`);\n }\n this.requestDepth = requestDepth;\n this.pipelineDepth = pipelineDepth;\n this.durableObject = durableObject;\n }\n runWith(closure) {\n return requestContextStorage.run(this, closure);\n }\n #subrequests = 0;\n get subrequests() {\n return this.#subrequests;\n }\n incrementSubrequests(count = 1) {\n this.#subrequests += count;\n if (MAX_SUBREQUESTS >= 0 && this.#subrequests > MAX_SUBREQUESTS) {\n throw new Error(`Too many subrequests. Workers can make up to ${MAX_SUBREQUESTS} subrequests per request.\nA subrequest is a call to fetch(), a redirect, or a call to any Cache API method.`);\n }\n }\n};\n\n// packages/shared/src/data.ts\nvar import_path = __toModule(require(\"path\"));\nvar import_ignore = __toModule(require(\"ignore\"));\nfunction nonCircularClone(value) {\n return JSON.parse(JSON.stringify(value));\n}\nfunction addAll(set, values) {\n for (const value of values)\n set.add(value);\n}\nfunction viewToArray(view) {\n return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n}\nfunction viewToBuffer(view) {\n return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);\n}\nfunction base64Encode(value) {\n return Buffer.from(value, \"utf8\").toString(\"base64\");\n}\nfunction base64Decode(encoded) {\n return Buffer.from(encoded, \"base64\").toString(\"utf8\");\n}\nfunction randomHex(digits = 8) {\n return Array.from(Array(digits)).map(() => Math.floor(Math.random() * 16).toString(16)).join(\"\");\n}\nfunction globsToMatcher(globs) {\n const ign = (0, import_ignore.default)();\n if (globs)\n ign.add(globs);\n return {\n test: (string) => ign.ignores(string),\n toString: () => globs?.join(\", \") ?? \"\"\n };\n}\nfunction kebabCase(s) {\n return s.replace(/[A-Z]/g, (sub) => `-${sub.toLowerCase()}`);\n}\nfunction spaceCase(s) {\n s = s.replace(/(.)([A-Z][a-z]+)/g, \"$1 $2\");\n return s.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\");\n}\nfunction titleCase(s) {\n return spaceCase(s).split(\" \").map((s2) => s2 ? s2[0].toUpperCase() + s2.substring(1) : s2).join(\" \");\n}\nvar urlRegexp = /^([a-z]+:)?\\/\\//i;\nfunction resolveStoragePersist(rootPath, persist) {\n if (typeof persist === \"string\") {\n if (urlRegexp.test(persist))\n return persist;\n return import_path.default.resolve(rootPath, persist);\n }\n return persist;\n}\nvar namespaceRegexp = /[/\\\\:|]/g;\nvar dotRegexp = /(^|\\/|\\\\)(\\.+)(\\/|\\\\|$)/g;\nvar illegalRegexp = /[?<>*\"'^\\x00-\\x1f\\x80-\\x9f]/g;\nvar windowsReservedRegexp = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\\..*)?$/i;\nvar leadingRegexp = /^[ /\\\\]+/;\nvar trailingRegexp = /[ /\\\\]+$/;\nfunction dotReplacement(match, g1, g2, g3) {\n return `${g1}${\"\".padStart(g2.length, \"_\")}${g3}`;\n}\nfunction underscoreReplacement(match) {\n return \"\".padStart(match.length, \"_\");\n}\nfunction sanitisePath(unsafe) {\n return unsafe.replace(namespaceRegexp, import_path.default.sep).replace(dotRegexp, dotReplacement).replace(dotRegexp, dotReplacement).replace(illegalRegexp, \"_\").replace(windowsReservedRegexp, \"_\").replace(leadingRegexp, underscoreReplacement).replace(trailingRegexp, underscoreReplacement).substring(0, 255);\n}\n\n// packages/shared/src/error.ts\nvar MiniflareError = class extends Error {\n constructor(code, message, cause) {\n super(message);\n this.code = code;\n this.cause = cause;\n Object.setPrototypeOf(this, new.target.prototype);\n this.name = `${new.target.name} [${code}]`;\n }\n};\nfunction prefixError(prefix, e) {\n if (e.stack) {\n return new Proxy(e, {\n get(target, propertyKey, receiver) {\n const value = Reflect.get(target, propertyKey, receiver);\n return propertyKey === \"stack\" ? `${prefix}: ${value}` : value;\n }\n });\n }\n return e;\n}\n\n// packages/shared/src/event.ts\nvar kWrapListener = Symbol(\"kWrapListener\");\nvar TypedEventTarget = class extends EventTarget {\n #wrappedListeners = new WeakMap();\n #wrap(listener) {\n if (!listener)\n return null;\n let wrappedListener = this.#wrappedListeners.get(listener);\n if (wrappedListener)\n return wrappedListener;\n wrappedListener = this[kWrapListener]((event) => {\n if (typeof listener === \"function\") {\n listener(event);\n } else {\n listener.handleEvent(event);\n }\n });\n this.#wrappedListeners.set(listener, wrappedListener);\n return wrappedListener;\n }\n addEventListener(type, listener, options) {\n super.addEventListener(type, this[kWrapListener] ? this.#wrap(listener) : listener, options);\n }\n removeEventListener(type, listener, options) {\n super.removeEventListener(type, this[kWrapListener] ? this.#wrap(listener) : listener, options);\n }\n dispatchEvent(event) {\n return super.dispatchEvent(event);\n }\n};\nvar ThrowingEventTarget = class extends TypedEventTarget {\n #wrappedError;\n [kWrapListener](listener) {\n return (event) => {\n try {\n listener(event);\n } catch (error) {\n event.stopImmediatePropagation();\n this.#wrappedError = error;\n }\n };\n }\n dispatchEvent(event) {\n this.#wrappedError = void 0;\n const result = super.dispatchEvent(event);\n if (this.#wrappedError !== void 0)\n throw this.#wrappedError;\n return result;\n }\n};\n\n// packages/shared/src/log.ts\nvar import_path2 = __toModule(require(\"path\"));\nvar import_colors = __toModule(require(\"kleur/colors\"));\nvar cwd = process.cwd();\nvar cwdNodeModules = import_path2.default.join(cwd, \"node_modules\");\nvar LogLevel;\n(function(LogLevel2) {\n LogLevel2[LogLevel2[\"NONE\"] = 0] = \"NONE\";\n LogLevel2[LogLevel2[\"ERROR\"] = 1] = \"ERROR\";\n LogLevel2[LogLevel2[\"WARN\"] = 2] = \"WARN\";\n LogLevel2[LogLevel2[\"INFO\"] = 3] = \"INFO\";\n LogLevel2[LogLevel2[\"DEBUG\"] = 4] = \"DEBUG\";\n LogLevel2[LogLevel2[\"VERBOSE\"] = 5] = \"VERBOSE\";\n})(LogLevel || (LogLevel = {}));\nvar LEVEL_PREFIX = {\n [0]: \"\",\n [1]: \"err\",\n [2]: \"wrn\",\n [3]: \"inf\",\n [4]: \"dbg\",\n [5]: \"vrb\"\n};\nvar LEVEL_COLOUR = {\n [0]: import_colors.reset,\n [1]: import_colors.red,\n [2]: import_colors.yellow,\n [3]: import_colors.green,\n [4]: import_colors.grey,\n [5]: (input) => (0, import_colors.dim)((0, import_colors.grey)(input))\n};\nfunction dimInternalStackLine(line) {\n if (line.startsWith(\" at\") && (!line.includes(cwd) || line.includes(cwdNodeModules))) {\n return (0, import_colors.dim)(line);\n }\n return line;\n}\nvar Log = class {\n constructor(level = 3, opts = {}) {\n this.level = level;\n const prefix = opts.prefix ?? \"mf\";\n const suffix = opts.suffix ?? \"\";\n this.#prefix = prefix ? prefix + \":\" : \"\";\n this.#suffix = suffix ? \":\" + suffix : \"\";\n }\n #prefix;\n #suffix;\n log(message) {\n console.log(message);\n }\n logWithLevel(level, message) {\n if (level <= this.level) {\n const prefix = `[${this.#prefix}${LEVEL_PREFIX[level]}${this.#suffix}]`;\n this.log(LEVEL_COLOUR[level](`${prefix} ${message}`));\n }\n }\n error(message) {\n if (this.level < 1) {\n throw message;\n } else if (message.stack) {\n const lines = message.stack.split(\"\\n\").map(dimInternalStackLine);\n this.logWithLevel(1, lines.join(\"\\n\"));\n } else {\n this.logWithLevel(1, message.toString());\n }\n if (message.cause) {\n this.error(prefixError(\"Cause\", message.cause));\n }\n }\n warn(message) {\n this.logWithLevel(2, message);\n }\n info(message) {\n this.logWithLevel(3, message);\n }\n debug(message) {\n this.logWithLevel(4, message);\n }\n verbose(message) {\n this.logWithLevel(5, message);\n }\n};\nvar NoOpLog = class extends Log {\n log() {\n }\n error(message) {\n throw message;\n }\n};\n\n// packages/shared/src/plugin.ts\nvar OptionType;\n(function(OptionType2) {\n OptionType2[OptionType2[\"NONE\"] = 0] = \"NONE\";\n OptionType2[OptionType2[\"BOOLEAN\"] = 1] = \"BOOLEAN\";\n OptionType2[OptionType2[\"NUMBER\"] = 2] = \"NUMBER\";\n OptionType2[OptionType2[\"STRING\"] = 3] = \"STRING\";\n OptionType2[OptionType2[\"STRING_POSITIONAL\"] = 4] = \"STRING_POSITIONAL\";\n OptionType2[OptionType2[\"BOOLEAN_STRING\"] = 5] = \"BOOLEAN_STRING\";\n OptionType2[OptionType2[\"BOOLEAN_NUMBER\"] = 6] = \"BOOLEAN_NUMBER\";\n OptionType2[OptionType2[\"ARRAY\"] = 7] = \"ARRAY\";\n OptionType2[OptionType2[\"OBJECT\"] = 8] = \"OBJECT\";\n})(OptionType || (OptionType = {}));\nfunction Option(metadata) {\n return function(prototype, key) {\n (prototype.opts ??= new Map()).set(key, metadata);\n };\n}\nvar Plugin = class {\n constructor(ctx) {\n this.ctx = ctx;\n this.opts = new.target.prototype.opts;\n }\n #phantom;\n opts;\n assignOptions(options) {\n if (options === void 0 || this.opts === void 0)\n return;\n for (const key of this.opts.keys()) {\n this[key] = options[key];\n }\n }\n};\nfunction logOptions(plugins, log, options) {\n log.debug(\"Options:\");\n for (const [name, plugin] of plugins) {\n const pluginOptions = options[name];\n for (const [key, meta] of plugin.prototype.opts?.entries() ?? []) {\n const value = pluginOptions[key];\n if (value === void 0 || meta.type === 0)\n continue;\n const keyName = meta?.logName ?? titleCase(typeof key === \"symbol\" ? \"<symbol>\" : key);\n let str;\n if (meta.logValue) {\n str = meta.logValue(value);\n if (str === void 0)\n continue;\n } else if (meta.type === 8) {\n str = Object.keys(value).join(\", \");\n } else if (meta.type === 7) {\n str = value.join(\", \");\n } else {\n str = value.toString();\n }\n log.debug(`- ${keyName}: ${str}`);\n }\n }\n}\n\n// packages/shared/src/runner.ts\nvar STRING_SCRIPT_PATH = \"<script>\";\n\n// packages/shared/src/storage.ts\nvar Storage = class {\n async hasMany(keys) {\n const results = keys.map(this.has.bind(this));\n let count = 0;\n for (const result of await Promise.all(results))\n if (result)\n count++;\n return count;\n }\n getMany(keys, skipMetadata) {\n return Promise.all(keys.map((key) => this.get(key, skipMetadata)));\n }\n async putMany(data) {\n await Promise.all(data.map(([key, value]) => this.put(key, value)));\n }\n async deleteMany(keys) {\n const results = keys.map(this.delete.bind(this));\n let count = 0;\n for (const result of await Promise.all(results))\n if (result)\n count++;\n return count;\n }\n};\n\n// packages/shared/src/sync/clock.ts\nvar defaultClock = () => Date.now();\nfunction millisToSeconds(millis) {\n return Math.floor(millis / 1e3);\n}\n\n// packages/shared/src/sync/gate.ts\nvar import_assert2 = __toModule(require(\"assert\"));\nvar import_async_hooks2 = __toModule(require(\"async_hooks\"));\nvar import_promises = __toModule(require(\"timers/promises\"));\nvar inputGateStorage = new import_async_hooks2.AsyncLocalStorage();\nvar outputGateStorage = new import_async_hooks2.AsyncLocalStorage();\nfunction waitForOpenInputGate() {\n const inputGate = inputGateStorage.getStore();\n return inputGate?.waitForOpen();\n}\nfunction runWithInputGateClosed(closure, allowConcurrency = false) {\n if (allowConcurrency)\n return closure();\n const inputGate = inputGateStorage.getStore();\n if (inputGate === void 0)\n return closure();\n return inputGate.runWithClosed(closure);\n}\nfunction waitForOpenOutputGate() {\n const outputGate = outputGateStorage.getStore();\n return outputGate?.waitForOpen();\n}\nfunction waitUntilOnOutputGate(promise, allowUnconfirmed = false) {\n if (allowUnconfirmed)\n return promise;\n const outputGate = outputGateStorage.getStore();\n outputGate?.waitUntil(promise);\n return promise;\n}\nvar InputGate = class {\n #lockCount = 0;\n #resolveQueue = [];\n #parent;\n constructor(parent) {\n this.#parent = parent;\n }\n async runWith(closure) {\n await this.waitForOpen();\n return inputGateStorage.run(this, closure);\n }\n async waitForOpen() {\n await (0, import_promises.setImmediate)();\n if (this.#lockCount === 0)\n return;\n return new Promise((resolve) => this.#resolveQueue.push(resolve));\n }\n async runWithClosed(closure) {\n this.#lock();\n await Promise.resolve();\n const childInputGate = new InputGate(this);\n try {\n return await inputGateStorage.run(childInputGate, closure);\n } finally {\n setImmediate(this.#unlock);\n }\n }\n #lock() {\n this.#lockCount++;\n if (this.#parent)\n this.#parent.#lock();\n }\n #unlock = async () => {\n (0, import_assert2.default)(this.#lockCount > 0);\n this.#lockCount--;\n while (this.#lockCount === 0 && this.#resolveQueue.length) {\n this.#resolveQueue.shift()();\n await (0, import_promises.setImmediate)();\n }\n if (this.#parent)\n return this.#parent.#unlock();\n };\n};\nvar OutputGate = class {\n #waitUntil = [];\n async runWith(closure) {\n try {\n return await outputGateStorage.run(this, closure);\n } finally {\n await this.waitForOpen();\n }\n }\n async waitForOpen() {\n await Promise.all(this.#waitUntil);\n }\n waitUntil(promise) {\n this.#waitUntil.push(promise);\n }\n};\nvar InputGatedEventTarget = class extends TypedEventTarget {\n [kWrapListener](listener) {\n const inputGate = inputGateStorage.getStore();\n return inputGate ? async (event) => {\n await inputGate.waitForOpen();\n listener(event);\n } : listener;\n }\n};\n\n// packages/shared/src/sync/mutex.ts\nvar import_assert3 = __toModule(require(\"assert\"));\nvar Mutex = class {\n locked = false;\n resolveQueue = [];\n lock() {\n if (!this.locked) {\n this.locked = true;\n return;\n }\n return new Promise((resolve) => this.resolveQueue.push(resolve));\n }\n unlock() {\n (0, import_assert3.default)(this.locked);\n if (this.resolveQueue.length > 0) {\n this.resolveQueue.shift()?.();\n } else {\n this.locked = false;\n }\n }\n get hasWaiting() {\n return this.resolveQueue.length > 0;\n }\n async runWith(closure) {\n const acquireAwaitable = this.lock();\n if (acquireAwaitable instanceof Promise)\n await acquireAwaitable;\n try {\n const awaitable = closure();\n if (awaitable instanceof Promise)\n return await awaitable;\n return awaitable;\n } finally {\n this.unlock();\n }\n }\n};\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n Compatibility,\n InputGate,\n InputGatedEventTarget,\n Log,\n LogLevel,\n MiniflareError,\n Mutex,\n NoOpLog,\n Option,\n OptionType,\n OutputGate,\n Plugin,\n RequestContext,\n STRING_SCRIPT_PATH,\n Storage,\n ThrowingEventTarget,\n TypedEventTarget,\n addAll,\n assertInRequest,\n base64Decode,\n base64Encode,\n defaultClock,\n getRequestContext,\n globsToMatcher,\n kWrapListener,\n kebabCase,\n logOptions,\n millisToSeconds,\n nonCircularClone,\n prefixError,\n randomHex,\n resolveStoragePersist,\n runWithInputGateClosed,\n sanitisePath,\n spaceCase,\n titleCase,\n viewToArray,\n viewToBuffer,\n waitForOpenInputGate,\n waitForOpenOutputGate,\n waitUntilOnOutputGate\n});\n/*! Path sanitisation regexps adapted from node-sanitize-filename:\n * https://github.com/parshap/node-sanitize-filename/blob/209c39b914c8eb48ee27bcbde64b2c7822fdf3de/index.js#L4-L37\n *\n * Licensed under the ISC license:\n *\n * Copyright Parsha Pourkhomami <parshap@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the\n * above copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY\n * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\n * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n//# sourceMappingURL=index.js.map\n","var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __markAsModule = (target) => __defProp(target, \"__esModule\", { value: true });\nvar __export = (target, all) => {\n __markAsModule(target);\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __reExport = (target, module2, desc) => {\n if (module2 && typeof module2 === \"object\" || typeof module2 === \"function\") {\n for (let key of __getOwnPropNames(module2))\n if (!__hasOwnProp.call(target, key) && key !== \"default\")\n __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });\n }\n return target;\n};\nvar __toModule = (module2) => {\n return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, \"default\", module2 && module2.__esModule && \"default\" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);\n};\n\n// packages/storage-memory/src/index.ts\n__export(exports, {\n LocalStorage: () => LocalStorage,\n MemoryStorage: () => MemoryStorage,\n cloneMetadata: () => cloneMetadata,\n listFilterMatch: () => listFilterMatch,\n listPaginate: () => listPaginate\n});\n\n// packages/storage-memory/src/helpers.ts\nvar import_shared = __toModule(require(\"@miniflare/shared\"));\nfunction cloneMetadata(metadata) {\n return metadata && (0, import_shared.nonCircularClone)(metadata);\n}\nvar collator = new Intl.Collator();\nfunction listFilterMatch(options, name) {\n return !(options?.prefix && !name.startsWith(options.prefix) || options?.start && collator.compare(name, options.start) < 0 || options?.end && collator.compare(name, options.end) >= 0);\n}\nfunction listPaginate(options, keys) {\n const direction = options?.reverse ? -1 : 1;\n keys.sort((a, b) => direction * collator.compare(a.name, b.name));\n const startAfter = options?.cursor ? (0, import_shared.base64Decode)(options.cursor) : \"\";\n let startIndex = 0;\n if (startAfter !== \"\") {\n startIndex = keys.findIndex(({ name }) => name === startAfter);\n if (startIndex === -1)\n startIndex = keys.length;\n startIndex++;\n }\n const endIndex = options?.limit === void 0 ? keys.length : startIndex + options.limit;\n const nextCursor = endIndex < keys.length ? (0, import_shared.base64Encode)(keys[endIndex - 1].name) : \"\";\n keys = keys.slice(startIndex, endIndex);\n return { keys, cursor: nextCursor };\n}\n\n// packages/storage-memory/src/local.ts\nvar import_shared2 = __toModule(require(\"@miniflare/shared\"));\nvar LocalStorage = class extends import_shared2.Storage {\n constructor(clock = import_shared2.defaultClock) {\n super();\n this.clock = clock;\n }\n expired({ expiration }, time = this.clock()) {\n return expiration !== void 0 && expiration <= (0, import_shared2.millisToSeconds)(time);\n }\n async has(key) {\n const stored = await this.hasMaybeExpired(key);\n if (stored === void 0)\n return false;\n if (this.expired(stored)) {\n await this.deleteMaybeExpired(key);\n return false;\n }\n return true;\n }\n async get(key) {\n const stored = await this.getMaybeExpired(key);\n if (stored === void 0)\n return void 0;\n if (this.expired(stored)) {\n await this.deleteMaybeExpired(key);\n return void 0;\n }\n return stored;\n }\n async delete(key) {\n const stored = await this.hasMaybeExpired(key);\n const expired = stored !== void 0 && this.expired(stored);\n const deleted = await this.deleteMaybeExpired(key);\n if (!deleted)\n return false;\n return !expired;\n }\n async list(options) {\n const time = this.clock();\n const deletePromises = [];\n let keys = await this.listAllMaybeExpired();\n keys = keys.filter((stored) => {\n if (this.expired(stored, time)) {\n deletePromises.push(this.deleteMaybeExpired(stored.name));\n return false;\n }\n return listFilterMatch(options, stored.name);\n });\n const res = listPaginate(options, keys);\n await Promise.all(deletePromises);\n return res;\n }\n};\n\n// packages/storage-memory/src/memory.ts\nvar import_shared3 = __toModule(require(\"@miniflare/shared\"));\nvar MemoryStorage = class extends LocalStorage {\n constructor(map = new Map(), clock = import_shared3.defaultClock) {\n super(clock);\n this.map = map;\n }\n hasMaybeExpired(key) {\n const stored = this.map.get(key);\n return stored && {\n expiration: stored.expiration,\n metadata: cloneMetadata(stored.metadata)\n };\n }\n getMaybeExpired(key) {\n const stored = this.map.get(key);\n return stored && {\n value: stored.value.slice(),\n expiration: stored.expiration,\n metadata: cloneMetadata(stored.metadata)\n };\n }\n put(key, value) {\n this.map.set(key, {\n value: value.value.slice(),\n expiration: value.expiration,\n metadata: cloneMetadata(value.metadata)\n });\n }\n deleteMaybeExpired(key) {\n return this.map.delete(key);\n }\n static entryToStoredKey([name, { expiration, metadata }]) {\n return {\n name,\n expiration,\n metadata: cloneMetadata(metadata)\n };\n }\n listAllMaybeExpired() {\n return Array.from(this.map.entries()).map(MemoryStorage.entryToStoredKey);\n }\n};\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n LocalStorage,\n MemoryStorage,\n cloneMetadata,\n listFilterMatch,\n listPaginate\n});\n//# sourceMappingURL=index.js.map\n","#!/usr/bin/env npx -y esno\n\n// this will let you mess with KV & DO in different environments\n\n// I use a global, so it's easier to mock in unit-tests, in ES6\n/* global fetch */\n\nimport path from 'path'\nimport { KVNamespace } from '@miniflare/kv'\nimport { FileStorage } from '@miniflare/storage-file'\nimport { MemoryStorage } from '@miniflare/storage-memory'\n\nfunction requiredOptions (needs, options) {\n for (const o of needs) {\n if (!options[o] || options[o] === '') {\n throw new Error(`${o} is required.`)\n }\n }\n}\n\nexport class CrossKV {\n constructor (name, options = {}) {\n // these are default env-vars\n const { CF_TOKEN, CF_ACCOUNTID, CLOUDFLARE_TOKEN } = (process?.env || {})\n\n this.options = {\n ...options,\n target: options.target || 'local',\n filepath: path.resolve(options.filepath || './.mf/kv', name),\n accountToken: options.accountToken || CF_TOKEN || CLOUDFLARE_TOKEN,\n accountID: options.accountID || CF_ACCOUNTID,\n env: options.env || {},\n name\n }\n\n if (this.options.target === 'local') {\n requiredOptions(['filepath'], this.options)\n this._db = new KVNamespace(new FileStorage(this.options.filepath))\n } else if (this.options.target === 'cf') {\n this._db = this.options.env[name] || global[name]\n if (!this._db) {\n throw new Error(`You chose \"cf\" for target, but env does not have \"${name}\" KV.`)\n }\n } else if (this.options.target === 'remote') {\n requiredOptions(['kvID', 'accountToken', 'accountID'], this.options)\n } else if (this.options.target === 'memory') {\n this._db = new KVNamespace(new MemoryStorage())\n }\n\n // bind all the methods to this object, if there is a db setup (miniflare or real)\n if (this._db) {\n this.get = this._db.get.bind(this._db)\n this.getWithMetadata = this._db.getWithMetadata.bind(this._db)\n this.list = this._db.list.bind(this._db)\n this.put = this._db.put.bind(this._db)\n this.delete = this._db.delete.bind(this._db)\n\n // this makes API match, but just calls regular function for each\n this.bulkdelete = (keys, paramsAll = {}) => Promise.all(keys.map(id => this.delete(id, paramsAll)))\n this.bulkput = (records, paramsAll = {}) => Promise.all(records.map(({ key, value, ...params }) => this.put(key, value, { ...paramsAll, ...params })))\n }\n }\n\n // below here is implementations that hits remote KV\n\n async get (id, paramsAll = {}) {\n const { type, ...params } = paramsAll\n const o = new URLSearchParams(params).toString()\n\n const r = await this.api(`/storage/kv/namespaces/${this.options.kvID}/values/${id}?${o}`)\n if (type === 'json') {\n return r.json()\n } else