@miniflare/shared
Version:
Shared utility module for Miniflare: a fun, full-featured, fully-local simulator for Cloudflare Workers
891 lines (875 loc) • 28.7 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && key !== "default")
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toModule = (module2) => {
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);
};
// packages/shared/src/index.ts
__export(exports, {
Compatibility: () => Compatibility,
EXTERNAL_SUBREQUEST_LIMIT_BUNDLED: () => EXTERNAL_SUBREQUEST_LIMIT_BUNDLED,
EXTERNAL_SUBREQUEST_LIMIT_UNBOUND: () => EXTERNAL_SUBREQUEST_LIMIT_UNBOUND,
INTERNAL_SUBREQUEST_LIMIT: () => INTERNAL_SUBREQUEST_LIMIT,
InputGate: () => InputGate,
InputGatedEventTarget: () => InputGatedEventTarget,
Log: () => Log,
LogLevel: () => LogLevel,
MiniflareError: () => MiniflareError,
Mutex: () => Mutex,
NoOpLog: () => NoOpLog,
Option: () => Option,
OptionType: () => OptionType,
OutputGate: () => OutputGate,
Plugin: () => Plugin,
RequestContext: () => RequestContext,
SITES_NO_CACHE_PREFIX: () => SITES_NO_CACHE_PREFIX,
STRING_SCRIPT_PATH: () => STRING_SCRIPT_PATH,
Storage: () => Storage,
ThrowingEventTarget: () => ThrowingEventTarget,
TypedEventTarget: () => TypedEventTarget,
addAll: () => addAll,
arrayCompare: () => arrayCompare,
assertInRequest: () => assertInRequest,
base64Decode: () => base64Decode,
base64Encode: () => base64Encode,
createSQLiteDB: () => createSQLiteDB,
defaultClock: () => defaultClock,
getRequestContext: () => getRequestContext,
getSQLiteNativeBindingLocation: () => getSQLiteNativeBindingLocation,
globsToMatcher: () => globsToMatcher,
kGetConsumer: () => kGetConsumer,
kSetConsumer: () => kSetConsumer,
kWrapListener: () => kWrapListener,
kebabCase: () => kebabCase,
lexicographicCompare: () => lexicographicCompare,
logOptions: () => logOptions,
millisToSeconds: () => millisToSeconds,
nonCircularClone: () => nonCircularClone,
numericCompare: () => numericCompare,
parseRange: () => parseRange,
prefixError: () => prefixError,
randomHex: () => randomHex,
resolveStoragePersist: () => resolveStoragePersist,
runWithInputGateClosed: () => runWithInputGateClosed,
sanitisePath: () => sanitisePath,
spaceCase: () => spaceCase,
structuredCloneImpl: () => structuredCloneImpl,
titleCase: () => titleCase,
usageModelExternalSubrequestLimit: () => usageModelExternalSubrequestLimit,
viewToArray: () => viewToArray,
viewToBuffer: () => viewToBuffer,
waitForOpenInputGate: () => waitForOpenInputGate,
waitForOpenOutputGate: () => waitForOpenOutputGate,
waitUntilOnOutputGate: () => waitUntilOnOutputGate
});
// packages/shared/src/data.ts
var import_assert = __toModule(require("assert"));
var import_path = __toModule(require("path"));
var import_util = __toModule(require("util"));
var import_worker_threads = __toModule(require("worker_threads"));
var import_picomatch = __toModule(require("picomatch"));
var encoder = new import_util.TextEncoder();
var numericCompare = new Intl.Collator(void 0, { numeric: true }).compare;
function arrayCompare(a, b) {
const minLength = Math.min(a.length, b.length);
for (let i = 0; i < minLength; i++) {
const aElement = a[i];
const bElement = b[i];
if (aElement < bElement)
return -1;
if (aElement > bElement)
return 1;
}
return a.length - b.length;
}
function lexicographicCompare(x, y) {
const xEncoded = encoder.encode(x);
const yEncoded = encoder.encode(y);
return arrayCompare(xEncoded, yEncoded);
}
function nonCircularClone(value) {
return JSON.parse(JSON.stringify(value));
}
var channel;
function structuredCloneImpl(value, options) {
channel ??= new import_worker_threads.MessageChannel();
channel.port1.unref();
channel.port2.unref();
channel.port1.postMessage(value, options?.transfer);
const message = (0, import_worker_threads.receiveMessageOnPort)(channel.port2);
(0, import_assert.default)(message !== void 0);
return message.message;
}
function addAll(set, values) {
for (const value of values)
set.add(value);
}
function viewToArray(view) {
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
}
function viewToBuffer(view) {
return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
}
function base64Encode(value) {
return Buffer.from(value, "utf8").toString("base64");
}
function base64Decode(encoded) {
return Buffer.from(encoded, "base64").toString("utf8");
}
function randomHex(digits = 8) {
return Array.from(Array(digits)).map(() => Math.floor(Math.random() * 16).toString(16)).join("");
}
var SITES_NO_CACHE_PREFIX = "$__MINIFLARE_SITES__$/";
function globsToMatcher(globs = []) {
const matchGlobs = [];
const ignoreGlobs = [];
for (const glob of globs) {
if (glob.startsWith("!")) {
ignoreGlobs.push(glob.slice(1));
} else {
matchGlobs.push(glob);
}
}
const isMatch = (0, import_picomatch.default)(matchGlobs, {
dot: true,
bash: true,
contains: true,
ignore: ignoreGlobs
});
return {
test: (string) => isMatch(string),
toString: () => globs.join(", ")
};
}
function kebabCase(s) {
return s.replace(/[A-Z]/g, (sub) => `-${sub.toLowerCase()}`);
}
function spaceCase(s) {
s = s.replace(/(.)([A-Z][a-z]+)/g, "$1 $2");
return s.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
}
function titleCase(s) {
return spaceCase(s).split(" ").map((s2) => s2 ? s2[0].toUpperCase() + s2.substring(1) : s2).join(" ");
}
var urlRegexp = /^([a-z]+:)?\/\//i;
function resolveStoragePersist(rootPath, persist) {
if (typeof persist === "string") {
if (urlRegexp.test(persist))
return persist;
return import_path.default.resolve(rootPath, persist);
}
return persist;
}
var namespaceRegexp = /[/\\:|]/g;
var dotRegexp = /(^|\/|\\)(\.+)(\/|\\|$)/g;
var illegalRegexp = /[?<>*"'^\x00-\x1f\x80-\x9f]/g;
var windowsReservedRegexp = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;
var leadingRegexp = /^[ /\\]+/;
var trailingRegexp = /[ /\\]+$/;
function dotReplacement(match, g1, g2, g3) {
return `${g1}${"".padStart(g2.length, "_")}${g3}`;
}
function underscoreReplacement(match) {
return "".padStart(match.length, "_");
}
function sanitisePath(unsafe) {
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);
}
// packages/shared/src/compat.ts
var FEATURES = [
{
enableFlag: "nodejs_compat"
},
{
defaultAsOf: "2022-11-30",
enableFlag: "streams_enable_constructors",
disableFlag: "streams_disable_constructors"
},
{
defaultAsOf: "2022-11-30",
enableFlag: "transformstream_enable_standard_constructor",
disableFlag: "transformstream_disable_standard_constructor"
},
{
defaultAsOf: "2022-10-31",
enableFlag: "export_commonjs_default",
disableFlag: "export_commonjs_namespace"
},
{
defaultAsOf: "2022-08-04",
enableFlag: "r2_list_honor_include"
},
{
defaultAsOf: "2022-03-21",
enableFlag: "global_navigator",
disableFlag: "no_global_navigator"
},
{
defaultAsOf: "2021-11-10",
enableFlag: "durable_object_fetch_requires_full_url",
disableFlag: "durable_object_fetch_allows_relative_url"
},
{
defaultAsOf: "2021-11-10",
enableFlag: "fetch_refuses_unknown_protocols",
disableFlag: "fetch_treats_unknown_protocols_as_http"
},
{
defaultAsOf: "2021-11-03",
enableFlag: "formdata_parser_supports_files",
disableFlag: "formdata_parser_converts_files_to_strings"
},
{
enableFlag: "html_rewriter_treats_esi_include_as_void_tag"
},
{
enableFlag: "experimental"
}
];
var Compatibility = class {
constructor(compatibilityDate = "1970-01-01", compatibilityFlags = []) {
this.compatibilityDate = compatibilityDate;
this.compatibilityFlags = compatibilityFlags;
this.#rebuildEnabled();
}
#enabled = new Set();
#rebuildEnabled() {
this.#enabled.clear();
const flags = new Set(this.compatibilityFlags);
for (const { defaultAsOf, enableFlag, disableFlag } of FEATURES) {
const disabledExplicitly = disableFlag && flags.has(disableFlag);
if (disabledExplicitly)
continue;
const enabledExplicitly = flags.has(enableFlag);
const enabledAutomatically = defaultAsOf && numericCompare(defaultAsOf, this.compatibilityDate) <= 0;
if (enabledExplicitly || enabledAutomatically) {
this.#enabled.add(enableFlag);
}
}
}
isEnabled(flag) {
return this.#enabled.has(flag);
}
update(compatibilityDate = "1970-01-01", compatibilityFlags = []) {
if (this.compatibilityDate === compatibilityDate && this.compatibilityFlags.length === compatibilityFlags.length && this.compatibilityFlags.every((flag, i) => compatibilityFlags[i] === flag)) {
return false;
}
this.compatibilityDate = compatibilityDate;
this.compatibilityFlags = compatibilityFlags;
this.#rebuildEnabled();
return true;
}
get enabled() {
return [...this.#enabled];
}
};
// packages/shared/src/context.ts
var import_assert2 = __toModule(require("assert"));
var import_async_hooks = __toModule(require("async_hooks"));
function parseSubrequestOverride(limit) {
const parsed = parseInt(limit);
if (Number.isNaN(parsed))
return void 0;
if (parsed < 0)
return false;
return parsed;
}
var EXTERNAL_SUBREQUEST_LIMIT_OVERRIDE = parseSubrequestOverride(process.env.MINIFLARE_SUBREQUEST_LIMIT);
var INTERNAL_SUBREQUEST_LIMIT_OVERRIDE = parseSubrequestOverride(process.env.MINIFLARE_INTERNAL_SUBREQUEST_LIMIT);
var EXTERNAL_SUBREQUEST_LIMIT_BUNDLED = 50;
var EXTERNAL_SUBREQUEST_LIMIT_UNBOUND = 1e3;
var INTERNAL_SUBREQUEST_LIMIT = 1e3;
function usageModelExternalSubrequestLimit(model) {
return model === "unbound" ? EXTERNAL_SUBREQUEST_LIMIT_UNBOUND : EXTERNAL_SUBREQUEST_LIMIT_BUNDLED;
}
var MAX_REQUEST_DEPTH = 16;
var MAX_PIPELINE_DEPTH = 32;
var 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.";
var requestContextStorage = new import_async_hooks.AsyncLocalStorage();
function getRequestContext() {
return requestContextStorage.getStore();
}
function assertInRequest() {
if (!getRequestContext()) {
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.");
}
}
var RequestContext = class {
requestDepth;
pipelineDepth;
durableObject;
externalSubrequestLimit;
internalSubrequestLimit;
#internalSubrequests = 0;
#externalSubrequests = 0;
#currentTime;
constructor({
requestDepth = 1,
pipelineDepth = 1,
durableObject = false,
externalSubrequestLimit = EXTERNAL_SUBREQUEST_LIMIT_BUNDLED,
internalSubrequestLimit = INTERNAL_SUBREQUEST_LIMIT
} = {}) {
(0, import_assert2.default)(requestDepth >= 1);
(0, import_assert2.default)(pipelineDepth >= 1);
if (requestDepth > MAX_REQUEST_DEPTH) {
throw new Error(`${depthError}
Workers and objects can recurse up to ${MAX_REQUEST_DEPTH} times.
If you're trying to fetch from an origin server, make sure you've set the \`upstream\` option.`);
}
if (pipelineDepth > MAX_PIPELINE_DEPTH) {
throw new Error(`${depthError}
Service bindings can recurse up to ${MAX_PIPELINE_DEPTH} times.`);
}
this.requestDepth = requestDepth;
this.pipelineDepth = pipelineDepth;
this.durableObject = durableObject;
this.externalSubrequestLimit = EXTERNAL_SUBREQUEST_LIMIT_OVERRIDE !== void 0 ? EXTERNAL_SUBREQUEST_LIMIT_OVERRIDE : externalSubrequestLimit;
this.internalSubrequestLimit = INTERNAL_SUBREQUEST_LIMIT_OVERRIDE !== void 0 ? INTERNAL_SUBREQUEST_LIMIT_OVERRIDE : internalSubrequestLimit;
this.#currentTime = Date.now();
}
runWith(closure) {
return requestContextStorage.run(this, closure);
}
get externalSubrequests() {
return this.#externalSubrequests;
}
get internalSubrequests() {
return this.#internalSubrequests;
}
incrementExternalSubrequests(count = 1) {
this.#externalSubrequests += count;
if (this.externalSubrequestLimit !== false && this.#externalSubrequests > this.externalSubrequestLimit) {
throw new Error(`Too many subrequests. Workers can make up to ${this.externalSubrequestLimit} subrequests per request.
A subrequest is a call to fetch(), a redirect, or a call to any Cache API method.`);
}
}
incrementInternalSubrequests(count = 1) {
this.#internalSubrequests += count;
if (this.internalSubrequestLimit !== false && this.#internalSubrequests > this.internalSubrequestLimit) {
throw new Error(`Too many API requests by single worker invocation. Workers can make up to ${this.internalSubrequestLimit} KV and Durable Object requests per invocation.`);
}
}
get currentTime() {
return this.#currentTime;
}
advanceCurrentTime() {
this.#currentTime = Date.now();
}
};
// packages/shared/src/error.ts
var MiniflareError = class extends Error {
constructor(code, message, cause) {
super(message);
this.code = code;
this.cause = cause;
Object.setPrototypeOf(this, new.target.prototype);
this.name = `${new.target.name} [${code}]`;
}
};
function prefixError(prefix, e) {
if (e.stack) {
return new Proxy(e, {
get(target, propertyKey, receiver) {
return propertyKey === "stack" ? `${prefix}: ${target.stack}` : Reflect.get(target, propertyKey, receiver);
}
});
}
return e;
}
// packages/shared/src/event.ts
var kWrapListener = Symbol("kWrapListener");
var TypedEventTarget = class extends EventTarget {
#wrappedListeners = new WeakMap();
#wrap(listener) {
if (!listener)
return null;
let wrappedListener = this.#wrappedListeners.get(listener);
if (wrappedListener)
return wrappedListener;
wrappedListener = this[kWrapListener]((event) => {
if (typeof listener === "function") {
listener(event);
} else {
listener.handleEvent(event);
}
});
this.#wrappedListeners.set(listener, wrappedListener);
return wrappedListener;
}
addEventListener(type, listener, options) {
super.addEventListener(type, this[kWrapListener] ? this.#wrap(listener) : listener, options);
}
removeEventListener(type, listener, options) {
super.removeEventListener(type, this[kWrapListener] ? this.#wrap(listener) : listener, options);
}
dispatchEvent(event) {
return super.dispatchEvent(event);
}
};
var ThrowingEventTarget = class extends TypedEventTarget {
#wrappedError;
[kWrapListener](listener) {
return (event) => {
try {
listener(event);
} catch (error) {
event.stopImmediatePropagation();
this.#wrappedError = error;
}
};
}
dispatchEvent(event) {
this.#wrappedError = void 0;
const result = super.dispatchEvent(event);
if (this.#wrappedError !== void 0)
throw this.#wrappedError;
return result;
}
};
// packages/shared/src/log.ts
var import_path2 = __toModule(require("path"));
var import_colors = __toModule(require("kleur/colors"));
var cwd = process.cwd();
var cwdNodeModules = import_path2.default.join(cwd, "node_modules");
var LogLevel;
(function(LogLevel2) {
LogLevel2[LogLevel2["NONE"] = 0] = "NONE";
LogLevel2[LogLevel2["ERROR"] = 1] = "ERROR";
LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
LogLevel2[LogLevel2["INFO"] = 3] = "INFO";
LogLevel2[LogLevel2["DEBUG"] = 4] = "DEBUG";
LogLevel2[LogLevel2["VERBOSE"] = 5] = "VERBOSE";
})(LogLevel || (LogLevel = {}));
var LEVEL_PREFIX = {
[0]: "",
[1]: "err",
[2]: "wrn",
[3]: "inf",
[4]: "dbg",
[5]: "vrb"
};
var LEVEL_COLOUR = {
[0]: import_colors.reset,
[1]: import_colors.red,
[2]: import_colors.yellow,
[3]: import_colors.green,
[4]: import_colors.grey,
[5]: (input) => (0, import_colors.dim)((0, import_colors.grey)(input))
};
function dimInternalStackLine(line) {
if (line.startsWith(" at") && (!line.includes(cwd) || line.includes(cwdNodeModules))) {
return (0, import_colors.dim)(line);
}
return line;
}
var Log = class {
constructor(level = 3, opts = {}) {
this.level = level;
const prefix = opts.prefix ?? "mf";
const suffix = opts.suffix ?? "";
this.#prefix = prefix ? prefix + ":" : "";
this.#suffix = suffix ? ":" + suffix : "";
}
#prefix;
#suffix;
log(message) {
console.log(message);
}
logWithLevel(level, message) {
if (level <= this.level) {
const prefix = `[${this.#prefix}${LEVEL_PREFIX[level]}${this.#suffix}]`;
this.log(LEVEL_COLOUR[level](`${prefix} ${message}`));
}
}
error(message) {
if (this.level < 1) {
throw message;
} else if (message.stack) {
const lines = message.stack.split("\n").map(dimInternalStackLine);
this.logWithLevel(1, lines.join("\n"));
} else {
this.logWithLevel(1, message.toString());
}
if (message.cause) {
this.error(prefixError("Cause", message.cause));
}
}
warn(message) {
this.logWithLevel(2, message);
}
info(message) {
this.logWithLevel(3, message);
}
debug(message) {
this.logWithLevel(4, message);
}
verbose(message) {
this.logWithLevel(5, message);
}
};
var NoOpLog = class extends Log {
log() {
}
error(message) {
throw message;
}
};
// packages/shared/src/plugin.ts
var OptionType;
(function(OptionType2) {
OptionType2[OptionType2["NONE"] = 0] = "NONE";
OptionType2[OptionType2["BOOLEAN"] = 1] = "BOOLEAN";
OptionType2[OptionType2["NUMBER"] = 2] = "NUMBER";
OptionType2[OptionType2["STRING"] = 3] = "STRING";
OptionType2[OptionType2["STRING_POSITIONAL"] = 4] = "STRING_POSITIONAL";
OptionType2[OptionType2["BOOLEAN_STRING"] = 5] = "BOOLEAN_STRING";
OptionType2[OptionType2["BOOLEAN_NUMBER"] = 6] = "BOOLEAN_NUMBER";
OptionType2[OptionType2["ARRAY"] = 7] = "ARRAY";
OptionType2[OptionType2["OBJECT"] = 8] = "OBJECT";
})(OptionType || (OptionType = {}));
function Option(metadata) {
return function(prototype, key) {
(prototype.opts ??= new Map()).set(key, metadata);
};
}
var Plugin = class {
constructor(ctx) {
this.ctx = ctx;
this.opts = new.target.prototype.opts;
}
#phantom;
opts;
assignOptions(options) {
if (options === void 0 || this.opts === void 0)
return;
for (const key of this.opts.keys()) {
this[key] = options[key];
}
}
};
function logOptions(plugins, log, options) {
log.debug("Options:");
for (const [name, plugin] of plugins) {
const pluginOptions = options[name];
for (const [key, meta] of plugin.prototype.opts?.entries() ?? []) {
const value = pluginOptions[key];
if (value === void 0 || meta.type === 0)
continue;
const keyName = meta?.logName ?? titleCase(typeof key === "symbol" ? "<symbol>" : key);
let str;
if (meta.logValue) {
str = meta.logValue(value);
if (str === void 0)
continue;
} else if (meta.type === 8) {
str = Object.keys(value).join(", ");
} else if (meta.type === 7) {
str = value.join(", ");
} else {
str = value.toString();
}
log.debug(`- ${keyName}: ${str}`);
}
}
}
// packages/shared/src/queues.ts
var kGetConsumer = Symbol("kGetConsumer");
var kSetConsumer = Symbol("kSetConsumer");
// packages/shared/src/runner.ts
var STRING_SCRIPT_PATH = "<script>";
// packages/shared/src/storage.ts
function parseRange({ offset, length, suffix }, size) {
if (suffix !== void 0) {
if (suffix <= 0) {
throw new Error("Suffix must be > 0");
}
if (suffix > size)
suffix = size;
offset = size - suffix;
length = size - offset;
}
if (offset === void 0)
offset = 0;
if (length === void 0)
length = size - offset;
if (offset < 0)
throw new Error("Offset must be >= 0");
if (offset > size)
throw new Error("Offset must be < size");
if (length <= 0)
throw new Error("Length must be > 0");
if (offset + length > size)
length = size - offset;
return { offset, length };
}
var Storage = class {
async getSqliteDatabase() {
throw new Error("D1 not implemented for this Storage class");
}
async hasMany(keys) {
const results = keys.map(this.has.bind(this));
let count = 0;
for (const result of await Promise.all(results))
if (result)
count++;
return count;
}
getMany(keys, skipMetadata) {
return Promise.all(keys.map((key) => this.get(key, skipMetadata)));
}
async putMany(data) {
await Promise.all(data.map(([key, value]) => this.put(key, value)));
}
async deleteMany(keys) {
const results = keys.map(this.delete.bind(this));
let count = 0;
for (const result of await Promise.all(results))
if (result)
count++;
return count;
}
};
// packages/shared/src/sync/clock.ts
var defaultClock = () => Date.now();
function millisToSeconds(millis) {
return Math.floor(millis / 1e3);
}
// packages/shared/src/sync/gate.ts
var import_assert3 = __toModule(require("assert"));
var import_async_hooks2 = __toModule(require("async_hooks"));
var import_timers = __toModule(require("timers"));
var import_promises = __toModule(require("timers/promises"));
var inputGateStorage = new import_async_hooks2.AsyncLocalStorage();
var outputGateStorage = new import_async_hooks2.AsyncLocalStorage();
function waitForOpenInputGate() {
const inputGate = inputGateStorage.getStore();
return inputGate?.waitForOpen();
}
function runWithInputGateClosed(closure, allowConcurrency = false) {
if (allowConcurrency)
return closure();
const inputGate = inputGateStorage.getStore();
if (inputGate === void 0)
return closure();
return inputGate.runWithClosed(closure);
}
function waitForOpenOutputGate() {
const outputGate = outputGateStorage.getStore();
return outputGate?.waitForOpen();
}
function waitUntilOnOutputGate(promise, allowUnconfirmed = false) {
if (allowUnconfirmed)
return promise;
const outputGate = outputGateStorage.getStore();
outputGate?.waitUntil(promise);
return promise;
}
var InputGate = class {
#lockCount = 0;
#resolveQueue = [];
#parent;
constructor(parent) {
this.#parent = parent;
}
async runWith(closure) {
await this.waitForOpen();
return inputGateStorage.run(this, closure);
}
async waitForOpen() {
await (0, import_promises.setImmediate)();
if (this.#lockCount === 0)
return;
return new Promise((resolve) => this.#resolveQueue.push(resolve));
}
async runWithClosed(closure) {
this.#lock();
await Promise.resolve();
const childInputGate = new InputGate(this);
try {
return await inputGateStorage.run(childInputGate, closure);
} finally {
(0, import_timers.setImmediate)(this.#unlock);
}
}
#lock() {
this.#lockCount++;
if (this.#parent)
this.#parent.#lock();
}
#unlock = async () => {
(0, import_assert3.default)(this.#lockCount > 0);
this.#lockCount--;
while (this.#lockCount === 0 && this.#resolveQueue.length) {
this.#resolveQueue.shift()();
await (0, import_promises.setImmediate)();
}
if (this.#parent)
return this.#parent.#unlock();
};
};
var OutputGate = class {
#waitUntil = [];
async runWith(closure) {
try {
return await outputGateStorage.run(this, closure);
} finally {
await this.waitForOpen();
}
}
async waitForOpen() {
await Promise.all(this.#waitUntil);
}
waitUntil(promise) {
this.#waitUntil.push(promise);
}
};
var InputGatedEventTarget = class extends TypedEventTarget {
[kWrapListener](listener) {
const inputGate = inputGateStorage.getStore();
return inputGate ? async (event) => {
await inputGate.waitForOpen();
listener(event);
} : listener;
}
};
// packages/shared/src/sync/mutex.ts
var import_assert4 = __toModule(require("assert"));
var Mutex = class {
locked = false;
resolveQueue = [];
lock() {
if (!this.locked) {
this.locked = true;
return;
}
return new Promise((resolve) => this.resolveQueue.push(resolve));
}
unlock() {
(0, import_assert4.default)(this.locked);
if (this.resolveQueue.length > 0) {
this.resolveQueue.shift()?.();
} else {
this.locked = false;
}
}
get hasWaiting() {
return this.resolveQueue.length > 0;
}
async runWith(closure) {
const acquireAwaitable = this.lock();
if (acquireAwaitable instanceof Promise)
await acquireAwaitable;
try {
const awaitable = closure();
if (awaitable instanceof Promise)
return await awaitable;
return awaitable;
} finally {
this.unlock();
}
}
};
// packages/shared/src/sqlite.ts
var import_node_path = __toModule(require("node:path"));
async function createSQLiteDB(dbPath) {
const { npxImport, npxResolve } = await import("npx-import");
const { default: DatabaseConstructor } = await npxImport("better-sqlite3@8.0.1");
return new DatabaseConstructor(dbPath, {
nativeBinding: getSQLiteNativeBindingLocation(npxResolve("better-sqlite3"))
});
}
function getSQLiteNativeBindingLocation(sqliteResolvePath) {
return import_node_path.default.resolve(import_node_path.default.dirname(sqliteResolvePath), "../build/Release/better_sqlite3.node");
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Compatibility,
EXTERNAL_SUBREQUEST_LIMIT_BUNDLED,
EXTERNAL_SUBREQUEST_LIMIT_UNBOUND,
INTERNAL_SUBREQUEST_LIMIT,
InputGate,
InputGatedEventTarget,
Log,
LogLevel,
MiniflareError,
Mutex,
NoOpLog,
Option,
OptionType,
OutputGate,
Plugin,
RequestContext,
SITES_NO_CACHE_PREFIX,
STRING_SCRIPT_PATH,
Storage,
ThrowingEventTarget,
TypedEventTarget,
addAll,
arrayCompare,
assertInRequest,
base64Decode,
base64Encode,
createSQLiteDB,
defaultClock,
getRequestContext,
getSQLiteNativeBindingLocation,
globsToMatcher,
kGetConsumer,
kSetConsumer,
kWrapListener,
kebabCase,
lexicographicCompare,
logOptions,
millisToSeconds,
nonCircularClone,
numericCompare,
parseRange,
prefixError,
randomHex,
resolveStoragePersist,
runWithInputGateClosed,
sanitisePath,
spaceCase,
structuredCloneImpl,
titleCase,
usageModelExternalSubrequestLimit,
viewToArray,
viewToBuffer,
waitForOpenInputGate,
waitForOpenOutputGate,
waitUntilOnOutputGate
});
/*! Path sanitisation regexps adapted from node-sanitize-filename:
* https://github.com/parshap/node-sanitize-filename/blob/209c39b914c8eb48ee27bcbde64b2c7822fdf3de/index.js#L4-L37
*
* Licensed under the ISC license:
*
* Copyright Parsha Pourkhomami <parshap@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//# sourceMappingURL=index.js.map