stratal 0.0.25 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/quarry.mjs +60 -4
- package/dist/bin/quarry.mjs.map +1 -1
- package/dist/cache/index.d.mts +1 -1
- package/dist/cache/index.mjs +2 -2
- package/dist/{command-4HnKnC-G.d.mts → command-DoBD2Cwl.d.mts} +2 -2
- package/dist/{command-4HnKnC-G.d.mts.map → command-DoBD2Cwl.d.mts.map} +1 -1
- package/dist/config/index.d.mts +1 -1
- package/dist/config/index.mjs +2 -2
- package/dist/{controller.decorator-DKeZ71aP.mjs → controller.decorator-YSTPQntu.mjs} +3 -3
- package/dist/{controller.decorator-DKeZ71aP.mjs.map → controller.decorator-YSTPQntu.mjs.map} +1 -1
- package/dist/cron/index.d.mts +1 -1
- package/dist/cron/index.mjs +1 -1
- package/dist/{cron.module-DgxLe8Xy.mjs → cron.module-C81HTzR7.mjs} +3 -3
- package/dist/{cron.module-DgxLe8Xy.mjs.map → cron.module-C81HTzR7.mjs.map} +1 -1
- package/dist/di/index.d.mts +2 -2
- package/dist/di/index.mjs +2 -2
- package/dist/{di-B0NXIdRF.mjs → di-D7qmrAir.mjs} +44 -3
- package/dist/di-D7qmrAir.mjs.map +1 -0
- package/dist/email/index.d.mts +2 -2
- package/dist/email/index.mjs +3 -3
- package/dist/errors/index.d.mts +2 -2
- package/dist/errors/index.mjs +3 -3
- package/dist/{errors-EUtwVfNm.mjs → errors-C01O2T-n.mjs} +19 -4
- package/dist/errors-C01O2T-n.mjs.map +1 -0
- package/dist/events/index.mjs +1 -1
- package/dist/{events-zbCMY_Gf.mjs → events-BhEQuT1X.mjs} +2 -2
- package/dist/{events-zbCMY_Gf.mjs.map → events-BhEQuT1X.mjs.map} +1 -1
- package/dist/{exception-context-Bd5Hk2c_.mjs → exception-context-D-kvney-.mjs} +2 -2
- package/dist/{exception-context-Bd5Hk2c_.mjs.map → exception-context-D-kvney-.mjs.map} +1 -1
- package/dist/{gateway-context-I0tKgGfh.mjs → gateway-context-m7kEzRa2.mjs} +4 -4
- package/dist/{gateway-context-I0tKgGfh.mjs.map → gateway-context-m7kEzRa2.mjs.map} +1 -1
- package/dist/guards/index.d.mts +1 -1
- package/dist/{hono-app-C7-1m9eK.mjs → hono-app-COAgmutc.mjs} +18 -11
- package/dist/hono-app-COAgmutc.mjs.map +1 -0
- package/dist/{http-method.decorator-xCuGoZPC.mjs → http-method.decorator-BljM8BDj.mjs} +2 -2
- package/dist/{http-method.decorator-xCuGoZPC.mjs.map → http-method.decorator-BljM8BDj.mjs.map} +1 -1
- package/dist/i18n/index.d.mts +10 -3
- package/dist/i18n/index.d.mts.map +1 -1
- package/dist/i18n/index.mjs +3 -3
- package/dist/{i18n.module-JOPUNpvi.mjs → i18n.module-B2DvWUPa.mjs} +24 -9
- package/dist/i18n.module-B2DvWUPa.mjs.map +1 -0
- package/dist/{index-BPJSBHhq.d.mts → index-CNuFQSNj.d.mts} +6 -4
- package/dist/{index-BPJSBHhq.d.mts.map → index-CNuFQSNj.d.mts.map} +1 -1
- package/dist/{index-C_t8VVQD.d.mts → index-uybm0bhQ.d.mts} +100 -6
- package/dist/index-uybm0bhQ.d.mts.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/{lazy-module-loader-DZQxOgRZ.d.mts → lazy-module-loader-M6YKudNL.d.mts} +2 -2
- package/dist/{lazy-module-loader-DZQxOgRZ.d.mts.map → lazy-module-loader-M6YKudNL.d.mts.map} +1 -1
- package/dist/{locale-path.service-DzA01Kvc.mjs → locale-path.service-CH0CaxwH.mjs} +3 -3
- package/dist/{locale-path.service-DzA01Kvc.mjs.map → locale-path.service-CH0CaxwH.mjs.map} +1 -1
- package/dist/{locale-url.service-DwTXZid3.mjs → locale-url.service-6bgia24_.mjs} +2 -2
- package/dist/{locale-url.service-DwTXZid3.mjs.map → locale-url.service-6bgia24_.mjs.map} +1 -1
- package/dist/logger/index.mjs +1 -1
- package/dist/module/index.d.mts +2 -2
- package/dist/module/index.mjs +2 -2
- package/dist/{module-registry-MfWmniZ7.mjs → module-registry-NxX5O0Qk.mjs} +4 -4
- package/dist/{module-registry-MfWmniZ7.mjs.map → module-registry-NxX5O0Qk.mjs.map} +1 -1
- package/dist/openapi/index.d.mts +2 -2
- package/dist/openapi/index.mjs +1 -1
- package/dist/{openapi-BKDwQKh-.mjs → openapi-CMwuCp31.mjs} +3 -3
- package/dist/{openapi-BKDwQKh-.mjs.map → openapi-CMwuCp31.mjs.map} +1 -1
- package/dist/{openapi.service-CM40bnBB.d.mts → openapi.service-2rvJBCEg.d.mts} +2 -2
- package/dist/{openapi.service-CM40bnBB.d.mts.map → openapi.service-2rvJBCEg.d.mts.map} +1 -1
- package/dist/quarry/index.d.mts +3 -3
- package/dist/quarry/index.mjs +1 -1
- package/dist/quarry/runner.d.mts +6 -6
- package/dist/quarry/runner.mjs +5 -5
- package/dist/{quarry-registry-CsStq0DB.d.mts → quarry-registry-DRnV-DDa.d.mts} +3 -3
- package/dist/{quarry-registry-CsStq0DB.d.mts.map → quarry-registry-DRnV-DDa.d.mts.map} +1 -1
- package/dist/{quarry.module-BOgcNJMU.mjs → quarry.module-CcGxU2dJ.mjs} +3 -3
- package/dist/{quarry.module-BOgcNJMU.mjs.map → quarry.module-CcGxU2dJ.mjs.map} +1 -1
- package/dist/queue/index.d.mts +1 -1
- package/dist/queue/index.mjs +2 -2
- package/dist/{queue.module-DSAH88gZ.mjs → queue.module-CEs4_kEM.mjs} +15 -8
- package/dist/{queue.module-DSAH88gZ.mjs.map → queue.module-CEs4_kEM.mjs.map} +1 -1
- package/dist/{r2-storage.provider-BJ4j23W6.mjs → r2-storage.provider-BoZmR6Ut.mjs} +2 -2
- package/dist/{r2-storage.provider-BJ4j23W6.mjs.map → r2-storage.provider-BoZmR6Ut.mjs.map} +1 -1
- package/dist/{rate-limit.decorator-B35jBEVD.mjs → rate-limit.decorator-Djs4oYDB.mjs} +2 -2
- package/dist/{rate-limit.decorator-B35jBEVD.mjs.map → rate-limit.decorator-Djs4oYDB.mjs.map} +1 -1
- package/dist/rate-limiter/index.d.mts +54 -47
- package/dist/rate-limiter/index.d.mts.map +1 -1
- package/dist/rate-limiter/index.mjs +16 -7
- package/dist/rate-limiter/index.mjs.map +1 -1
- package/dist/{route-registration.service-HN8WgIis.mjs → route-registration.service-CDPQKpm4.mjs} +9 -9
- package/dist/{route-registration.service-HN8WgIis.mjs.map → route-registration.service-CDPQKpm4.mjs.map} +1 -1
- package/dist/{route-registry-CtW26Suv.mjs → route-registry-BvLJisvK.mjs} +3 -3
- package/dist/{route-registry-CtW26Suv.mjs.map → route-registry-BvLJisvK.mjs.map} +1 -1
- package/dist/router/index.d.mts +2 -2
- package/dist/router/index.mjs +16 -16
- package/dist/{router-OCnf4VB6.mjs → router-DwyqEXgf.mjs} +13 -13
- package/dist/{router-OCnf4VB6.mjs.map → router-DwyqEXgf.mjs.map} +1 -1
- package/dist/{router-resolver-CMNuw-s0.mjs → router-resolver-sUV_jTrU.mjs} +2 -2
- package/dist/{router-resolver-CMNuw-s0.mjs.map → router-resolver-sUV_jTrU.mjs.map} +1 -1
- package/dist/seeder/index.d.mts +2 -2
- package/dist/seeder/index.mjs +3 -3
- package/dist/{seeder-DI-rUoZx.mjs → seeder-BPGY5rUb.mjs} +4 -4
- package/dist/{seeder-DI-rUoZx.mjs.map → seeder-BPGY5rUb.mjs.map} +1 -1
- package/dist/{seeder-registry-B5FwBeCU.mjs → seeder-registry-DEvCycsT.mjs} +3 -3
- package/dist/{seeder-registry-B5FwBeCU.mjs.map → seeder-registry-DEvCycsT.mjs.map} +1 -1
- package/dist/{seeder.module-DaY0RYoB.mjs → seeder.module-CIwQbdN4.mjs} +2 -2
- package/dist/{seeder.module-DaY0RYoB.mjs.map → seeder.module-CIwQbdN4.mjs.map} +1 -1
- package/dist/storage/index.d.mts +1 -1
- package/dist/storage/index.mjs +2 -2
- package/dist/storage/providers/index.mjs +1 -1
- package/dist/{storage-BE6-kzaN.mjs → storage-C30X81CS.mjs} +7 -7
- package/dist/{storage-BE6-kzaN.mjs.map → storage-C30X81CS.mjs.map} +1 -1
- package/dist/{storage.error-Dai3rShJ.mjs → storage.error-BStXPmO4.mjs} +2 -2
- package/dist/{storage.error-Dai3rShJ.mjs.map → storage.error-BStXPmO4.mjs.map} +1 -1
- package/dist/{stratal-DtAj21uF.mjs → stratal-BL6FKUM_.mjs} +84 -35
- package/dist/stratal-BL6FKUM_.mjs.map +1 -0
- package/dist/{stratal-Bmc6WT3k.d.mts → stratal-D5j_I14G.d.mts} +13 -3
- package/dist/stratal-D5j_I14G.d.mts.map +1 -0
- package/dist/trailing-slash-2SctvePW.mjs +80 -0
- package/dist/trailing-slash-2SctvePW.mjs.map +1 -0
- package/dist/{uri-h6ITRpqr.mjs → uri-iwofWJ_T.mjs} +12 -10
- package/dist/uri-iwofWJ_T.mjs.map +1 -0
- package/dist/{versioning.service-B4rtmgMQ.mjs → versioning.service-CCa2oYMJ.mjs} +3 -3
- package/dist/{versioning.service-B4rtmgMQ.mjs.map → versioning.service-CCa2oYMJ.mjs.map} +1 -1
- package/dist/websocket/index.d.mts +1 -1
- package/dist/websocket/index.mjs +1 -1
- package/dist/workers/index.d.mts +1 -1
- package/dist/workers/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/di-B0NXIdRF.mjs.map +0 -1
- package/dist/errors-EUtwVfNm.mjs.map +0 -1
- package/dist/hono-app-C7-1m9eK.mjs.map +0 -1
- package/dist/i18n.module-JOPUNpvi.mjs.map +0 -1
- package/dist/index-C_t8VVQD.d.mts.map +0 -1
- package/dist/stratal-Bmc6WT3k.d.mts.map +0 -1
- package/dist/stratal-DtAj21uF.mjs.map +0 -1
- package/dist/trailing-slash-CFyw8nYu.mjs +0 -34
- package/dist/trailing-slash-CFyw8nYu.mjs.map +0 -1
- package/dist/uri-h6ITRpqr.mjs.map +0 -1
package/dist/bin/quarry.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --no-warnings
|
|
2
2
|
import { createRequire, register } from "node:module";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
|
-
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { dirname, join, parse, resolve } from "node:path";
|
|
5
5
|
import { URL, pathToFileURL } from "node:url";
|
|
6
6
|
import { Command, Option } from "clipanion";
|
|
7
7
|
//#region src/bin/argv.ts
|
|
@@ -92,6 +92,59 @@ function createDynamicCommands(quarry, parseSignature, app) {
|
|
|
92
92
|
return commands;
|
|
93
93
|
}
|
|
94
94
|
//#endregion
|
|
95
|
+
//#region src/bin/registry.ts
|
|
96
|
+
const LOCKFILES = [
|
|
97
|
+
"yarn.lock",
|
|
98
|
+
"package-lock.json",
|
|
99
|
+
"pnpm-lock.yaml",
|
|
100
|
+
"bun.lock",
|
|
101
|
+
"bun.lockb"
|
|
102
|
+
];
|
|
103
|
+
/**
|
|
104
|
+
* Walk up from `startDir` to the project root.
|
|
105
|
+
*
|
|
106
|
+
* The root is the nearest ancestor containing a package-manager lockfile —
|
|
107
|
+
* lockfiles exist only at install roots, so the marker is immune to nested
|
|
108
|
+
* workspace `package.json`s and to stray `.git` directories tools sometimes
|
|
109
|
+
* leave behind. When no lockfile exists (e.g. a project before its first
|
|
110
|
+
* install), the outermost ancestor containing a `package.json` is used —
|
|
111
|
+
* every project has one, monorepo or not, git or not.
|
|
112
|
+
*
|
|
113
|
+
* Returns `undefined` when neither marker is found.
|
|
114
|
+
*/
|
|
115
|
+
function findProjectRoot(startDir) {
|
|
116
|
+
let dir = resolve(startDir);
|
|
117
|
+
const { root } = parse(dir);
|
|
118
|
+
let outermostPackageJson;
|
|
119
|
+
while (true) {
|
|
120
|
+
if (LOCKFILES.some((lockfile) => existsSync(join(dir, lockfile)))) return dir;
|
|
121
|
+
if (existsSync(join(dir, "package.json"))) outermostPackageJson = dir;
|
|
122
|
+
if (dir === root) return outermostPackageJson;
|
|
123
|
+
dir = dirname(dir);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Resolve the Miniflare dev-registry path for a quarry run.
|
|
128
|
+
*
|
|
129
|
+
* Precedence:
|
|
130
|
+
* 1. an explicit `MINIFLARE_REGISTRY_PATH` (the variable Miniflare actually
|
|
131
|
+
* reads) or `WRANGLER_REGISTRY_PATH` (the variable `wrangler dev` reads —
|
|
132
|
+
* honoured here too so one override redirects every tool the same way)
|
|
133
|
+
* 2. `<projectRoot>/.wrangler/registry` (see `findProjectRoot`) — so every
|
|
134
|
+
* process in a checkout (dev servers, quarry CLI runs) deterministically
|
|
135
|
+
* shares one registry, and parallel checkouts (git worktrees) each get
|
|
136
|
+
* their own.
|
|
137
|
+
*
|
|
138
|
+
* The global `~/.wrangler/registry` is deliberately never used: a registry
|
|
139
|
+
* shared across checkouts lets identically-named workers from parallel dev
|
|
140
|
+
* environments overwrite each other and breaks service-binding resolution.
|
|
141
|
+
*/
|
|
142
|
+
function resolveDevRegistryPath(env, cwd) {
|
|
143
|
+
const explicit = env.MINIFLARE_REGISTRY_PATH ?? env.WRANGLER_REGISTRY_PATH;
|
|
144
|
+
if (explicit) return explicit;
|
|
145
|
+
return join(findProjectRoot(cwd) ?? cwd, ".wrangler", "registry");
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
95
148
|
//#region src/bin/quarry.ts
|
|
96
149
|
const require = createRequire(import.meta.url);
|
|
97
150
|
register(pathToFileURL(join(dirname(require.resolve("@swc-node/register")), "esm/esm.mjs")), pathToFileURL("./"));
|
|
@@ -123,7 +176,7 @@ if (!existsSync(entryPath)) {
|
|
|
123
176
|
async function main() {
|
|
124
177
|
const cwdRequire = createRequire(join(process.cwd(), "package.json"));
|
|
125
178
|
const { unstable_readConfig: readConfig, unstable_getMiniflareWorkerOptions: getMiniflareWorkerOptions, unstable_getVarsForDev: getVarsForDev } = await import(cwdRequire.resolve("wrangler"));
|
|
126
|
-
const { Miniflare
|
|
179
|
+
const { Miniflare } = await import(cwdRequire.resolve("miniflare"));
|
|
127
180
|
const configName = [
|
|
128
181
|
"wrangler.jsonc",
|
|
129
182
|
"wrangler.json",
|
|
@@ -141,7 +194,11 @@ async function main() {
|
|
|
141
194
|
const envPath = resolve(process.cwd(), envFile);
|
|
142
195
|
if (existsSync(envPath)) process.loadEnvFile(envPath);
|
|
143
196
|
}
|
|
144
|
-
|
|
197
|
+
const registryPath = resolveDevRegistryPath({
|
|
198
|
+
MINIFLARE_REGISTRY_PATH: process.env.MINIFLARE_REGISTRY_PATH,
|
|
199
|
+
WRANGLER_REGISTRY_PATH: process.env.WRANGLER_REGISTRY_PATH
|
|
200
|
+
}, process.cwd());
|
|
201
|
+
process.env.MINIFLARE_REGISTRY_PATH = registryPath;
|
|
145
202
|
const config = readConfig({
|
|
146
203
|
config: configPath,
|
|
147
204
|
env: environment
|
|
@@ -156,7 +213,6 @@ async function main() {
|
|
|
156
213
|
QUEUE_PROVIDER: "sync"
|
|
157
214
|
};
|
|
158
215
|
workerOptions.name = config.name ? `quarry-${config.name}-${process.pid}` : `quarry-${process.pid}`;
|
|
159
|
-
const registryPath = getDefaultDevRegistryPath();
|
|
160
216
|
const mf = new Miniflare({
|
|
161
217
|
...workerOptions,
|
|
162
218
|
script: "",
|
package/dist/bin/quarry.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quarry.mjs","names":[],"sources":["../../src/bin/argv.ts","../../src/bin/commands/dynamic-command.ts","../../src/bin/quarry.ts"],"sourcesContent":["export function extractEnvFlag(argv: string[]): { env: string | undefined; rest: string[] } {\n let env: string | undefined\n const rest: string[] = []\n for (let i = 0; i < argv.length; i++) {\n const tok = argv[i]\n if (tok === '--') {\n rest.push(...argv.slice(i))\n break\n }\n const eqMatch = tok.match(/^(?:--env|-e)=(.*)$/)\n if (eqMatch) {\n if (!eqMatch[1]) throw new Error('--env requires a value (e.g. --env staging)')\n if (env !== undefined) throw new Error('--env specified more than once')\n env = eqMatch[1]\n continue\n }\n if (tok === '--env' || tok === '-e') {\n const next = argv[i + 1]\n if (!next || next.startsWith('-')) throw new Error('--env requires a value (e.g. --env staging)')\n if (env !== undefined) throw new Error('--env specified more than once')\n env = next\n i++\n continue\n }\n rest.push(tok)\n }\n return { env, rest }\n}\n","import { Command, type CommandClass, Option, type Usage } from 'clipanion'\n\nimport type { Application } from 'stratal'\nimport type { ParsedSignature, QuarryRegistry } from 'stratal/quarry'\n\n/** Create Clipanion command classes from Quarry-registered commands. */\nexport function createDynamicCommands(\n quarry: QuarryRegistry,\n parseSignature: (command: string) => ParsedSignature,\n app: Application,\n) {\n const commands: CommandClass[] = []\n\n for (const entry of quarry.list()) {\n const commandClass = quarry.get(entry.name)! as unknown as { command: string; description?: string; aliases?: string[] }\n const signature = parseSignature(commandClass.command)\n\n const paths: string[][] = [entry.name.split(' ')]\n if (commandClass.aliases) {\n for (const alias of commandClass.aliases) {\n paths.push(alias.split(' '))\n }\n }\n\n // Allow bare `npx quarry` (no arguments) to invoke the help command\n if (entry.name === 'help') {\n paths.push([])\n }\n\n class DynCmd extends Command {\n static override paths = paths\n static override usage: Usage | undefined = commandClass.description\n ? Command.Usage({ description: commandClass.description })\n : undefined\n\n async execute(): Promise<number> {\n const input: Record<string, unknown> = {}\n\n for (const arg of signature.arguments) {\n const value = (this as Record<string, unknown>)[arg.name]\n if (value !== undefined) input[arg.name] = value\n }\n\n for (const opt of signature.options) {\n const value = (this as Record<string, unknown>)[opt.name]\n if (value !== undefined) input[opt.name] = value\n }\n\n const result = await app.handleCommand(entry.name, input)\n\n for (const line of result.output) {\n this.context.stdout.write(line + '\\n')\n }\n\n for (const err of result.errors) {\n this.context.stderr.write(err + '\\n')\n }\n\n return result.exitCode\n }\n }\n\n // Define Clipanion options/arguments as class property defaults\n const proto = DynCmd.prototype as unknown as Record<string, unknown>\n for (const arg of signature.arguments) {\n if (arg.isArray) {\n proto[arg.name] = Option.Rest({ name: arg.name, required: arg.required ? 1 : 0 })\n } else {\n proto[arg.name] = Option.String({ name: arg.name, required: arg.required })\n }\n }\n\n for (const opt of signature.options) {\n const optName = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n const optDescParts: string[] = []\n if (opt.description) optDescParts.push(opt.description)\n if (opt.default !== undefined) optDescParts.push(`(default: ${opt.default})`)\n const optDesc = optDescParts.length > 0 ? optDescParts.join(' ') : undefined\n\n if (opt.isFlag) {\n proto[opt.name] = Option.Boolean(optName, { description: optDesc })\n } else if (opt.isArray) {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.Array(optName, [opt.default], { description: optDesc })\n } else {\n proto[opt.name] = Option.Array(optName, { description: optDesc })\n }\n } else {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.String(optName, opt.default, { description: optDesc })\n } else {\n proto[opt.name] = Option.String(optName, { description: optDesc })\n }\n }\n }\n\n commands.push(DynCmd)\n }\n\n return commands\n}\n","import type { MiniflareOptions } from 'miniflare';\nimport { existsSync } from 'node:fs';\nimport { createRequire, register } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { URL, pathToFileURL } from 'node:url';\nimport type { QuarryRegistry } from 'stratal/quarry';\nimport { type Application } from '../application';\nimport { extractEnvFlag } from './argv';\nimport { createDynamicCommands } from './commands/dynamic-command';\n\ninterface WranglerConfig {\n name?: string\n vars?: Record<string, unknown>\n}\n\ninterface MiniflareWorkerResult {\n workerOptions: Record<string, unknown>\n}\n\ninterface WranglerModule {\n unstable_readConfig: (args: { config?: string; env?: string }) => WranglerConfig\n unstable_getMiniflareWorkerOptions: (config: WranglerConfig, env?: string) => MiniflareWorkerResult\n unstable_getVarsForDev: (configPath: string | undefined, envFiles: undefined, vars: unknown, env: string | undefined) => Record<string, { value: string }>\n}\n\ninterface MiniflareModule {\n Miniflare: new (opts: MiniflareOptions) => { ready: Promise<URL>; getBindings: (name?: string) => Promise<Record<string, unknown>>; dispose: () => Promise<void> }\n getDefaultDevRegistryPath: () => string\n}\n\nconst require = createRequire(import.meta.url)\n\n// Register @swc-node/register for TypeScript + decorator support\nconst swcRegisterPath = join(dirname(require.resolve('@swc-node/register')), 'esm/esm.mjs')\nregister(pathToFileURL(swcRegisterPath), pathToFileURL('./'))\n\n// Register cloudflare:workers virtual module loader\nregister(new URL('./cloudflare-workers-loader.mjs', import.meta.url), pathToFileURL('./'))\n\nconst DEFAULT_ENTRY = './src/quarry.ts'\n\nlet environment: string | undefined\ntry {\n const parsed = extractEnvFlag(process.argv.slice(2))\n environment = parsed.env\n process.argv.splice(2, process.argv.length - 2, ...parsed.rest)\n} catch (e) {\n console.error(`Error: ${(e as Error).message}`)\n process.exit(1)\n}\n\n// Determine entry file: if first arg looks like a file path, use it; otherwise use default\nconst firstArg = process.argv[2]\nlet entryFile = DEFAULT_ENTRY\n\nif (firstArg && (firstArg.includes('/') || firstArg.includes('\\\\') || /\\.(ts|js|mts|mjs)$/.test(firstArg))) {\n entryFile = firstArg\n // Remove the entry file from argv so Clipanion sees: [node, script, command, ...options]\n process.argv.splice(2, 1)\n}\n\n// Resolve and validate the entry file\nconst entryPath = resolve(process.cwd(), entryFile)\n\nif (!existsSync(entryPath)) {\n console.error(`Error: Entry file not found: ${entryFile}`)\n console.error('')\n console.error('Create src/quarry.ts that exports `QuarryRunner.run({ module, seeders })`, or specify a custom path:')\n console.error(' npx quarry ./path/to/entry.ts <command> [options]')\n process.exit(1)\n}\n\nasync function main(): Promise<void> {\n const cwdRequire = createRequire(join(process.cwd(), 'package.json'))\n\n const { unstable_readConfig: readConfig, unstable_getMiniflareWorkerOptions: getMiniflareWorkerOptions, unstable_getVarsForDev: getVarsForDev } = await import(cwdRequire.resolve('wrangler')) as WranglerModule\n const { Miniflare, getDefaultDevRegistryPath } = await import(cwdRequire.resolve('miniflare')) as MiniflareModule\n\n const candidates = ['wrangler.jsonc', 'wrangler.json', 'wrangler.toml']\n const configName = candidates.find(c => existsSync(resolve(process.cwd(), c)))\n const configPath = configName ? resolve(process.cwd(), configName) : undefined\n\n // Load .env into process.env before building Miniflare options, mirroring\n // `wrangler dev`'s precedence: base `.env`, then `.env.local`, then the\n // env-specific `.env.<environment>` and `.env.<environment>.local` (later\n // load wins).\n const envFiles = [\n '.env',\n '.env.local',\n environment ? `.env.${environment}` : null,\n environment ? `.env.${environment}.local` : null,\n ]\n for (const envFile of envFiles) {\n if (!envFile) continue\n const envPath = resolve(process.cwd(), envFile)\n if (existsSync(envPath)) process.loadEnvFile(envPath)\n }\n\n // Bridge the documented `WRANGLER_REGISTRY_PATH` to `MINIFLARE_REGISTRY_PATH`,\n // the variable Miniflare's `getDefaultDevRegistryPath()` actually reads.\n // `wrangler dev` performs the same translation internally; mirroring it here\n // lets a single documented env var redirect the dev service registry for BOTH\n // this CLI's Miniflare (below) AND any vite dev server a command launches\n // (`@cloudflare/vite-plugin` also resolves its registry via\n // `getDefaultDevRegistryPath()`). That allows several isolated dev environments\n // to run in parallel without sharing the global `~/.wrangler/registry`, where\n // their identically-named workers would otherwise overwrite each other and\n // break cross-worker service-binding resolution. Only set when unset so an\n // explicit override still wins.\n if (process.env.WRANGLER_REGISTRY_PATH && !process.env.MINIFLARE_REGISTRY_PATH) {\n process.env.MINIFLARE_REGISTRY_PATH = process.env.WRANGLER_REGISTRY_PATH\n }\n\n const config = readConfig({ config: configPath, env: environment })\n const { workerOptions } = getMiniflareWorkerOptions(config, environment)\n\n const vars = getVarsForDev(configPath, undefined, config.vars, environment)\n const varsRecord: Record<string, string> = {}\n for (const [key, binding] of Object.entries(vars)) {\n varsRecord[key] = binding.value\n }\n\n const existingBindings = workerOptions.bindings as Record<string, unknown> ?? {}\n workerOptions.bindings = {\n ...existingBindings,\n ...varsRecord,\n QUEUE_PROVIDER: 'sync',\n }\n\n // Rename so quarry doesn't overwrite a running `wrangler dev` session's\n // dev-registry entry. The registry is how Miniflare discovers peer workers\n // for service binding resolution — a collision would break the running session.\n const workerName = config.name ? `quarry-${config.name}-${process.pid}` : `quarry-${process.pid}`\n workerOptions.name = workerName\n\n // Resolve the dev-registry path so Miniflare can discover running\n // `wrangler dev` sessions for service binding resolution.\n const registryPath = getDefaultDevRegistryPath()\n\n const mf = new Miniflare({\n ...workerOptions,\n script: '',\n modules: true,\n unsafeDevRegistryPath: registryPath,\n // Persist every durable plugin (KV, D1, R2, Durable Objects, cache) under\n // the same root `wrangler dev` uses, so state survives across `quarry`\n // invocations and is shared with a running `wrangler dev` session.\n defaultPersistRoot: join(process.cwd(), '.wrangler/state/v3'),\n })\n\n await mf.ready\n const env = await mf.getBindings()\n\n const pendingPromises: Promise<unknown>[] = []\n const trackedWaitUntil = (promise: Promise<unknown>) => {\n pendingPromises.push(promise)\n }\n\n let app: Application | undefined\n try {\n (globalThis as Record<string, unknown>).__stratalPlatformProxy = {\n env,\n waitUntil: trackedWaitUntil,\n }\n\n await import(pathToFileURL(entryPath).href)\n\n const [\n { Stratal },\n { DI_TOKENS },\n { parseSignature },\n ] = await Promise.all([\n import('stratal'),\n import('stratal/di'),\n import('stratal/quarry'),\n ])\n\n app = await Stratal.resolveApplication()\n const quarry = app.container.resolve<QuarryRegistry>(DI_TOKENS.Quarry)\n\n const { Cli } = await import('clipanion')\n const pkg = require('../../package.json') as { version: string }\n\n const cli = new Cli({\n binaryName: 'quarry',\n binaryLabel: 'Quarry CLI',\n binaryVersion: pkg.version,\n })\n\n for (const cmd of createDynamicCommands(quarry, parseSignature, app)) {\n cli.register(cmd)\n }\n\n await cli.runExit(process.argv.slice(2), { ...Cli.defaultContext })\n } finally {\n await Promise.allSettled(pendingPromises)\n await app?.shutdown()\n await mf.dispose()\n }\n}\n\nmain().catch(async (error: unknown) => {\n const { ConfigValidationError } = await import('stratal/config')\n\n const message = error instanceof Error ? error.message : String(error)\n console.error('Fatal error:', message)\n if (error instanceof ConfigValidationError) {\n console.error(error.errors.message)\n }\n process.exit(1)\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"quarry.mjs","names":[],"sources":["../../src/bin/argv.ts","../../src/bin/commands/dynamic-command.ts","../../src/bin/registry.ts","../../src/bin/quarry.ts"],"sourcesContent":["export function extractEnvFlag(argv: string[]): { env: string | undefined; rest: string[] } {\n let env: string | undefined\n const rest: string[] = []\n for (let i = 0; i < argv.length; i++) {\n const tok = argv[i]\n if (tok === '--') {\n rest.push(...argv.slice(i))\n break\n }\n const eqMatch = tok.match(/^(?:--env|-e)=(.*)$/)\n if (eqMatch) {\n if (!eqMatch[1]) throw new Error('--env requires a value (e.g. --env staging)')\n if (env !== undefined) throw new Error('--env specified more than once')\n env = eqMatch[1]\n continue\n }\n if (tok === '--env' || tok === '-e') {\n const next = argv[i + 1]\n if (!next || next.startsWith('-')) throw new Error('--env requires a value (e.g. --env staging)')\n if (env !== undefined) throw new Error('--env specified more than once')\n env = next\n i++\n continue\n }\n rest.push(tok)\n }\n return { env, rest }\n}\n","import { Command, type CommandClass, Option, type Usage } from 'clipanion'\n\nimport type { Application } from 'stratal'\nimport type { ParsedSignature, QuarryRegistry } from 'stratal/quarry'\n\n/** Create Clipanion command classes from Quarry-registered commands. */\nexport function createDynamicCommands(\n quarry: QuarryRegistry,\n parseSignature: (command: string) => ParsedSignature,\n app: Application,\n) {\n const commands: CommandClass[] = []\n\n for (const entry of quarry.list()) {\n const commandClass = quarry.get(entry.name)! as unknown as { command: string; description?: string; aliases?: string[] }\n const signature = parseSignature(commandClass.command)\n\n const paths: string[][] = [entry.name.split(' ')]\n if (commandClass.aliases) {\n for (const alias of commandClass.aliases) {\n paths.push(alias.split(' '))\n }\n }\n\n // Allow bare `npx quarry` (no arguments) to invoke the help command\n if (entry.name === 'help') {\n paths.push([])\n }\n\n class DynCmd extends Command {\n static override paths = paths\n static override usage: Usage | undefined = commandClass.description\n ? Command.Usage({ description: commandClass.description })\n : undefined\n\n async execute(): Promise<number> {\n const input: Record<string, unknown> = {}\n\n for (const arg of signature.arguments) {\n const value = (this as Record<string, unknown>)[arg.name]\n if (value !== undefined) input[arg.name] = value\n }\n\n for (const opt of signature.options) {\n const value = (this as Record<string, unknown>)[opt.name]\n if (value !== undefined) input[opt.name] = value\n }\n\n const result = await app.handleCommand(entry.name, input)\n\n for (const line of result.output) {\n this.context.stdout.write(line + '\\n')\n }\n\n for (const err of result.errors) {\n this.context.stderr.write(err + '\\n')\n }\n\n return result.exitCode\n }\n }\n\n // Define Clipanion options/arguments as class property defaults\n const proto = DynCmd.prototype as unknown as Record<string, unknown>\n for (const arg of signature.arguments) {\n if (arg.isArray) {\n proto[arg.name] = Option.Rest({ name: arg.name, required: arg.required ? 1 : 0 })\n } else {\n proto[arg.name] = Option.String({ name: arg.name, required: arg.required })\n }\n }\n\n for (const opt of signature.options) {\n const optName = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n const optDescParts: string[] = []\n if (opt.description) optDescParts.push(opt.description)\n if (opt.default !== undefined) optDescParts.push(`(default: ${opt.default})`)\n const optDesc = optDescParts.length > 0 ? optDescParts.join(' ') : undefined\n\n if (opt.isFlag) {\n proto[opt.name] = Option.Boolean(optName, { description: optDesc })\n } else if (opt.isArray) {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.Array(optName, [opt.default], { description: optDesc })\n } else {\n proto[opt.name] = Option.Array(optName, { description: optDesc })\n }\n } else {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.String(optName, opt.default, { description: optDesc })\n } else {\n proto[opt.name] = Option.String(optName, { description: optDesc })\n }\n }\n }\n\n commands.push(DynCmd)\n }\n\n return commands\n}\n","import { existsSync } from 'node:fs'\nimport { dirname, join, parse, resolve } from 'node:path'\n\nconst LOCKFILES = [\n 'yarn.lock',\n 'package-lock.json',\n 'pnpm-lock.yaml',\n 'bun.lock',\n 'bun.lockb',\n]\n\n/**\n * Walk up from `startDir` to the project root.\n *\n * The root is the nearest ancestor containing a package-manager lockfile —\n * lockfiles exist only at install roots, so the marker is immune to nested\n * workspace `package.json`s and to stray `.git` directories tools sometimes\n * leave behind. When no lockfile exists (e.g. a project before its first\n * install), the outermost ancestor containing a `package.json` is used —\n * every project has one, monorepo or not, git or not.\n *\n * Returns `undefined` when neither marker is found.\n */\nexport function findProjectRoot(startDir: string): string | undefined {\n // A relative `startDir` would never equal its parsed root (`''`) — `dirname`\n // converges to `'.'` and the walk never terminates. Resolve up front so the\n // traversal (and the returned path) is always absolute.\n let dir = resolve(startDir)\n const { root } = parse(dir)\n let outermostPackageJson: string | undefined\n while (true) {\n if (LOCKFILES.some(lockfile => existsSync(join(dir, lockfile)))) return dir\n if (existsSync(join(dir, 'package.json'))) outermostPackageJson = dir\n if (dir === root) return outermostPackageJson\n dir = dirname(dir)\n }\n}\n\nexport interface DevRegistryEnv {\n MINIFLARE_REGISTRY_PATH?: string\n WRANGLER_REGISTRY_PATH?: string\n}\n\n/**\n * Resolve the Miniflare dev-registry path for a quarry run.\n *\n * Precedence:\n * 1. an explicit `MINIFLARE_REGISTRY_PATH` (the variable Miniflare actually\n * reads) or `WRANGLER_REGISTRY_PATH` (the variable `wrangler dev` reads —\n * honoured here too so one override redirects every tool the same way)\n * 2. `<projectRoot>/.wrangler/registry` (see `findProjectRoot`) — so every\n * process in a checkout (dev servers, quarry CLI runs) deterministically\n * shares one registry, and parallel checkouts (git worktrees) each get\n * their own.\n *\n * The global `~/.wrangler/registry` is deliberately never used: a registry\n * shared across checkouts lets identically-named workers from parallel dev\n * environments overwrite each other and breaks service-binding resolution.\n */\nexport function resolveDevRegistryPath(env: DevRegistryEnv, cwd: string): string {\n const explicit = env.MINIFLARE_REGISTRY_PATH ?? env.WRANGLER_REGISTRY_PATH\n if (explicit) return explicit\n return join(findProjectRoot(cwd) ?? cwd, '.wrangler', 'registry')\n}\n","import type { MiniflareOptions } from 'miniflare';\nimport { existsSync } from 'node:fs';\nimport { createRequire, register } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { URL, pathToFileURL } from 'node:url';\nimport type { QuarryRegistry } from 'stratal/quarry';\nimport { type Application } from '../application';\nimport { extractEnvFlag } from './argv';\nimport { createDynamicCommands } from './commands/dynamic-command';\nimport { resolveDevRegistryPath } from './registry';\n\ninterface WranglerConfig {\n name?: string\n vars?: Record<string, unknown>\n}\n\ninterface MiniflareWorkerResult {\n workerOptions: Record<string, unknown>\n}\n\ninterface WranglerModule {\n unstable_readConfig: (args: { config?: string; env?: string }) => WranglerConfig\n unstable_getMiniflareWorkerOptions: (config: WranglerConfig, env?: string) => MiniflareWorkerResult\n unstable_getVarsForDev: (configPath: string | undefined, envFiles: undefined, vars: unknown, env: string | undefined) => Record<string, { value: string }>\n}\n\ninterface MiniflareModule {\n Miniflare: new (opts: MiniflareOptions) => { ready: Promise<URL>; getBindings: (name?: string) => Promise<Record<string, unknown>>; dispose: () => Promise<void> }\n}\n\nconst require = createRequire(import.meta.url)\n\n// Register @swc-node/register for TypeScript + decorator support\nconst swcRegisterPath = join(dirname(require.resolve('@swc-node/register')), 'esm/esm.mjs')\nregister(pathToFileURL(swcRegisterPath), pathToFileURL('./'))\n\n// Register cloudflare:workers virtual module loader\nregister(new URL('./cloudflare-workers-loader.mjs', import.meta.url), pathToFileURL('./'))\n\nconst DEFAULT_ENTRY = './src/quarry.ts'\n\nlet environment: string | undefined\ntry {\n const parsed = extractEnvFlag(process.argv.slice(2))\n environment = parsed.env\n process.argv.splice(2, process.argv.length - 2, ...parsed.rest)\n} catch (e) {\n console.error(`Error: ${(e as Error).message}`)\n process.exit(1)\n}\n\n// Determine entry file: if first arg looks like a file path, use it; otherwise use default\nconst firstArg = process.argv[2]\nlet entryFile = DEFAULT_ENTRY\n\nif (firstArg && (firstArg.includes('/') || firstArg.includes('\\\\') || /\\.(ts|js|mts|mjs)$/.test(firstArg))) {\n entryFile = firstArg\n // Remove the entry file from argv so Clipanion sees: [node, script, command, ...options]\n process.argv.splice(2, 1)\n}\n\n// Resolve and validate the entry file\nconst entryPath = resolve(process.cwd(), entryFile)\n\nif (!existsSync(entryPath)) {\n console.error(`Error: Entry file not found: ${entryFile}`)\n console.error('')\n console.error('Create src/quarry.ts that exports `QuarryRunner.run({ module, seeders })`, or specify a custom path:')\n console.error(' npx quarry ./path/to/entry.ts <command> [options]')\n process.exit(1)\n}\n\nasync function main(): Promise<void> {\n const cwdRequire = createRequire(join(process.cwd(), 'package.json'))\n\n const { unstable_readConfig: readConfig, unstable_getMiniflareWorkerOptions: getMiniflareWorkerOptions, unstable_getVarsForDev: getVarsForDev } = await import(cwdRequire.resolve('wrangler')) as WranglerModule\n const { Miniflare } = await import(cwdRequire.resolve('miniflare')) as MiniflareModule\n\n const candidates = ['wrangler.jsonc', 'wrangler.json', 'wrangler.toml']\n const configName = candidates.find(c => existsSync(resolve(process.cwd(), c)))\n const configPath = configName ? resolve(process.cwd(), configName) : undefined\n\n // Load .env into process.env before building Miniflare options, mirroring\n // `wrangler dev`'s precedence: base `.env`, then `.env.local`, then the\n // env-specific `.env.<environment>` and `.env.<environment>.local` (later\n // load wins).\n const envFiles = [\n '.env',\n '.env.local',\n environment ? `.env.${environment}` : null,\n environment ? `.env.${environment}.local` : null,\n ]\n for (const envFile of envFiles) {\n if (!envFile) continue\n const envPath = resolve(process.cwd(), envFile)\n if (existsSync(envPath)) process.loadEnvFile(envPath)\n }\n\n // Deterministically resolve the dev service registry from the project root\n // (`<projectRoot>/.wrangler/registry`) so a bare `quarry` invocation shares\n // the SAME project-local registry every other process in this checkout uses —\n // never the global `~/.wrangler/registry`, where parallel checkouts'\n // identically-named workers would overwrite each other and break cross-worker\n // service-binding resolution. An explicit `WRANGLER_REGISTRY_PATH` /\n // `MINIFLARE_REGISTRY_PATH` (from the shell or the `.env` files above) wins.\n //\n // Exported as `MINIFLARE_REGISTRY_PATH` — the variable Miniflare's\n // `getDefaultDevRegistryPath()` reads at call time — so any child process a\n // command spawns (notably the vite dev server launched by `inertia:dev`,\n // whose `@cloudflare/vite-plugin` resolves its registry the same way) lands\n // in the identical registry.\n const registryPath = resolveDevRegistryPath({\n MINIFLARE_REGISTRY_PATH: process.env.MINIFLARE_REGISTRY_PATH,\n WRANGLER_REGISTRY_PATH: process.env.WRANGLER_REGISTRY_PATH,\n }, process.cwd())\n process.env.MINIFLARE_REGISTRY_PATH = registryPath\n\n const config = readConfig({ config: configPath, env: environment })\n const { workerOptions } = getMiniflareWorkerOptions(config, environment)\n\n const vars = getVarsForDev(configPath, undefined, config.vars, environment)\n const varsRecord: Record<string, string> = {}\n for (const [key, binding] of Object.entries(vars)) {\n varsRecord[key] = binding.value\n }\n\n const existingBindings = workerOptions.bindings as Record<string, unknown> ?? {}\n workerOptions.bindings = {\n ...existingBindings,\n ...varsRecord,\n QUEUE_PROVIDER: 'sync',\n }\n\n // Rename so quarry doesn't overwrite a running `wrangler dev` session's\n // dev-registry entry. The registry is how Miniflare discovers peer workers\n // for service binding resolution — a collision would break the running session.\n const workerName = config.name ? `quarry-${config.name}-${process.pid}` : `quarry-${process.pid}`\n workerOptions.name = workerName\n\n const mf = new Miniflare({\n ...workerOptions,\n script: '',\n modules: true,\n unsafeDevRegistryPath: registryPath,\n // Persist every durable plugin (KV, D1, R2, Durable Objects, cache) under\n // the same root `wrangler dev` uses, so state survives across `quarry`\n // invocations and is shared with a running `wrangler dev` session.\n defaultPersistRoot: join(process.cwd(), '.wrangler/state/v3'),\n })\n\n await mf.ready\n const env = await mf.getBindings()\n\n const pendingPromises: Promise<unknown>[] = []\n const trackedWaitUntil = (promise: Promise<unknown>) => {\n pendingPromises.push(promise)\n }\n\n let app: Application | undefined\n try {\n (globalThis as Record<string, unknown>).__stratalPlatformProxy = {\n env,\n waitUntil: trackedWaitUntil,\n }\n\n await import(pathToFileURL(entryPath).href)\n\n const [\n { Stratal },\n { DI_TOKENS },\n { parseSignature },\n ] = await Promise.all([\n import('stratal'),\n import('stratal/di'),\n import('stratal/quarry'),\n ])\n\n app = await Stratal.resolveApplication()\n const quarry = app.container.resolve<QuarryRegistry>(DI_TOKENS.Quarry)\n\n const { Cli } = await import('clipanion')\n const pkg = require('../../package.json') as { version: string }\n\n const cli = new Cli({\n binaryName: 'quarry',\n binaryLabel: 'Quarry CLI',\n binaryVersion: pkg.version,\n })\n\n for (const cmd of createDynamicCommands(quarry, parseSignature, app)) {\n cli.register(cmd)\n }\n\n await cli.runExit(process.argv.slice(2), { ...Cli.defaultContext })\n } finally {\n await Promise.allSettled(pendingPromises)\n await app?.shutdown()\n await mf.dispose()\n }\n}\n\nmain().catch(async (error: unknown) => {\n const { ConfigValidationError } = await import('stratal/config')\n\n const message = error instanceof Error ? error.message : String(error)\n console.error('Fatal error:', message)\n if (error instanceof ConfigValidationError) {\n console.error(error.errors.message)\n }\n process.exit(1)\n})\n"],"mappings":"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"}
|
package/dist/cache/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ir as ApplicationError } from "../index-uybm0bhQ.mjs";
|
|
2
2
|
import { t as CacheService } from "../cache.service-uElmBtdS.mjs";
|
|
3
3
|
import { t as TieredCacheService } from "../tiered-cache.service-Dv3BhxxE.mjs";
|
|
4
4
|
|
package/dist/cache/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { l as Singleton, p as inject, r as DI_TOKENS } from "../di-D7qmrAir.mjs";
|
|
2
2
|
import { a as ApplicationError } from "../container-storage-BmOJ4_Na.mjs";
|
|
3
3
|
import { n as __decorateParam, t as __decorate } from "../decorate-CuAoSZvs.mjs";
|
|
4
4
|
import { LOGGER_TOKENS } from "../logger/index.mjs";
|
|
5
|
-
import "../errors-
|
|
5
|
+
import "../errors-C01O2T-n.mjs";
|
|
6
6
|
import { n as Module } from "../module.decorator-CYHY6pG5.mjs";
|
|
7
7
|
import "../module/index.mjs";
|
|
8
8
|
//#region src/cache/cache.error.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dn as CommandInternals, En as CommandInput, On as CommandResult } from "./index-uybm0bhQ.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/quarry/constants.d.ts
|
|
4
4
|
/**
|
|
@@ -118,4 +118,4 @@ declare abstract class Command {
|
|
|
118
118
|
}
|
|
119
119
|
//#endregion
|
|
120
120
|
export { Command as t };
|
|
121
|
-
//# sourceMappingURL=command-
|
|
121
|
+
//# sourceMappingURL=command-DoBD2Cwl.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-
|
|
1
|
+
{"version":3,"file":"command-DoBD2Cwl.d.mts","names":[],"sources":["../src/quarry/constants.ts","../src/quarry/command.ts"],"mappings":";;;;;;AAIA;cAAa,iBAAA;;;;AAAb;;;;AAAwE;;;;ACoBxE;;;;;;;;;;uBAAsB,OAAA;EA8LmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAA,OA7JhD,OAAA;EA4HC;EAAA,OA1HD,WAAA;EA+HD;EAAA,OA7HC,OAAA;EAAA,CAEN,iBAAA,GAAoB,gBAAA;;EA4IC;;;;EAAA,SA3Hb,MAAA,oBAA0B,OAAA;EAsIa;;;EA/HhD,KAAA,IAAS,IAAA,WAAe,CAAA;;;;EAOxB,MAAA,CAAO,IAAA;;;;EAcP,OAAA,CAAQ,IAAA;;;;EAcR,MAAA,CAAO,IAAA;;;;EAeP,KAAA,CAAM,IAAA;;EAcN,IAAA,CAAK,OAAA;;EAKL,OAAA,CAAQ,OAAA;;EAKR,IAAA,CAAK,OAAA;;EAKL,KAAA,CAAM,OAAA;;EAKN,IAAA,CAAK,OAAA;;EAKL,OAAA;;EAKA,OAAA,CAAQ,OAAA;;EAKR,KAAA,CAAM,OAAA,YAAmB,IAAA;;EAiBzB,IAAA,CAAK,OAAA,UAAiB,QAAA;;;;;EAWhB,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,aAAA;AAAA"}
|
package/dist/config/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fn as DynamicModule, Hn as OnInitialize, Ir as ApplicationError, Jn as InjectionToken, Ln as FactoryProvider, zn as ModuleContext } from "../index-uybm0bhQ.mjs";
|
|
2
2
|
import { t as Macroable } from "../index-0ItCjaqw.mjs";
|
|
3
3
|
import { a as z } from "../zod-wecrEVAs.mjs";
|
|
4
4
|
|
package/dist/config/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as Request, l as Singleton, p as inject, r as DI_TOKENS } from "../di-D7qmrAir.mjs";
|
|
2
2
|
import { a as ApplicationError } from "../container-storage-BmOJ4_Na.mjs";
|
|
3
3
|
import { n as __decorateParam, t as __decorate } from "../decorate-CuAoSZvs.mjs";
|
|
4
|
-
import "../errors-
|
|
4
|
+
import "../errors-C01O2T-n.mjs";
|
|
5
5
|
import { t as Macroable } from "../macroable-cvDTFZ_A.mjs";
|
|
6
6
|
import { n as Module } from "../module.decorator-CYHY6pG5.mjs";
|
|
7
7
|
import "../module/index.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { u as Transient } from "./di-D7qmrAir.mjs";
|
|
2
2
|
import { n as getMetadata, t as defineMetadata } from "./metadata-DzzprcID.mjs";
|
|
3
|
-
import { u as ROUTE_METADATA_KEYS } from "./exception-context-
|
|
3
|
+
import { u as ROUTE_METADATA_KEYS } from "./exception-context-D-kvney-.mjs";
|
|
4
4
|
//#region src/router/decorators/controller.decorator.ts
|
|
5
5
|
const CONTROLLER_ROUTE_KEY = ROUTE_METADATA_KEYS.CONTROLLER_ROUTE;
|
|
6
6
|
/**
|
|
@@ -63,4 +63,4 @@ function getControllerVersion(target) {
|
|
|
63
63
|
//#endregion
|
|
64
64
|
export { getControllerVersion as i, getControllerOptions as n, getControllerRoute as r, Controller as t };
|
|
65
65
|
|
|
66
|
-
//# sourceMappingURL=controller.decorator-
|
|
66
|
+
//# sourceMappingURL=controller.decorator-YSTPQntu.mjs.map
|
package/dist/{controller.decorator-DKeZ71aP.mjs.map → controller.decorator-YSTPQntu.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.decorator-
|
|
1
|
+
{"version":3,"file":"controller.decorator-YSTPQntu.mjs","names":[],"sources":["../src/router/decorators/controller.decorator.ts"],"sourcesContent":["import { Transient } from '../../di/decorators'\nimport { defineMetadata, getMetadata } from '../../di/metadata'\nimport { type Constructor } from '../../types'\nimport { ROUTE_METADATA_KEYS } from '../constants'\nimport { type ControllerOptions } from '../types'\n\nconst CONTROLLER_ROUTE_KEY = ROUTE_METADATA_KEYS.CONTROLLER_ROUTE\n\n/**\n * Base controller decorator for route registration\n *\n * This is the core controller decorator that handles:\n * - Transient scope registration (request-scoped)\n * - Route metadata storage\n * - Controller options (tags, security schemes, hideFromDocs)\n *\n * @param route - Base route for this controller (e.g., '/api/v1/users')\n * @param options - Optional configuration (tags, security schemes, hideFromDocs)\n *\n * @example\n * ```typescript\n * import { Controller } from 'stratal/router'\n *\n * @Controller('/api/v1/users', { tags: ['Users'] })\n * export class UsersController implements IController {\n * // All routes accessible\n * }\n * ```\n */\nexport function Controller(route: string, options?: ControllerOptions) {\n return function <T extends Constructor>(target: T) {\n // Wrap @Transient (handles @injectable and scope metadata)\n Transient()(target)\n\n // Store route metadata on the class\n defineMetadata(CONTROLLER_ROUTE_KEY, route, target)\n\n // Store options metadata if provided\n if (options) {\n defineMetadata(ROUTE_METADATA_KEYS.CONTROLLER_OPTIONS, options, target)\n }\n\n return target\n }\n}\n\n/**\n * Get the route from controller class metadata\n *\n * @param target - Controller class or instance\n * @returns Route string or undefined if not set\n */\nexport function getControllerRoute(target: object): string | undefined {\n // Check if target is a class constructor (function) or an instance\n // If class, get metadata from it directly; if instance, get from constructor\n const metadataTarget = typeof target === 'function' ? target : (target as { constructor: object }).constructor\n return getMetadata<string>(CONTROLLER_ROUTE_KEY, metadataTarget)\n}\n\n/**\n * Get the options from controller class metadata\n *\n * @param target - Controller class or instance\n * @returns Controller options or undefined if not set\n */\nexport function getControllerOptions(target: object): ControllerOptions | undefined {\n const metadataTarget = typeof target === 'function' ? target : (target as { constructor: object }).constructor\n return getMetadata<ControllerOptions>(ROUTE_METADATA_KEYS.CONTROLLER_OPTIONS, metadataTarget)\n}\n\n/**\n * Get the version from controller class metadata\n *\n * @param target - Controller class or instance\n * @returns Version string, array, VERSION_NEUTRAL symbol, or undefined if not set\n */\nexport function getControllerVersion(target: object): ControllerOptions['version'] {\n const options = getControllerOptions(target)\n return options?.version\n}\n"],"mappings":";;;;AAMA,MAAM,uBAAuB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;AAuBjD,SAAgB,WAAW,OAAe,SAA6B;CACrE,OAAO,SAAiC,QAAW;EAEjD,UAAU,EAAE,MAAM;EAGlB,eAAe,sBAAsB,OAAO,MAAM;EAGlD,IAAI,SACF,eAAe,oBAAoB,oBAAoB,SAAS,MAAM;EAGxE,OAAO;CACT;AACF;;;;;;;AAQA,SAAgB,mBAAmB,QAAoC;CAIrE,OAAO,YAAoB,sBADJ,OAAO,WAAW,aAAa,SAAU,OAAmC,WACpC;AACjE;;;;;;;AAQA,SAAgB,qBAAqB,QAA+C;CAClF,MAAM,iBAAiB,OAAO,WAAW,aAAa,SAAU,OAAmC;CACnG,OAAO,YAA+B,oBAAoB,oBAAoB,cAAc;AAC9F;;;;;;;AAQA,SAAgB,qBAAqB,QAA8C;CAEjF,OADgB,qBAAqB,MACxB,GAAG;AAClB"}
|
package/dist/cron/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as Container, Ir as ApplicationError } from "../index-uybm0bhQ.mjs";
|
|
2
2
|
import { n as RegisteredJob, t as CronJob } from "../cron-job-NesZRk8F.mjs";
|
|
3
3
|
import { ScheduledController as ScheduledController$1 } from "@cloudflare/workers-types";
|
|
4
4
|
|
package/dist/cron/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as CronExecutionError, r as CronManager, t as CronModule } from "../cron.module-
|
|
1
|
+
import { i as CronExecutionError, r as CronManager, t as CronModule } from "../cron.module-C81HTzR7.mjs";
|
|
2
2
|
export { CronExecutionError, CronManager, CronModule };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BBjsoOtd.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { l as Singleton, r as DI_TOKENS } from "./di-D7qmrAir.mjs";
|
|
3
3
|
import { a as ApplicationError } from "./container-storage-BmOJ4_Na.mjs";
|
|
4
4
|
import { t as __decorate } from "./decorate-CuAoSZvs.mjs";
|
|
5
5
|
import { LOGGER_TOKENS } from "./logger/index.mjs";
|
|
6
|
-
import "./errors-
|
|
6
|
+
import "./errors-C01O2T-n.mjs";
|
|
7
7
|
import { n as Module } from "./module.decorator-CYHY6pG5.mjs";
|
|
8
8
|
//#region src/cron/errors/cron-execution.error.ts
|
|
9
9
|
/**
|
|
@@ -150,4 +150,4 @@ CronModule = __decorate([Module({ providers: [{
|
|
|
150
150
|
//#endregion
|
|
151
151
|
export { CronExecutionError as i, cron_module_exports as n, CronManager as r, CronModule as t };
|
|
152
152
|
|
|
153
|
-
//# sourceMappingURL=cron.module-
|
|
153
|
+
//# sourceMappingURL=cron.module-C81HTzR7.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron.module-
|
|
1
|
+
{"version":3,"file":"cron.module-C81HTzR7.mjs","names":[],"sources":["../src/cron/errors/cron-execution.error.ts","../src/cron/cron-manager.ts","../src/cron/cron.module.ts"],"sourcesContent":["import { ApplicationError } from '../../errors'\n\nexport interface CronJobFailure {\n\tjob: string\n\terror: Error\n}\n\ninterface SerializedJobFailure {\n\tjob: string\n\tname: string\n\tcode?: number | string\n\tmessage: string\n\tdbErrorCode?: string\n\tsql?: string\n}\n\n/**\n * Error thrown when one or more cron jobs fail execution.\n *\n * Aggregates failures from multiple jobs that share the same schedule while\n * preserving each underlying error:\n * - The originals are kept on `this.failures` for typed access.\n * - `this.cause` is set to the only failure (1 job) or an `AggregateError`\n * wrapping all of them (2+ jobs), so `LoggerService.serializeError` can\n * walk the chain and surface every stack/cause.\n */\nexport class CronExecutionError extends ApplicationError {\n\tpublic readonly failures: readonly CronJobFailure[]\n\tpublic readonly schedule: string\n\tpublic readonly failureCount: number\n\tpublic readonly jobs: SerializedJobFailure[]\n\n\tconstructor(schedule: string, failures: CronJobFailure[]) {\n\t\tconst cause =\n\t\t\tfailures.length === 0\n\t\t\t\t? undefined\n\t\t\t\t: failures.length === 1\n\t\t\t\t\t? failures[0].error\n\t\t\t\t\t: new AggregateError(failures.map((f) => f.error), `${failures.length} cron jobs failed`)\n\n\t\tsuper(\n\t\t\t`${failures.length} cron job(s) failed for schedule \"${schedule}\"`,\n\t\t\tcause,\n\t\t)\n\n\t\tthis.failures = failures\n\t\tthis.schedule = schedule\n\t\tthis.failureCount = failures.length\n\t\tthis.jobs = failures.map((f) => serializeFailure(f))\n\t}\n}\n\nfunction serializeFailure({ job, error }: CronJobFailure): SerializedJobFailure {\n\tconst out: SerializedJobFailure = {\n\t\tjob,\n\t\tname: error.name,\n\t\tmessage: error.message,\n\t}\n\tconst maybeCoded = error as { code?: number | string }\n\tif (maybeCoded.code !== undefined) out.code = maybeCoded.code\n\treturn out\n}\n","import type { Container } from '../di/container'\nimport { Singleton } from '../di/decorators'\nimport { DI_TOKENS } from '../di/tokens'\nimport { LOGGER_TOKENS } from '../logger/logger.tokens'\nimport type { LoggerService } from '../logger/services/logger.service'\nimport type { CronJob, RegisteredJob } from './cron-job'\nimport { CronExecutionError } from './errors/cron-execution.error'\n\n/**\n * Manages cron job registration and execution\n *\n * CronManager is a singleton service that:\n * - Registers cron job class references from modules\n * - Routes scheduled events to matching jobs\n * - Resolves jobs from a request-scoped container at execution time\n *\n * Jobs are grouped by their cron expression, allowing multiple jobs\n * to run on the same schedule.\n */\n@Singleton(DI_TOKENS.Cron)\nexport class CronManager {\n\t/**\n\t * Map of cron expressions to registered job entries\n\t * Key: Cron expression (e.g., '0 2 * * *')\n\t * Value: Array of registered jobs (class ref + schedule)\n\t */\n\tprivate jobs = new Map<string, RegisteredJob[]>()\n\n\t/**\n\t * Register a cron job class\n\t *\n\t * Jobs with the same schedule are grouped together and executed\n\t * sequentially when the trigger fires.\n\t *\n\t * @param schedule - Cron expression (e.g., '0 2 * * *')\n\t * @param jobClass - CronJob class constructor (resolved at execution time)\n\t */\n\tregisterJob(schedule: string, jobClass: RegisteredJob['jobClass']): void {\n\t\tconst existing = this.jobs.get(schedule) ?? []\n\t\texisting.push({ schedule, jobClass })\n\t\tthis.jobs.set(schedule, existing)\n\t}\n\n\t/**\n\t * Execute all jobs matching the triggered cron expression\n\t *\n\t * Jobs are resolved from the provided request-scoped container,\n\t * ensuring dependencies (e.g. database) are properly scoped.\n\t *\n\t * Jobs are executed sequentially. If a job fails:\n\t * - Its onError() hook is called (if defined)\n\t * - Execution continues with the next job\n\t * - Errors are collected and thrown as CronExecutionError\n\t *\n\t * @param controller - Cloudflare ScheduledController\n\t * @param container - Request-scoped container to resolve jobs from\n\t */\n\tasync executeScheduled(controller: ScheduledController, container: Container): Promise<void> {\n\t\tconst { cron } = controller\n\t\tconst matchingJobs = this.jobs.get(cron) ?? []\n\n\t\tif (matchingJobs.length === 0) {\n\t\t\tconst logger = container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n\t\t\tlogger.warn('No cron jobs matched scheduled trigger', {\n\t\t\t\tincomingCron: cron,\n\t\t\t\tregisteredSchedules: Array.from(this.jobs.keys()),\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tconst errors: { job: string; error: Error }[] = []\n\n\t\tfor (const { jobClass } of matchingJobs) {\n\t\t\tconst jobName = jobClass.name\n\n\t\t\ttry {\n\t\t\t\t// Register the job class in the request-scoped container so its\n\t\t\t\t// dependencies are resolved from request scope (not the parent).\n\t\t\t\tcontainer.register(jobClass, jobClass)\n\t\t\t\tconst job = container.resolve<CronJob>(jobClass)\n\t\t\t\tawait job.execute(controller)\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error as Error\n\t\t\t\terrors.push({ job: jobName, error: err })\n\n\t\t\t\t// Try to resolve and call onError if possible\n\t\t\t\ttry {\n\t\t\t\t\tconst job = container.resolve<CronJob>(jobClass)\n\t\t\t\t\tif (job.onError) {\n\t\t\t\t\t\tawait job.onError(err, controller)\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// If resolution or onError fails, continue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If any jobs failed, throw an aggregate error so ExceptionHandler logs\n\t\t// it. The full per-job errors are passed through so cause/stacks survive.\n\t\tif (errors.length > 0) {\n\t\t\tthrow new CronExecutionError(cron, errors)\n\t\t}\n\t}\n\n\t/**\n\t * Get all registered jobs for a specific cron expression\n\t *\n\t * @param schedule - Cron expression\n\t * @returns Array of registered jobs, or empty array if none\n\t */\n\tgetJobsForSchedule(schedule: string): RegisteredJob[] {\n\t\treturn this.jobs.get(schedule) ?? []\n\t}\n\n\t/**\n\t * Get all registered cron expressions\n\t *\n\t * @returns Array of unique cron expressions\n\t */\n\tgetAllSchedules(): string[] {\n\t\treturn Array.from(this.jobs.keys())\n\t}\n\n\t/**\n\t * Get total number of registered jobs across all schedules\n\t *\n\t * @returns Total job count\n\t */\n\tgetTotalJobCount(): number {\n\t\tlet count = 0\n\t\tfor (const jobs of this.jobs.values()) {\n\t\t\tcount += jobs.length\n\t\t}\n\t\treturn count\n\t}\n}\n","import { DI_TOKENS } from '../di/tokens'\nimport { Module } from '../module/module.decorator'\nimport { CronManager } from './cron-manager'\n\n/**\n * Registers the cron manager (`DI_TOKENS.Cron`).\n *\n * Lazy: loaded on demand via `await import()` — by `Application.ensureCron`\n * (first scheduled trigger, or at bootstrap when the app declares jobs) and by\n * the `schedule:list` command. Kept out of cold start for apps without cron.\n */\n@Module({\n providers: [\n { provide: DI_TOKENS.Cron, useClass: CronManager },\n ],\n})\nexport class CronModule { }\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,IAAa,qBAAb,cAAwC,iBAAiB;CACxD;CACA;CACA;CACA;CAEA,YAAY,UAAkB,UAA4B;EACzD,MAAM,QACL,SAAS,WAAW,IACjB,KAAA,IACA,SAAS,WAAW,IACnB,SAAS,GAAG,QACZ,IAAI,eAAe,SAAS,KAAK,MAAM,EAAE,KAAK,GAAG,GAAG,SAAS,OAAO,kBAAkB;EAE3F,MACC,GAAG,SAAS,OAAO,oCAAoC,SAAS,IAChE,KACD;EAEA,KAAK,WAAW;EAChB,KAAK,WAAW;EAChB,KAAK,eAAe,SAAS;EAC7B,KAAK,OAAO,SAAS,KAAK,MAAM,iBAAiB,CAAC,CAAC;CACpD;AACD;AAEA,SAAS,iBAAiB,EAAE,KAAK,SAA+C;CAC/E,MAAM,MAA4B;EACjC;EACA,MAAM,MAAM;EACZ,SAAS,MAAM;CAChB;CACA,MAAM,aAAa;CACnB,IAAI,WAAW,SAAS,KAAA,GAAW,IAAI,OAAO,WAAW;CACzD,OAAO;AACR;;;ACzCO,IAAA,cAAA,MAAM,YAAY;;;;;;CAMxB,uBAAe,IAAI,IAA6B;;;;;;;;;;CAWhD,YAAY,UAAkB,UAA2C;EACxE,MAAM,WAAW,KAAK,KAAK,IAAI,QAAQ,KAAK,CAAC;EAC7C,SAAS,KAAK;GAAE;GAAU;EAAS,CAAC;EACpC,KAAK,KAAK,IAAI,UAAU,QAAQ;CACjC;;;;;;;;;;;;;;;CAgBA,MAAM,iBAAiB,YAAiC,WAAqC;EAC5F,MAAM,EAAE,SAAS;EACjB,MAAM,eAAe,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC;EAE7C,IAAI,aAAa,WAAW,GAAG;GAE9B,UADyB,QAAuB,cAAc,aACzD,EAAE,KAAK,0CAA0C;IACrD,cAAc;IACd,qBAAqB,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC;GACjD,CAAC;GACD;EACD;EAEA,MAAM,SAA0C,CAAC;EAEjD,KAAK,MAAM,EAAE,cAAc,cAAc;GACxC,MAAM,UAAU,SAAS;GAEzB,IAAI;IAGH,UAAU,SAAS,UAAU,QAAQ;IAErC,MADY,UAAU,QAAiB,QAC/B,EAAE,QAAQ,UAAU;GAC7B,SAAS,OAAO;IACf,MAAM,MAAM;IACZ,OAAO,KAAK;KAAE,KAAK;KAAS,OAAO;IAAI,CAAC;IAGxC,IAAI;KACH,MAAM,MAAM,UAAU,QAAiB,QAAQ;KAC/C,IAAI,IAAI,SACP,MAAM,IAAI,QAAQ,KAAK,UAAU;IAEnC,QAAQ,CAER;GACD;EACD;EAIA,IAAI,OAAO,SAAS,GACnB,MAAM,IAAI,mBAAmB,MAAM,MAAM;CAE3C;;;;;;;CAQA,mBAAmB,UAAmC;EACrD,OAAO,KAAK,KAAK,IAAI,QAAQ,KAAK,CAAC;CACpC;;;;;;CAOA,kBAA4B;EAC3B,OAAO,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC;CACnC;;;;;;CAOA,mBAA2B;EAC1B,IAAI,QAAQ;EACZ,KAAK,MAAM,QAAQ,KAAK,KAAK,OAAO,GACnC,SAAS,KAAK;EAEf,OAAO;CACR;AACD;0BApHC,UAAU,UAAU,IAAI,CAAA,GAAA,WAAA;;;;ACHlB,IAAA,aAAA,MAAM,WAAW,CAAE;yBALzB,OAAO,EACN,WAAW,CACT;CAAE,SAAS,UAAU;CAAM,UAAU;AAAY,CACnD,EACF,CAAC,CAAA,GAAA,UAAA"}
|
package/dist/di/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
export { CONTAINER_TOKEN, ConditionalBindingBuilder, ConditionalBindingBuilderImpl, ConditionalBindingGive, ConditionalBindingUse, Container, ContainerError, ContainerLike, ContainerOptions, DIToken, DI_TOKENS, ExtensionDecorator, INJECT_PARAM_METADATA_KEY, InjectParam, InjectionToken, LazyToken, type ParamInjection, PredicateContainer, Request, Scope, Singleton, Transient, WhenOptions, containerStorage, defineMetadata, getClassMetadata, getContainer, getInjectionTokens, getMetadata, getMethodInjections, hasMetadata, inject, isLazyToken, lazy, runWithContainer };
|
|
1
|
+
import { $ as Container, $n as lazy, B as getMetadata, F as runWithContainer, Fr as DI_TOKENS, G as getClassMetadata, H as Request, I as Disposable, J as INJECT_PARAM_METADATA_KEY, Jn as InjectionToken, K as getInjectionTokens, Kn as ContainerLike, L as disposeInstance, N as containerStorage, Nr as CONTAINER_TOKEN, P as getContainer, Pr as DIToken, Q as ContainerError, Qn as isLazyToken, R as isDisposable, U as Singleton, V as hasMetadata, W as Transient, X as ParamInjection, Xn as WhenOptions, Y as InjectParam, Yn as Scope, Z as getMethodInjections, Zn as LazyToken, at as PredicateContainer, et as ContainerOptions, it as ConditionalBindingUse, nt as ConditionalBindingBuilderImpl, q as inject, qn as ExtensionDecorator, rt as ConditionalBindingGive, tt as ConditionalBindingBuilder, z as defineMetadata } from "../index-uybm0bhQ.mjs";
|
|
2
|
+
export { CONTAINER_TOKEN, ConditionalBindingBuilder, ConditionalBindingBuilderImpl, ConditionalBindingGive, ConditionalBindingUse, Container, ContainerError, ContainerLike, ContainerOptions, DIToken, DI_TOKENS, Disposable, ExtensionDecorator, INJECT_PARAM_METADATA_KEY, InjectParam, InjectionToken, LazyToken, type ParamInjection, PredicateContainer, Request, Scope, Singleton, Transient, WhenOptions, containerStorage, defineMetadata, disposeInstance, getClassMetadata, getContainer, getInjectionTokens, getMetadata, getMethodInjections, hasMetadata, inject, isDisposable, isLazyToken, lazy, runWithContainer };
|
package/dist/di/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { _ as Scope, a as lazy, c as Request, d as getClassMetadata, f as getInjectionTokens, g as getMethodInjections, h as InjectParam, i as isLazyToken, l as Singleton, m as INJECT_PARAM_METADATA_KEY, n as CONTAINER_TOKEN, o as disposeInstance, p as inject, r as DI_TOKENS, s as isDisposable, t as Container, u as Transient, v as ConditionalBindingBuilderImpl, y as ContainerError } from "../di-D7qmrAir.mjs";
|
|
2
2
|
import { n as getContainer, r as runWithContainer, t as containerStorage } from "../container-storage-BmOJ4_Na.mjs";
|
|
3
3
|
import { n as getMetadata, r as hasMetadata, t as defineMetadata } from "../metadata-DzzprcID.mjs";
|
|
4
|
-
export { CONTAINER_TOKEN, ConditionalBindingBuilderImpl, Container, ContainerError, DI_TOKENS, INJECT_PARAM_METADATA_KEY, InjectParam, Request, Scope, Singleton, Transient, containerStorage, defineMetadata, getClassMetadata, getContainer, getInjectionTokens, getMetadata, getMethodInjections, hasMetadata, inject, isLazyToken, lazy, runWithContainer };
|
|
4
|
+
export { CONTAINER_TOKEN, ConditionalBindingBuilderImpl, Container, ContainerError, DI_TOKENS, INJECT_PARAM_METADATA_KEY, InjectParam, Request, Scope, Singleton, Transient, containerStorage, defineMetadata, disposeInstance, getClassMetadata, getContainer, getInjectionTokens, getMetadata, getMethodInjections, hasMetadata, inject, isDisposable, isLazyToken, lazy, runWithContainer };
|
|
@@ -182,6 +182,27 @@ function getClassMetadata(target) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
//#endregion
|
|
185
|
+
//#region src/di/disposable.ts
|
|
186
|
+
function isDisposable(instance) {
|
|
187
|
+
if (typeof instance !== "object" || instance === null) return false;
|
|
188
|
+
const candidate = instance;
|
|
189
|
+
return typeof candidate[Symbol.asyncDispose] === "function" || typeof candidate[Symbol.dispose] === "function" || typeof candidate.dispose === "function";
|
|
190
|
+
}
|
|
191
|
+
/** Invoke the instance's dispose hook, preferring async > sync > method form. */
|
|
192
|
+
async function disposeInstance(instance) {
|
|
193
|
+
const asyncDispose = instance[Symbol.asyncDispose];
|
|
194
|
+
if (typeof asyncDispose === "function") {
|
|
195
|
+
await asyncDispose.call(instance);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const syncDispose = instance[Symbol.dispose];
|
|
199
|
+
if (typeof syncDispose === "function") {
|
|
200
|
+
syncDispose.call(instance);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
await instance.dispose?.();
|
|
204
|
+
}
|
|
205
|
+
//#endregion
|
|
185
206
|
//#region src/di/lazy.ts
|
|
186
207
|
const LAZY_MARKER = Symbol.for("stratal:lazy");
|
|
187
208
|
function lazy(factory) {
|
|
@@ -372,7 +393,27 @@ var Container = class Container {
|
|
|
372
393
|
child.registerValue(ROUTER_TOKENS.RouterContext, routerContext);
|
|
373
394
|
return child;
|
|
374
395
|
}
|
|
375
|
-
|
|
396
|
+
/**
|
|
397
|
+
* Disposes every container-instantiated instance that implements the
|
|
398
|
+
* {@link Disposable} contract (singletons and request-cached instances),
|
|
399
|
+
* then clears all registrations. Value registrations are not disposed —
|
|
400
|
+
* the container doesn't own them. A failing disposer is logged and
|
|
401
|
+
* skipped so it can't block the rest of the teardown.
|
|
402
|
+
*
|
|
403
|
+
* Instances are disposed in reverse creation order (LIFO): a disposer may
|
|
404
|
+
* still use dependencies that were constructed before its own instance.
|
|
405
|
+
*/
|
|
406
|
+
async dispose() {
|
|
407
|
+
const seen = /* @__PURE__ */ new Set();
|
|
408
|
+
for (const instance of [...this.singletons.values(), ...this.requestCache.values()].reverse()) {
|
|
409
|
+
if (seen.has(instance) || !isDisposable(instance)) continue;
|
|
410
|
+
seen.add(instance);
|
|
411
|
+
try {
|
|
412
|
+
await disposeInstance(instance);
|
|
413
|
+
} catch (error) {
|
|
414
|
+
console.error("[stratal] Failed to dispose instance during container teardown:", error);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
376
417
|
this.registrations.clear();
|
|
377
418
|
this.singletons.clear();
|
|
378
419
|
this.requestCache.clear();
|
|
@@ -535,6 +576,6 @@ var Container = class Container {
|
|
|
535
576
|
}
|
|
536
577
|
};
|
|
537
578
|
//#endregion
|
|
538
|
-
export {
|
|
579
|
+
export { Scope as _, lazy as a, ROUTER_TOKENS as b, Request as c, getClassMetadata as d, getInjectionTokens as f, getMethodInjections as g, InjectParam as h, isLazyToken as i, Singleton as l, INJECT_PARAM_METADATA_KEY as m, CONTAINER_TOKEN as n, disposeInstance as o, inject as p, DI_TOKENS as r, isDisposable as s, Container as t, Transient as u, ConditionalBindingBuilderImpl as v, ContainerError as y };
|
|
539
580
|
|
|
540
|
-
//# sourceMappingURL=di-
|
|
581
|
+
//# sourceMappingURL=di-D7qmrAir.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"di-D7qmrAir.mjs","names":["g"],"sources":["../src/router/router.tokens.ts","../src/di/container.error.ts","../src/di/conditional-binding-builder.ts","../src/di/types.ts","../src/di/decorators/inject-param.decorator.ts","../src/di/decorators/inject.decorator.ts","../src/di/decorators.ts","../src/di/disposable.ts","../src/di/lazy.ts","../src/di/tokens.ts","../src/di/container.ts"],"sourcesContent":["/**\n * Dependency injection tokens for the router system\n */\nexport const ROUTER_TOKENS = {\n /**\n * Token for RouterContext (request-scoped)\n * Contains Hono context wrapper with helper methods\n */\n RouterContext: Symbol.for('stratal:router:context'),\n\n /**\n * Token for RouteRegistry (singleton)\n * Central registry of all application routes — source of truth for route:list, route:types, URL generation\n */\n RouteRegistry: Symbol.for('stratal:router:route-registry'),\n\n /**\n * Token for VersioningService (singleton)\n * Resolves version prefixes for route paths\n */\n VersioningService: Symbol.for('stratal:router:versioning-service'),\n\n /**\n * Token for LocalePathService (singleton)\n * Resolves locale path variants and computes LocalePathConfig\n */\n LocalePathService: Symbol.for('stratal:router:locale-path-service'),\n\n /**\n * Token for LocaleUrlService (singleton)\n * Ergonomic wrapper around the pure locale-url helpers — applies, strips,\n * and tests locale prefixes against the resolved LocalePathService config.\n */\n LocaleUrlService: Symbol.for('stratal:router:locale-url-service'),\n\n /**\n * Token for RouterResolver (singleton, may be null)\n * Internal resolver that computes effective Router config per controller\n */\n RouterResolver: Symbol.for('stratal:router:router-resolver'),\n\n /**\n * Token for HonoApp (singleton)\n * The Hono application instance with Stratal-specific setup\n */\n HonoApp: Symbol.for('stratal:router:hono-app'),\n\n /**\n * Token for Uri (request-scoped)\n * URL generation service — route URLs, signed URLs, current/previous URL access\n */\n Uri: Symbol.for('stratal:router:uri'),\n} as const\n","import { ApplicationError } from '../errors/application-error';\n\nexport class ContainerError extends ApplicationError {\n}\n","import type { Container } from './container'\nimport { ContainerError } from './container.error'\nimport type { InjectionToken, WhenOptions } from './types'\nimport type { Constructor } from '../types'\n\nexport interface PredicateContainer {\n resolve<T>(token: InjectionToken<T>): T\n isRegistered<T>(token: InjectionToken<T>): boolean\n}\n\nexport interface ConditionalBindingBuilder {\n use<T extends object>(token: InjectionToken<T>): ConditionalBindingUse<T>\n}\n\nexport interface ConditionalBindingUse<T extends object> {\n give(implementation: Constructor<T>): ConditionalBindingGive<T>\n}\n\nexport interface ConditionalBindingGive<T extends object> {\n otherwise(implementation: Constructor<T>): void\n}\n\nexport class ConditionalBindingBuilderImpl implements ConditionalBindingBuilder {\n constructor(\n private readonly container: Container,\n private readonly predicate: (container: PredicateContainer) => boolean,\n private readonly options: WhenOptions,\n ) {}\n\n use<T extends object>(token: InjectionToken<T>): ConditionalBindingUse<T> {\n return new ConditionalBindingUseImpl<T>(\n this.container,\n this.predicate,\n this.options,\n token,\n )\n }\n}\n\nclass ConditionalBindingUseImpl<T extends object> implements ConditionalBindingUse<T> {\n constructor(\n private readonly container: Container,\n private readonly predicate: (container: PredicateContainer) => boolean,\n private readonly options: WhenOptions,\n private readonly token: InjectionToken<T>,\n ) {}\n\n give(trueImpl: Constructor<T>): ConditionalBindingGive<T> {\n this.registerConditional(trueImpl, undefined)\n\n return {\n otherwise: (falseImpl: Constructor<T>) => {\n this.registerConditional(trueImpl, falseImpl)\n },\n }\n }\n\n private registerConditional(trueImpl: Constructor<T>, falseImpl: Constructor<T> | undefined): void {\n const { predicate, container, options, token } = this\n let cachedResult: boolean | undefined\n\n // Register both implementations so the container can instantiate them\n container.register(trueImpl)\n if (falseImpl) container.register(falseImpl)\n\n container.registerFactory(token, (c) => {\n let result: boolean\n if (options.cache && cachedResult !== undefined) {\n result = cachedResult\n } else {\n result = predicate(c)\n if (options.cache) cachedResult = result\n }\n\n if (result) {\n return c.resolve(trueImpl as unknown as InjectionToken<T>)\n }\n\n if (falseImpl) {\n return c.resolve(falseImpl as unknown as InjectionToken<T>)\n }\n\n const tokenStr = typeof token === 'symbol'\n ? (token.description ?? 'unknown')\n : typeof token === 'function'\n ? token.name\n : typeof token === 'string'\n ? token\n : 'lazy'\n throw new ContainerError(`No fallback registered for conditional binding \"${tokenStr}\". Use .otherwise() or register a default implementation.`)\n })\n }\n}\n","import type { Constructor } from '../types'\nimport type { LazyToken } from './lazy'\n\nexport type InjectionToken<T = unknown> = Constructor<T> | string | symbol | LazyToken<T>\n\nexport enum Scope {\n Transient = 0,\n Singleton = 1,\n Request = 2,\n}\n\nexport interface WhenOptions {\n cache?: boolean\n}\n\nexport type ExtensionDecorator<T> = (service: T, container: ContainerLike) => T\n\nexport interface ContainerLike {\n resolve<T>(token: InjectionToken<T>): T\n /**\n * Resolves an optional dependency: `undefined` when nothing is registered,\n * or when a request-scoped provider is requested outside a request scope.\n */\n tryResolve<T>(token: InjectionToken<T>): T | undefined\n}\n","import type { InjectionToken } from '../types'\nimport { defineMetadata, getMetadata } from '../metadata'\n\nexport const INJECT_PARAM_METADATA_KEY = Symbol.for('stratal:inject:param')\n\nexport interface ParamInjection {\n index: number\n token: InjectionToken\n}\n\nexport function InjectParam<T>(token: InjectionToken<T>): ParameterDecorator {\n return (target: object, propertyKey: string | symbol | undefined, parameterIndex: number) => {\n if (propertyKey === undefined) {\n throw new Error('@InjectParam can only be used on method parameters, not constructor parameters')\n }\n\n const existing = getMetadata<ParamInjection[]>(INJECT_PARAM_METADATA_KEY, target, propertyKey) ?? []\n existing.push({ index: parameterIndex, token })\n defineMetadata(INJECT_PARAM_METADATA_KEY, existing, target, propertyKey)\n }\n}\n\nexport function getMethodInjections(target: object, propertyKey: string | symbol): ParamInjection[] {\n const injections = getMetadata<ParamInjection[]>(INJECT_PARAM_METADATA_KEY, target, propertyKey) ?? []\n return injections.sort((a, b) => a.index - b.index)\n}\n","import type { InjectionToken } from '../types'\n\ninterface InjectionEntry {\n token: InjectionToken\n optional: boolean\n}\n\nconst INJECTION_TOKENS_KEY = Symbol.for('stratal:di:injection-tokens')\nconst g = globalThis as Record<symbol, unknown>\nconst INJECTION_TOKENS: WeakMap<object, Map<number, InjectionEntry>> =\n (g[INJECTION_TOKENS_KEY] as WeakMap<object, Map<number, InjectionEntry>>) ??\n (g[INJECTION_TOKENS_KEY] = new WeakMap<object, Map<number, InjectionEntry>>())\n\nexport function inject<T>(\n token: InjectionToken<T>,\n options?: { isOptional?: boolean },\n): ParameterDecorator {\n return (target: object, _propertyKey: string | symbol | undefined, parameterIndex: number) => {\n let params = INJECTION_TOKENS.get(target)\n if (!params) {\n params = new Map()\n INJECTION_TOKENS.set(target, params)\n }\n params.set(parameterIndex, { token, optional: options?.isOptional ?? false })\n }\n}\n\nexport function getInjectionTokens(target: object): Map<number, InjectionEntry> {\n const direct = INJECTION_TOKENS.get(target)\n if (direct && direct.size > 0) return direct\n\n let proto = Object.getPrototypeOf(target) as object | null\n while (proto !== null && proto !== Function.prototype) {\n const inherited = INJECTION_TOKENS.get(proto)\n if (inherited && inherited.size > 0) return inherited\n proto = Object.getPrototypeOf(proto) as object | null\n }\n\n return new Map<number, InjectionEntry>()\n}\n","import type { InjectionToken } from './types'\nimport { Scope } from './types'\n\nexport {\n InjectParam,\n getMethodInjections,\n type ParamInjection,\n INJECT_PARAM_METADATA_KEY,\n} from './decorators/inject-param.decorator'\n\nexport { inject, getInjectionTokens } from './decorators/inject.decorator'\n\ninterface ClassMetadata {\n scope: Scope\n token?: InjectionToken\n}\n\nconst CLASS_METADATA_KEY = Symbol.for('stratal:di:class-metadata')\nconst g = globalThis as Record<symbol, unknown>\nconst CLASS_METADATA: WeakMap<object, ClassMetadata> =\n (g[CLASS_METADATA_KEY] as WeakMap<object, ClassMetadata>) ??\n (g[CLASS_METADATA_KEY] = new WeakMap<object, ClassMetadata>())\n\nfunction scopeDecorator(scope: Scope) {\n return <T>(token?: InjectionToken<T>) =>\n <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction): TFunction => {\n CLASS_METADATA.set(target, { scope, token })\n return target\n }\n}\n\nexport const Singleton = scopeDecorator(Scope.Singleton)\nexport const Request = scopeDecorator(Scope.Request)\nexport const Transient = scopeDecorator(Scope.Transient)\n\nexport function getClassMetadata(target: object): ClassMetadata | undefined {\n const direct = CLASS_METADATA.get(target)\n if (direct) return direct\n\n let proto = Object.getPrototypeOf(target) as object | null\n while (proto !== null && proto !== Function.prototype) {\n const inherited = CLASS_METADATA.get(proto)\n if (inherited) return inherited\n proto = Object.getPrototypeOf(proto) as object | null\n }\n\n return undefined\n}\n","/**\n * Disposal contract for container-managed instances.\n *\n * Singletons (and request-cached instances) that hold live resources —\n * timers, sockets, connection pools, event subscriptions — implement one of\n * these hooks so {@link Container.dispose} can release them on shutdown\n * (e.g. when a Vite HMR reload replaces the running Application).\n *\n * Precedence when multiple hooks are present: `Symbol.asyncDispose`,\n * then `Symbol.dispose`, then `dispose()`.\n */\nexport interface Disposable {\n dispose?(): void | Promise<void>\n [Symbol.dispose]?(): void\n [Symbol.asyncDispose]?(): PromiseLike<void>\n}\n\nexport function isDisposable(instance: unknown): instance is Disposable {\n if (typeof instance !== 'object' || instance === null) return false\n const candidate = instance as Disposable\n return typeof candidate[Symbol.asyncDispose] === 'function'\n || typeof candidate[Symbol.dispose] === 'function'\n || typeof candidate.dispose === 'function'\n}\n\n/** Invoke the instance's dispose hook, preferring async > sync > method form. */\nexport async function disposeInstance(instance: Disposable): Promise<void> {\n const asyncDispose = instance[Symbol.asyncDispose]\n if (typeof asyncDispose === 'function') {\n await asyncDispose.call(instance)\n return\n }\n const syncDispose = instance[Symbol.dispose]\n if (typeof syncDispose === 'function') {\n syncDispose.call(instance)\n return\n }\n await instance.dispose?.()\n}\n","import type { Constructor } from '../types'\n\nconst LAZY_MARKER = Symbol.for('stratal:lazy')\n\nexport interface LazyToken<T = unknown> {\n [LAZY_MARKER]: true\n factory: () => Constructor<T>\n}\n\nexport function lazy<T>(factory: () => Constructor<T>): LazyToken<T> {\n return { [LAZY_MARKER]: true, factory } as LazyToken<T>\n}\n\nexport function isLazyToken(value: unknown): value is LazyToken {\n return typeof value === 'object' && value !== null && LAZY_MARKER in value\n}\n","/**\n * Token for the Container instance\n * Used for injecting the Container into services that need dynamic resolution\n */\nexport const CONTAINER_TOKEN = Symbol.for('stratal:di:container')\n\nexport const DI_TOKENS = {\n // Cloudflare\n CloudflareEnv: Symbol.for('stratal:cloudflare:env'),\n ExecutionContext: Symbol.for('stratal:execution:context'),\n\n // Infrastructure\n Container: CONTAINER_TOKEN,\n Application: Symbol.for('stratal:application'),\n ModuleRegistry: Symbol.for('stratal:module:registry'),\n LazyModuleLoader: Symbol.for('stratal:lazy-module-loader'),\n ExceptionHandler: Symbol.for('stratal:exception:handler'),\n Database: Symbol.for('stratal:database:service'),\n Queue: Symbol.for('stratal:queue:manager'),\n ConsumerRegistry: Symbol.for('stratal:consumer:registry'),\n Cron: Symbol.for('stratal:cron:manager'),\n EventRegistry: Symbol.for('stratal:event:registry'),\n Quarry: Symbol.for('stratal:quarry'),\n\n // Context\n /**\n * AuthContext: Use for services that need user authentication (userId).\n */\n AuthContext: Symbol.for('stratal:auth:context'),\n\n // Workers\n DurableObjectState: Symbol.for('stratal:durable:object:state'),\n DurableObjectId: Symbol.for('stratal:durable:object:id'),\n} as const\n\nexport type DIToken = typeof DI_TOKENS[keyof typeof DI_TOKENS]\n","import type { RouterContext } from '../router/router-context';\nimport { ROUTER_TOKENS } from '../router/router.tokens';\nimport type { Constructor } from '../types';\nimport { ConditionalBindingBuilderImpl, type ConditionalBindingBuilder, type PredicateContainer } from './conditional-binding-builder';\nimport { containerStorage } from './container-storage';\nimport { ContainerError } from './container.error';\nimport { getClassMetadata } from './decorators';\nimport { getInjectionTokens } from './decorators/inject.decorator';\nimport { disposeInstance, isDisposable } from './disposable';\nimport { isLazyToken, type LazyToken } from './lazy';\nimport { CONTAINER_TOKEN } from './tokens';\nimport { Scope, type ExtensionDecorator, type InjectionToken, type WhenOptions } from './types';\n\ninterface ClassRegistration {\n kind: 'class'\n useClass: Constructor\n scope: Scope\n}\n\ninterface LazyClassRegistration {\n kind: 'lazy'\n factory: () => Constructor\n}\n\ninterface ValueRegistration {\n kind: 'value'\n value: unknown\n}\n\ninterface FactoryRegistration {\n kind: 'factory'\n factory: (container: Container) => unknown\n}\n\ninterface AliasRegistration {\n kind: 'alias'\n target: InjectionToken\n}\n\ntype Registration = ClassRegistration | LazyClassRegistration | ValueRegistration | FactoryRegistration | AliasRegistration\n\nfunction tokenToString(token: InjectionToken): string {\n if (typeof token === 'symbol') return token.description ?? 'Symbol'\n if (typeof token === 'function') return token.name\n if (typeof token === 'object' && token !== null && 'factory' in token) return '(lazy)'\n return String(token)\n}\n\nexport interface ContainerOptions {\n parent?: Container\n isRequestScoped?: boolean\n}\n\nexport class Container {\n private readonly registrations = new Map<InjectionToken, Registration>()\n private readonly singletons = new Map<InjectionToken, unknown>()\n private readonly requestCache = new Map<InjectionToken, unknown>()\n private readonly requestCacheDeps = new Map<InjectionToken, Set<InjectionToken>>()\n /**\n * Classes currently being constructed, held on the root so it spans the\n * global ↔ request-scope boundary. Used to turn an otherwise-opaque stack\n * overflow on a circular dependency into a clear error naming the cycle.\n */\n private readonly resolutionStack: Constructor[] = []\n private readonly parent: Container | null\n private readonly isRequestScoped: boolean\n\n constructor(options: ContainerOptions = {}) {\n this.parent = options.parent ?? null\n this.isRequestScoped = options.isRequestScoped ?? false\n\n if (!this.isRequestScoped) {\n this.registrations.set(CONTAINER_TOKEN, { kind: 'value', value: this })\n }\n }\n\n // ── Registration ──────────────────────────────────────────────\n\n register<T extends object>(serviceClass: Constructor<T>): void\n register<T extends object>(token: InjectionToken<T>, serviceClassOrLazy: Constructor<T> | LazyToken<T>): void\n register<T extends object>(\n tokenOrClass: InjectionToken<T> | Constructor<T>,\n serviceClassOrLazy?: Constructor<T> | LazyToken<T>,\n ): void {\n if (serviceClassOrLazy !== undefined && isLazyToken(serviceClassOrLazy)) {\n const lazyToken = serviceClassOrLazy\n this.registrations.set(tokenOrClass, {\n kind: 'lazy',\n factory: lazyToken.factory,\n })\n return\n }\n\n let token: InjectionToken<T>\n let impl: Constructor<T>\n\n if (serviceClassOrLazy !== undefined) {\n token = tokenOrClass\n impl = serviceClassOrLazy\n } else {\n token = tokenOrClass as Constructor<T>\n impl = tokenOrClass as Constructor<T>\n }\n\n const meta = getClassMetadata(impl)\n const scope = meta?.scope ?? Scope.Transient\n const effectiveToken = (serviceClassOrLazy === undefined && meta?.token) ? meta.token : token\n\n this.registrations.set(effectiveToken, { kind: 'class', useClass: impl, scope })\n }\n\n registerSingleton<T extends object>(serviceClass: Constructor<T>): void\n registerSingleton<T extends object>(token: InjectionToken<T>, serviceClass: Constructor<T>): void\n registerSingleton<T extends object>(\n tokenOrClass: InjectionToken<T> | Constructor<T>,\n serviceClass?: Constructor<T>,\n ): void {\n const impl = serviceClass ?? tokenOrClass as Constructor<T>\n const meta = getClassMetadata(impl)\n const token = serviceClass !== undefined\n ? tokenOrClass\n : (meta?.token ?? tokenOrClass as Constructor<T>)\n this.registrations.set(token, { kind: 'class', useClass: impl, scope: Scope.Singleton })\n }\n\n registerValue<T>(token: InjectionToken<T>, value: T): void {\n this.registrations.set(token, { kind: 'value', value })\n if (this.isRequestScoped) {\n this.invalidateRequestCache(token)\n }\n }\n\n registerFactory<T>(token: InjectionToken<T>, factory: (container: Container) => T): void {\n this.registrations.set(token, { kind: 'factory', factory })\n }\n\n registerExisting<T>(alias: InjectionToken<T>, target: InjectionToken<T>): void {\n this.registrations.set(alias, { kind: 'alias', target })\n }\n\n // ── Resolution ────────────────────────────────────────────────\n\n resolve<T>(token: InjectionToken<T>): T {\n if (isLazyToken(token)) {\n const realToken = token.factory() as InjectionToken<T>\n return this.resolve(realToken)\n }\n\n // Check request cache (request-scoped containers)\n if (this.isRequestScoped && this.requestCache.has(token)) {\n return this.requestCache.get(token) as T\n }\n\n // Check local registrations first\n const reg = this.registrations.get(token)\n if (reg) return this.resolveRegistration(token, reg) as T\n\n // Check parent chain — request-scoped containers resolve locally to access request values\n if (this.parent) {\n const parentReg = this.parent.findRegistration(token)\n if (parentReg) {\n if (this.isRequestScoped) {\n return this.resolveRegistration(token, parentReg) as T\n }\n return this.parent.resolve(token)\n }\n }\n\n // Auto-resolve class constructors: any class with DI decorators can be\n // instantiated without explicit registration\n if (typeof token === 'function') {\n const meta = getClassMetadata(token)\n const scope = meta?.scope ?? Scope.Transient\n const classReg: ClassRegistration = { kind: 'class', useClass: token as unknown as Constructor, scope }\n this.getRoot().registrations.set(token, classReg)\n return this.resolveClass(token, classReg) as T\n }\n\n throw new ContainerError(`No provider for ${tokenToString(token)}. Did you forget to register it?`)\n }\n\n tryResolve<T>(token: InjectionToken<T>): T | undefined {\n const realToken = isLazyToken(token) ? (token.factory() as InjectionToken<T>) : token\n\n // Only \"nothing is registered\" yields undefined for an optional dependency.\n // A provider that exists but throws while constructing is a real error and\n // must surface — swallowing it would silently inject `undefined` and turn a\n // bug into a baffling downstream failure.\n if (!this.isResolvable(realToken)) return undefined\n\n // An optional request-scoped dependency outside a request scope is absent,\n // not an error — mirrors `@inject(..., { isOptional: true })` semantics.\n if (!this.isRequestScoped && this.scopeForToken(realToken) === Scope.Request) return undefined\n\n return this.resolve(realToken)\n }\n\n isRegistered<T>(token: InjectionToken<T>): boolean {\n if (this.registrations.has(token)) return true\n return this.parent?.isRegistered(token) ?? false\n }\n\n /**\n * Whether a token has anything to resolve to: an explicit registration, or a\n * bare class constructor (auto-resolvable). Distinct from {@link isRegistered}\n * so {@link tryResolve} can tell \"no provider\" (→ undefined) apart from\n * \"provider exists but failed\" (→ rethrow).\n */\n private isResolvable(token: InjectionToken): boolean {\n return typeof token === 'function' || this.isRegistered(token)\n }\n\n // ── Conditional ───────────────────────────────────────────────\n\n when(\n predicate: (container: PredicateContainer) => boolean,\n options: WhenOptions = {},\n ): ConditionalBindingBuilder {\n return new ConditionalBindingBuilderImpl(this, predicate, options)\n }\n\n extend<T>(token: InjectionToken<T>, decorator: ExtensionDecorator<T>): void {\n const current = this.resolve<T>(token)\n const decorated = decorator(current, this)\n this.registerValue(token, decorated)\n }\n\n // ── Request Scope ─────────────────────────────────────────────\n\n async runInRequestScope<T>(\n routerContext: RouterContext,\n callback: (requestContainer: Container) => T | Promise<T>,\n ): Promise<T> {\n if (this.isRequestScoped) {\n throw new ContainerError('Cannot call runInRequestScope on a request-scoped container')\n }\n\n const requestContainer = this.createRequestScope(routerContext)\n return await containerStorage.run(requestContainer, () => callback(requestContainer))\n }\n\n createRequestScope(routerContext: RouterContext): Container {\n if (this.isRequestScoped) {\n throw new ContainerError('Cannot call createRequestScope on a request-scoped container')\n }\n\n const child = new Container({ parent: this, isRequestScoped: true })\n child.registerValue(ROUTER_TOKENS.RouterContext, routerContext)\n return child\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────\n\n /**\n * Disposes every container-instantiated instance that implements the\n * {@link Disposable} contract (singletons and request-cached instances),\n * then clears all registrations. Value registrations are not disposed —\n * the container doesn't own them. A failing disposer is logged and\n * skipped so it can't block the rest of the teardown.\n *\n * Instances are disposed in reverse creation order (LIFO): a disposer may\n * still use dependencies that were constructed before its own instance.\n */\n async dispose(): Promise<void> {\n const seen = new Set<unknown>()\n for (const instance of [...this.singletons.values(), ...this.requestCache.values()].reverse()) {\n if (seen.has(instance) || !isDisposable(instance)) continue\n seen.add(instance)\n try {\n await disposeInstance(instance)\n } catch (error) {\n console.error('[stratal] Failed to dispose instance during container teardown:', error)\n }\n }\n\n this.registrations.clear()\n this.singletons.clear()\n this.requestCache.clear()\n this.requestCacheDeps.clear()\n }\n\n // ── Internal ──────────────────────────────────────────────────\n\n /**\n * Transitive constructor dependency tokens of a class, with lazy tokens\n * unwrapped to the concrete token they resolve to. Recorded when a\n * request-scoped instance is cached so {@link invalidateRequestCache} can find\n * dependents.\n *\n * The walk follows class/alias registrations through transient intermediaries:\n * a cached service A that depends on a (non-cached) transient B which depends\n * on token C must still be invalidated when C is re-registered, even though B\n * itself is never cached. Value/factory/lazy providers are not traversed —\n * their dependencies aren't introspectable (factory) or would re-enter a\n * cycle (lazy). Over-collecting is safe: it only rebuilds extra request-scoped\n * instances, which is correct.\n */\n private collectDependencyTokens(Class: Constructor): Set<InjectionToken> {\n const deps = new Set<InjectionToken>()\n const visited = new Set<Constructor>()\n\n const walk = (cls: Constructor): void => {\n if (visited.has(cls)) return\n visited.add(cls)\n for (const { token } of getInjectionTokens(cls).values()) {\n const real = isLazyToken(token) ? token.factory() : token\n deps.add(real)\n const childClass = this.classForToken(real)\n if (childClass) walk(childClass)\n }\n }\n\n walk(Class)\n return deps\n }\n\n /** The implementing class for a token, following class/alias registrations. */\n private classForToken(token: InjectionToken): Constructor | undefined {\n const reg = this.findRegistration(token)\n if (reg) {\n if (reg.kind === 'class') return reg.useClass\n if (reg.kind === 'alias') return this.classForToken(reg.target)\n return undefined\n }\n // A bare constructor token that is auto-resolvable (carries DI metadata).\n if (typeof token === 'function' && getClassMetadata(token as Constructor)) {\n return token as unknown as Constructor\n }\n return undefined\n }\n\n /**\n * The effective scope a token would resolve with, following alias\n * registrations. Bare constructor tokens fall back to their decorator\n * metadata — the same scope {@link resolve} uses when auto-registering.\n */\n private scopeForToken(token: InjectionToken): Scope | undefined {\n const reg = this.findRegistration(token)\n if (reg) {\n if (reg.kind === 'class') return reg.scope\n if (reg.kind === 'alias') return this.scopeForToken(reg.target)\n // Same scope derivation `resolveRegistration` uses for lazy registrations\n if (reg.kind === 'lazy') return getClassMetadata(reg.factory())?.scope ?? Scope.Transient\n return undefined\n }\n if (typeof token === 'function') {\n return getClassMetadata(token as Constructor)?.scope\n }\n return undefined\n }\n\n /**\n * Evict a token from the request cache along with every cached request-scoped\n * instance that transitively depends on it. Re-registering a value must\n * rebuild its dependents (so they pick up the new value) while leaving\n * unrelated cached services intact.\n */\n private invalidateRequestCache(token: InjectionToken): void {\n const invalidated = new Set<InjectionToken>([token])\n\n let changed = true\n while (changed) {\n changed = false\n for (const [cachedToken, deps] of this.requestCacheDeps) {\n if (invalidated.has(cachedToken)) continue\n for (const dep of deps) {\n if (invalidated.has(dep)) {\n invalidated.add(cachedToken)\n changed = true\n break\n }\n }\n }\n }\n\n for (const t of invalidated) {\n this.requestCache.delete(t)\n this.requestCacheDeps.delete(t)\n }\n }\n\n private resolveRegistration(token: InjectionToken, reg: Registration): unknown {\n switch (reg.kind) {\n case 'value':\n return reg.value\n\n case 'alias':\n return this.resolve(reg.target)\n\n case 'factory':\n return reg.factory(this)\n\n case 'lazy': {\n const useClass = reg.factory()\n const scope = getClassMetadata(useClass)?.scope ?? Scope.Transient\n return this.resolveClass(token, { kind: 'class', useClass, scope })\n }\n\n case 'class':\n return this.resolveClass(token, reg)\n }\n }\n\n private resolveClass(token: InjectionToken, reg: ClassRegistration): unknown {\n const { useClass, scope } = reg\n\n // Singleton: check global cache (root or current)\n if (scope === Scope.Singleton) {\n const root = this.getRoot()\n if (root.singletons.has(token)) return root.singletons.get(token)\n // Always construct against the root container. Constructing against a\n // request-scoped child would let the singleton permanently capture that\n // one request's request-scoped dependencies (a captive dependency leaking\n // state across every later request on the isolate). Resolving a @Request\n // dependency from root instead throws the request-scope error below,\n // surfacing the illegal singleton→request dependency loudly.\n const instance = root.instantiate(useClass)\n root.singletons.set(token, instance)\n return instance\n }\n\n // Request: cache in the request-scoped container\n if (scope === Scope.Request) {\n if (!this.isRequestScoped) {\n throw new ContainerError(\n `Cannot resolve request-scoped provider ${tokenToString(token)} outside a request scope. ` +\n `Resolve it within an HTTP request, or via runInScope()/runInRequestScope() for queues, cron, and other non-HTTP entrypoints.`,\n )\n }\n if (this.requestCache.has(token)) return this.requestCache.get(token)\n const instance = this.instantiate(useClass)\n this.requestCache.set(token, instance)\n this.requestCacheDeps.set(token, this.collectDependencyTokens(useClass))\n return instance\n }\n\n // Transient: always new instance\n return this.instantiate(useClass)\n }\n\n private instantiate(Class: Constructor): unknown {\n const root = this.getRoot()\n\n // A class re-entering its own construction is a circular dependency. Detect\n // it and throw a clear error naming the cycle instead of recursing into a\n // stack overflow. `lazy()` only defers a forward *reference*, not\n // resolution, so it cannot break a true runtime cycle — the graph must be\n // refactored.\n if (root.resolutionStack.includes(Class)) {\n const cycle = [...root.resolutionStack, Class].map((c) => c.name).join(' → ')\n throw new ContainerError(\n `Circular dependency detected while constructing: ${cycle}. ` +\n `Break the cycle by extracting the shared dependency, or inject a provider/factory instead of the instance.`,\n )\n }\n\n root.resolutionStack.push(Class)\n try {\n const injections = getInjectionTokens(Class)\n\n // Without reflect-metadata there is no `design:paramtypes` fallback, so every\n // constructor dependency must carry an explicit @inject. A required parameter\n // with no entry would otherwise be silently injected as `undefined`; fail loud.\n if (injections.size === 0) {\n if (Class.length > 0) {\n throw new ContainerError(\n `${Class.name} has ${Class.length} required constructor parameter(s) but none are decorated with @inject. ` +\n `Every constructor dependency must be explicitly injected.`,\n )\n }\n return new Class()\n }\n\n const maxIndex = Math.max(...injections.keys())\n const args: unknown[] = new Array(maxIndex + 1)\n\n for (let index = 0; index <= maxIndex; index++) {\n const entry = injections.get(index)\n if (!entry) {\n throw new ContainerError(\n `${Class.name} is missing @inject on constructor parameter ${index}. ` +\n `Every constructor dependency must be explicitly injected.`,\n )\n }\n args[index] = entry.optional ? this.tryResolve(entry.token) : this.resolve(entry.token)\n }\n\n return new Class(...args)\n } finally {\n root.resolutionStack.pop()\n }\n }\n\n findRegistration(token: InjectionToken): Registration | undefined {\n const local = this.registrations.get(token)\n if (local) return local\n return this.parent?.findRegistration(token)\n }\n\n /**\n * The global (non-request-scoped) container at the top of the parent chain.\n * Lazy module loading registers providers here so singletons persist across\n * requests even when `load()` is called from within a request scope.\n */\n getRootContainer(): Container {\n return this.getRoot()\n }\n\n private getRoot(): Container {\n if (!this.parent) return this\n return this.parent.getRoot()\n }\n}\n"],"mappings":"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"}
|
package/dist/email/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fn as DynamicModule, Ir as ApplicationError, Nn as AsyncModuleOptions } from "../index-uybm0bhQ.mjs";
|
|
2
2
|
import { a as z } from "../zod-wecrEVAs.mjs";
|
|
3
3
|
import { a as QueueBinding } from "../consumer-registry-D3iMTSdy.mjs";
|
|
4
|
-
import { m as IQueueSender } from "../index-
|
|
4
|
+
import { m as IQueueSender } from "../index-CNuFQSNj.mjs";
|
|
5
5
|
import { ReactElement } from "react";
|
|
6
6
|
|
|
7
7
|
//#region src/email/email.error.d.ts
|
package/dist/email/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { p as inject, u as Transient } from "../di-D7qmrAir.mjs";
|
|
2
2
|
import { a as ApplicationError } from "../container-storage-BmOJ4_Na.mjs";
|
|
3
3
|
import { n as __decorateParam, t as __decorate } from "../decorate-CuAoSZvs.mjs";
|
|
4
4
|
import { LOGGER_TOKENS } from "../logger/index.mjs";
|
|
5
|
-
import "../errors-
|
|
5
|
+
import "../errors-C01O2T-n.mjs";
|
|
6
6
|
import { n as Module } from "../module.decorator-CYHY6pG5.mjs";
|
|
7
7
|
import "../module/index.mjs";
|
|
8
8
|
import { t as QUEUE_TOKENS } from "../queue.tokens-DjHnFmre.mjs";
|
|
9
9
|
import "../queue/index.mjs";
|
|
10
|
-
import { p as STORAGE_TOKENS } from "../storage-
|
|
10
|
+
import { p as STORAGE_TOKENS } from "../storage-C30X81CS.mjs";
|
|
11
11
|
import { r as z } from "../zod-eKqqhZ5_.mjs";
|
|
12
12
|
import { t as withZodI18n } from "../validation-CpOjviyT.mjs";
|
|
13
13
|
//#region src/email/email.error.ts
|