sqlstack 3.5.0 → 3.6.0-dev.0
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/cjs/codegen/generateManifest.d.ts +3 -1
- package/dist/cjs/codegen/generateManifest.d.ts.map +1 -1
- package/dist/cjs/codegen/generateManifest.js +195 -3
- package/dist/cjs/codegen/generateManifest.js.map +1 -1
- package/dist/cjs/core/fileResolution.d.ts +7 -0
- package/dist/cjs/core/fileResolution.d.ts.map +1 -1
- package/dist/cjs/core/fileResolution.js +53 -14
- package/dist/cjs/core/fileResolution.js.map +1 -1
- package/dist/cjs/core/metadata.d.ts +5 -0
- package/dist/cjs/core/metadata.d.ts.map +1 -1
- package/dist/cjs/core/metadata.js.map +1 -1
- package/dist/cjs/core/resources.d.ts +36 -0
- package/dist/cjs/core/resources.d.ts.map +1 -0
- package/dist/cjs/core/resources.js +98 -0
- package/dist/cjs/core/resources.js.map +1 -0
- package/dist/cjs/core/sourceScanResolver.d.ts +8 -14
- package/dist/cjs/core/sourceScanResolver.d.ts.map +1 -1
- package/dist/cjs/core/sourceScanResolver.js +8 -20
- package/dist/cjs/core/sourceScanResolver.js.map +1 -1
- package/dist/cjs/decorators/query.d.ts.map +1 -1
- package/dist/cjs/decorators/query.js +96 -35
- package/dist/cjs/decorators/query.js.map +1 -1
- package/dist/cjs/family.d.ts.map +1 -1
- package/dist/cjs/family.js +3 -1
- package/dist/cjs/family.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/run.d.ts +44 -4
- package/dist/cjs/run.d.ts.map +1 -1
- package/dist/cjs/run.js +38 -7
- package/dist/cjs/run.js.map +1 -1
- package/dist/cjs/runtime.d.ts +6 -0
- package/dist/cjs/runtime.d.ts.map +1 -1
- package/dist/cjs/runtime.js +18 -0
- package/dist/cjs/runtime.js.map +1 -1
- package/dist/cjs/stack.d.ts +14 -0
- package/dist/cjs/stack.d.ts.map +1 -1
- package/dist/cjs/stack.js +20 -0
- package/dist/cjs/stack.js.map +1 -1
- package/dist/cjs/transactions.d.ts +52 -0
- package/dist/cjs/transactions.d.ts.map +1 -1
- package/dist/cjs/transactions.js +557 -3
- package/dist/cjs/transactions.js.map +1 -1
- package/dist/esm/codegen/generateManifest.js +195 -3
- package/dist/esm/codegen/generateManifest.js.map +1 -1
- package/dist/esm/core/fileResolution.js +52 -14
- package/dist/esm/core/fileResolution.js.map +1 -1
- package/dist/esm/core/metadata.js.map +1 -1
- package/dist/esm/core/resources.js +91 -0
- package/dist/esm/core/resources.js.map +1 -0
- package/dist/esm/core/sourceScanResolver.js +8 -19
- package/dist/esm/core/sourceScanResolver.js.map +1 -1
- package/dist/esm/decorators/query.js +101 -40
- package/dist/esm/decorators/query.js.map +1 -1
- package/dist/esm/family.js +3 -1
- package/dist/esm/family.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/run.js +38 -8
- package/dist/esm/run.js.map +1 -1
- package/dist/esm/runtime.js +17 -0
- package/dist/esm/runtime.js.map +1 -1
- package/dist/esm/stack.js +21 -1
- package/dist/esm/stack.js.map +1 -1
- package/dist/esm/transactions.js +554 -3
- package/dist/esm/transactions.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +74 -133
package/dist/cjs/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport { SqlStackError, DatabaseError } from './core/errors';\nimport type { Dialect } from './registry';\nimport { SqlFragment, isSqlFragment, compileFragment } from './sql';\nimport { resolveExecution } from './runtime';\nimport type { SqlResolver } from './core/resolver';\nimport { getActiveTransaction, getActiveTransactionForDatabase } from './transactions';\nimport type { ActiveTransaction } from './transactions';\n\n/**\n * Anything run(db, ...) can execute against: sqlstack's own `Database`\n * (from createSqliteDb/createPgDb/createMysqlDb), or any application handle\n * exposing `query(sql, params)`. `dialect` selects placeholder style and\n * defaults to `'sqlite'` when absent. run never opens databases by path.\n */\nexport interface RunDatabase {\n readonly dialect?: Dialect;\n query(sql: string, params: unknown[]): Promise<unknown>;\n}\n\n/**\n * Type-level guard for the params form of run: rejects the\n * `{ sql, params }` object returned by `fragment.toSQL()`. Pass the sql``\n * fragment itself instead, so run owns dialect binding and error handling.\n */\nexport type RejectCompiledSql<P> = P extends { readonly sql: string; readonly params: readonly unknown[] }\n ? never\n : unknown;\n\n/**\n * What a run(...) call made inside a @Query body asks of the wrapper's\n * pipeline. `default` is the zero-argument run().\n */\nexport type RunInvocation =\n | { readonly kind: 'default' }\n | { readonly kind: 'fragment'; readonly db?: RunDatabase | string; readonly fragment: SqlFragment }\n | { readonly kind: 'params'; readonly db: RunDatabase | string; readonly params: object };\n\n/**\n * Per-invocation context established by the @Query wrapper before the method\n * body executes. `execute` performs the full query pipeline (resolve SQL,\n * bind, execute, shape/transform/validate); `ran` records that the body\n * invoked run(), so the wrapper returns the body's result verbatim instead\n * of falling through to the legacy pipeline. `invocations` marks a wrapper\n * that understands the argument-taking run forms (an older duplicated copy\n * of the decorator would silently ignore them).\n */\nexport type RunContext = {\n execute: (invocation?: RunInvocation) => Promise<unknown>;\n ran: boolean;\n invocations?: true;\n};\n\n// Anchored on globalThis via Symbol.for so duplicated module instances\n// (npm link, dual ESM/CJS loads) share one channel between the decorator\n// and the run() the application imports.\nconst RUN_CHANNEL = Symbol.for('noego.sqlstack.runContext');\nconst anchor = globalThis as Record<PropertyKey, unknown>;\nif (!anchor[RUN_CHANNEL]) {\n anchor[RUN_CHANNEL] = new AsyncLocalStorage<RunContext>();\n}\nexport const runStorage = anchor[RUN_CHANNEL] as AsyncLocalStorage<RunContext>;\n\n/**\n * Execute the current @Query method's SQL and return the finished result.\n * Call it as the body of a @Query-decorated method:\n *\n * @Query()\n * async getUsers(active: boolean): Promise<User[]> {\n * return run();\n * }\n *\n * Takes no arguments — the method's own arguments, database, SQL source,\n * transaction, shaping, transform, and validation all come from the\n * decorator context. T is inferred from the method's declared return type.\n *\n * @throws {DatabaseError} When the driver rejects the statement (original\n * error in `.cause`).\n * @throws {SqlStackError} When called outside a @Query method, or for\n * shape/validation failures (ExactlyOneRowError, NoRowsError, ValidationError, ...).\n */\nexport function run<T = any>(): Promise<T>;\n/**\n * Inside a @Query method: execute this inline sql`` fragment instead of the\n * method's SQL file. The database comes from the method/class/registry\n * context (`@Query({ db })`, `@QueryBinder({ db })`, the default), the\n * active transaction on it is joined, and the method's shape/transform/\n * validation decorators apply. The method's arguments are not auto-bound —\n * the fragment's `${}` values are the parameters.\n *\n * @Single @Query()\n * async byEmail(email: string): Promise<User | null> {\n * return run(sql`SELECT * FROM users WHERE email = ${email}`);\n * }\n *\n * @throws {DatabaseError} When the fragment cannot be compiled (macro input\n * errors), the database cannot be resolved, or the driver rejects the\n * statement. The original error is in `.cause`.\n * @throws {SqlStackError} When called outside a @Query method (use\n * `run(db, query)` there), or for shape/validation failures.\n */\nexport function run<T = unknown>(query: SqlFragment): Promise<T>;\n/**\n * Execute an sql`` fragment against an explicit database: a handle\n * (anything with `query(sql, params)`) or the name of a database registered\n * with the active SqlStack / legacy registry. Usable anywhere.\n *\n * Binds for the database's dialect (`$1..` for Postgres, `?` otherwise;\n * default sqlite). Joins an active transaction opened on the same database\n * (same registered handle, or same name). Outside a @Query method the raw\n * result is returned (rows array, or `{ rowsAffected }` for writes); inside\n * one, the method's shape/transform/validation decorators apply.\n *\n * const rows = await run<Row[]>(accountsDb, sql`SELECT * FROM t WHERE id = ${id}`);\n *\n * @throws {DatabaseError} When the fragment cannot be compiled, a named\n * database cannot be resolved, or the driver rejects the statement. The\n * original error is in `.cause`, and its string `code` is copied to `.code`.\n * @throws {SqlStackError} For invalid arguments, or shape/validation failures.\n */\nexport function run<T = unknown>(db: RunDatabase | string, query: SqlFragment): Promise<T>;\n/**\n * Inside a @Query method: run the method's own SQL (its .sql file or inline\n * `@Query({ sql })`) against `db`, binding `params` (an object for `:named`\n * placeholders, an array for `:arg1..`). The method's raw arguments are NOT\n * auto-bound in this form — `params` is the whole binding input. @Defaults,\n * @Page, shaping, transform, and validation still apply.\n *\n * @Single @Query()\n * async byEmail(db: Database, p: { email: string }): Promise<User | null> {\n * return run(db, p);\n * }\n *\n * @throws {DatabaseError} When binding fails, a named database cannot be\n * resolved, or the driver rejects the statement. The original error is in\n * `.cause`.\n * @throws {SqlStackError} When called outside a @Query method, when passed\n * `.toSQL()` output, or for shape/validation failures.\n */\nexport function run<T = unknown, P extends object = object>(\n db: RunDatabase | string,\n params: P & RejectCompiledSql<P>\n): Promise<T>;\nexport async function run(...args: unknown[]): Promise<unknown> {\n const invocation = parseRunArgs(args);\n const ctx = runStorage.getStore();\n\n if (!ctx) {\n if (invocation.kind === 'fragment' && invocation.db !== undefined) {\n return executeFragment(invocation.db, invocation.fragment);\n }\n if (invocation.kind === 'default') {\n throw new SqlStackError(\n 'run() called outside a @Query method. It may only be invoked from the body of a @Query-decorated method.'\n );\n }\n if (invocation.kind === 'fragment') {\n throw new SqlStackError(\n 'run(query) called outside a @Query method has no database. Pass one explicitly: run(db, query).'\n );\n }\n throw new SqlStackError(\n 'run(db, params) called outside a @Query method has no SQL source. ' +\n 'Pass an sql`` fragment instead: run(db, sql`...`).'\n );\n }\n\n if (invocation.kind !== 'default' && !ctx.invocations) {\n throw new SqlStackError(\n 'run(...) with arguments reached a @Query wrapper from an older sqlstack copy that cannot honour them. ' +\n 'Make sure a single sqlstack version is installed.'\n );\n }\n\n ctx.ran = true;\n return invocation.kind === 'default' ? ctx.execute() : ctx.execute(invocation);\n}\n\nfunction parseRunArgs(args: unknown[]): RunInvocation {\n if (args.length === 0) return { kind: 'default' };\n\n if (args.length === 1) {\n const [query] = args;\n if (isSqlFragment(query)) return { kind: 'fragment', fragment: query };\n throw new SqlStackError(\n typeof query === 'string'\n ? 'run(query) does not accept SQL strings. Build the statement with the sql`` tag: run(sql`...`).'\n : 'run(query) requires an sql`` fragment.'\n );\n }\n\n if (args.length === 2) {\n const [db, second] = args;\n assertRunDatabase(db);\n if (isSqlFragment(second)) return { kind: 'fragment', db, fragment: second };\n if (typeof second === 'string') {\n throw new SqlStackError(\n 'run(db, query) does not accept SQL strings. Build the statement with the sql`` tag: run(db, sql`...`).'\n );\n }\n if (isCompiledSql(second)) {\n throw new SqlStackError(\n 'run(db, ...) received the { sql, params } output of .toSQL(). Pass the sql`` fragment itself so run can ' +\n 'bind it for the target dialect: run(db, sql`...`).'\n );\n }\n if (typeof second === 'object' && second !== null) return { kind: 'params', db, params: second };\n throw new SqlStackError('run(db, x) requires an sql`` fragment or a params object/array as its second argument.');\n }\n\n throw new SqlStackError(`run() accepts at most 2 arguments, got ${args.length}.`);\n}\n\nfunction assertRunDatabase(db: unknown): asserts db is RunDatabase | string {\n if (typeof db === 'string' && db.length > 0) return;\n if (typeof db === 'object' && db !== null && typeof (db as { query?: unknown }).query === 'function') return;\n throw new SqlStackError(\n 'run(db, ...) requires a database handle with query(sql, params) or a registered database name as its first argument.'\n );\n}\n\nfunction isCompiledSql(value: unknown): boolean {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const keys = Object.keys(value);\n const rec = value as { sql?: unknown; params?: unknown };\n return keys.length === 2 && typeof rec.sql === 'string' && Array.isArray(rec.params);\n}\n\n// ---------------------------------------------------------------------------\n// Shared execution helpers (also used by the @Query wrapper)\n// ---------------------------------------------------------------------------\n\n/** @internal A database chosen for one run, plus the transaction it joins. */\nexport type RunTarget = {\n readonly db: RunDatabase;\n readonly tx: ActiveTransaction | undefined;\n /** SQL resolver of the environment, when the target was resolved by name. */\n readonly resolver: SqlResolver | undefined;\n readonly byName: boolean;\n};\n\n/**\n * @internal Resolve run's database argument. A name goes through the active\n * SqlStack (or legacy registry) and joins that entry's transaction. A handle\n * is used as-is — no registry lookup, so it works without any SqlStack — and\n * joins an active transaction only if one is open on that same handle.\n */\nexport async function resolveRunTarget(db: RunDatabase | string): Promise<RunTarget> {\n if (typeof db === 'string') {\n const { entry, resolver } = await resolveExecution(db);\n return { db: entry.db, tx: getActiveTransaction(entry), resolver, byName: true };\n }\n return { db, tx: getActiveTransactionForDatabase(db), resolver: undefined, byName: false };\n}\n\n/** @internal Run one bound statement on the target (inside its transaction, if any). */\nexport async function executeOnTarget(target: RunTarget, boundSql: string, params: unknown[]): Promise<unknown> {\n try {\n return target.tx ? await target.tx.query(boundSql, params) : await target.db.query(boundSql, params);\n } catch (dbError) {\n throw toDatabaseError(dbError, boundSql);\n }\n}\n\n/**\n * @internal Normalize a failure from run's argument-taking forms: errors that\n * are already SqlStackError (DatabaseError, shape/validation errors) pass\n * through; anything else becomes DatabaseError with the original in `.cause`.\n */\nexport function toRunError(err: unknown, sqlText: string): SqlStackError {\n return err instanceof SqlStackError ? err : toDatabaseError(err, sqlText);\n}\n\nfunction toDatabaseError(err: unknown, sqlText: string): DatabaseError {\n const message = (err as { message?: unknown } | undefined)?.message;\n return new DatabaseError(\n typeof message === 'string' && message ? message : String(err),\n sqlText,\n err instanceof Error ? err : undefined\n );\n}\n\n/** @internal Raw template text of a fragment, for error messages. */\nexport function fragmentText(fragment: SqlFragment): string {\n return fragment.strings.join('?');\n}\n\n/** @internal Compile a fragment for the dialect, wrapping macro errors. */\nexport function compileForRun(fragment: SqlFragment, dialect: Dialect): { sql: string; params: unknown[] } {\n try {\n return compileFragment(fragment, dialect);\n } catch (err) {\n throw toRunError(err, fragmentText(fragment));\n }\n}\n\nasync function executeFragment(db: RunDatabase | string, fragment: SqlFragment): Promise<unknown> {\n let target: RunTarget;\n try {\n target = await resolveRunTarget(db);\n } catch (err) {\n throw toRunError(err, fragmentText(fragment));\n }\n const { sql: boundSql, params } = compileForRun(fragment, target.db.dialect ?? 'sqlite');\n return executeOnTarget(target, boundSql, params);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport { SqlStackError, DatabaseError } from './core/errors';\nimport type { Dialect } from './registry';\nimport { SqlFragment, isSqlFragment, compileFragment } from './sql';\nimport { resolveExecution } from './runtime';\nimport type { SqlResolver } from './core/resolver';\nimport { getTransactionTarget, getTransactionTargetForHandle } from './transactions';\nimport type { ActiveTransaction } from './transactions';\n\n/**\n * Anything run(db, ...) can execute against: sqlstack's own `Database`\n * (from createSqliteDb/createPgDb/createMysqlDb), or any application handle\n * exposing `query(sql, params)`. `dialect` selects placeholder style and\n * defaults to `'sqlite'` when absent. run never opens databases by path.\n */\nexport interface RunDatabase {\n readonly dialect?: Dialect;\n query(sql: string, params: unknown[]): Promise<unknown>;\n}\n\n/**\n * Type-level guard for the params form of run: rejects the\n * `{ sql, params }` object returned by `fragment.toSQL()`. Pass the sql``\n * fragment itself instead, so run owns dialect binding and error handling.\n */\nexport type RejectCompiledSql<P> = P extends { readonly sql: string; readonly params: readonly unknown[] }\n ? never\n : unknown;\n\n/**\n * What a run(...) call made inside a @Query body asks of the wrapper's\n * pipeline. `default` is the zero-argument run().\n */\nexport type RunInvocation =\n | { readonly kind: 'default' }\n | { readonly kind: 'fragment'; readonly db?: RunDatabase | string; readonly fragment: SqlFragment }\n | { readonly kind: 'params'; readonly db?: RunDatabase | string; readonly params: object }\n | { readonly kind: 'db'; readonly db: RunDatabase | string };\n\n/**\n * Type-level guard for run(db) with a name: a string containing whitespace is\n * SQL text, never a database name. Build statements with the sql`` tag.\n */\nexport type RejectSqlText<D> = D extends string\n ? D extends `${string} ${string}` | `${string}\\n${string}` | `${string}\\t${string}`\n ? never\n : unknown\n : unknown;\n\n/**\n * Per-invocation context established by the @Query wrapper before the method\n * body executes. `execute` performs the full query pipeline (resolve SQL,\n * bind, execute, shape/transform/validate); `ran` records that the body\n * invoked run(), so the wrapper returns the body's result verbatim instead\n * of falling through to the legacy pipeline. `invocations` marks a wrapper\n * that understands the argument-taking run forms (an older duplicated copy\n * of the decorator would silently ignore them).\n */\nexport type RunContext = {\n execute: (invocation?: RunInvocation) => Promise<unknown>;\n ran: boolean;\n invocations?: true;\n};\n\n// Anchored on globalThis via Symbol.for so duplicated module instances\n// (npm link, dual ESM/CJS loads) share one channel between the decorator\n// and the run() the application imports.\nconst RUN_CHANNEL = Symbol.for('noego.sqlstack.runContext');\nconst anchor = globalThis as Record<PropertyKey, unknown>;\nif (!anchor[RUN_CHANNEL]) {\n anchor[RUN_CHANNEL] = new AsyncLocalStorage<RunContext>();\n}\nexport const runStorage = anchor[RUN_CHANNEL] as AsyncLocalStorage<RunContext>;\n\n/**\n * Execute the current @Query method's SQL and return the finished result.\n * Call it as the body of a @Query-decorated method:\n *\n * @Query()\n * async getUsers(active: boolean): Promise<User[]> {\n * return run();\n * }\n *\n * Takes no arguments — the method's own arguments, database, SQL source,\n * transaction, shaping, transform, and validation all come from the\n * decorator context — except that a leading method argument that is a\n * database handle (or a registered database name) selects the database and\n * is not bound. T is inferred from the method's declared return type.\n *\n * @throws {DatabaseError} When the driver rejects the statement (original\n * error in `.cause`).\n * @throws {SqlStackError} When called outside a @Query method, or for\n * shape/validation failures (ExactlyOneRowError, NoRowsError, ValidationError, ...).\n */\nexport function run<T = any>(): Promise<T>;\n/**\n * Inside a @Query method: execute this inline sql`` fragment instead of the\n * method's SQL file. The database comes from the method/class/registry\n * context (`@Query({ db })`, `@QueryBinder({ db })`, the default), the\n * active transaction on it is joined, and the method's shape/transform/\n * validation decorators apply. The method's arguments are not auto-bound —\n * the fragment's `${}` values are the parameters.\n *\n * @Single @Query()\n * async byEmail(email: string): Promise<User | null> {\n * return run(sql`SELECT * FROM users WHERE email = ${email}`);\n * }\n *\n * @throws {DatabaseError} When the fragment cannot be compiled (macro input\n * errors), the database cannot be resolved, or the driver rejects the\n * statement. The original error is in `.cause`.\n * @throws {SqlStackError} When called outside a @Query method (use\n * `run(db, query)` there), or for shape/validation failures.\n */\nexport function run<T = unknown>(query: SqlFragment): Promise<T>;\n/**\n * Execute an sql`` fragment against an explicit database: a handle\n * (anything with `query(sql, params)`) or the name of a database registered\n * with the active SqlStack / legacy registry. Usable anywhere.\n *\n * Binds for the database's dialect (`$1..` for Postgres, `?` otherwise;\n * default sqlite). Joins an active transaction opened on the same database\n * (same registered handle, or same name). Outside a @Query method the raw\n * result is returned (rows array, or `{ rowsAffected }` for writes); inside\n * one, the method's shape/transform/validation decorators apply.\n *\n * const rows = await run<Row[]>(accountsDb, sql`SELECT * FROM t WHERE id = ${id}`);\n *\n * @throws {DatabaseError} When the fragment cannot be compiled, a named\n * database cannot be resolved, or the driver rejects the statement. The\n * original error is in `.cause`, and its string `code` is copied to `.code`.\n * @throws {SqlStackError} For invalid arguments, or shape/validation failures.\n */\nexport function run<T = unknown>(db: RunDatabase | string, query: SqlFragment): Promise<T>;\n/**\n * Inside a @Query method: run the method's own SQL (its .sql file or inline\n * `@Query({ sql })`) against `db`, binding `params` (an object for `:named`\n * placeholders, an array for `:arg1..`). The method's raw arguments are NOT\n * auto-bound in this form — `params` is the whole binding input. @Defaults,\n * @Page, shaping, transform, and validation still apply.\n *\n * @Single @Query()\n * async byEmail(db: Database, p: { email: string }): Promise<User | null> {\n * return run(db, p);\n * }\n *\n * @throws {DatabaseError} When binding fails, a named database cannot be\n * resolved, or the driver rejects the statement. The original error is in\n * `.cause`.\n * @throws {SqlStackError} When called outside a @Query method, when passed\n * `.toSQL()` output, or for shape/validation failures.\n */\nexport function run<T = unknown, P extends object = object>(\n db: RunDatabase | string,\n params: P & RejectCompiledSql<P>\n): Promise<T>;\n/**\n * Inside a @Query method: run the method's own SQL against `db` (a handle or\n * a registered database name), binding the method's own arguments exactly as\n * run() does — except that a leading database handle/name argument of the\n * method is never bound.\n *\n * @throws {DatabaseError} When binding fails, a named database cannot be\n * resolved, or the driver rejects the statement.\n * @throws {SqlStackError} When called outside a @Query method, or for\n * shape/validation failures.\n */\nexport function run<T = unknown, D extends RunDatabase | string = RunDatabase | string>(\n db: D & RejectSqlText<D>\n): Promise<T>;\n/**\n * Inside a @Query method: run the method's own SQL binding only `params` (an\n * object for `:named`, an array for `:argN`) against the database run() would\n * use: the method's leading database handle/name argument, else the\n * decorator context.\n *\n * @throws {DatabaseError} When binding fails, the database cannot be\n * resolved, or the driver rejects the statement.\n * @throws {SqlStackError} When called outside a @Query method, when passed\n * `.toSQL()` output, or for shape/validation failures.\n */\nexport function run<T = unknown, P extends object = object>(params: P & RejectCompiledSql<P>): Promise<T>;\nexport async function run(...args: unknown[]): Promise<unknown> {\n const invocation = parseRunArgs(args);\n const ctx = runStorage.getStore();\n\n if (!ctx) {\n if (invocation.kind === 'fragment' && invocation.db !== undefined) {\n return executeFragment(invocation.db, invocation.fragment);\n }\n if (invocation.kind === 'default') {\n throw new SqlStackError(\n 'run() called outside a @Query method. It may only be invoked from the body of a @Query-decorated method.'\n );\n }\n if (invocation.kind === 'fragment') {\n throw new SqlStackError(\n 'run(query) called outside a @Query method has no database. Pass one explicitly: run(db, query).'\n );\n }\n if (invocation.kind === 'db') {\n throw new SqlStackError(\n 'run(db) called outside a @Query method has no SQL source. Pass an sql`` fragment instead: run(db, sql`...`).'\n );\n }\n if (invocation.db === undefined) {\n throw new SqlStackError(\n 'run(params) called outside a @Query method has no SQL source or database. ' +\n 'Pass a database and an sql`` fragment instead: run(db, sql`...`).'\n );\n }\n throw new SqlStackError(\n 'run(db, params) called outside a @Query method has no SQL source. ' +\n 'Pass an sql`` fragment instead: run(db, sql`...`).'\n );\n }\n\n if (invocation.kind !== 'default' && !ctx.invocations) {\n throw new SqlStackError(\n 'run(...) with arguments reached a @Query wrapper from an older sqlstack copy that cannot honour them. ' +\n 'Make sure a single sqlstack version is installed.'\n );\n }\n\n ctx.ran = true;\n return invocation.kind === 'default' ? ctx.execute() : ctx.execute(invocation);\n}\n\nfunction parseRunArgs(args: unknown[]): RunInvocation {\n if (args.length === 0) return { kind: 'default' };\n\n if (args.length === 1) {\n const [query] = args;\n if (isSqlFragment(query)) return { kind: 'fragment', fragment: query };\n if (typeof query === 'string') {\n // A whitespace-free string is a database name: run(db).\n if (isDatabaseNameText(query)) return { kind: 'db', db: query };\n throw new SqlStackError(\n 'run(query) does not accept SQL strings. Build the statement with the sql`` tag: run(sql`...`).'\n );\n }\n if (isRunDatabaseHandle(query)) return { kind: 'db', db: query };\n if (isCompiledSql(query)) {\n throw new SqlStackError(\n 'run(...) received the { sql, params } output of .toSQL(). Pass the sql`` fragment itself so run can ' +\n 'bind it for the target dialect: run(sql`...`).'\n );\n }\n if (typeof query === 'object' && query !== null) return { kind: 'params', params: query };\n throw new SqlStackError(\n 'run(x) requires an sql`` fragment, a params object/array, or a database handle/name.'\n );\n }\n\n if (args.length === 2) {\n const [db, second] = args;\n assertRunDatabase(db);\n if (isSqlFragment(second)) return { kind: 'fragment', db, fragment: second };\n if (typeof second === 'string') {\n throw new SqlStackError(\n 'run(db, query) does not accept SQL strings. Build the statement with the sql`` tag: run(db, sql`...`).'\n );\n }\n if (isCompiledSql(second)) {\n throw new SqlStackError(\n 'run(db, ...) received the { sql, params } output of .toSQL(). Pass the sql`` fragment itself so run can ' +\n 'bind it for the target dialect: run(db, sql`...`).'\n );\n }\n if (typeof second === 'object' && second !== null) return { kind: 'params', db, params: second };\n throw new SqlStackError('run(db, x) requires an sql`` fragment or a params object/array as its second argument.');\n }\n\n throw new SqlStackError(`run() accepts at most 2 arguments, got ${args.length}.`);\n}\n\n/** @internal A database handle: any object exposing query(sql, params). */\nexport function isRunDatabaseHandle(value: unknown): value is RunDatabase {\n return typeof value === 'object' && value !== null && typeof (value as { query?: unknown }).query === 'function';\n}\n\nfunction isDatabaseNameText(value: string): boolean {\n return value.length > 0 && !/\\s/.test(value);\n}\n\nfunction assertRunDatabase(db: unknown): asserts db is RunDatabase | string {\n if (typeof db === 'string' && db.length > 0) return;\n if (typeof db === 'object' && db !== null && typeof (db as { query?: unknown }).query === 'function') return;\n throw new SqlStackError(\n 'run(db, ...) requires a database handle with query(sql, params) or a registered database name as its first argument.'\n );\n}\n\nfunction isCompiledSql(value: unknown): boolean {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const keys = Object.keys(value);\n const rec = value as { sql?: unknown; params?: unknown };\n return keys.length === 2 && typeof rec.sql === 'string' && Array.isArray(rec.params);\n}\n\n// ---------------------------------------------------------------------------\n// Shared execution helpers (also used by the @Query wrapper)\n// ---------------------------------------------------------------------------\n\n/** @internal A database chosen for one run, plus the transaction it joins. */\nexport type RunTarget = {\n readonly db: RunDatabase;\n readonly tx: ActiveTransaction | undefined;\n /** SQL resolver of the environment, when the target was resolved by name. */\n readonly resolver: SqlResolver | undefined;\n readonly byName: boolean;\n};\n\n/**\n * @internal Resolve run's database argument. A name goes through the active\n * SqlStack (or legacy registry) and joins that entry's transaction — or,\n * inside a @transaction scope with none open, opens one on first execution. A handle\n * is used as-is — no registry lookup, so it works without any SqlStack — and\n * behaves the same: it joins a transaction open in this flow on that same\n * object, or, inside a @transaction scope with none open, opens one on the\n * handle on first execution. Outside any scope a handle with no open\n * transaction runs directly.\n */\nexport async function resolveRunTarget(db: RunDatabase | string): Promise<RunTarget> {\n if (typeof db === 'string') {\n const { entry, resolver } = await resolveExecution(db);\n return { db: entry.db, tx: getTransactionTarget(entry), resolver, byName: true };\n }\n return { db, tx: getTransactionTargetForHandle(db), resolver: undefined, byName: false };\n}\n\n/** @internal Run one bound statement on the target (inside its transaction, if any). */\nexport async function executeOnTarget(target: RunTarget, boundSql: string, params: unknown[]): Promise<unknown> {\n try {\n return target.tx ? await target.tx.query(boundSql, params) : await target.db.query(boundSql, params);\n } catch (dbError) {\n throw toDatabaseError(dbError, boundSql);\n }\n}\n\n/**\n * @internal Normalize a failure from run's argument-taking forms: errors that\n * are already SqlStackError (DatabaseError, shape/validation errors) pass\n * through; anything else becomes DatabaseError with the original in `.cause`.\n */\nexport function toRunError(err: unknown, sqlText: string): SqlStackError {\n return err instanceof SqlStackError ? err : toDatabaseError(err, sqlText);\n}\n\nfunction toDatabaseError(err: unknown, sqlText: string): DatabaseError {\n const message = (err as { message?: unknown } | undefined)?.message;\n return new DatabaseError(\n typeof message === 'string' && message ? message : String(err),\n sqlText,\n err instanceof Error ? err : undefined\n );\n}\n\n/** @internal Raw template text of a fragment, for error messages. */\nexport function fragmentText(fragment: SqlFragment): string {\n return fragment.strings.join('?');\n}\n\n/** @internal Compile a fragment for the dialect, wrapping macro errors. */\nexport function compileForRun(fragment: SqlFragment, dialect: Dialect): { sql: string; params: unknown[] } {\n try {\n return compileFragment(fragment, dialect);\n } catch (err) {\n throw toRunError(err, fragmentText(fragment));\n }\n}\n\nasync function executeFragment(db: RunDatabase | string, fragment: SqlFragment): Promise<unknown> {\n let target: RunTarget;\n try {\n target = await resolveRunTarget(db);\n } catch (err) {\n throw toRunError(err, fragmentText(fragment));\n }\n const { sql: boundSql, params } = compileForRun(fragment, target.db.dialect ?? 'sqlite');\n return executeOnTarget(target, boundSql, params);\n}\n"]}
|
package/dist/cjs/runtime.d.ts
CHANGED
|
@@ -28,6 +28,12 @@ export declare function resolveExecution(dbName?: string): Promise<ResolvedExecu
|
|
|
28
28
|
* error when that environment has no SqlStack), else the legacy global one.
|
|
29
29
|
*/
|
|
30
30
|
export declare function resolveSqlResolver(): Promise<SqlResolver | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* @internal Whether `name` is a database (or family) registered with the
|
|
33
|
+
* active environment: the active root's SqlStack, else the legacy global
|
|
34
|
+
* registry. Never throws; an environment that cannot answer reports false.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isRegisteredDatabaseName(name: string): Promise<boolean>;
|
|
31
37
|
/** @internal Resolve a legacy global-registry database as a DatabaseEntry. */
|
|
32
38
|
export declare function legacyEntry(dbName?: string): DatabaseEntry;
|
|
33
39
|
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAyCnD,6DAA6D;AAC7D,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAkBD;;;;;;GAMG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAyBpE;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,WAAW,GAAG,SAAS,CAAC;IAClC,gEAAgE;IAChE,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAUlF;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAG3E;AAgBD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAQ1D"}
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAyCnD,6DAA6D;AAC7D,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAkBD;;;;;;GAMG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAyBpE;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,WAAW,GAAG,SAAS,CAAC;IAClC,gEAAgE;IAChE,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAUlF;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAG3E;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS7E;AAgBD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAQ1D"}
|
package/dist/cjs/runtime.js
CHANGED
|
@@ -37,6 +37,7 @@ exports.__resetIocDetection = __resetIocDetection;
|
|
|
37
37
|
exports.activeSqlStack = activeSqlStack;
|
|
38
38
|
exports.resolveExecution = resolveExecution;
|
|
39
39
|
exports.resolveSqlResolver = resolveSqlResolver;
|
|
40
|
+
exports.isRegisteredDatabaseName = isRegisteredDatabaseName;
|
|
40
41
|
exports.legacyEntry = legacyEntry;
|
|
41
42
|
const stack_1 = require("./stack");
|
|
42
43
|
const registry_1 = require("./registry");
|
|
@@ -123,6 +124,23 @@ async function resolveSqlResolver() {
|
|
|
123
124
|
const stack = await activeSqlStack();
|
|
124
125
|
return stack ? stack.resolver() : (0, resolver_1.getActiveResolver)();
|
|
125
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* @internal Whether `name` is a database (or family) registered with the
|
|
129
|
+
* active environment: the active root's SqlStack, else the legacy global
|
|
130
|
+
* registry. Never throws; an environment that cannot answer reports false.
|
|
131
|
+
*/
|
|
132
|
+
async function isRegisteredDatabaseName(name) {
|
|
133
|
+
try {
|
|
134
|
+
const stack = await activeSqlStack();
|
|
135
|
+
if (stack)
|
|
136
|
+
return stack.has(name);
|
|
137
|
+
registry_1.SqlStackDB.getEntry(name);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
126
144
|
// ---------------------------------------------------------------------------
|
|
127
145
|
// Legacy (deprecated) global-registry support
|
|
128
146
|
// ---------------------------------------------------------------------------
|
package/dist/cjs/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,kDAEC;AAyBD,wCAyBC;AAYD,4CAUC;AASD,gDAGC;AAiBD,kCAQC;
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { SqlStack, DatabaseEntry } from './stack';\nimport { SqlStackDB } from './registry';\nimport type { Database } from './registry';\nimport type { SqlResolver } from './core/resolver';\nimport { getActiveResolver } from './core/resolver';\nimport { SqlStackError } from './core/errors';\n\n/**\n * Active-environment resolution for @Query and transactions (spec 16 §17,\n * repo spec 19 §7/§9).\n *\n * Canonical path: the active IoC execution context (owned by @noego/ioc)\n * supplies the current scope; the scope resolves its root's SqlStack\n * Singleton. When an IoC environment is active, the process-global legacy\n * registry is NEVER consulted — legacy state cannot override an active root.\n *\n * Legacy path: with no active IoC environment, execution falls back to the\n * deprecated process-global SqlStackDB registry so existing consumers keep\n * working during migration.\n */\n\ntype IocModule = {\n ExecutionContext: { current(): any };\n DependencyNotFoundError?: new (...args: any[]) => Error;\n};\n\ntype ActiveScope = {\n get(label: any): unknown;\n isRegistered?(label: any): boolean;\n};\n\n// @noego/ioc is an optional peer: sqlstack remains usable standalone. The\n// import is dynamic so the CJS and ESM builds both work and so a missing\n// peer only disables the IoC path instead of breaking module load.\nlet iocModulePromise: Promise<IocModule | undefined> | undefined;\n\nfunction loadIoc(): Promise<IocModule | undefined> {\n iocModulePromise ??= import('@noego/ioc').then(\n (m: any) => (m?.ExecutionContext ? (m as IocModule) : undefined),\n () => undefined\n );\n return iocModulePromise;\n}\n\n/** @internal Test-only: force re-detection of @noego/ioc. */\nexport function __resetIocDetection(): void {\n iocModulePromise = undefined;\n}\n\nfunction missingActiveSqlStackError(): SqlStackError {\n return new SqlStackError(\n 'An IoC execution environment is active, but no SqlStack is registered in it. ' +\n 'Register a SqlStack at root composition (see registerSqlStack in \"sqlstack/ioc\").'\n );\n}\n\nfunction isDirectMissingSqlStackError(ioc: IocModule, err: unknown): boolean {\n const DependencyNotFoundError = ioc.DependencyNotFoundError;\n return (\n typeof DependencyNotFoundError === 'function' &&\n err instanceof DependencyNotFoundError &&\n err.message === 'Dependency not found: SqlStack'\n );\n}\n\n/**\n * The SqlStack for the active IoC execution context, or undefined when no\n * IoC environment is active (or @noego/ioc is not installed).\n *\n * Throws when an environment IS active but has no SqlStack registered —\n * silently falling back to global state under an active root is forbidden.\n */\nexport async function activeSqlStack(): Promise<SqlStack | undefined> {\n const ioc = await loadIoc();\n if (!ioc) return undefined;\n const scope = ioc.ExecutionContext.current() as ActiveScope | undefined;\n if (!scope) return undefined;\n\n // Newer IoC peers expose exact-token registration knowledge. Consulting it\n // before resolution distinguishes an absent SqlStack from errors raised by a\n // registered SqlStack provider (including DependencyNotFoundError).\n const registrationKnown = typeof scope.isRegistered === 'function';\n if (registrationKnown && !scope.isRegistered!(SqlStack)) {\n throw missingActiveSqlStackError();\n }\n\n try {\n return (await scope.get(SqlStack)) as SqlStack;\n } catch (err) {\n // Older optional peers cannot answer isRegistered(). Their direct missing\n // error is recognized by exported error identity plus the exact SqlStack\n // label; nested provider errors retain their original identity.\n if (!registrationKnown && isDirectMissingSqlStackError(ioc, err)) {\n throw missingActiveSqlStackError();\n }\n throw err;\n }\n}\n\nexport type ResolvedExecution = {\n entry: DatabaseEntry;\n resolver: SqlResolver | undefined;\n /** True when resolved through an active IoC root's SqlStack. */\n viaStack: boolean;\n};\n\n/**\n * Resolve the concrete database entry (and SQL resolver) for one execution.\n */\nexport async function resolveExecution(dbName?: string): Promise<ResolvedExecution> {\n const stack = await activeSqlStack();\n if (stack) {\n return { entry: await stack.resolveEntry(dbName), resolver: stack.resolver(), viaStack: true };\n }\n return {\n entry: legacyEntry(dbName),\n resolver: getActiveResolver(),\n viaStack: false,\n };\n}\n\n/**\n * @internal The SQL source resolver for one execution WITHOUT resolving a\n * database — used when the caller supplied a database handle directly\n * (`run(db, params)`). Same environment rules as resolveExecution: the\n * active root's SqlStack resolver when an IoC environment is active (and an\n * error when that environment has no SqlStack), else the legacy global one.\n */\nexport async function resolveSqlResolver(): Promise<SqlResolver | undefined> {\n const stack = await activeSqlStack();\n return stack ? stack.resolver() : getActiveResolver();\n}\n\n/**\n * @internal Whether `name` is a database (or family) registered with the\n * active environment: the active root's SqlStack, else the legacy global\n * registry. Never throws; an environment that cannot answer reports false.\n */\nexport async function isRegisteredDatabaseName(name: string): Promise<boolean> {\n try {\n const stack = await activeSqlStack();\n if (stack) return stack.has(name);\n SqlStackDB.getEntry(name);\n return true;\n } catch {\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Legacy (deprecated) global-registry support\n// ---------------------------------------------------------------------------\n\n// Stable DatabaseEntry identities for the legacy global registry, so the\n// entry-keyed transaction store works identically on both paths. Keyed by\n// name AND database object so re-registration under a name yields a fresh\n// identity (matching the fresh underlying connection).\nconst legacyEntries = new Map<string, { db: Database; entry: DatabaseEntry }>();\n\n// One shared legacy pseudo-stack so legacy entries carry a stack identity for\n// diagnostics. It is intentionally NOT usable as a real stack.\nlet legacyStack: SqlStack | undefined;\n\n/** @internal Resolve a legacy global-registry database as a DatabaseEntry. */\nexport function legacyEntry(dbName?: string): DatabaseEntry {\n const { name, db } = SqlStackDB.getEntry(dbName);\n const cached = legacyEntries.get(name);\n if (cached && cached.db === db) return cached.entry;\n legacyStack ??= new SqlStack();\n const entry: DatabaseEntry = { name, db, owned: false, stack: legacyStack };\n legacyEntries.set(name, { db, entry });\n return entry;\n}\n"]}
|
package/dist/cjs/stack.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Database } from './registry';
|
|
2
2
|
import type { SqlResolver } from './core/resolver';
|
|
3
|
+
import { type SqlResources } from './core/resources';
|
|
3
4
|
import { FamilyRuntime } from './family';
|
|
4
5
|
import type { FamilyConfig } from './family';
|
|
5
6
|
/**
|
|
@@ -50,6 +51,19 @@ export declare class SqlStack {
|
|
|
50
51
|
static useResolver(resolver: SqlResolver): void;
|
|
51
52
|
/** @deprecated See static useResolver. */
|
|
52
53
|
static clearResolver(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Install the packaged SQL resources for this process: a path-keyed map
|
|
56
|
+
* `{ 'server/.../<method>.sql': '<sql>' }` (an `import.meta.glob` raw
|
|
57
|
+
* import, or a build-generated module). Bare `@Query()` methods resolve
|
|
58
|
+
* their guessed module directory + `<method>.sql` against it by path
|
|
59
|
+
* suffix, so the map works unchanged across an asar, a Worker module tree
|
|
60
|
+
* and a plain checkout. Replaces any previously installed map.
|
|
61
|
+
*/
|
|
62
|
+
static useResources(resources: SqlResources): void;
|
|
63
|
+
/** Remove the packaged SQL resources (tests). */
|
|
64
|
+
static clearResources(): void;
|
|
65
|
+
/** The installed packaged SQL resources, if any. */
|
|
66
|
+
static resources(): SqlResources | undefined;
|
|
53
67
|
constructor(config?: SqlStackConfig);
|
|
54
68
|
register(name: string, db: Database, options?: {
|
|
55
69
|
owned?: boolean;
|
package/dist/cjs/stack.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../src/stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AASnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,YAAY,EAAoC,MAAM,UAAU,CAAC;AAG/E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR;IACE,EAAE,EAAE,QAAQ,GAAG,CAAC,MAAM,QAAQ,CAAC,CAAC;IAChC,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEN,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IACjD,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED;;;;;;GAMG;AACH,qBAAa,QAAQ;;IACnB;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAI/C,0CAA0C;IAC1C,MAAM,CAAC,aAAa,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../src/stack.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/stack.js
CHANGED
|
@@ -48,6 +48,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
48
48
|
exports.SqlStack = void 0;
|
|
49
49
|
const resolver_1 = require("./core/resolver");
|
|
50
50
|
const errors_1 = require("./core/errors");
|
|
51
|
+
const resources_1 = require("./core/resources");
|
|
51
52
|
const family_1 = require("./family");
|
|
52
53
|
const familyBinding_1 = require("./familyBinding");
|
|
53
54
|
/**
|
|
@@ -71,6 +72,25 @@ class SqlStack {
|
|
|
71
72
|
static clearResolver() {
|
|
72
73
|
(0, resolver_1.clearGlobalResolver)();
|
|
73
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Install the packaged SQL resources for this process: a path-keyed map
|
|
77
|
+
* `{ 'server/.../<method>.sql': '<sql>' }` (an `import.meta.glob` raw
|
|
78
|
+
* import, or a build-generated module). Bare `@Query()` methods resolve
|
|
79
|
+
* their guessed module directory + `<method>.sql` against it by path
|
|
80
|
+
* suffix, so the map works unchanged across an asar, a Worker module tree
|
|
81
|
+
* and a plain checkout. Replaces any previously installed map.
|
|
82
|
+
*/
|
|
83
|
+
static useResources(resources) {
|
|
84
|
+
(0, resources_1.setResources)(resources);
|
|
85
|
+
}
|
|
86
|
+
/** Remove the packaged SQL resources (tests). */
|
|
87
|
+
static clearResources() {
|
|
88
|
+
(0, resources_1.setResources)(undefined);
|
|
89
|
+
}
|
|
90
|
+
/** The installed packaged SQL resources, if any. */
|
|
91
|
+
static resources() {
|
|
92
|
+
return (0, resources_1.getResources)();
|
|
93
|
+
}
|
|
74
94
|
constructor(config) {
|
|
75
95
|
_SqlStack_instances.add(this);
|
|
76
96
|
_SqlStack_entries.set(this, new Map());
|
package/dist/cjs/stack.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../src/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Database } from './registry';\nimport type { SqlResolver } from './core/resolver';\nimport {\n setGlobalResolver,\n clearGlobalResolver,\n ManifestResolver,\n assertManifestCoverage,\n assertManifestCoversClasses,\n} from './core/resolver';\nimport { SqlStackError } from './core/errors';\nimport { FamilyRuntime } from './family';\nimport type { FamilyConfig, FamilyMemberEntry, DatabaseLease } from './family';\nimport { currentBinding, runWithBinding, BindingFrame } from './familyBinding';\n\n/**\n * Concrete database identity inside one SqlStack instance.\n *\n * The entry OBJECT is the identity: two roots that both register a database\n * under the name \"primary\" produce two distinct DatabaseEntry instances, so\n * transaction lookup, caches, and diagnostics keyed by entry can never collide\n * across roots merely because the registration text matches.\n *\n * Dynamic database families (spec 17) extend this identity with a normalized\n * key; a static database is the no-key case.\n */\nexport interface DatabaseEntry {\n readonly name: string;\n readonly db: Database;\n /** Close() closes owned databases; externally supplied ones are left open. */\n readonly owned: boolean;\n /** The stack this entry belongs to, for diagnostics and mismatch checks. */\n readonly stack: SqlStack;\n}\n\nexport type DatabaseRegistration =\n | Database\n | {\n db: Database | (() => Database);\n /** Default false for direct Database values, true for factories. */\n owned?: boolean;\n };\n\nexport interface SqlStackConfig {\n databases?: Record<string, DatabaseRegistration>;\n /** Name of the default database. Required when more than one is registered. */\n default?: string;\n resolver?: SqlResolver;\n}\n\n/**\n * Environment-owned SQLStack runtime (spec 16 §12-13, repo spec 19 §3-5).\n *\n * One instance per owning IoC root; child scopes resolve the root's Singleton.\n * Native @Query/transaction/resolver execution goes through an instance —\n * never through the process-global SqlStackDB registry.\n */\nexport class SqlStack {\n /**\n * @deprecated Legacy v2 process-global resolver registration\n * (`SqlStack.useResolver(...)`). Forwards to the deprecated global state,\n * which is only consulted when no IoC environment is active. Use the\n * per-instance `useResolver` / SqlStackConfig.resolver instead.\n */\n static useResolver(resolver: SqlResolver): void {\n setGlobalResolver(resolver);\n }\n\n /** @deprecated See static useResolver. */\n static clearResolver(): void {\n clearGlobalResolver();\n }\n\n #entries = new Map<string, DatabaseEntry>();\n #families = new Map<string, FamilyRuntime<any>>();\n #defaultName: string | undefined;\n #resolver: SqlResolver | undefined;\n #closed = false;\n #closing: Promise<void> | undefined;\n\n constructor(config?: SqlStackConfig) {\n if (config?.databases) {\n for (const [name, reg] of Object.entries(config.databases)) {\n if (typeof reg === 'object' && reg !== null && 'db' in reg) {\n const db = typeof reg.db === 'function' ? reg.db() : reg.db;\n this.register(name, db, { owned: reg.owned ?? typeof reg.db === 'function' });\n } else {\n this.register(name, reg as Database);\n }\n }\n }\n if (config?.default) this.setDefault(config.default);\n if (config?.resolver) this.useResolver(config.resolver);\n }\n\n register(name: string, db: Database, options?: { owned?: boolean; default?: boolean }): this {\n this.#assertOpen();\n const entry: DatabaseEntry = { name, db, owned: options?.owned ?? false, stack: this };\n this.#entries.set(name, entry);\n if (options?.default || this.#entries.size === 1) {\n this.#defaultName ??= name;\n if (options?.default) this.#defaultName = name;\n }\n return this;\n }\n\n setDefault(name: string): this {\n this.#assertOpen();\n if (!this.#entries.has(name)) {\n throw new SqlStackError(\n `SqlStack has no database registered under \"${name}\". Registered: ${this.#registeredNames()}`\n );\n }\n this.#defaultName = name;\n return this;\n }\n\n getEntry(name?: string): DatabaseEntry {\n this.#assertOpen();\n const key = name ?? this.#defaultName;\n if (!key) {\n throw new SqlStackError(\n 'SqlStack has no default database. Register one with { default: true } or call setDefault(name).'\n );\n }\n const entry = this.#entries.get(key);\n if (!entry) {\n throw new SqlStackError(\n `SqlStack has no database registered under \"${key}\". Registered: ${this.#registeredNames()}`\n );\n }\n return entry;\n }\n\n database(name?: string): Database {\n return this.getEntry(name).db;\n }\n\n has(name: string): boolean {\n return this.#entries.has(name) || this.#families.has(name);\n }\n\n /**\n * Register a dynamic database family (spec 17): one registration whose\n * concrete member is selected per execution flow via withDatabase(...).\n */\n registerFamily<K = string>(name: string, config: FamilyConfig<K>): this {\n this.#assertOpen();\n if (this.#entries.has(name)) {\n throw new SqlStackError(`\"${name}\" is already registered as a static database.`);\n }\n this.#families.set(name, new FamilyRuntime(this, name, config));\n return this;\n }\n\n family<K = string>(name: string): FamilyRuntime<K> {\n const fam = this.#families.get(name);\n if (!fam) {\n throw new SqlStackError(\n `SqlStack has no database family registered under \"${name}\". Families: ${\n [...this.#families.keys()].map((n) => `\"${n}\"`).join(', ') || '(none)'\n }`\n );\n }\n return fam;\n }\n\n /**\n * Bind a family registration to a concrete member for the duration of fn\n * (spec 17 §10). The binding is flow-local to this SqlStack; the member's\n * connection is leased lazily on first database resolution and released\n * when fn settles. Rebinding a family to a different key while it has an\n * active transaction fails deterministically (spec 17 §29).\n */\n async withDatabase<T>(family: string, key: unknown, fn: () => Promise<T>): Promise<T> {\n this.#assertOpen();\n const fam = this.family(family);\n const { keyId } = fam.normalize(key);\n\n const outer = currentBinding(this, family);\n if (outer && outer.keyId !== keyId && outer.lease) {\n const { getActiveTransaction } = await import('./transactions');\n if (getActiveTransaction(outer.lease.entry)) {\n throw new SqlStackError(\n `Cannot rebind database family \"${family}\" from \"${outer.keyId}\" to \"${keyId}\": ` +\n 'a transaction is active for the current member. Finish the transaction first.'\n );\n }\n }\n\n const frame: BindingFrame = { stack: this, family, keyInput: key, keyId };\n try {\n return await runWithBinding(frame, fn);\n } finally {\n await frame.lease?.release();\n }\n }\n\n /**\n * Async database resolution for query/transaction execution. Static\n * registrations resolve directly; family registrations resolve through the\n * active flow-local binding, opening/leasing the member on first use.\n */\n async resolveEntry(name?: string): Promise<DatabaseEntry> {\n this.#assertOpen();\n const key =\n name ??\n this.#defaultName ??\n // A stack whose only registration is one family treats it as default.\n (this.#entries.size === 0 && this.#families.size === 1\n ? [...this.#families.keys()][0]\n : undefined);\n if (key !== undefined) {\n const entry = this.#entries.get(key);\n if (entry) return entry;\n const fam = this.#families.get(key);\n if (fam) {\n const frame = currentBinding(this, key);\n if (!frame) {\n throw new SqlStackError(\n `SQLStack database family \"${key}\" requires a concrete database key. ` +\n 'No active binding exists for this execution. Establish the database at the ' +\n `orchestration boundary with sqlStack.withDatabase(\"${key}\", key, ...) ` +\n 'or acquire a member explicitly via sqlStack.family(...).with(...).'\n );\n }\n if (!frame.lease) {\n frame.lease = await fam.acquire(frame.keyInput);\n }\n return frame.lease.entry;\n }\n }\n return this.getEntry(name);\n }\n\n /**\n * Set this stack's SQL resolver. When `options.classes` supplies the\n * repository catalog, manifest coverage is validated from those classes'\n * immutable metadata (environment-local, unpollutable by unrelated\n * imports). Without a catalog, coverage falls back to the deprecated\n * process-global decorated list.\n */\n useResolver(\n resolver: SqlResolver,\n options?: { classes?: ReadonlyArray<abstract new (...args: any[]) => any> }\n ): this {\n this.#assertOpen();\n if (resolver instanceof ManifestResolver && resolver.options.assert !== false) {\n if (options?.classes) {\n assertManifestCoversClasses(resolver, options.classes);\n } else {\n assertManifestCoverage(resolver);\n }\n }\n this.#resolver = resolver;\n return this;\n }\n\n resolver(): SqlResolver | undefined {\n return this.#resolver;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Close owned database adapters exactly once and release runtime resources.\n * Externally supplied databases (owned: false) are not touched. Failures are\n * collected and reported with database identity rather than swallowed.\n */\n close(): Promise<void> {\n if (this.#closing) return this.#closing;\n this.#closed = true;\n this.#closing = Promise.resolve().then(async () => {\n const failures: string[] = [];\n const errors: unknown[] = [];\n const closed = new Set<Database>();\n for (const entry of this.#entries.values()) {\n if (!entry.owned || closed.has(entry.db)) continue;\n closed.add(entry.db);\n try { await entry.db.close(); }\n catch (error: any) {\n errors.push(error);\n failures.push(`\"${entry.name}\": ${error?.message ?? String(error)}`);\n }\n }\n for (const fam of this.#families.values()) {\n try { await fam.closeAll(); }\n catch (error: any) { errors.push(error); failures.push(error?.message ?? String(error)); }\n }\n this.#entries.clear();\n this.#families.clear();\n this.#resolver = undefined;\n if (failures.length) {\n throw Object.assign(new SqlStackError(`SqlStack close failed for ${failures.join(', ')}`), {\n errors: Object.freeze(errors), cause: errors[0],\n });\n }\n });\n return this.#closing;\n }\n\n /** Native IoC resource hook; manually calling close remains supported. */\n dispose(): Promise<void> { return this.close(); }\n\n #assertOpen(): void {\n if (this.#closed) {\n throw new SqlStackError('SqlStack has been closed; its owning root was disposed.');\n }\n }\n\n #registeredNames(): string {\n const names = [\n ...[...this.#entries.keys()].map((n) => `\"${n}\"`),\n ...[...this.#families.keys()].map((n) => `\"${n}\" (family)`),\n ];\n return names.length ? names.join(', ') : '(none)';\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../src/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Database } from './registry';\nimport type { SqlResolver } from './core/resolver';\nimport {\n setGlobalResolver,\n clearGlobalResolver,\n ManifestResolver,\n assertManifestCoverage,\n assertManifestCoversClasses,\n} from './core/resolver';\nimport { SqlStackError } from './core/errors';\nimport { setResources, getResources, type SqlResources } from './core/resources';\nimport { FamilyRuntime } from './family';\nimport type { FamilyConfig, FamilyMemberEntry, DatabaseLease } from './family';\nimport { currentBinding, runWithBinding, BindingFrame } from './familyBinding';\n\n/**\n * Concrete database identity inside one SqlStack instance.\n *\n * The entry OBJECT is the identity: two roots that both register a database\n * under the name \"primary\" produce two distinct DatabaseEntry instances, so\n * transaction lookup, caches, and diagnostics keyed by entry can never collide\n * across roots merely because the registration text matches.\n *\n * Dynamic database families (spec 17) extend this identity with a normalized\n * key; a static database is the no-key case.\n */\nexport interface DatabaseEntry {\n readonly name: string;\n readonly db: Database;\n /** Close() closes owned databases; externally supplied ones are left open. */\n readonly owned: boolean;\n /** The stack this entry belongs to, for diagnostics and mismatch checks. */\n readonly stack: SqlStack;\n}\n\nexport type DatabaseRegistration =\n | Database\n | {\n db: Database | (() => Database);\n /** Default false for direct Database values, true for factories. */\n owned?: boolean;\n };\n\nexport interface SqlStackConfig {\n databases?: Record<string, DatabaseRegistration>;\n /** Name of the default database. Required when more than one is registered. */\n default?: string;\n resolver?: SqlResolver;\n}\n\n/**\n * Environment-owned SQLStack runtime (spec 16 §12-13, repo spec 19 §3-5).\n *\n * One instance per owning IoC root; child scopes resolve the root's Singleton.\n * Native @Query/transaction/resolver execution goes through an instance —\n * never through the process-global SqlStackDB registry.\n */\nexport class SqlStack {\n /**\n * @deprecated Legacy v2 process-global resolver registration\n * (`SqlStack.useResolver(...)`). Forwards to the deprecated global state,\n * which is only consulted when no IoC environment is active. Use the\n * per-instance `useResolver` / SqlStackConfig.resolver instead.\n */\n static useResolver(resolver: SqlResolver): void {\n setGlobalResolver(resolver);\n }\n\n /** @deprecated See static useResolver. */\n static clearResolver(): void {\n clearGlobalResolver();\n }\n\n /**\n * Install the packaged SQL resources for this process: a path-keyed map\n * `{ 'server/.../<method>.sql': '<sql>' }` (an `import.meta.glob` raw\n * import, or a build-generated module). Bare `@Query()` methods resolve\n * their guessed module directory + `<method>.sql` against it by path\n * suffix, so the map works unchanged across an asar, a Worker module tree\n * and a plain checkout. Replaces any previously installed map.\n */\n static useResources(resources: SqlResources): void {\n setResources(resources);\n }\n\n /** Remove the packaged SQL resources (tests). */\n static clearResources(): void {\n setResources(undefined);\n }\n\n /** The installed packaged SQL resources, if any. */\n static resources(): SqlResources | undefined {\n return getResources();\n }\n\n #entries = new Map<string, DatabaseEntry>();\n #families = new Map<string, FamilyRuntime<any>>();\n #defaultName: string | undefined;\n #resolver: SqlResolver | undefined;\n #closed = false;\n #closing: Promise<void> | undefined;\n\n constructor(config?: SqlStackConfig) {\n if (config?.databases) {\n for (const [name, reg] of Object.entries(config.databases)) {\n if (typeof reg === 'object' && reg !== null && 'db' in reg) {\n const db = typeof reg.db === 'function' ? reg.db() : reg.db;\n this.register(name, db, { owned: reg.owned ?? typeof reg.db === 'function' });\n } else {\n this.register(name, reg as Database);\n }\n }\n }\n if (config?.default) this.setDefault(config.default);\n if (config?.resolver) this.useResolver(config.resolver);\n }\n\n register(name: string, db: Database, options?: { owned?: boolean; default?: boolean }): this {\n this.#assertOpen();\n const entry: DatabaseEntry = { name, db, owned: options?.owned ?? false, stack: this };\n this.#entries.set(name, entry);\n if (options?.default || this.#entries.size === 1) {\n this.#defaultName ??= name;\n if (options?.default) this.#defaultName = name;\n }\n return this;\n }\n\n setDefault(name: string): this {\n this.#assertOpen();\n if (!this.#entries.has(name)) {\n throw new SqlStackError(\n `SqlStack has no database registered under \"${name}\". Registered: ${this.#registeredNames()}`\n );\n }\n this.#defaultName = name;\n return this;\n }\n\n getEntry(name?: string): DatabaseEntry {\n this.#assertOpen();\n const key = name ?? this.#defaultName;\n if (!key) {\n throw new SqlStackError(\n 'SqlStack has no default database. Register one with { default: true } or call setDefault(name).'\n );\n }\n const entry = this.#entries.get(key);\n if (!entry) {\n throw new SqlStackError(\n `SqlStack has no database registered under \"${key}\". Registered: ${this.#registeredNames()}`\n );\n }\n return entry;\n }\n\n database(name?: string): Database {\n return this.getEntry(name).db;\n }\n\n has(name: string): boolean {\n return this.#entries.has(name) || this.#families.has(name);\n }\n\n /**\n * Register a dynamic database family (spec 17): one registration whose\n * concrete member is selected per execution flow via withDatabase(...).\n */\n registerFamily<K = string>(name: string, config: FamilyConfig<K>): this {\n this.#assertOpen();\n if (this.#entries.has(name)) {\n throw new SqlStackError(`\"${name}\" is already registered as a static database.`);\n }\n this.#families.set(name, new FamilyRuntime(this, name, config));\n return this;\n }\n\n family<K = string>(name: string): FamilyRuntime<K> {\n const fam = this.#families.get(name);\n if (!fam) {\n throw new SqlStackError(\n `SqlStack has no database family registered under \"${name}\". Families: ${\n [...this.#families.keys()].map((n) => `\"${n}\"`).join(', ') || '(none)'\n }`\n );\n }\n return fam;\n }\n\n /**\n * Bind a family registration to a concrete member for the duration of fn\n * (spec 17 §10). The binding is flow-local to this SqlStack; the member's\n * connection is leased lazily on first database resolution and released\n * when fn settles. Rebinding a family to a different key while it has an\n * active transaction fails deterministically (spec 17 §29).\n */\n async withDatabase<T>(family: string, key: unknown, fn: () => Promise<T>): Promise<T> {\n this.#assertOpen();\n const fam = this.family(family);\n const { keyId } = fam.normalize(key);\n\n const outer = currentBinding(this, family);\n if (outer && outer.keyId !== keyId && outer.lease) {\n const { getActiveTransaction } = await import('./transactions');\n if (getActiveTransaction(outer.lease.entry)) {\n throw new SqlStackError(\n `Cannot rebind database family \"${family}\" from \"${outer.keyId}\" to \"${keyId}\": ` +\n 'a transaction is active for the current member. Finish the transaction first.'\n );\n }\n }\n\n const frame: BindingFrame = { stack: this, family, keyInput: key, keyId };\n try {\n return await runWithBinding(frame, fn);\n } finally {\n await frame.lease?.release();\n }\n }\n\n /**\n * Async database resolution for query/transaction execution. Static\n * registrations resolve directly; family registrations resolve through the\n * active flow-local binding, opening/leasing the member on first use.\n */\n async resolveEntry(name?: string): Promise<DatabaseEntry> {\n this.#assertOpen();\n const key =\n name ??\n this.#defaultName ??\n // A stack whose only registration is one family treats it as default.\n (this.#entries.size === 0 && this.#families.size === 1\n ? [...this.#families.keys()][0]\n : undefined);\n if (key !== undefined) {\n const entry = this.#entries.get(key);\n if (entry) return entry;\n const fam = this.#families.get(key);\n if (fam) {\n const frame = currentBinding(this, key);\n if (!frame) {\n throw new SqlStackError(\n `SQLStack database family \"${key}\" requires a concrete database key. ` +\n 'No active binding exists for this execution. Establish the database at the ' +\n `orchestration boundary with sqlStack.withDatabase(\"${key}\", key, ...) ` +\n 'or acquire a member explicitly via sqlStack.family(...).with(...).'\n );\n }\n if (!frame.lease) {\n frame.lease = await fam.acquire(frame.keyInput);\n }\n return frame.lease.entry;\n }\n }\n return this.getEntry(name);\n }\n\n /**\n * Set this stack's SQL resolver. When `options.classes` supplies the\n * repository catalog, manifest coverage is validated from those classes'\n * immutable metadata (environment-local, unpollutable by unrelated\n * imports). Without a catalog, coverage falls back to the deprecated\n * process-global decorated list.\n */\n useResolver(\n resolver: SqlResolver,\n options?: { classes?: ReadonlyArray<abstract new (...args: any[]) => any> }\n ): this {\n this.#assertOpen();\n if (resolver instanceof ManifestResolver && resolver.options.assert !== false) {\n if (options?.classes) {\n assertManifestCoversClasses(resolver, options.classes);\n } else {\n assertManifestCoverage(resolver);\n }\n }\n this.#resolver = resolver;\n return this;\n }\n\n resolver(): SqlResolver | undefined {\n return this.#resolver;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Close owned database adapters exactly once and release runtime resources.\n * Externally supplied databases (owned: false) are not touched. Failures are\n * collected and reported with database identity rather than swallowed.\n */\n close(): Promise<void> {\n if (this.#closing) return this.#closing;\n this.#closed = true;\n this.#closing = Promise.resolve().then(async () => {\n const failures: string[] = [];\n const errors: unknown[] = [];\n const closed = new Set<Database>();\n for (const entry of this.#entries.values()) {\n if (!entry.owned || closed.has(entry.db)) continue;\n closed.add(entry.db);\n try { await entry.db.close(); }\n catch (error: any) {\n errors.push(error);\n failures.push(`\"${entry.name}\": ${error?.message ?? String(error)}`);\n }\n }\n for (const fam of this.#families.values()) {\n try { await fam.closeAll(); }\n catch (error: any) { errors.push(error); failures.push(error?.message ?? String(error)); }\n }\n this.#entries.clear();\n this.#families.clear();\n this.#resolver = undefined;\n if (failures.length) {\n throw Object.assign(new SqlStackError(`SqlStack close failed for ${failures.join(', ')}`), {\n errors: Object.freeze(errors), cause: errors[0],\n });\n }\n });\n return this.#closing;\n }\n\n /** Native IoC resource hook; manually calling close remains supported. */\n dispose(): Promise<void> { return this.close(); }\n\n #assertOpen(): void {\n if (this.#closed) {\n throw new SqlStackError('SqlStack has been closed; its owning root was disposed.');\n }\n }\n\n #registeredNames(): string {\n const names = [\n ...[...this.#entries.keys()].map((n) => `\"${n}\"`),\n ...[...this.#families.keys()].map((n) => `\"${n}\" (family)`),\n ];\n return names.length ? names.join(', ') : '(none)';\n }\n}\n"]}
|
|
@@ -5,6 +5,15 @@ export type TransactionOptions = {
|
|
|
5
5
|
lazy?: boolean;
|
|
6
6
|
nested?: 'join';
|
|
7
7
|
};
|
|
8
|
+
/** Work registered with transaction.afterCommit / transaction.afterSettled. */
|
|
9
|
+
export type TransactionHook = () => unknown;
|
|
10
|
+
/** Observable transaction events (see onTransactionEvent). */
|
|
11
|
+
export type TransactionEvent = {
|
|
12
|
+
readonly type: 'sqlstack.transaction.multi_database';
|
|
13
|
+
/** Names of the databases the scope has opened, in open order. */
|
|
14
|
+
readonly databases: readonly string[];
|
|
15
|
+
};
|
|
16
|
+
export type TransactionEventListener = (event: TransactionEvent) => void;
|
|
8
17
|
export declare class TransactionHandle {
|
|
9
18
|
#private;
|
|
10
19
|
readonly entry: DatabaseEntry;
|
|
@@ -27,6 +36,10 @@ declare class TxState {
|
|
|
27
36
|
completed: boolean;
|
|
28
37
|
rollbackOnly: boolean;
|
|
29
38
|
rollbackError: unknown | undefined;
|
|
39
|
+
/** SQLite opening statement: name-based transactions keep plain BEGIN. */
|
|
40
|
+
sqliteBegin: 'BEGIN' | 'BEGIN IMMEDIATE';
|
|
41
|
+
/** Called once when the transaction releases its connection (SQLite queue turn). */
|
|
42
|
+
onRelease: (() => void) | undefined;
|
|
30
43
|
private txDb;
|
|
31
44
|
private releaseFn;
|
|
32
45
|
constructor(entry: DatabaseEntry, options: TransactionOptions | undefined);
|
|
@@ -54,9 +67,48 @@ export declare function hasTransactionContext(): boolean;
|
|
|
54
67
|
/** Active transaction handle for a concrete database entry, if any. */
|
|
55
68
|
export declare function currentTransactionFor(entry: DatabaseEntry): TransactionHandle | undefined;
|
|
56
69
|
export declare function withTransaction<T>(fn: () => Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
70
|
+
/**
|
|
71
|
+
* Observe transaction trace events. Today the only event is
|
|
72
|
+
* `sqlstack.transaction.multi_database`, emitted once per root scope the
|
|
73
|
+
* moment it opens its second database. Returns an unsubscribe function.
|
|
74
|
+
* Listener errors are ignored so observation never affects a transaction.
|
|
75
|
+
*/
|
|
76
|
+
export declare function onTransactionEvent(listener: TransactionEventListener): () => void;
|
|
77
|
+
/**
|
|
78
|
+
* @internal The transaction a query on `entry` runs in: the one already open
|
|
79
|
+
* in this flow (including one a handle of the same database opened), or —
|
|
80
|
+
* while a @transaction scope is active — one opened on that entry by the
|
|
81
|
+
* query itself (on first execution, not on resolution). Undefined means "run
|
|
82
|
+
* on the database directly".
|
|
83
|
+
*/
|
|
84
|
+
export declare function getTransactionTarget(entry: DatabaseEntry): ActiveTransaction | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* @internal The transaction a query on a Database handle (run(db, ...)) runs
|
|
87
|
+
* in. A transaction already open in this flow on that exact object is joined
|
|
88
|
+
* (identity; registered or handle-opened). Inside a @transaction scope with
|
|
89
|
+
* none open, the query opens one on the handle on first execution, exactly as
|
|
90
|
+
* the name-resolved path does. Outside any scope the behaviour is unchanged:
|
|
91
|
+
* join by identity or run directly (undefined).
|
|
92
|
+
*/
|
|
93
|
+
export declare function getTransactionTargetForHandle(db: {
|
|
94
|
+
query(sql: string, params: unknown[]): Promise<unknown>;
|
|
95
|
+
}): ActiveTransaction | undefined;
|
|
57
96
|
export type TransactionDecorator = {
|
|
58
97
|
(target: any, prop: string | symbol, desc: PropertyDescriptor): void;
|
|
59
98
|
(options?: TransactionOptions): (target: any, prop: string | symbol, desc: PropertyDescriptor) => void;
|
|
99
|
+
/**
|
|
100
|
+
* Mark the innermost scope (or, with a database name or handle, only that
|
|
101
|
+
* database's open transaction) for rollback at scope exit. Never throws
|
|
102
|
+
* inside a scope for a valid target; throws SqlStackError outside any
|
|
103
|
+
* scope or when no open transaction matches the target.
|
|
104
|
+
*/
|
|
105
|
+
rollback(target?: string | object): void;
|
|
106
|
+
/** Roll back the scope's work now; the next query opens fresh transactions. */
|
|
107
|
+
restart(): Promise<void>;
|
|
108
|
+
/** Run fn after the root scope commits (dropped on rollback). */
|
|
109
|
+
afterCommit(fn: TransactionHook): void;
|
|
110
|
+
/** Run fn after the root scope finishes, committed or not. */
|
|
111
|
+
afterSettled(fn: TransactionHook): void;
|
|
60
112
|
};
|
|
61
113
|
export declare const transaction: TransactionDecorator;
|
|
62
114
|
export type ActiveTransaction = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../../src/transactions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../../src/transactions.ts"],"names":[],"mappings":"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"}
|