Skip to content

Instantly share code, notes, and snippets.

@cometkim
Created June 24, 2025 16:47
Show Gist options
  • Save cometkim/f4d3134a32a62d7558932a052d805b29 to your computer and use it in GitHub Desktop.
Save cometkim/f4d3134a32a62d7558932a052d805b29 to your computer and use it in GitHub Desktop.
Cloudflare Containers' bundle dumped
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// node_modules/unenv/dist/runtime/_internal/utils.mjs
// @__NO_SIDE_EFFECTS__
function createNotImplementedError(name) {
return new Error(`[unenv] ${name} is not implemented yet!`);
}
__name(createNotImplementedError, "createNotImplementedError");
// @__NO_SIDE_EFFECTS__
function notImplemented(name) {
const fn = /* @__PURE__ */ __name(() => {
throw /* @__PURE__ */ createNotImplementedError(name);
}, "fn");
return Object.assign(fn, { __unenv__: true });
}
__name(notImplemented, "notImplemented");
// @__NO_SIDE_EFFECTS__
function notImplementedClass(name) {
return class {
__unenv__ = true;
constructor() {
throw new Error(`[unenv] ${name} is not implemented yet!`);
}
};
}
__name(notImplementedClass, "notImplementedClass");
// node_modules/unenv/dist/runtime/node/internal/perf_hooks/performance.mjs
var _timeOrigin = globalThis.performance?.timeOrigin ?? Date.now();
var _performanceNow = globalThis.performance?.now ? globalThis.performance.now.bind(globalThis.performance) : () => Date.now() - _timeOrigin;
var nodeTiming = {
name: "node",
entryType: "node",
startTime: 0,
duration: 0,
nodeStart: 0,
v8Start: 0,
bootstrapComplete: 0,
environment: 0,
loopStart: 0,
loopExit: 0,
idleTime: 0,
uvMetricsInfo: {
loopCount: 0,
events: 0,
eventsWaiting: 0
},
detail: void 0,
toJSON() {
return this;
}
};
var PerformanceEntry = class {
static {
__name(this, "PerformanceEntry");
}
__unenv__ = true;
detail;
entryType = "event";
name;
startTime;
constructor(name, options) {
this.name = name;
this.startTime = options?.startTime || _performanceNow();
this.detail = options?.detail;
}
get duration() {
return _performanceNow() - this.startTime;
}
toJSON() {
return {
name: this.name,
entryType: this.entryType,
startTime: this.startTime,
duration: this.duration,
detail: this.detail
};
}
};
var PerformanceMark = class PerformanceMark2 extends PerformanceEntry {
static {
__name(this, "PerformanceMark");
}
entryType = "mark";
constructor() {
super(...arguments);
}
get duration() {
return 0;
}
};
var PerformanceMeasure = class extends PerformanceEntry {
static {
__name(this, "PerformanceMeasure");
}
entryType = "measure";
};
var PerformanceResourceTiming = class extends PerformanceEntry {
static {
__name(this, "PerformanceResourceTiming");
}
entryType = "resource";
serverTiming = [];
connectEnd = 0;
connectStart = 0;
decodedBodySize = 0;
domainLookupEnd = 0;
domainLookupStart = 0;
encodedBodySize = 0;
fetchStart = 0;
initiatorType = "";
name = "";
nextHopProtocol = "";
redirectEnd = 0;
redirectStart = 0;
requestStart = 0;
responseEnd = 0;
responseStart = 0;
secureConnectionStart = 0;
startTime = 0;
transferSize = 0;
workerStart = 0;
responseStatus = 0;
};
var PerformanceObserverEntryList = class {
static {
__name(this, "PerformanceObserverEntryList");
}
__unenv__ = true;
getEntries() {
return [];
}
getEntriesByName(_name, _type) {
return [];
}
getEntriesByType(type) {
return [];
}
};
var Performance = class {
static {
__name(this, "Performance");
}
__unenv__ = true;
timeOrigin = _timeOrigin;
eventCounts = /* @__PURE__ */ new Map();
_entries = [];
_resourceTimingBufferSize = 0;
navigation = void 0;
timing = void 0;
timerify(_fn, _options) {
throw createNotImplementedError("Performance.timerify");
}
get nodeTiming() {
return nodeTiming;
}
eventLoopUtilization() {
return {};
}
markResourceTiming() {
return new PerformanceResourceTiming("");
}
onresourcetimingbufferfull = null;
now() {
if (this.timeOrigin === _timeOrigin) {
return _performanceNow();
}
return Date.now() - this.timeOrigin;
}
clearMarks(markName) {
this._entries = markName ? this._entries.filter((e) => e.name !== markName) : this._entries.filter((e) => e.entryType !== "mark");
}
clearMeasures(measureName) {
this._entries = measureName ? this._entries.filter((e) => e.name !== measureName) : this._entries.filter((e) => e.entryType !== "measure");
}
clearResourceTimings() {
this._entries = this._entries.filter((e) => e.entryType !== "resource" || e.entryType !== "navigation");
}
getEntries() {
return this._entries;
}
getEntriesByName(name, type) {
return this._entries.filter((e) => e.name === name && (!type || e.entryType === type));
}
getEntriesByType(type) {
return this._entries.filter((e) => e.entryType === type);
}
mark(name, options) {
const entry = new PerformanceMark(name, options);
this._entries.push(entry);
return entry;
}
measure(measureName, startOrMeasureOptions, endMark) {
let start;
let end;
if (typeof startOrMeasureOptions === "string") {
start = this.getEntriesByName(startOrMeasureOptions, "mark")[0]?.startTime;
end = this.getEntriesByName(endMark, "mark")[0]?.startTime;
} else {
start = Number.parseFloat(startOrMeasureOptions?.start) || this.now();
end = Number.parseFloat(startOrMeasureOptions?.end) || this.now();
}
const entry = new PerformanceMeasure(measureName, {
startTime: start,
detail: {
start,
end
}
});
this._entries.push(entry);
return entry;
}
setResourceTimingBufferSize(maxSize) {
this._resourceTimingBufferSize = maxSize;
}
addEventListener(type, listener, options) {
throw createNotImplementedError("Performance.addEventListener");
}
removeEventListener(type, listener, options) {
throw createNotImplementedError("Performance.removeEventListener");
}
dispatchEvent(event) {
throw createNotImplementedError("Performance.dispatchEvent");
}
toJSON() {
return this;
}
};
var PerformanceObserver = class {
static {
__name(this, "PerformanceObserver");
}
__unenv__ = true;
static supportedEntryTypes = [];
_callback = null;
constructor(callback) {
this._callback = callback;
}
takeRecords() {
return [];
}
disconnect() {
throw createNotImplementedError("PerformanceObserver.disconnect");
}
observe(options) {
throw createNotImplementedError("PerformanceObserver.observe");
}
bind(fn) {
return fn;
}
runInAsyncScope(fn, thisArg, ...args) {
return fn.call(thisArg, ...args);
}
asyncId() {
return 0;
}
triggerAsyncId() {
return 0;
}
emitDestroy() {
return this;
}
};
var performance = globalThis.performance && "addEventListener" in globalThis.performance ? globalThis.performance : new Performance();
// node_modules/@cloudflare/unenv-preset/dist/runtime/polyfill/performance.mjs
globalThis.performance = performance;
globalThis.Performance = Performance;
globalThis.PerformanceEntry = PerformanceEntry;
globalThis.PerformanceMark = PerformanceMark;
globalThis.PerformanceMeasure = PerformanceMeasure;
globalThis.PerformanceObserver = PerformanceObserver;
globalThis.PerformanceObserverEntryList = PerformanceObserverEntryList;
globalThis.PerformanceResourceTiming = PerformanceResourceTiming;
// node_modules/unenv/dist/runtime/node/console.mjs
import { Writable } from "node:stream";
// node_modules/unenv/dist/runtime/mock/noop.mjs
var noop_default = Object.assign(() => {
}, { __unenv__: true });
// node_modules/unenv/dist/runtime/node/console.mjs
var _console = globalThis.console;
var _ignoreErrors = true;
var _stderr = new Writable();
var _stdout = new Writable();
var log = _console?.log ?? noop_default;
var info = _console?.info ?? log;
var trace = _console?.trace ?? info;
var debug = _console?.debug ?? log;
var table = _console?.table ?? log;
var error = _console?.error ?? log;
var warn = _console?.warn ?? error;
var createTask = _console?.createTask ?? /* @__PURE__ */ notImplemented("console.createTask");
var clear = _console?.clear ?? noop_default;
var count = _console?.count ?? noop_default;
var countReset = _console?.countReset ?? noop_default;
var dir = _console?.dir ?? noop_default;
var dirxml = _console?.dirxml ?? noop_default;
var group = _console?.group ?? noop_default;
var groupEnd = _console?.groupEnd ?? noop_default;
var groupCollapsed = _console?.groupCollapsed ?? noop_default;
var profile = _console?.profile ?? noop_default;
var profileEnd = _console?.profileEnd ?? noop_default;
var time = _console?.time ?? noop_default;
var timeEnd = _console?.timeEnd ?? noop_default;
var timeLog = _console?.timeLog ?? noop_default;
var timeStamp = _console?.timeStamp ?? noop_default;
var Console = _console?.Console ?? /* @__PURE__ */ notImplementedClass("console.Console");
var _times = /* @__PURE__ */ new Map();
var _stdoutErrorHandler = noop_default;
var _stderrErrorHandler = noop_default;
// node_modules/@cloudflare/unenv-preset/dist/runtime/node/console.mjs
var workerdConsole = globalThis["console"];
var {
assert,
clear: clear2,
// @ts-expect-error undocumented public API
context,
count: count2,
countReset: countReset2,
// @ts-expect-error undocumented public API
createTask: createTask2,
debug: debug2,
dir: dir2,
dirxml: dirxml2,
error: error2,
group: group2,
groupCollapsed: groupCollapsed2,
groupEnd: groupEnd2,
info: info2,
log: log2,
profile: profile2,
profileEnd: profileEnd2,
table: table2,
time: time2,
timeEnd: timeEnd2,
timeLog: timeLog2,
timeStamp: timeStamp2,
trace: trace2,
warn: warn2
} = workerdConsole;
Object.assign(workerdConsole, {
Console,
_ignoreErrors,
_stderr,
_stderrErrorHandler,
_stdout,
_stdoutErrorHandler,
_times
});
var console_default = workerdConsole;
// node_modules/wrangler/_virtual_unenv_global_polyfill-@cloudflare-unenv-preset-node-console
globalThis.console = console_default;
// node_modules/unenv/dist/runtime/node/internal/process/hrtime.mjs
var hrtime = /* @__PURE__ */ Object.assign(/* @__PURE__ */ __name(function hrtime2(startTime) {
const now = Date.now();
const seconds = Math.trunc(now / 1e3);
const nanos = now % 1e3 * 1e6;
if (startTime) {
let diffSeconds = seconds - startTime[0];
let diffNanos = nanos - startTime[0];
if (diffNanos < 0) {
diffSeconds = diffSeconds - 1;
diffNanos = 1e9 + diffNanos;
}
return [diffSeconds, diffNanos];
}
return [seconds, nanos];
}, "hrtime"), { bigint: /* @__PURE__ */ __name(function bigint() {
return BigInt(Date.now() * 1e6);
}, "bigint") });
// node_modules/unenv/dist/runtime/node/internal/process/process.mjs
import { EventEmitter } from "node:events";
// node_modules/unenv/dist/runtime/node/internal/tty/write-stream.mjs
var WriteStream = class {
static {
__name(this, "WriteStream");
}
fd;
columns = 80;
rows = 24;
isTTY = false;
constructor(fd) {
this.fd = fd;
}
clearLine(dir3, callback) {
callback && callback();
return false;
}
clearScreenDown(callback) {
callback && callback();
return false;
}
cursorTo(x, y, callback) {
callback && typeof callback === "function" && callback();
return false;
}
moveCursor(dx, dy, callback) {
callback && callback();
return false;
}
getColorDepth(env2) {
return 1;
}
hasColors(count3, env2) {
return false;
}
getWindowSize() {
return [this.columns, this.rows];
}
write(str, encoding, cb) {
if (str instanceof Uint8Array) {
str = new TextDecoder().decode(str);
}
try {
console.log(str);
} catch {
}
cb && typeof cb === "function" && cb();
return false;
}
};
// node_modules/unenv/dist/runtime/node/internal/tty/read-stream.mjs
var ReadStream = class {
static {
__name(this, "ReadStream");
}
fd;
isRaw = false;
isTTY = false;
constructor(fd) {
this.fd = fd;
}
setRawMode(mode) {
this.isRaw = mode;
return this;
}
};
// node_modules/unenv/dist/runtime/node/internal/process/node-version.mjs
var NODE_VERSION = "22.14.0";
// node_modules/unenv/dist/runtime/node/internal/process/process.mjs
var Process = class _Process extends EventEmitter {
static {
__name(this, "Process");
}
env;
hrtime;
nextTick;
constructor(impl) {
super();
this.env = impl.env;
this.hrtime = impl.hrtime;
this.nextTick = impl.nextTick;
for (const prop of [...Object.getOwnPropertyNames(_Process.prototype), ...Object.getOwnPropertyNames(EventEmitter.prototype)]) {
const value = this[prop];
if (typeof value === "function") {
this[prop] = value.bind(this);
}
}
}
emitWarning(warning, type, code) {
console.warn(`${code ? `[${code}] ` : ""}${type ? `${type}: ` : ""}${warning}`);
}
emit(...args) {
return super.emit(...args);
}
listeners(eventName) {
return super.listeners(eventName);
}
#stdin;
#stdout;
#stderr;
get stdin() {
return this.#stdin ??= new ReadStream(0);
}
get stdout() {
return this.#stdout ??= new WriteStream(1);
}
get stderr() {
return this.#stderr ??= new WriteStream(2);
}
#cwd = "/";
chdir(cwd2) {
this.#cwd = cwd2;
}
cwd() {
return this.#cwd;
}
arch = "";
platform = "";
argv = [];
argv0 = "";
execArgv = [];
execPath = "";
title = "";
pid = 200;
ppid = 100;
get version() {
return `v${NODE_VERSION}`;
}
get versions() {
return { node: NODE_VERSION };
}
get allowedNodeEnvironmentFlags() {
return /* @__PURE__ */ new Set();
}
get sourceMapsEnabled() {
return false;
}
get debugPort() {
return 0;
}
get throwDeprecation() {
return false;
}
get traceDeprecation() {
return false;
}
get features() {
return {};
}
get release() {
return {};
}
get connected() {
return false;
}
get config() {
return {};
}
get moduleLoadList() {
return [];
}
constrainedMemory() {
return 0;
}
availableMemory() {
return 0;
}
uptime() {
return 0;
}
resourceUsage() {
return {};
}
ref() {
}
unref() {
}
umask() {
throw createNotImplementedError("process.umask");
}
getBuiltinModule() {
return void 0;
}
getActiveResourcesInfo() {
throw createNotImplementedError("process.getActiveResourcesInfo");
}
exit() {
throw createNotImplementedError("process.exit");
}
reallyExit() {
throw createNotImplementedError("process.reallyExit");
}
kill() {
throw createNotImplementedError("process.kill");
}
abort() {
throw createNotImplementedError("process.abort");
}
dlopen() {
throw createNotImplementedError("process.dlopen");
}
setSourceMapsEnabled() {
throw createNotImplementedError("process.setSourceMapsEnabled");
}
loadEnvFile() {
throw createNotImplementedError("process.loadEnvFile");
}
disconnect() {
throw createNotImplementedError("process.disconnect");
}
cpuUsage() {
throw createNotImplementedError("process.cpuUsage");
}
setUncaughtExceptionCaptureCallback() {
throw createNotImplementedError("process.setUncaughtExceptionCaptureCallback");
}
hasUncaughtExceptionCaptureCallback() {
throw createNotImplementedError("process.hasUncaughtExceptionCaptureCallback");
}
initgroups() {
throw createNotImplementedError("process.initgroups");
}
openStdin() {
throw createNotImplementedError("process.openStdin");
}
assert() {
throw createNotImplementedError("process.assert");
}
binding() {
throw createNotImplementedError("process.binding");
}
permission = { has: /* @__PURE__ */ notImplemented("process.permission.has") };
report = {
directory: "",
filename: "",
signal: "SIGUSR2",
compact: false,
reportOnFatalError: false,
reportOnSignal: false,
reportOnUncaughtException: false,
getReport: /* @__PURE__ */ notImplemented("process.report.getReport"),
writeReport: /* @__PURE__ */ notImplemented("process.report.writeReport")
};
finalization = {
register: /* @__PURE__ */ notImplemented("process.finalization.register"),
unregister: /* @__PURE__ */ notImplemented("process.finalization.unregister"),
registerBeforeExit: /* @__PURE__ */ notImplemented("process.finalization.registerBeforeExit")
};
memoryUsage = Object.assign(() => ({
arrayBuffers: 0,
rss: 0,
external: 0,
heapTotal: 0,
heapUsed: 0
}), { rss: /* @__PURE__ */ __name(() => 0, "rss") });
mainModule = void 0;
domain = void 0;
send = void 0;
exitCode = void 0;
channel = void 0;
getegid = void 0;
geteuid = void 0;
getgid = void 0;
getgroups = void 0;
getuid = void 0;
setegid = void 0;
seteuid = void 0;
setgid = void 0;
setgroups = void 0;
setuid = void 0;
_events = void 0;
_eventsCount = void 0;
_exiting = void 0;
_maxListeners = void 0;
_debugEnd = void 0;
_debugProcess = void 0;
_fatalException = void 0;
_getActiveHandles = void 0;
_getActiveRequests = void 0;
_kill = void 0;
_preload_modules = void 0;
_rawDebug = void 0;
_startProfilerIdleNotifier = void 0;
_stopProfilerIdleNotifier = void 0;
_tickCallback = void 0;
_disconnect = void 0;
_handleQueue = void 0;
_pendingMessage = void 0;
_channel = void 0;
_send = void 0;
_linkedBinding = void 0;
};
// node_modules/@cloudflare/unenv-preset/dist/runtime/node/process.mjs
var globalProcess = globalThis["process"];
var getBuiltinModule = globalProcess.getBuiltinModule;
var { exit, platform, nextTick } = getBuiltinModule(
"node:process"
);
var unenvProcess = new Process({
env: globalProcess.env,
hrtime,
nextTick
});
var {
abort,
addListener,
allowedNodeEnvironmentFlags,
hasUncaughtExceptionCaptureCallback,
setUncaughtExceptionCaptureCallback,
loadEnvFile,
sourceMapsEnabled,
arch,
argv,
argv0,
chdir,
config,
connected,
constrainedMemory,
availableMemory,
cpuUsage,
cwd,
debugPort,
dlopen,
disconnect,
emit,
emitWarning,
env,
eventNames,
execArgv,
execPath,
finalization,
features,
getActiveResourcesInfo,
getMaxListeners,
hrtime: hrtime3,
kill,
listeners,
listenerCount,
memoryUsage,
on,
off,
once,
pid,
ppid,
prependListener,
prependOnceListener,
rawListeners,
release,
removeAllListeners,
removeListener,
report,
resourceUsage,
setMaxListeners,
setSourceMapsEnabled,
stderr,
stdin,
stdout,
title,
throwDeprecation,
traceDeprecation,
umask,
uptime,
version,
versions,
domain,
initgroups,
moduleLoadList,
reallyExit,
openStdin,
assert: assert2,
binding,
send,
exitCode,
channel,
getegid,
geteuid,
getgid,
getgroups,
getuid,
setegid,
seteuid,
setgid,
setgroups,
setuid,
permission,
mainModule,
_events,
_eventsCount,
_exiting,
_maxListeners,
_debugEnd,
_debugProcess,
_fatalException,
_getActiveHandles,
_getActiveRequests,
_kill,
_preload_modules,
_rawDebug,
_startProfilerIdleNotifier,
_stopProfilerIdleNotifier,
_tickCallback,
_disconnect,
_handleQueue,
_pendingMessage,
_channel,
_send,
_linkedBinding
} = unenvProcess;
var _process = {
abort,
addListener,
allowedNodeEnvironmentFlags,
hasUncaughtExceptionCaptureCallback,
setUncaughtExceptionCaptureCallback,
loadEnvFile,
sourceMapsEnabled,
arch,
argv,
argv0,
chdir,
config,
connected,
constrainedMemory,
availableMemory,
cpuUsage,
cwd,
debugPort,
dlopen,
disconnect,
emit,
emitWarning,
env,
eventNames,
execArgv,
execPath,
exit,
finalization,
features,
getBuiltinModule,
getActiveResourcesInfo,
getMaxListeners,
hrtime: hrtime3,
kill,
listeners,
listenerCount,
memoryUsage,
nextTick,
on,
off,
once,
pid,
platform,
ppid,
prependListener,
prependOnceListener,
rawListeners,
release,
removeAllListeners,
removeListener,
report,
resourceUsage,
setMaxListeners,
setSourceMapsEnabled,
stderr,
stdin,
stdout,
title,
throwDeprecation,
traceDeprecation,
umask,
uptime,
version,
versions,
// @ts-expect-error old API
domain,
initgroups,
moduleLoadList,
reallyExit,
openStdin,
assert: assert2,
binding,
send,
exitCode,
channel,
getegid,
geteuid,
getgid,
getgroups,
getuid,
setegid,
seteuid,
setgid,
setgroups,
setuid,
permission,
mainModule,
_events,
_eventsCount,
_exiting,
_maxListeners,
_debugEnd,
_debugProcess,
_fatalException,
_getActiveHandles,
_getActiveRequests,
_kill,
_preload_modules,
_rawDebug,
_startProfilerIdleNotifier,
_stopProfilerIdleNotifier,
_tickCallback,
_disconnect,
_handleQueue,
_pendingMessage,
_channel,
_send,
_linkedBinding
};
var process_default = _process;
// node_modules/wrangler/_virtual_unenv_global_polyfill-@cloudflare-unenv-preset-node-process
globalThis.process = process_default;
// node_modules/@cloudflare/containers/dist/index.mjs
import { DurableObject } from "cloudflare:workers";
function generateId(length = 9) {
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const bytes = new Uint8Array(length);
crypto.getRandomValues(bytes);
let result = "";
for (let i = 0; i < length; i++) {
result += alphabet[bytes[i] % alphabet.length];
}
return result;
}
__name(generateId, "generateId");
function parseTimeExpression(timeExpression) {
if (typeof timeExpression === "number") {
return timeExpression;
}
if (typeof timeExpression === "string") {
const match = timeExpression.match(/^(\d+)([smh])$/);
if (!match) {
throw new Error(`invalid time expression ${timeExpression}`);
}
const value = parseInt(match[1]);
const unit = match[2];
switch (unit) {
case "s":
return value;
case "m":
return value * 60;
case "h":
return value * 60 * 60;
default:
throw new Error(`unknown time unit ${unit}`);
}
}
throw new Error(`invalid type for a time expression: ${typeof timeExpression}`);
}
__name(parseTimeExpression, "parseTimeExpression");
var NO_CONTAINER_INSTANCE_ERROR = "there is no container instance that can be provided to this durable object";
var RUNTIME_SIGNALLED_ERROR = "runtime signalled the container to exit:";
var UNEXPECTED_EDIT_ERROR = "container exited with unexpected exit code:";
var NOT_LISTENING_ERROR = "the container is not listening";
var CONTAINER_STATE_KEY = "__CF_CONTAINER_STATE";
var MAX_ALAEM_RETRIES = 3;
var PING_TIMEOUT_MS = 1500;
var DEFAULT_SLEEP_AFTER = "10m";
var INSTANCE_POLL_INTERVAL_MS = 300;
var TIMEOUT_TO_GET_CONTAINER_SECONDS = 8;
var TIMEOUT_TO_GET_PORTS = 20;
var TRIES_TO_GET_CONTAINER = Math.ceil(
TIMEOUT_TO_GET_CONTAINER_SECONDS * 1e3 / INSTANCE_POLL_INTERVAL_MS
);
var TRIES_TO_GET_PORTS = Math.ceil(TIMEOUT_TO_GET_PORTS * 1e3 / INSTANCE_POLL_INTERVAL_MS);
var FALLBACK_PORT_TO_CHECK = 33;
var TEMPORARY_HARDCODED_ATTEMPT_MAX = 6;
function isErrorOfType(e, matchingString) {
const errorString = e instanceof Error ? e.message : String(e);
return errorString.toLowerCase().includes(matchingString);
}
__name(isErrorOfType, "isErrorOfType");
var isNoInstanceError = /* @__PURE__ */ __name((error3) => isErrorOfType(error3, NO_CONTAINER_INSTANCE_ERROR), "isNoInstanceError");
var isRuntimeSignalledError = /* @__PURE__ */ __name((error3) => isErrorOfType(error3, RUNTIME_SIGNALLED_ERROR), "isRuntimeSignalledError");
var isNotListeningError = /* @__PURE__ */ __name((error3) => isErrorOfType(error3, NOT_LISTENING_ERROR), "isNotListeningError");
var isContainerExitNonZeroError = /* @__PURE__ */ __name((error3) => isErrorOfType(error3, UNEXPECTED_EDIT_ERROR), "isContainerExitNonZeroError");
function getExitCodeFromError(error3) {
if (!(error3 instanceof Error)) {
return null;
}
if (isRuntimeSignalledError(error3)) {
return +error3.message.toLowerCase().slice(
error3.message.toLowerCase().indexOf(RUNTIME_SIGNALLED_ERROR) + RUNTIME_SIGNALLED_ERROR.length + 1
);
}
if (isContainerExitNonZeroError(error3)) {
return +error3.message.toLowerCase().slice(
error3.message.toLowerCase().indexOf(UNEXPECTED_EDIT_ERROR) + UNEXPECTED_EDIT_ERROR.length + 1
);
}
return null;
}
__name(getExitCodeFromError, "getExitCodeFromError");
function addTimeoutSignal(existingSignal, timeoutMs) {
const controller = new AbortController();
if (existingSignal?.aborted) {
controller.abort();
return controller.signal;
}
existingSignal?.addEventListener("abort", () => controller.abort());
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
controller.signal.addEventListener("abort", () => clearTimeout(timeoutId));
return controller.signal;
}
__name(addTimeoutSignal, "addTimeoutSignal");
function attachOnClosedHook(stream, onClosed) {
let destructor = /* @__PURE__ */ __name(() => {
onClosed();
destructor = null;
}, "destructor");
const transformStream = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk);
},
flush() {
if (destructor) {
destructor();
}
},
cancel() {
if (destructor) {
destructor();
}
}
});
return stream.pipeThrough(transformStream);
}
__name(attachOnClosedHook, "attachOnClosedHook");
var ContainerState = class {
static {
__name(this, "ContainerState");
}
constructor(storage) {
this.storage = storage;
}
status;
async setRunning() {
await this.setStatusAndupdate("running");
}
async setHealthy() {
await this.setStatusAndupdate("healthy");
}
async setStopping() {
await this.setStatusAndupdate("stopping");
}
async setStopped() {
await this.setStatusAndupdate("stopped");
}
async setStoppedWithCode(exitCode2) {
this.status = { status: "stopped_with_code", lastChange: Date.now(), exitCode: exitCode2 };
await this.update();
}
async getState() {
if (!this.status) {
const state = await this.storage.get(CONTAINER_STATE_KEY);
if (!state) {
this.status = {
status: "stopped",
lastChange: Date.now()
};
await this.update();
} else {
this.status = state;
}
}
return this.status;
}
async setStatusAndupdate(status) {
this.status = { status, lastChange: Date.now() };
await this.update();
}
async update() {
if (!this.status) throw new Error("status should be init");
await this.storage.put(CONTAINER_STATE_KEY, this.status);
}
};
var Container = class extends DurableObject {
static {
__name(this, "Container");
}
// =========================
// Public Attributes
// =========================
// Default port for the container (undefined means no default port)
defaultPort;
// Required ports that should be checked for availability during container startup
// Override this in your subclass to specify ports that must be ready
requiredPorts;
// Timeout after which the container will sleep if no activity
// The signal sent to the container by default is a SIGTERM.
// The container won't get a SIGKILL if this threshold is triggered.
sleepAfter = DEFAULT_SLEEP_AFTER;
// Container configuration properties
// Set these properties directly in your container instance
envVars = {};
entrypoint;
enableInternet = true;
// =========================
// PUBLIC INTERFACE
// =========================
constructor(ctx, env2, options) {
super(ctx, env2);
this.state = new ContainerState(this.ctx.storage);
this.ctx.blockConcurrencyWhile(async () => {
this.renewActivityTimeout();
await this.scheduleNextAlarm();
});
if (ctx.container === void 0) {
throw new Error(
"Container is not enabled for this durable object class. Have you correctly setup your wrangler.toml?"
);
}
this.container = ctx.container;
if (options) {
if (options.defaultPort !== void 0) this.defaultPort = options.defaultPort;
if (options.sleepAfter !== void 0) this.sleepAfter = options.sleepAfter;
}
this.sql`
CREATE TABLE IF NOT EXISTS container_schedules (
id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),
callback TEXT NOT NULL,
payload TEXT,
type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed')),
time INTEGER NOT NULL,
delayInSeconds INTEGER,
created_at INTEGER DEFAULT (unixepoch())
)
`;
if (this.container.running) {
this.monitor = this.container.monitor();
this.setupMonitorCallbacks();
}
}
// ==========================
// CONTAINER STARTING
// ==========================
/**
* Start the container if it's not running and set up monitoring
*
* This method handles the core container startup process without waiting for ports to be ready.
* It will automatically retry if the container fails to start, up to maxTries attempts.
*
* It's useful when you need to:
* - Start a container without blocking until a port is available
* - Initialize a container that doesn't expose ports
* - Perform custom port availability checks separately
*
* The method applies the container configuration from your instance properties by default, but allows
* overriding these values for this specific startup:
* - Environment variables (defaults to this.envVars)
* - Custom entrypoint commands (defaults to this.entrypoint)
* - Internet access settings (defaults to this.enableInternet)
*
* It also sets up monitoring to track container lifecycle events and automatically
* calls the onStop handler when the container terminates.
*
* @example
* // Basic usage in a custom Container implementation
* async customInitialize() {
* // Start the container without waiting for a port
* await this.start();
*
* // Perform additional initialization steps
* // that don't require port access
* }
*
* @example
* // Start with custom configuration
* await this.start({
* envVars: { DEBUG: 'true', NODE_ENV: 'development' },
* entrypoint: ['npm', 'run', 'dev'],
* enableInternet: false
* });
*
* @param options - Optional configuration to override instance defaults
* @param waitOptions - Optional wait configuration with abort signal for cancellation
* @returns A promise that resolves when the container start command has been issued
* @throws Error if no container context is available or if all start attempts fail
*/
async start(options, waitOptions) {
const portToCheck = this.defaultPort ?? (this.requiredPorts ? this.requiredPorts[0] : FALLBACK_PORT_TO_CHECK);
await this.startContainerIfNotRunning(
{
abort: waitOptions?.signal,
waitInterval: INSTANCE_POLL_INTERVAL_MS,
retries: TRIES_TO_GET_CONTAINER,
portToCheck
},
options
);
this.setupMonitorCallbacks();
}
/**
* Start the container and wait for ports to be available
* Based on containers-starter-go implementation
*
* This method builds on start() by adding port availability verification:
* 1. Calls start() to ensure the container is running
* 2. If no ports are specified and requiredPorts is not set, it uses defaultPort (if set)
* 3. If no ports can be determined, it calls onStart and renewActivityTimeout immediately
* 4. For each specified port, it polls until the port is available or maxTries is reached
* 5. When all ports are available, it triggers onStart and renewActivityTimeout
*
* The method prioritizes port sources in this order:
* 1. Ports specified directly in the method call
* 2. requiredPorts class property (if set)
* 3. defaultPort (if neither of the above is specified)
*
* @param ports - The ports to wait for (if undefined, uses requiredPorts or defaultPort)
* @param maxTries - Maximum number of attempts to connect to each port before failing
* @throws Error if port checks fail after maxTries attempts
*/
async startAndWaitForPorts(ports, cancellationOptions) {
let portsToCheck = [];
if (ports !== void 0) {
portsToCheck = Array.isArray(ports) ? ports : [ports];
} else if (this.requiredPorts && this.requiredPorts.length > 0) {
portsToCheck = [...this.requiredPorts];
} else if (this.defaultPort !== void 0) {
portsToCheck = [this.defaultPort];
}
const state = await this.state.getState();
cancellationOptions ??= {};
let containerGetRetries = cancellationOptions.instanceGetTimeoutMS ? Math.ceil(cancellationOptions.instanceGetTimeoutMS / INSTANCE_POLL_INTERVAL_MS) : TRIES_TO_GET_CONTAINER;
cancellationOptions ??= {};
let totalPortReadyTries = cancellationOptions.portReadyTimeoutMS ? Math.ceil(cancellationOptions.portReadyTimeoutMS / INSTANCE_POLL_INTERVAL_MS) : TRIES_TO_GET_PORTS;
const options = {
abort: cancellationOptions.abort,
retries: containerGetRetries,
waitInterval: cancellationOptions.waitInterval ?? INSTANCE_POLL_INTERVAL_MS,
portToCheck: portsToCheck[0] ?? FALLBACK_PORT_TO_CHECK
};
if (state.status === "healthy" && this.container.running) {
if (this.container.running && !this.monitor) {
await this.startContainerIfNotRunning(options);
this.setupMonitorCallbacks();
}
return;
}
await this.syncPendingStoppedEvents();
const abortedSignal = new Promise((res) => {
options.abort?.addEventListener("abort", () => {
res(true);
});
});
const errorFromBCW = await this.blockConcurrencyThrowable(async () => {
const triesUsed = await this.startContainerIfNotRunning(options);
const triesLeft = totalPortReadyTries - triesUsed;
for (const port of portsToCheck) {
const tcpPort = this.container.getTcpPort(port);
let portReady = false;
for (let i = 0; i < triesLeft && !portReady; i++) {
try {
const combinedSignal = addTimeoutSignal(options.abort, PING_TIMEOUT_MS);
await tcpPort.fetch("http://ping", { signal: combinedSignal });
portReady = true;
console.log(`Port ${port} is ready`);
} catch (e) {
const errorMessage = e instanceof Error ? e.message : String(e);
console.warn(`Error checking ${port}: ${errorMessage}`);
if (!this.container.running) {
try {
await this.onError(
new Error(
`Container crashed while checking for ports, did you setup the entrypoint correctly?`
)
);
} catch {
}
throw e;
}
if (i === triesLeft - 1) {
try {
this.onError(
`Failed to verify port ${port} is available after ${options.retries} attempts, last error: ${errorMessage}`
);
} catch {
}
throw e;
}
await Promise.any([
new Promise((resolve) => setTimeout(resolve, options.waitInterval)),
abortedSignal
]);
if (options.abort?.aborted) {
throw new Error("Container request timed out.");
}
}
}
}
});
if (errorFromBCW) {
throw errorFromBCW;
}
this.setupMonitorCallbacks();
await this.ctx.blockConcurrencyWhile(async () => {
await this.onStart();
await this.state.setHealthy();
});
}
// =======================
// LIFECYCLE HOOKS
// =======================
/**
* Shuts down the container.
* @param signal - The signal to send to the container (default: 15 for SIGTERM)
*/
async stop(signal = 15) {
this.container.signal(signal);
}
/**
* Destroys the container. It will trigger onError instead of onStop.
*/
async destroy() {
await this.container.destroy();
}
/**
* Lifecycle method called when container starts successfully
* Override this method in subclasses to handle container start events
*/
onStart() {
}
/**
* Lifecycle method called when container shuts down
* Override this method in subclasses to handle Container stopped events
* @param params - Object containing exitCode and reason for the stop
*/
onStop(_) {
}
/**
* Error handler for container errors
* Override this method in subclasses to handle container errors
* @param error - The error that occurred
* @returns Can return any value or throw the error
*/
onError(error3) {
console.error("Container error:", error3);
throw error3;
}
/**
* Renew the container's activity timeout
*
* Call this method whenever there is activity on the container
*/
renewActivityTimeout() {
const timeoutInMs = parseTimeExpression(this.sleepAfter) * 1e3;
this.sleepAfterMs = Date.now() + timeoutInMs;
}
// ==================
// SCHEDULING
// ==================
/**
* Schedule a task to be executed in the future
* @template T Type of the payload data
* @param when When to execute the task (Date object or number of seconds delay)
* @param callback Name of the method to call
* @param payload Data to pass to the callback
* @returns Schedule object representing the scheduled task
*/
async schedule(when, callback, payload) {
const id = generateId(9);
if (typeof callback !== "string") {
throw new Error("Callback must be a string (method name)");
}
if (typeof this[callback] !== "function") {
throw new Error(`this.${callback} is not a function`);
}
if (when instanceof Date) {
const timestamp = Math.floor(when.getTime() / 1e3);
this.sql`
INSERT OR REPLACE INTO container_schedules (id, callback, payload, type, time)
VALUES (${id}, ${callback}, ${JSON.stringify(payload)}, 'scheduled', ${timestamp})
`;
await this.scheduleNextAlarm();
return {
taskId: id,
callback,
payload,
time: timestamp,
type: "scheduled"
};
}
if (typeof when === "number") {
const time3 = Math.floor(Date.now() / 1e3 + when);
this.sql`
INSERT OR REPLACE INTO container_schedules (id, callback, payload, type, delayInSeconds, time)
VALUES (${id}, ${callback}, ${JSON.stringify(payload)}, 'delayed', ${when}, ${time3})
`;
await this.scheduleNextAlarm();
return {
taskId: id,
callback,
payload,
delayInSeconds: when,
time: time3,
type: "delayed"
};
}
throw new Error("Invalid schedule type. 'when' must be a Date or number of seconds");
}
// ============
// HTTP
// ============
/**
* Send a request to the container (HTTP or WebSocket) using standard fetch API signature
* Based on containers-starter-go implementation
*
* This method handles both HTTP and WebSocket requests to the container.
* For WebSocket requests, it sets up bidirectional message forwarding with proper
* activity timeout renewal.
*
* Method supports multiple signatures to match standard fetch API:
* - containerFetch(request: Request, port?: number)
* - containerFetch(url: string | URL, init?: RequestInit, port?: number)
*
* @param requestOrUrl The request object or URL string/object to send to the container
* @param portOrInit Port number or fetch RequestInit options
* @param portParam Optional port number when using URL+init signature
* @returns A Response from the container, or WebSocket connection
*/
async containerFetch(requestOrUrl, portOrInit, portParam) {
let { request, port } = this.requestAndPortFromContainerFetchArgs(
requestOrUrl,
portOrInit,
portParam
);
const state = await this.state.getState();
if (!this.container.running || state.status !== "healthy") {
try {
await this.startAndWaitForPorts(port, { abort: request.signal });
} catch (e) {
if (isNoInstanceError(e)) {
return new Response(
"There is no Container instance available at this time.\nThis is likely because you have reached your max concurrent instance count (set in wrangler config) or are you currently provisioning the Container.\nIf you are deploying your Container for the first time, check your dashboard to see provisioning status, this may take a few minutes.",
{ status: 503 }
);
} else {
return new Response(
`Failed to start container: ${e instanceof Error ? e.message : String(e)}`,
{ status: 500 }
);
}
}
}
const tcpPort = this.container.getTcpPort(port);
const containerUrl = request.url.replace("https:", "http:");
try {
this.renewActivityTimeout();
if (request.body != null) {
this.openStreamCount++;
const destructor = /* @__PURE__ */ __name(() => {
this.openStreamCount--;
this.renewActivityTimeout();
}, "destructor");
const readable = attachOnClosedHook(request.body, destructor);
request = new Request(request, { body: readable });
}
const res = await tcpPort.fetch(containerUrl, request);
if (res.webSocket) {
this.openStreamCount++;
res.webSocket.addEventListener("close", async () => {
this.openStreamCount--;
this.renewActivityTimeout();
});
} else if (res.body != null) {
this.openStreamCount++;
const destructor = /* @__PURE__ */ __name(() => {
this.openStreamCount--;
this.renewActivityTimeout();
}, "destructor");
const readable = attachOnClosedHook(res.body, destructor);
return new Response(readable, res);
}
return res;
} catch (e) {
if (!(e instanceof Error)) {
throw e;
}
if (e.message.includes("Network connection lost.")) {
return new Response("Container suddenly disconnected, try again", { status: 500 });
}
console.error(`Error proxying request to container ${this.ctx.id}:`, e);
return new Response(
`Error proxying request to container: ${e instanceof Error ? e.message : String(e)}`,
{ status: 500 }
);
}
}
/**
* Handle fetch requests to the Container
* Default implementation forwards all HTTP and WebSocket requests to the container
* Override this in your subclass to specify a port or implement custom request handling
*
* @param request The request to handle
*/
async fetch(request) {
if (this.defaultPort === void 0) {
return new Response(
"No default port configured for this container. Override the fetch method or set defaultPort in your Container subclass.",
{ status: 500 }
);
}
return await this.containerFetch(request, this.defaultPort);
}
// ===============================
// ===============================
// PRIVATE METHODS & ATTRS
// ===============================
// ===============================
// ==========================
// PRIVATE ATTRIBUTES
// ==========================
container;
state;
monitor;
monitorSetup = false;
// openStreamCount keeps track of the number of open streams to the container
openStreamCount = 0;
sleepAfterMs = 0;
clearTimeout = /* @__PURE__ */ __name((_) => {
}, "clearTimeout");
// ==========================
// GENERAL HELPERS
// ==========================
// This wraps blockConcurrencyWhile so you can throw in it,
// then check for a string return value that you can throw from the parent
// Note that the DO will continue to run, unlike normal errors in blockConcurrencyWhile
async blockConcurrencyThrowable(blockingFunction) {
return this.ctx.blockConcurrencyWhile(async () => {
try {
return await blockingFunction();
} catch (e) {
return `${e instanceof Error ? e.message : String(e)}`;
}
});
}
/**
* Execute SQL queries against the Container's database
*/
sql(strings, ...values) {
let query = "";
try {
query = strings.reduce((acc, str, i) => acc + str + (i < values.length ? "?" : ""), "");
return [...this.ctx.storage.sql.exec(query, ...values)];
} catch (e) {
console.error(`Failed to execute SQL query: ${query}`, e);
throw this.onError(e);
}
}
requestAndPortFromContainerFetchArgs(requestOrUrl, portOrInit, portParam) {
let request;
let port;
if (requestOrUrl instanceof Request) {
request = requestOrUrl;
port = typeof portOrInit === "number" ? portOrInit : void 0;
} else {
const url = typeof requestOrUrl === "string" ? requestOrUrl : requestOrUrl.toString();
const init = typeof portOrInit === "number" ? {} : portOrInit || {};
port = typeof portOrInit === "number" ? portOrInit : typeof portParam === "number" ? portParam : void 0;
request = new Request(url, init);
}
if (port === void 0 && this.defaultPort === void 0) {
throw new Error(
"No port specified for container fetch. Set defaultPort or specify a port parameter."
);
}
port = port ?? this.defaultPort;
return { request, port };
}
// ===========================================
// CONTAINER INTERACTION & MONITORING
// ===========================================
// Tries to start a container if it's not running
// Reutns the number of tries used
async startContainerIfNotRunning(waitOptions, options) {
if (this.container.running) {
if (!this.monitor) {
this.monitor = this.container.monitor();
}
return 0;
}
const abortedSignal = new Promise((res) => {
waitOptions.abort?.addEventListener("abort", () => {
res(true);
});
});
await this.state.setRunning();
for (let tries = 0; tries < waitOptions.retries; tries++) {
const envVars = options?.envVars ?? this.envVars;
const entrypoint = options?.entrypoint ?? this.entrypoint;
const enableInternet = options?.enableInternet ?? this.enableInternet;
const startConfig = {
enableInternet
};
if (envVars && Object.keys(envVars).length > 0) startConfig.env = envVars;
if (entrypoint) startConfig.entrypoint = entrypoint;
this.renewActivityTimeout();
const handleError = /* @__PURE__ */ __name(async () => {
const err = await this.monitor?.catch((err2) => err2);
if (typeof err === "number") {
const toThrow = new Error(
`Error starting container, early exit code 0 before we could check for healthiness, did it crash early?`
);
try {
await this.onError(toThrow);
} catch {
}
throw toThrow;
} else if (!isNoInstanceError(err)) {
try {
await this.onError(err);
} catch {
}
throw err;
}
}, "handleError");
if (!this.container.running) {
if (tries > 0) {
await handleError();
}
await this.scheduleNextAlarm();
this.container.start(startConfig);
this.monitor = this.container.monitor();
} else {
await this.scheduleNextAlarm();
}
this.renewActivityTimeout();
const port = this.container.getTcpPort(waitOptions.portToCheck);
try {
const combinedSignal = addTimeoutSignal(waitOptions.abort, PING_TIMEOUT_MS);
await port.fetch("http://containerstarthealthcheck", { signal: combinedSignal });
return tries;
} catch (error3) {
if (isNotListeningError(error3) && this.container.running) {
return tries;
}
if (!this.container.running && isNotListeningError(error3)) {
try {
await this.onError(new Error(`container crashed when checking if it was ready`));
} catch {
}
throw error3;
}
console.warn(
"Error checking if container is ready:",
error3 instanceof Error ? error3.message : String(error3)
);
await Promise.any([
new Promise((res) => setTimeout(res, waitOptions.waitInterval)),
abortedSignal
]);
if (waitOptions.abort?.aborted) {
throw new Error(
"Aborted waiting for container to start as we received a cancellation signal"
);
}
if (TEMPORARY_HARDCODED_ATTEMPT_MAX === tries) {
if (error3 instanceof Error && error3.message.includes("Network connection lost")) {
this.ctx.abort();
}
throw new Error(NO_CONTAINER_INSTANCE_ERROR);
}
continue;
}
}
throw new Error(`Container did not start after ${waitOptions.retries} attempts`);
}
setupMonitorCallbacks() {
if (this.monitorSetup) {
return;
}
this.monitorSetup = true;
this.monitor?.then(async () => {
const state = await this.state.getState();
await this.ctx.blockConcurrencyWhile(async () => {
const newState = await this.state.getState();
if (newState.status !== state.status) {
return;
}
await this.state.setStoppedWithCode(0);
await this.onStop({ exitCode: 0, reason: "exit" });
await this.state.setStopped();
});
}).catch(async (error3) => {
if (isNoInstanceError(error3)) {
return;
}
const exitCode2 = getExitCodeFromError(error3);
if (exitCode2 !== null) {
const state = await this.state.getState();
this.ctx.blockConcurrencyWhile(async () => {
const newState = await this.state.getState();
if (newState.status !== state.status) {
return;
}
await this.state.setStoppedWithCode(exitCode2);
await this.onStop({
exitCode: exitCode2,
reason: isRuntimeSignalledError(error3) ? "runtime_signal" : "exit"
});
await this.state.setStopped();
});
return;
}
try {
await this.onError(error3);
} catch {
}
}).finally(() => {
this.monitorSetup = false;
this.clearTimeout("monitor finally");
});
}
// ============================
// ALARMS AND SCHEDULES
// ============================
/**
* Method called when an alarm fires
* Executes any scheduled tasks that are due
*/
async alarm(alarmProps) {
if (alarmProps.isRetry && alarmProps.retryCount > MAX_ALAEM_RETRIES) {
const scheduleCount = Number(this.sql`SELECT COUNT(*) as count FROM container_schedules`[0]?.count) || 0;
const hasScheduledTasks = scheduleCount > 0;
if (hasScheduledTasks || this.container.running) {
await this.scheduleNextAlarm();
}
return;
}
this.clearTimeout("set alarm");
void this.ctx.storage.setAlarm(Date.now() + 1e3);
await this.ctx.storage.sync();
const now = Math.floor(Date.now() / 1e3);
const result = this.sql`
SELECT * FROM container_schedules;
`;
let maxTime = 0;
for (const row of result) {
if (row.time > now) {
maxTime = Math.max(maxTime, row.time * 1e3);
continue;
}
const callback = this[row.callback];
if (!callback || typeof callback !== "function") {
console.error(`Callback ${row.callback} not found or is not a function`);
continue;
}
const schedule = this.getSchedule(row.id);
try {
const payload = row.payload ? JSON.parse(row.payload) : void 0;
await callback.call(this, payload, await schedule);
} catch (e) {
console.error(`Error executing scheduled callback "${row.callback}":`, e);
}
this.sql`DELETE FROM container_schedules WHERE id = ${row.id}`;
}
await this.syncPendingStoppedEvents();
if (!this.container.running) {
await this.ctx.storage.deleteAlarm();
await this.ctx.storage.sync();
this.clearTimeout("activity expired");
return;
}
if (this.isActivityExpired()) {
await this.stopDueToInactivity();
await this.ctx.storage.deleteAlarm();
await this.ctx.storage.sync();
this.clearTimeout("activity expired");
return;
}
let resolve = /* @__PURE__ */ __name((_) => {
}, "resolve");
maxTime = maxTime === 0 ? Date.now() + 60 * 3 * 1e3 : maxTime;
maxTime = Math.min(maxTime, this.sleepAfterMs);
const timeout = Math.max(0, maxTime - Date.now());
const t = setTimeout(() => {
resolve("setTimeout");
}, timeout);
this.clearTimeout = () => {
clearTimeout(t);
};
void this.ctx.storage.setAlarm(timeout + Date.now());
await this.ctx.storage.sync();
}
// synchronises container state with the container source of truth to process events
async syncPendingStoppedEvents() {
const state = await this.state.getState();
if (!this.container.running && state.status === "healthy") {
await new Promise(
(res) => (
// setTimeout to process monitor() just in case
setTimeout(async () => {
await this.ctx.blockConcurrencyWhile(async () => {
const newState = await this.state.getState();
if (newState.status !== state.status) {
return;
}
await this.onStop({ exitCode: 0, reason: "exit" });
await this.state.setStopped();
});
res(true);
})
)
);
return;
}
if (!this.container.running && state.status === "stopped_with_code") {
await new Promise(
(res) => (
// setTimeout to process monitor() just in case
setTimeout(async () => {
await this.ctx.blockConcurrencyWhile(async () => {
const newState = await this.state.getState();
if (newState.status !== state.status) {
return;
}
await this.onStop({ exitCode: state.exitCode ?? 0, reason: "exit" });
await this.state.setStopped();
res(true);
});
})
)
);
return;
}
}
/**
* Schedule the next alarm based on upcoming tasks
* @private
*/
async scheduleNextAlarm(ms = 1e3) {
const existingAlarm = await this.ctx.storage.getAlarm();
const nextTime = ms + Date.now();
if (existingAlarm === null || existingAlarm > nextTime || existingAlarm < Date.now()) {
await this.ctx.storage.setAlarm(nextTime);
await this.ctx.storage.sync();
this.clearTimeout("scheduling next alarm");
}
}
/**
* Get a scheduled task by ID
* @template T Type of the payload data
* @param id ID of the scheduled task
* @returns The Schedule object or undefined if not found
*/
async getSchedule(id) {
const result = this.sql`
SELECT * FROM container_schedules WHERE id = ${id} LIMIT 1
`;
if (!result || result.length === 0) {
return void 0;
}
const schedule = result[0];
let payload;
try {
payload = JSON.parse(schedule.payload);
} catch (e) {
console.error(`Error parsing payload for schedule ${id}:`, e);
payload = void 0;
}
if (schedule.type === "delayed") {
return {
taskId: schedule.id,
callback: schedule.callback,
payload,
type: "delayed",
time: schedule.time,
delayInSeconds: schedule.delayInSeconds
};
}
return {
taskId: schedule.id,
callback: schedule.callback,
payload,
type: "scheduled",
time: schedule.time
};
}
isActivityExpired() {
return this.sleepAfterMs <= Date.now();
}
/**
* Method called by scheduled task to stop the container due to inactivity
*/
async stopDueToInactivity() {
const alreadyStopped = !this.container.running;
const hasOpenStream = this.openStreamCount > 0;
if (alreadyStopped || hasOpenStream) {
return;
}
await this.stop();
}
};
async function getRandom(binding2, instances = 3) {
const id = Math.floor(Math.random() * instances).toString();
const objectId = binding2.idFromName(`instance-${id}`);
return binding2.get(objectId);
}
__name(getRandom, "getRandom");
async function loadBalance(binding2, instances = 3) {
console.warn(
"loadBalance is deprecated, please use getRandom instead. This will be removed in a future version."
);
return getRandom(binding2, instances);
}
__name(loadBalance, "loadBalance");
var singletonContainerId = "cf-singleton-container";
function getContainer(binding2, name) {
const objectId = binding2.idFromName(name ?? singletonContainerId);
return binding2.get(objectId);
}
__name(getContainer, "getContainer");
// node_modules/hono/dist/compose.js
var compose = /* @__PURE__ */ __name((middleware, onError, onNotFound) => {
return (context2, next) => {
let index = -1;
return dispatch(0);
async function dispatch(i) {
if (i <= index) {
throw new Error("next() called multiple times");
}
index = i;
let res;
let isError = false;
let handler;
if (middleware[i]) {
handler = middleware[i][0][0];
context2.req.routeIndex = i;
} else {
handler = i === middleware.length && next || void 0;
}
if (handler) {
try {
res = await handler(context2, () => dispatch(i + 1));
} catch (err) {
if (err instanceof Error && onError) {
context2.error = err;
res = await onError(err, context2);
isError = true;
} else {
throw err;
}
}
} else {
if (context2.finalized === false && onNotFound) {
res = await onNotFound(context2);
}
}
if (res && (context2.finalized === false || isError)) {
context2.res = res;
}
return context2;
}
__name(dispatch, "dispatch");
};
}, "compose");
// node_modules/hono/dist/request/constants.js
var GET_MATCH_RESULT = Symbol();
// node_modules/hono/dist/utils/body.js
var parseBody = /* @__PURE__ */ __name(async (request, options = /* @__PURE__ */ Object.create(null)) => {
const { all = false, dot = false } = options;
const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
const contentType = headers.get("Content-Type");
if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
return parseFormData(request, { all, dot });
}
return {};
}, "parseBody");
async function parseFormData(request, options) {
const formData = await request.formData();
if (formData) {
return convertFormDataToBodyData(formData, options);
}
return {};
}
__name(parseFormData, "parseFormData");
function convertFormDataToBodyData(formData, options) {
const form = /* @__PURE__ */ Object.create(null);
formData.forEach((value, key) => {
const shouldParseAllValues = options.all || key.endsWith("[]");
if (!shouldParseAllValues) {
form[key] = value;
} else {
handleParsingAllValues(form, key, value);
}
});
if (options.dot) {
Object.entries(form).forEach(([key, value]) => {
const shouldParseDotValues = key.includes(".");
if (shouldParseDotValues) {
handleParsingNestedValues(form, key, value);
delete form[key];
}
});
}
return form;
}
__name(convertFormDataToBodyData, "convertFormDataToBodyData");
var handleParsingAllValues = /* @__PURE__ */ __name((form, key, value) => {
if (form[key] !== void 0) {
if (Array.isArray(form[key])) {
;
form[key].push(value);
} else {
form[key] = [form[key], value];
}
} else {
if (!key.endsWith("[]")) {
form[key] = value;
} else {
form[key] = [value];
}
}
}, "handleParsingAllValues");
var handleParsingNestedValues = /* @__PURE__ */ __name((form, key, value) => {
let nestedForm = form;
const keys = key.split(".");
keys.forEach((key2, index) => {
if (index === keys.length - 1) {
nestedForm[key2] = value;
} else {
if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) {
nestedForm[key2] = /* @__PURE__ */ Object.create(null);
}
nestedForm = nestedForm[key2];
}
});
}, "handleParsingNestedValues");
// node_modules/hono/dist/utils/url.js
var splitPath = /* @__PURE__ */ __name((path) => {
const paths = path.split("/");
if (paths[0] === "") {
paths.shift();
}
return paths;
}, "splitPath");
var splitRoutingPath = /* @__PURE__ */ __name((routePath) => {
const { groups, path } = extractGroupsFromPath(routePath);
const paths = splitPath(path);
return replaceGroupMarks(paths, groups);
}, "splitRoutingPath");
var extractGroupsFromPath = /* @__PURE__ */ __name((path) => {
const groups = [];
path = path.replace(/\{[^}]+\}/g, (match, index) => {
const mark = `@${index}`;
groups.push([mark, match]);
return mark;
});
return { groups, path };
}, "extractGroupsFromPath");
var replaceGroupMarks = /* @__PURE__ */ __name((paths, groups) => {
for (let i = groups.length - 1; i >= 0; i--) {
const [mark] = groups[i];
for (let j = paths.length - 1; j >= 0; j--) {
if (paths[j].includes(mark)) {
paths[j] = paths[j].replace(mark, groups[i][1]);
break;
}
}
}
return paths;
}, "replaceGroupMarks");
var patternCache = {};
var getPattern = /* @__PURE__ */ __name((label, next) => {
if (label === "*") {
return "*";
}
const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
if (match) {
const cacheKey = `${label}#${next}`;
if (!patternCache[cacheKey]) {
if (match[2]) {
patternCache[cacheKey] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey, match[1], new RegExp(`^${match[2]}(?=/${next})`)] : [label, match[1], new RegExp(`^${match[2]}$`)];
} else {
patternCache[cacheKey] = [label, match[1], true];
}
}
return patternCache[cacheKey];
}
return null;
}, "getPattern");
var tryDecode = /* @__PURE__ */ __name((str, decoder) => {
try {
return decoder(str);
} catch {
return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
try {
return decoder(match);
} catch {
return match;
}
});
}
}, "tryDecode");
var tryDecodeURI = /* @__PURE__ */ __name((str) => tryDecode(str, decodeURI), "tryDecodeURI");
var getPath = /* @__PURE__ */ __name((request) => {
const url = request.url;
const start = url.indexOf(
"/",
url.charCodeAt(9) === 58 ? 13 : 8
);
let i = start;
for (; i < url.length; i++) {
const charCode = url.charCodeAt(i);
if (charCode === 37) {
const queryIndex = url.indexOf("?", i);
const path = url.slice(start, queryIndex === -1 ? void 0 : queryIndex);
return tryDecodeURI(path.includes("%25") ? path.replace(/%25/g, "%2525") : path);
} else if (charCode === 63) {
break;
}
}
return url.slice(start, i);
}, "getPath");
var getPathNoStrict = /* @__PURE__ */ __name((request) => {
const result = getPath(request);
return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result;
}, "getPathNoStrict");
var mergePath = /* @__PURE__ */ __name((base, sub, ...rest) => {
if (rest.length) {
sub = mergePath(sub, ...rest);
}
return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
}, "mergePath");
var checkOptionalParameter = /* @__PURE__ */ __name((path) => {
if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(":")) {
return null;
}
const segments = path.split("/");
const results = [];
let basePath = "";
segments.forEach((segment) => {
if (segment !== "" && !/\:/.test(segment)) {
basePath += "/" + segment;
} else if (/\:/.test(segment)) {
if (/\?/.test(segment)) {
if (results.length === 0 && basePath === "") {
results.push("/");
} else {
results.push(basePath);
}
const optionalSegment = segment.replace("?", "");
basePath += "/" + optionalSegment;
results.push(basePath);
} else {
basePath += "/" + segment;
}
}
});
return results.filter((v, i, a) => a.indexOf(v) === i);
}, "checkOptionalParameter");
var _decodeURI = /* @__PURE__ */ __name((value) => {
if (!/[%+]/.test(value)) {
return value;
}
if (value.indexOf("+") !== -1) {
value = value.replace(/\+/g, " ");
}
return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
}, "_decodeURI");
var _getQueryParam = /* @__PURE__ */ __name((url, key, multiple) => {
let encoded;
if (!multiple && key && !/[%+]/.test(key)) {
let keyIndex2 = url.indexOf(`?${key}`, 8);
if (keyIndex2 === -1) {
keyIndex2 = url.indexOf(`&${key}`, 8);
}
while (keyIndex2 !== -1) {
const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1);
if (trailingKeyCode === 61) {
const valueIndex = keyIndex2 + key.length + 2;
const endIndex = url.indexOf("&", valueIndex);
return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex));
} else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) {
return "";
}
keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
}
encoded = /[%+]/.test(url);
if (!encoded) {
return void 0;
}
}
const results = {};
encoded ??= /[%+]/.test(url);
let keyIndex = url.indexOf("?", 8);
while (keyIndex !== -1) {
const nextKeyIndex = url.indexOf("&", keyIndex + 1);
let valueIndex = url.indexOf("=", keyIndex);
if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) {
valueIndex = -1;
}
let name = url.slice(
keyIndex + 1,
valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex
);
if (encoded) {
name = _decodeURI(name);
}
keyIndex = nextKeyIndex;
if (name === "") {
continue;
}
let value;
if (valueIndex === -1) {
value = "";
} else {
value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex);
if (encoded) {
value = _decodeURI(value);
}
}
if (multiple) {
if (!(results[name] && Array.isArray(results[name]))) {
results[name] = [];
}
;
results[name].push(value);
} else {
results[name] ??= value;
}
}
return key ? results[key] : results;
}, "_getQueryParam");
var getQueryParam = _getQueryParam;
var getQueryParams = /* @__PURE__ */ __name((url, key) => {
return _getQueryParam(url, key, true);
}, "getQueryParams");
var decodeURIComponent_ = decodeURIComponent;
// node_modules/hono/dist/request.js
var tryDecodeURIComponent = /* @__PURE__ */ __name((str) => tryDecode(str, decodeURIComponent_), "tryDecodeURIComponent");
var HonoRequest = class {
static {
__name(this, "HonoRequest");
}
raw;
#validatedData;
#matchResult;
routeIndex = 0;
path;
bodyCache = {};
constructor(request, path = "/", matchResult = [[]]) {
this.raw = request;
this.path = path;
this.#matchResult = matchResult;
this.#validatedData = {};
}
param(key) {
return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams();
}
#getDecodedParam(key) {
const paramKey = this.#matchResult[0][this.routeIndex][1][key];
const param = this.#getParamValue(paramKey);
return param ? /\%/.test(param) ? tryDecodeURIComponent(param) : param : void 0;
}
#getAllDecodedParams() {
const decoded = {};
const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]);
for (const key of keys) {
const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);
if (value && typeof value === "string") {
decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value;
}
}
return decoded;
}
#getParamValue(paramKey) {
return this.#matchResult[1] ? this.#matchResult[1][paramKey] : paramKey;
}
query(key) {
return getQueryParam(this.url, key);
}
queries(key) {
return getQueryParams(this.url, key);
}
header(name) {
if (name) {
return this.raw.headers.get(name) ?? void 0;
}
const headerData = {};
this.raw.headers.forEach((value, key) => {
headerData[key] = value;
});
return headerData;
}
async parseBody(options) {
return this.bodyCache.parsedBody ??= await parseBody(this, options);
}
#cachedBody = /* @__PURE__ */ __name((key) => {
const { bodyCache, raw: raw2 } = this;
const cachedBody = bodyCache[key];
if (cachedBody) {
return cachedBody;
}
const anyCachedKey = Object.keys(bodyCache)[0];
if (anyCachedKey) {
return bodyCache[anyCachedKey].then((body) => {
if (anyCachedKey === "json") {
body = JSON.stringify(body);
}
return new Response(body)[key]();
});
}
return bodyCache[key] = raw2[key]();
}, "#cachedBody");
json() {
return this.#cachedBody("json");
}
text() {
return this.#cachedBody("text");
}
arrayBuffer() {
return this.#cachedBody("arrayBuffer");
}
blob() {
return this.#cachedBody("blob");
}
formData() {
return this.#cachedBody("formData");
}
addValidatedData(target, data) {
this.#validatedData[target] = data;
}
valid(target) {
return this.#validatedData[target];
}
get url() {
return this.raw.url;
}
get method() {
return this.raw.method;
}
get [GET_MATCH_RESULT]() {
return this.#matchResult;
}
get matchedRoutes() {
return this.#matchResult[0].map(([[, route]]) => route);
}
get routePath() {
return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
}
};
// node_modules/hono/dist/utils/html.js
var HtmlEscapedCallbackPhase = {
Stringify: 1,
BeforeStream: 2,
Stream: 3
};
var raw = /* @__PURE__ */ __name((value, callbacks) => {
const escapedString = new String(value);
escapedString.isEscaped = true;
escapedString.callbacks = callbacks;
return escapedString;
}, "raw");
var resolveCallback = /* @__PURE__ */ __name(async (str, phase, preserveCallbacks, context2, buffer) => {
if (typeof str === "object" && !(str instanceof String)) {
if (!(str instanceof Promise)) {
str = str.toString();
}
if (str instanceof Promise) {
str = await str;
}
}
const callbacks = str.callbacks;
if (!callbacks?.length) {
return Promise.resolve(str);
}
if (buffer) {
buffer[0] += str;
} else {
buffer = [str];
}
const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context: context2 }))).then(
(res) => Promise.all(
res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context2, buffer))
).then(() => buffer[0])
);
if (preserveCallbacks) {
return raw(await resStr, callbacks);
} else {
return resStr;
}
}, "resolveCallback");
// node_modules/hono/dist/context.js
var TEXT_PLAIN = "text/plain; charset=UTF-8";
var setDefaultContentType = /* @__PURE__ */ __name((contentType, headers) => {
return {
"Content-Type": contentType,
...headers
};
}, "setDefaultContentType");
var Context = class {
static {
__name(this, "Context");
}
#rawRequest;
#req;
env = {};
#var;
finalized = false;
error;
#status;
#executionCtx;
#res;
#layout;
#renderer;
#notFoundHandler;
#preparedHeaders;
#matchResult;
#path;
constructor(req, options) {
this.#rawRequest = req;
if (options) {
this.#executionCtx = options.executionCtx;
this.env = options.env;
this.#notFoundHandler = options.notFoundHandler;
this.#path = options.path;
this.#matchResult = options.matchResult;
}
}
get req() {
this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult);
return this.#req;
}
get event() {
if (this.#executionCtx && "respondWith" in this.#executionCtx) {
return this.#executionCtx;
} else {
throw Error("This context has no FetchEvent");
}
}
get executionCtx() {
if (this.#executionCtx) {
return this.#executionCtx;
} else {
throw Error("This context has no ExecutionContext");
}
}
get res() {
return this.#res ||= new Response(null, {
headers: this.#preparedHeaders ??= new Headers()
});
}
set res(_res) {
if (this.#res && _res) {
_res = new Response(_res.body, _res);
for (const [k, v] of this.#res.headers.entries()) {
if (k === "content-type") {
continue;
}
if (k === "set-cookie") {
const cookies = this.#res.headers.getSetCookie();
_res.headers.delete("set-cookie");
for (const cookie of cookies) {
_res.headers.append("set-cookie", cookie);
}
} else {
_res.headers.set(k, v);
}
}
}
this.#res = _res;
this.finalized = true;
}
render = /* @__PURE__ */ __name((...args) => {
this.#renderer ??= (content) => this.html(content);
return this.#renderer(...args);
}, "render");
setLayout = /* @__PURE__ */ __name((layout) => this.#layout = layout, "setLayout");
getLayout = /* @__PURE__ */ __name(() => this.#layout, "getLayout");
setRenderer = /* @__PURE__ */ __name((renderer) => {
this.#renderer = renderer;
}, "setRenderer");
header = /* @__PURE__ */ __name((name, value, options) => {
if (this.finalized) {
this.#res = new Response(this.#res.body, this.#res);
}
const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();
if (value === void 0) {
headers.delete(name);
} else if (options?.append) {
headers.append(name, value);
} else {
headers.set(name, value);
}
}, "header");
status = /* @__PURE__ */ __name((status) => {
this.#status = status;
}, "status");
set = /* @__PURE__ */ __name((key, value) => {
this.#var ??= /* @__PURE__ */ new Map();
this.#var.set(key, value);
}, "set");
get = /* @__PURE__ */ __name((key) => {
return this.#var ? this.#var.get(key) : void 0;
}, "get");
get var() {
if (!this.#var) {
return {};
}
return Object.fromEntries(this.#var);
}
#newResponse(data, arg, headers) {
const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers();
if (typeof arg === "object" && "headers" in arg) {
const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
for (const [key, value] of argHeaders) {
if (key.toLowerCase() === "set-cookie") {
responseHeaders.append(key, value);
} else {
responseHeaders.set(key, value);
}
}
}
if (headers) {
for (const [k, v] of Object.entries(headers)) {
if (typeof v === "string") {
responseHeaders.set(k, v);
} else {
responseHeaders.delete(k);
for (const v2 of v) {
responseHeaders.append(k, v2);
}
}
}
}
const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
return new Response(data, { status, headers: responseHeaders });
}
newResponse = /* @__PURE__ */ __name((...args) => this.#newResponse(...args), "newResponse");
body = /* @__PURE__ */ __name((data, arg, headers) => this.#newResponse(data, arg, headers), "body");
text = /* @__PURE__ */ __name((text, arg, headers) => {
return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(
text,
arg,
setDefaultContentType(TEXT_PLAIN, headers)
);
}, "text");
json = /* @__PURE__ */ __name((object, arg, headers) => {
return this.#newResponse(
JSON.stringify(object),
arg,
setDefaultContentType("application/json", headers)
);
}, "json");
html = /* @__PURE__ */ __name((html, arg, headers) => {
const res = /* @__PURE__ */ __name((html2) => this.#newResponse(html2, arg, setDefaultContentType("text/html; charset=UTF-8", headers)), "res");
return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html);
}, "html");
redirect = /* @__PURE__ */ __name((location, status) => {
this.header("Location", String(location));
return this.newResponse(null, status ?? 302);
}, "redirect");
notFound = /* @__PURE__ */ __name(() => {
this.#notFoundHandler ??= () => new Response();
return this.#notFoundHandler(this);
}, "notFound");
};
// node_modules/hono/dist/router.js
var METHOD_NAME_ALL = "ALL";
var METHOD_NAME_ALL_LOWERCASE = "all";
var METHODS = ["get", "post", "put", "delete", "options", "patch"];
var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
var UnsupportedPathError = class extends Error {
static {
__name(this, "UnsupportedPathError");
}
};
// node_modules/hono/dist/utils/constants.js
var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
// node_modules/hono/dist/hono-base.js
var notFoundHandler = /* @__PURE__ */ __name((c) => {
return c.text("404 Not Found", 404);
}, "notFoundHandler");
var errorHandler = /* @__PURE__ */ __name((err, c) => {
if ("getResponse" in err) {
const res = err.getResponse();
return c.newResponse(res.body, res);
}
console.error(err);
return c.text("Internal Server Error", 500);
}, "errorHandler");
var Hono = class {
static {
__name(this, "Hono");
}
get;
post;
put;
delete;
options;
patch;
all;
on;
use;
router;
getPath;
_basePath = "/";
#path = "/";
routes = [];
constructor(options = {}) {
const allMethods = [...METHODS, METHOD_NAME_ALL_LOWERCASE];
allMethods.forEach((method) => {
this[method] = (args1, ...args) => {
if (typeof args1 === "string") {
this.#path = args1;
} else {
this.#addRoute(method, this.#path, args1);
}
args.forEach((handler) => {
this.#addRoute(method, this.#path, handler);
});
return this;
};
});
this.on = (method, path, ...handlers) => {
for (const p of [path].flat()) {
this.#path = p;
for (const m of [method].flat()) {
handlers.map((handler) => {
this.#addRoute(m.toUpperCase(), this.#path, handler);
});
}
}
return this;
};
this.use = (arg1, ...handlers) => {
if (typeof arg1 === "string") {
this.#path = arg1;
} else {
this.#path = "*";
handlers.unshift(arg1);
}
handlers.forEach((handler) => {
this.#addRoute(METHOD_NAME_ALL, this.#path, handler);
});
return this;
};
const { strict, ...optionsWithoutStrict } = options;
Object.assign(this, optionsWithoutStrict);
this.getPath = strict ?? true ? options.getPath ?? getPath : getPathNoStrict;
}
#clone() {
const clone = new Hono({
router: this.router,
getPath: this.getPath
});
clone.errorHandler = this.errorHandler;
clone.#notFoundHandler = this.#notFoundHandler;
clone.routes = this.routes;
return clone;
}
#notFoundHandler = notFoundHandler;
errorHandler = errorHandler;
route(path, app2) {
const subApp = this.basePath(path);
app2.routes.map((r) => {
let handler;
if (app2.errorHandler === errorHandler) {
handler = r.handler;
} else {
handler = /* @__PURE__ */ __name(async (c, next) => (await compose([], app2.errorHandler)(c, () => r.handler(c, next))).res, "handler");
handler[COMPOSED_HANDLER] = r.handler;
}
subApp.#addRoute(r.method, r.path, handler);
});
return this;
}
basePath(path) {
const subApp = this.#clone();
subApp._basePath = mergePath(this._basePath, path);
return subApp;
}
onError = /* @__PURE__ */ __name((handler) => {
this.errorHandler = handler;
return this;
}, "onError");
notFound = /* @__PURE__ */ __name((handler) => {
this.#notFoundHandler = handler;
return this;
}, "notFound");
mount(path, applicationHandler, options) {
let replaceRequest;
let optionHandler;
if (options) {
if (typeof options === "function") {
optionHandler = options;
} else {
optionHandler = options.optionHandler;
if (options.replaceRequest === false) {
replaceRequest = /* @__PURE__ */ __name((request) => request, "replaceRequest");
} else {
replaceRequest = options.replaceRequest;
}
}
}
const getOptions = optionHandler ? (c) => {
const options2 = optionHandler(c);
return Array.isArray(options2) ? options2 : [options2];
} : (c) => {
let executionContext = void 0;
try {
executionContext = c.executionCtx;
} catch {
}
return [c.env, executionContext];
};
replaceRequest ||= (() => {
const mergedPath = mergePath(this._basePath, path);
const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
return (request) => {
const url = new URL(request.url);
url.pathname = url.pathname.slice(pathPrefixLength) || "/";
return new Request(url, request);
};
})();
const handler = /* @__PURE__ */ __name(async (c, next) => {
const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c));
if (res) {
return res;
}
await next();
}, "handler");
this.#addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler);
return this;
}
#addRoute(method, path, handler) {
method = method.toUpperCase();
path = mergePath(this._basePath, path);
const r = { basePath: this._basePath, path, method, handler };
this.router.add(method, path, [handler, r]);
this.routes.push(r);
}
#handleError(err, c) {
if (err instanceof Error) {
return this.errorHandler(err, c);
}
throw err;
}
#dispatch(request, executionCtx, env2, method) {
if (method === "HEAD") {
return (async () => new Response(null, await this.#dispatch(request, executionCtx, env2, "GET")))();
}
const path = this.getPath(request, { env: env2 });
const matchResult = this.router.match(method, path);
const c = new Context(request, {
path,
matchResult,
env: env2,
executionCtx,
notFoundHandler: this.#notFoundHandler
});
if (matchResult[0].length === 1) {
let res;
try {
res = matchResult[0][0][0][0](c, async () => {
c.res = await this.#notFoundHandler(c);
});
} catch (err) {
return this.#handleError(err, c);
}
return res instanceof Promise ? res.then(
(resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c))
).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c);
}
const composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler);
return (async () => {
try {
const context2 = await composed(c);
if (!context2.finalized) {
throw new Error(
"Context is not finalized. Did you forget to return a Response object or `await next()`?"
);
}
return context2.res;
} catch (err) {
return this.#handleError(err, c);
}
})();
}
fetch = /* @__PURE__ */ __name((request, ...rest) => {
return this.#dispatch(request, rest[1], rest[0], request.method);
}, "fetch");
request = /* @__PURE__ */ __name((input, requestInit, Env, executionCtx) => {
if (input instanceof Request) {
return this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx);
}
input = input.toString();
return this.fetch(
new Request(
/^https?:\/\//.test(input) ? input : `http://localhost${mergePath("/", input)}`,
requestInit
),
Env,
executionCtx
);
}, "request");
fire = /* @__PURE__ */ __name(() => {
addEventListener("fetch", (event) => {
event.respondWith(this.#dispatch(event.request, event, void 0, event.request.method));
});
}, "fire");
};
// node_modules/hono/dist/router/reg-exp-router/node.js
var LABEL_REG_EXP_STR = "[^/]+";
var ONLY_WILDCARD_REG_EXP_STR = ".*";
var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
var PATH_ERROR = Symbol();
var regExpMetaChars = new Set(".\\+*[^]$()");
function compareKey(a, b) {
if (a.length === 1) {
return b.length === 1 ? a < b ? -1 : 1 : -1;
}
if (b.length === 1) {
return 1;
}
if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
return 1;
} else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
return -1;
}
if (a === LABEL_REG_EXP_STR) {
return 1;
} else if (b === LABEL_REG_EXP_STR) {
return -1;
}
return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length;
}
__name(compareKey, "compareKey");
var Node = class {
static {
__name(this, "Node");
}
#index;
#varIndex;
#children = /* @__PURE__ */ Object.create(null);
insert(tokens, index, paramMap, context2, pathErrorCheckOnly) {
if (tokens.length === 0) {
if (this.#index !== void 0) {
throw PATH_ERROR;
}
if (pathErrorCheckOnly) {
return;
}
this.#index = index;
return;
}
const [token, ...restTokens] = tokens;
const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
let node;
if (pattern) {
const name = pattern[1];
let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
if (name && pattern[2]) {
regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
if (/\((?!\?:)/.test(regexpStr)) {
throw PATH_ERROR;
}
}
node = this.#children[regexpStr];
if (!node) {
if (Object.keys(this.#children).some(
(k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
)) {
throw PATH_ERROR;
}
if (pathErrorCheckOnly) {
return;
}
node = this.#children[regexpStr] = new Node();
if (name !== "") {
node.#varIndex = context2.varIndex++;
}
}
if (!pathErrorCheckOnly && name !== "") {
paramMap.push([name, node.#varIndex]);
}
} else {
node = this.#children[token];
if (!node) {
if (Object.keys(this.#children).some(
(k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
)) {
throw PATH_ERROR;
}
if (pathErrorCheckOnly) {
return;
}
node = this.#children[token] = new Node();
}
}
node.insert(restTokens, index, paramMap, context2, pathErrorCheckOnly);
}
buildRegExpStr() {
const childKeys = Object.keys(this.#children).sort(compareKey);
const strList = childKeys.map((k) => {
const c = this.#children[k];
return (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
});
if (typeof this.#index === "number") {
strList.unshift(`#${this.#index}`);
}
if (strList.length === 0) {
return "";
}
if (strList.length === 1) {
return strList[0];
}
return "(?:" + strList.join("|") + ")";
}
};
// node_modules/hono/dist/router/reg-exp-router/trie.js
var Trie = class {
static {
__name(this, "Trie");
}
#context = { varIndex: 0 };
#root = new Node();
insert(path, index, pathErrorCheckOnly) {
const paramAssoc = [];
const groups = [];
for (let i = 0; ; ) {
let replaced = false;
path = path.replace(/\{[^}]+\}/g, (m) => {
const mark = `@\\${i}`;
groups[i] = [mark, m];
i++;
replaced = true;
return mark;
});
if (!replaced) {
break;
}
}
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
for (let i = groups.length - 1; i >= 0; i--) {
const [mark] = groups[i];
for (let j = tokens.length - 1; j >= 0; j--) {
if (tokens[j].indexOf(mark) !== -1) {
tokens[j] = tokens[j].replace(mark, groups[i][1]);
break;
}
}
}
this.#root.insert(tokens, index, paramAssoc, this.#context, pathErrorCheckOnly);
return paramAssoc;
}
buildRegExp() {
let regexp = this.#root.buildRegExpStr();
if (regexp === "") {
return [/^$/, [], []];
}
let captureIndex = 0;
const indexReplacementMap = [];
const paramReplacementMap = [];
regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => {
if (handlerIndex !== void 0) {
indexReplacementMap[++captureIndex] = Number(handlerIndex);
return "$()";
}
if (paramIndex !== void 0) {
paramReplacementMap[Number(paramIndex)] = ++captureIndex;
return "";
}
return "";
});
return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
}
};
// node_modules/hono/dist/router/reg-exp-router/router.js
var emptyParam = [];
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
function buildWildcardRegExp(path) {
return wildcardRegExpCache[path] ??= new RegExp(
path === "*" ? "" : `^${path.replace(
/\/\*$|([.\\+*[^\]$()])/g,
(_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
)}$`
);
}
__name(buildWildcardRegExp, "buildWildcardRegExp");
function clearWildcardRegExpCache() {
wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
}
__name(clearWildcardRegExpCache, "clearWildcardRegExpCache");
function buildMatcherFromPreprocessedRoutes(routes) {
const trie = new Trie();
const handlerData = [];
if (routes.length === 0) {
return nullMatcher;
}
const routesWithStaticPathFlag = routes.map(
(route) => [!/\*|\/:/.test(route[0]), ...route]
).sort(
([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
);
const staticMap = /* @__PURE__ */ Object.create(null);
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
if (pathErrorCheckOnly) {
staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
} else {
j++;
}
let paramAssoc;
try {
paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
} catch (e) {
throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
}
if (pathErrorCheckOnly) {
continue;
}
handlerData[j] = handlers.map(([h, paramCount]) => {
const paramIndexMap = /* @__PURE__ */ Object.create(null);
paramCount -= 1;
for (; paramCount >= 0; paramCount--) {
const [key, value] = paramAssoc[paramCount];
paramIndexMap[key] = value;
}
return [h, paramIndexMap];
});
}
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
for (let i = 0, len = handlerData.length; i < len; i++) {
for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
const map = handlerData[i][j]?.[1];
if (!map) {
continue;
}
const keys = Object.keys(map);
for (let k = 0, len3 = keys.length; k < len3; k++) {
map[keys[k]] = paramReplacementMap[map[keys[k]]];
}
}
}
const handlerMap = [];
for (const i in indexReplacementMap) {
handlerMap[i] = handlerData[indexReplacementMap[i]];
}
return [regexp, handlerMap, staticMap];
}
__name(buildMatcherFromPreprocessedRoutes, "buildMatcherFromPreprocessedRoutes");
function findMiddleware(middleware, path) {
if (!middleware) {
return void 0;
}
for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
if (buildWildcardRegExp(k).test(path)) {
return [...middleware[k]];
}
}
return void 0;
}
__name(findMiddleware, "findMiddleware");
var RegExpRouter = class {
static {
__name(this, "RegExpRouter");
}
name = "RegExpRouter";
#middleware;
#routes;
constructor() {
this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
}
add(method, path, handler) {
const middleware = this.#middleware;
const routes = this.#routes;
if (!middleware || !routes) {
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
}
if (!middleware[method]) {
;
[middleware, routes].forEach((handlerMap) => {
handlerMap[method] = /* @__PURE__ */ Object.create(null);
Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
});
});
}
if (path === "/*") {
path = "*";
}
const paramCount = (path.match(/\/:/g) || []).length;
if (/\*$/.test(path)) {
const re = buildWildcardRegExp(path);
if (method === METHOD_NAME_ALL) {
Object.keys(middleware).forEach((m) => {
middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
});
} else {
middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
}
Object.keys(middleware).forEach((m) => {
if (method === METHOD_NAME_ALL || method === m) {
Object.keys(middleware[m]).forEach((p) => {
re.test(p) && middleware[m][p].push([handler, paramCount]);
});
}
});
Object.keys(routes).forEach((m) => {
if (method === METHOD_NAME_ALL || method === m) {
Object.keys(routes[m]).forEach(
(p) => re.test(p) && routes[m][p].push([handler, paramCount])
);
}
});
return;
}
const paths = checkOptionalParameter(path) || [path];
for (let i = 0, len = paths.length; i < len; i++) {
const path2 = paths[i];
Object.keys(routes).forEach((m) => {
if (method === METHOD_NAME_ALL || method === m) {
routes[m][path2] ||= [
...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
];
routes[m][path2].push([handler, paramCount - len + i + 1]);
}
});
}
}
match(method, path) {
clearWildcardRegExpCache();
const matchers = this.#buildAllMatchers();
this.match = (method2, path2) => {
const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
const staticMatch = matcher[2][path2];
if (staticMatch) {
return staticMatch;
}
const match = path2.match(matcher[0]);
if (!match) {
return [[], emptyParam];
}
const index = match.indexOf("", 1);
return [matcher[1][index], match];
};
return this.match(method, path);
}
#buildAllMatchers() {
const matchers = /* @__PURE__ */ Object.create(null);
Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
matchers[method] ||= this.#buildMatcher(method);
});
this.#middleware = this.#routes = void 0;
return matchers;
}
#buildMatcher(method) {
const routes = [];
let hasOwnRoute = method === METHOD_NAME_ALL;
[this.#middleware, this.#routes].forEach((r) => {
const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
if (ownRoute.length !== 0) {
hasOwnRoute ||= true;
routes.push(...ownRoute);
} else if (method !== METHOD_NAME_ALL) {
routes.push(
...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]])
);
}
});
if (!hasOwnRoute) {
return null;
} else {
return buildMatcherFromPreprocessedRoutes(routes);
}
}
};
// node_modules/hono/dist/router/smart-router/router.js
var SmartRouter = class {
static {
__name(this, "SmartRouter");
}
name = "SmartRouter";
#routers = [];
#routes = [];
constructor(init) {
this.#routers = init.routers;
}
add(method, path, handler) {
if (!this.#routes) {
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
}
this.#routes.push([method, path, handler]);
}
match(method, path) {
if (!this.#routes) {
throw new Error("Fatal error");
}
const routers = this.#routers;
const routes = this.#routes;
const len = routers.length;
let i = 0;
let res;
for (; i < len; i++) {
const router = routers[i];
try {
for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) {
router.add(...routes[i2]);
}
res = router.match(method, path);
} catch (e) {
if (e instanceof UnsupportedPathError) {
continue;
}
throw e;
}
this.match = router.match.bind(router);
this.#routers = [router];
this.#routes = void 0;
break;
}
if (i === len) {
throw new Error("Fatal error");
}
this.name = `SmartRouter + ${this.activeRouter.name}`;
return res;
}
get activeRouter() {
if (this.#routes || this.#routers.length !== 1) {
throw new Error("No active router has been determined yet.");
}
return this.#routers[0];
}
};
// node_modules/hono/dist/router/trie-router/node.js
var emptyParams = /* @__PURE__ */ Object.create(null);
var Node2 = class {
static {
__name(this, "Node");
}
#methods;
#children;
#patterns;
#order = 0;
#params = emptyParams;
constructor(method, handler, children) {
this.#children = children || /* @__PURE__ */ Object.create(null);
this.#methods = [];
if (method && handler) {
const m = /* @__PURE__ */ Object.create(null);
m[method] = { handler, possibleKeys: [], score: 0 };
this.#methods = [m];
}
this.#patterns = [];
}
insert(method, path, handler) {
this.#order = ++this.#order;
let curNode = this;
const parts = splitRoutingPath(path);
const possibleKeys = [];
for (let i = 0, len = parts.length; i < len; i++) {
const p = parts[i];
const nextP = parts[i + 1];
const pattern = getPattern(p, nextP);
const key = Array.isArray(pattern) ? pattern[0] : p;
if (key in curNode.#children) {
curNode = curNode.#children[key];
if (pattern) {
possibleKeys.push(pattern[1]);
}
continue;
}
curNode.#children[key] = new Node2();
if (pattern) {
curNode.#patterns.push(pattern);
possibleKeys.push(pattern[1]);
}
curNode = curNode.#children[key];
}
curNode.#methods.push({
[method]: {
handler,
possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
score: this.#order
}
});
return curNode;
}
#getHandlerSets(node, method, nodeParams, params) {
const handlerSets = [];
for (let i = 0, len = node.#methods.length; i < len; i++) {
const m = node.#methods[i];
const handlerSet = m[method] || m[METHOD_NAME_ALL];
const processedSet = {};
if (handlerSet !== void 0) {
handlerSet.params = /* @__PURE__ */ Object.create(null);
handlerSets.push(handlerSet);
if (nodeParams !== emptyParams || params && params !== emptyParams) {
for (let i2 = 0, len2 = handlerSet.possibleKeys.length; i2 < len2; i2++) {
const key = handlerSet.possibleKeys[i2];
const processed = processedSet[handlerSet.score];
handlerSet.params[key] = params?.[key] && !processed ? params[key] : nodeParams[key] ?? params?.[key];
processedSet[handlerSet.score] = true;
}
}
}
}
return handlerSets;
}
search(method, path) {
const handlerSets = [];
this.#params = emptyParams;
const curNode = this;
let curNodes = [curNode];
const parts = splitPath(path);
const curNodesQueue = [];
for (let i = 0, len = parts.length; i < len; i++) {
const part = parts[i];
const isLast = i === len - 1;
const tempNodes = [];
for (let j = 0, len2 = curNodes.length; j < len2; j++) {
const node = curNodes[j];
const nextNode = node.#children[part];
if (nextNode) {
nextNode.#params = node.#params;
if (isLast) {
if (nextNode.#children["*"]) {
handlerSets.push(
...this.#getHandlerSets(nextNode.#children["*"], method, node.#params)
);
}
handlerSets.push(...this.#getHandlerSets(nextNode, method, node.#params));
} else {
tempNodes.push(nextNode);
}
}
for (let k = 0, len3 = node.#patterns.length; k < len3; k++) {
const pattern = node.#patterns[k];
const params = node.#params === emptyParams ? {} : { ...node.#params };
if (pattern === "*") {
const astNode = node.#children["*"];
if (astNode) {
handlerSets.push(...this.#getHandlerSets(astNode, method, node.#params));
astNode.#params = params;
tempNodes.push(astNode);
}
continue;
}
if (!part) {
continue;
}
const [key, name, matcher] = pattern;
const child = node.#children[key];
const restPathString = parts.slice(i).join("/");
if (matcher instanceof RegExp) {
const m = matcher.exec(restPathString);
if (m) {
params[name] = m[0];
handlerSets.push(...this.#getHandlerSets(child, method, node.#params, params));
if (Object.keys(child.#children).length) {
child.#params = params;
const componentCount = m[0].match(/\//)?.length ?? 0;
const targetCurNodes = curNodesQueue[componentCount] ||= [];
targetCurNodes.push(child);
}
continue;
}
}
if (matcher === true || matcher.test(part)) {
params[name] = part;
if (isLast) {
handlerSets.push(...this.#getHandlerSets(child, method, params, node.#params));
if (child.#children["*"]) {
handlerSets.push(
...this.#getHandlerSets(child.#children["*"], method, params, node.#params)
);
}
} else {
child.#params = params;
tempNodes.push(child);
}
}
}
}
curNodes = tempNodes.concat(curNodesQueue.shift() ?? []);
}
if (handlerSets.length > 1) {
handlerSets.sort((a, b) => {
return a.score - b.score;
});
}
return [handlerSets.map(({ handler, params }) => [handler, params])];
}
};
// node_modules/hono/dist/router/trie-router/router.js
var TrieRouter = class {
static {
__name(this, "TrieRouter");
}
name = "TrieRouter";
#node;
constructor() {
this.#node = new Node2();
}
add(method, path, handler) {
const results = checkOptionalParameter(path);
if (results) {
for (let i = 0, len = results.length; i < len; i++) {
this.#node.insert(method, results[i], handler);
}
return;
}
this.#node.insert(method, path, handler);
}
match(method, path) {
return this.#node.search(method, path);
}
};
// node_modules/hono/dist/hono.js
var Hono2 = class extends Hono {
static {
__name(this, "Hono");
}
constructor(options = {}) {
super(options);
this.router = options.router ?? new SmartRouter({
routers: [new RegExpRouter(), new TrieRouter()]
});
}
};
// src/index.ts
var MyContainer = class extends Container {
constructor() {
super(...arguments);
// Port the container listens on (default: 8080)
this.defaultPort = 8080;
// Time before container sleeps due to inactivity (default: 30s)
this.sleepAfter = "2m";
// Environment variables passed to the container
this.envVars = {
MESSAGE: "I was passed in via the container class!"
};
}
static {
__name(this, "MyContainer");
}
// Optional lifecycle hooks
onStart() {
console.log("Container successfully started");
}
onStop() {
console.log("Container successfully shut down");
}
onError(error3) {
console.log("Container error:", error3);
}
};
var app = new Hono2();
app.get("/", (c) => {
return c.text(
"Available endpoints:\nGET /container/<ID> - Start a container for each ID with a 2m timeout\nGET /lb - Load balance requests over multiple containers\nGET /error - Start a container that errors (demonstrates error handling)\nGET /singleton - Get a single specific container instance"
);
});
app.get("/container/:id", async (c) => {
const id = c.req.param("id");
const containerId = c.env.MY_CONTAINER.idFromName(`/container/${id}`);
const container = c.env.MY_CONTAINER.get(containerId);
return await container.fetch(c.req.raw);
});
app.get("/error", async (c) => {
const container = getContainer(c.env.MY_CONTAINER, "error-test");
return await container.fetch(c.req.raw);
});
app.get("/lb", async (c) => {
const container = await loadBalance(c.env.MY_CONTAINER, 3);
return await container.fetch(c.req.raw);
});
app.get("/singleton", async (c) => {
const container = getContainer(c.env.MY_CONTAINER);
return await container.fetch(c.req.raw);
});
var index_default = app;
export {
MyContainer,
index_default as default
};
//# sourceMappingURL=index.js.map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment