sqlstack 3.4.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/errors.d.ts +9 -0
- package/dist/cjs/core/errors.d.ts.map +1 -1
- package/dist/cjs/core/errors.js +10 -0
- package/dist/cjs/core/errors.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 +14 -0
- package/dist/cjs/decorators/query.d.ts.map +1 -1
- package/dist/cjs/decorators/query.js +208 -40
- 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 +3 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +6 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/run.d.ts +180 -6
- package/dist/cjs/run.d.ts.map +1 -1
- package/dist/cjs/run.js +158 -17
- package/dist/cjs/run.js.map +1 -1
- package/dist/cjs/runtime.d.ts +14 -0
- package/dist/cjs/runtime.d.ts.map +1 -1
- package/dist/cjs/runtime.js +30 -0
- package/dist/cjs/runtime.js.map +1 -1
- package/dist/cjs/sql.d.ts +19 -0
- package/dist/cjs/sql.d.ts.map +1 -1
- package/dist/cjs/sql.js +66 -28
- package/dist/cjs/sql.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 +60 -0
- package/dist/cjs/transactions.d.ts.map +1 -1
- package/dist/cjs/transactions.js +575 -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/errors.js +10 -0
- package/dist/esm/core/errors.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 +214 -46
- 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 +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/run.js +153 -18
- package/dist/esm/run.js.map +1 -1
- package/dist/esm/runtime.js +28 -0
- package/dist/esm/runtime.js.map +1 -1
- package/dist/esm/sql.js +63 -27
- package/dist/esm/sql.js.map +1 -1
- package/dist/esm/stack.js +21 -1
- package/dist/esm/stack.js.map +1 -1
- package/dist/esm/transactions.js +571 -3
- package/dist/esm/transactions.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +201 -171
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { sql, SqlFragment } from './sql';
|
|
2
2
|
export { run } from './run';
|
|
3
|
+
export type { RunDatabase, RejectCompiledSql } from './run';
|
|
3
4
|
export * from './decorators/queryBinder';
|
|
4
5
|
export * from './decorators/query';
|
|
5
6
|
export * from './decorators/defaults';
|
|
@@ -24,5 +25,7 @@ export type { SqliteFamilyOptions } from './families/sqliteFamily';
|
|
|
24
25
|
export type { SqlResolver, SqlManifest, SqlResolutionRequest, ManifestResolverOptions } from './core/resolver';
|
|
25
26
|
export { FsResolver, ManifestResolver, MANIFEST_DIALECT_EXT, getActiveResolver } from './core/resolver';
|
|
26
27
|
export { SourceScanResolver } from './core/sourceScanResolver';
|
|
28
|
+
export type { SqlResources } from './core/resources';
|
|
29
|
+
export { lookupResource, normalizeResourcePath } from './core/resources';
|
|
27
30
|
export * from './binders/sqlBinder';
|
|
28
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAIzC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG5D,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,YAAY,CAAC;AAG3B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAGjC,cAAc,aAAa,CAAC;AAG5B,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,YAAY,EACV,sBAAsB,EACtB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGnE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/G,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACxG,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGzE,cAAc,qBAAqB,CAAC"}
|
package/dist/cjs/index.js
CHANGED
|
@@ -14,12 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.SourceScanResolver = exports.getActiveResolver = exports.MANIFEST_DIALECT_EXT = exports.ManifestResolver = exports.FsResolver = exports.sqliteFamily = exports.FamilyRuntime = exports.resolveExecution = exports.activeSqlStack = exports.SqlStack = exports.SqlStackDB = exports.run = exports.SqlFragment = exports.sql = void 0;
|
|
17
|
+
exports.normalizeResourcePath = exports.lookupResource = exports.SourceScanResolver = exports.getActiveResolver = exports.MANIFEST_DIALECT_EXT = exports.ManifestResolver = exports.FsResolver = exports.sqliteFamily = exports.FamilyRuntime = exports.resolveExecution = exports.activeSqlStack = exports.SqlStack = exports.SqlStackDB = exports.run = exports.SqlFragment = exports.sql = void 0;
|
|
18
18
|
// SQL Template Strings
|
|
19
19
|
var sql_1 = require("./sql");
|
|
20
20
|
Object.defineProperty(exports, "sql", { enumerable: true, get: function () { return sql_1.sql; } });
|
|
21
21
|
Object.defineProperty(exports, "SqlFragment", { enumerable: true, get: function () { return sql_1.SqlFragment; } });
|
|
22
|
-
// Query
|
|
22
|
+
// Query execution — `return run()` inside a @Query method body, or
|
|
23
|
+
// `run(db, sql`...`)` anywhere with a database chosen at call time
|
|
23
24
|
var run_1 = require("./run");
|
|
24
25
|
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return run_1.run; } });
|
|
25
26
|
// Decorators
|
|
@@ -59,6 +60,9 @@ Object.defineProperty(exports, "MANIFEST_DIALECT_EXT", { enumerable: true, get:
|
|
|
59
60
|
Object.defineProperty(exports, "getActiveResolver", { enumerable: true, get: function () { return resolver_1.getActiveResolver; } });
|
|
60
61
|
var sourceScanResolver_1 = require("./core/sourceScanResolver");
|
|
61
62
|
Object.defineProperty(exports, "SourceScanResolver", { enumerable: true, get: function () { return sourceScanResolver_1.SourceScanResolver; } });
|
|
63
|
+
var resources_1 = require("./core/resources");
|
|
64
|
+
Object.defineProperty(exports, "lookupResource", { enumerable: true, get: function () { return resources_1.lookupResource; } });
|
|
65
|
+
Object.defineProperty(exports, "normalizeResourcePath", { enumerable: true, get: function () { return resources_1.normalizeResourcePath; } });
|
|
62
66
|
// Legacy exports (kept for backward compatibility)
|
|
63
67
|
__exportStar(require("./binders/sqlBinder"), exports);
|
|
64
68
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uBAAuB;AACvB,6BAAyC;AAAhC,0FAAA,GAAG,OAAA;AAAE,kGAAA,WAAW,OAAA;AAEzB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uBAAuB;AACvB,6BAAyC;AAAhC,0FAAA,GAAG,OAAA;AAAE,kGAAA,WAAW,OAAA;AAEzB,mEAAmE;AACnE,mEAAmE;AACnE,6BAA4B;AAAnB,0FAAA,GAAG,OAAA;AAGZ,aAAa;AACb,2DAAyC;AACzC,qDAAmC;AACnC,wDAAsC;AACtC,2DAAyC;AACzC,8DAA4C;AAC5C,yDAAuC;AACvC,oDAAkC;AAElC,eAAe;AACf,iDAA+B;AAE/B,WAAW;AACX,6CAA2B;AAE3B,wBAAwB;AACxB,gDAA8B;AAC9B,mDAAiC;AAEjC,aAAa;AACb,8CAA4B;AAI5B,uCAAkD;AAAzC,sGAAA,UAAU,OAAA;AAEnB,gFAAgF;AAChF,iCAAmC;AAA1B,iGAAA,QAAQ,OAAA;AAEjB,qCAA6D;AAApD,yGAAA,cAAc,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAEzC,sCAAsC;AACtC,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AAQtB,wDAAuD;AAA9C,4GAAA,YAAY,OAAA;AAKrB,4CAAwG;AAA/F,sGAAA,UAAU,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,gHAAA,oBAAoB,OAAA;AAAE,6GAAA,iBAAiB,OAAA;AAC9E,gEAA+D;AAAtD,wHAAA,kBAAkB,OAAA;AAE3B,8CAAyE;AAAhE,2GAAA,cAAc,OAAA;AAAE,kHAAA,qBAAqB,OAAA;AAE9C,mDAAmD;AACnD,sDAAoC","sourcesContent":["// SQL Template Strings\nexport { sql, SqlFragment } from './sql';\n\n// Query execution — `return run()` inside a @Query method body, or\n// `run(db, sql`...`)` anywhere with a database chosen at call time\nexport { run } from './run';\nexport type { RunDatabase, RejectCompiledSql } from './run';\n\n// Decorators\nexport * from './decorators/queryBinder';\nexport * from './decorators/query';\nexport * from './decorators/defaults';\nexport * from './decorators/resultShape';\nexport * from './decorators/validateResult';\nexport * from './decorators/transform';\nexport * from './decorators/page';\n\n// Transactions\nexport * from './transactions';\n\n// Adapters\nexport * from './adapters';\n\n// Errors and Validation\nexport * from './core/errors';\nexport * from './core/validator';\n\n// DTO Helper\nexport * from './utils/dto';\n\n// Database Registry and Types\nexport type { Dialect, WriteResult, PostgresWriteResult, QueryResult, Database } from './registry';\nexport { SqlStackDB, IStackDB } from './registry';\n\n// Environment-owned runtime (v3): per-root SqlStack + active-context resolution\nexport { SqlStack } from './stack';\nexport type { DatabaseEntry, DatabaseRegistration, SqlStackConfig } from './stack';\nexport { activeSqlStack, resolveExecution } from './runtime';\n\n// Dynamic database families (spec 17)\nexport { FamilyRuntime } from './family';\nexport type {\n DatabaseFamilyProvider,\n FamilyConfig,\n FamilyMemberEntry,\n DatabaseLease,\n DatabaseInspection,\n} from './family';\nexport { sqliteFamily } from './families/sqliteFamily';\nexport type { SqliteFamilyOptions } from './families/sqliteFamily';\n\n// SQL Resolvers (v2): pluggable SQL source resolution\nexport type { SqlResolver, SqlManifest, SqlResolutionRequest, ManifestResolverOptions } from './core/resolver';\nexport { FsResolver, ManifestResolver, MANIFEST_DIALECT_EXT, getActiveResolver } from './core/resolver';\nexport { SourceScanResolver } from './core/sourceScanResolver';\nexport type { SqlResources } from './core/resources';\nexport { lookupResource, normalizeResourcePath } from './core/resources';\n\n// Legacy exports (kept for backward compatibility)\nexport * from './binders/sqlBinder';\n"]}
|
package/dist/cjs/run.d.ts
CHANGED
|
@@ -1,29 +1,203 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { SqlStackError } from './core/errors';
|
|
3
|
+
import type { Dialect } from './registry';
|
|
4
|
+
import { SqlFragment } from './sql';
|
|
5
|
+
import type { SqlResolver } from './core/resolver';
|
|
6
|
+
import type { ActiveTransaction } from './transactions';
|
|
7
|
+
/**
|
|
8
|
+
* Anything run(db, ...) can execute against: sqlstack's own `Database`
|
|
9
|
+
* (from createSqliteDb/createPgDb/createMysqlDb), or any application handle
|
|
10
|
+
* exposing `query(sql, params)`. `dialect` selects placeholder style and
|
|
11
|
+
* defaults to `'sqlite'` when absent. run never opens databases by path.
|
|
12
|
+
*/
|
|
13
|
+
export interface RunDatabase {
|
|
14
|
+
readonly dialect?: Dialect;
|
|
15
|
+
query(sql: string, params: unknown[]): Promise<unknown>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Type-level guard for the params form of run: rejects the
|
|
19
|
+
* `{ sql, params }` object returned by `fragment.toSQL()`. Pass the sql``
|
|
20
|
+
* fragment itself instead, so run owns dialect binding and error handling.
|
|
21
|
+
*/
|
|
22
|
+
export type RejectCompiledSql<P> = P extends {
|
|
23
|
+
readonly sql: string;
|
|
24
|
+
readonly params: readonly unknown[];
|
|
25
|
+
} ? never : unknown;
|
|
26
|
+
/**
|
|
27
|
+
* What a run(...) call made inside a @Query body asks of the wrapper's
|
|
28
|
+
* pipeline. `default` is the zero-argument run().
|
|
29
|
+
*/
|
|
30
|
+
export type RunInvocation = {
|
|
31
|
+
readonly kind: 'default';
|
|
32
|
+
} | {
|
|
33
|
+
readonly kind: 'fragment';
|
|
34
|
+
readonly db?: RunDatabase | string;
|
|
35
|
+
readonly fragment: SqlFragment;
|
|
36
|
+
} | {
|
|
37
|
+
readonly kind: 'params';
|
|
38
|
+
readonly db?: RunDatabase | string;
|
|
39
|
+
readonly params: object;
|
|
40
|
+
} | {
|
|
41
|
+
readonly kind: 'db';
|
|
42
|
+
readonly db: RunDatabase | string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Type-level guard for run(db) with a name: a string containing whitespace is
|
|
46
|
+
* SQL text, never a database name. Build statements with the sql`` tag.
|
|
47
|
+
*/
|
|
48
|
+
export type RejectSqlText<D> = D extends string ? D extends `${string} ${string}` | `${string}\n${string}` | `${string}\t${string}` ? never : unknown : unknown;
|
|
2
49
|
/**
|
|
3
50
|
* Per-invocation context established by the @Query wrapper before the method
|
|
4
51
|
* body executes. `execute` performs the full query pipeline (resolve SQL,
|
|
5
52
|
* bind, execute, shape/transform/validate); `ran` records that the body
|
|
6
53
|
* invoked run(), so the wrapper returns the body's result verbatim instead
|
|
7
|
-
* of falling through to the legacy pipeline.
|
|
54
|
+
* of falling through to the legacy pipeline. `invocations` marks a wrapper
|
|
55
|
+
* that understands the argument-taking run forms (an older duplicated copy
|
|
56
|
+
* of the decorator would silently ignore them).
|
|
8
57
|
*/
|
|
9
58
|
export type RunContext = {
|
|
10
|
-
execute: () => Promise<unknown>;
|
|
59
|
+
execute: (invocation?: RunInvocation) => Promise<unknown>;
|
|
11
60
|
ran: boolean;
|
|
61
|
+
invocations?: true;
|
|
12
62
|
};
|
|
13
63
|
export declare const runStorage: AsyncLocalStorage<RunContext>;
|
|
14
64
|
/**
|
|
15
65
|
* Execute the current @Query method's SQL and return the finished result.
|
|
16
|
-
* Call it as the body of a @Query-decorated method
|
|
17
|
-
* placeholder throw:
|
|
66
|
+
* Call it as the body of a @Query-decorated method:
|
|
18
67
|
*
|
|
19
68
|
* @Query()
|
|
20
69
|
* async getUsers(active: boolean): Promise<User[]> {
|
|
21
|
-
* return run
|
|
70
|
+
* return run();
|
|
22
71
|
* }
|
|
23
72
|
*
|
|
24
73
|
* Takes no arguments — the method's own arguments, database, SQL source,
|
|
25
74
|
* transaction, shaping, transform, and validation all come from the
|
|
26
|
-
* decorator context
|
|
75
|
+
* decorator context — except that a leading method argument that is a
|
|
76
|
+
* database handle (or a registered database name) selects the database and
|
|
77
|
+
* is not bound. T is inferred from the method's declared return type.
|
|
78
|
+
*
|
|
79
|
+
* @throws {DatabaseError} When the driver rejects the statement (original
|
|
80
|
+
* error in `.cause`).
|
|
81
|
+
* @throws {SqlStackError} When called outside a @Query method, or for
|
|
82
|
+
* shape/validation failures (ExactlyOneRowError, NoRowsError, ValidationError, ...).
|
|
27
83
|
*/
|
|
28
84
|
export declare function run<T = any>(): Promise<T>;
|
|
85
|
+
/**
|
|
86
|
+
* Inside a @Query method: execute this inline sql`` fragment instead of the
|
|
87
|
+
* method's SQL file. The database comes from the method/class/registry
|
|
88
|
+
* context (`@Query({ db })`, `@QueryBinder({ db })`, the default), the
|
|
89
|
+
* active transaction on it is joined, and the method's shape/transform/
|
|
90
|
+
* validation decorators apply. The method's arguments are not auto-bound —
|
|
91
|
+
* the fragment's `${}` values are the parameters.
|
|
92
|
+
*
|
|
93
|
+
* @Single @Query()
|
|
94
|
+
* async byEmail(email: string): Promise<User | null> {
|
|
95
|
+
* return run(sql`SELECT * FROM users WHERE email = ${email}`);
|
|
96
|
+
* }
|
|
97
|
+
*
|
|
98
|
+
* @throws {DatabaseError} When the fragment cannot be compiled (macro input
|
|
99
|
+
* errors), the database cannot be resolved, or the driver rejects the
|
|
100
|
+
* statement. The original error is in `.cause`.
|
|
101
|
+
* @throws {SqlStackError} When called outside a @Query method (use
|
|
102
|
+
* `run(db, query)` there), or for shape/validation failures.
|
|
103
|
+
*/
|
|
104
|
+
export declare function run<T = unknown>(query: SqlFragment): Promise<T>;
|
|
105
|
+
/**
|
|
106
|
+
* Execute an sql`` fragment against an explicit database: a handle
|
|
107
|
+
* (anything with `query(sql, params)`) or the name of a database registered
|
|
108
|
+
* with the active SqlStack / legacy registry. Usable anywhere.
|
|
109
|
+
*
|
|
110
|
+
* Binds for the database's dialect (`$1..` for Postgres, `?` otherwise;
|
|
111
|
+
* default sqlite). Joins an active transaction opened on the same database
|
|
112
|
+
* (same registered handle, or same name). Outside a @Query method the raw
|
|
113
|
+
* result is returned (rows array, or `{ rowsAffected }` for writes); inside
|
|
114
|
+
* one, the method's shape/transform/validation decorators apply.
|
|
115
|
+
*
|
|
116
|
+
* const rows = await run<Row[]>(accountsDb, sql`SELECT * FROM t WHERE id = ${id}`);
|
|
117
|
+
*
|
|
118
|
+
* @throws {DatabaseError} When the fragment cannot be compiled, a named
|
|
119
|
+
* database cannot be resolved, or the driver rejects the statement. The
|
|
120
|
+
* original error is in `.cause`, and its string `code` is copied to `.code`.
|
|
121
|
+
* @throws {SqlStackError} For invalid arguments, or shape/validation failures.
|
|
122
|
+
*/
|
|
123
|
+
export declare function run<T = unknown>(db: RunDatabase | string, query: SqlFragment): Promise<T>;
|
|
124
|
+
/**
|
|
125
|
+
* Inside a @Query method: run the method's own SQL (its .sql file or inline
|
|
126
|
+
* `@Query({ sql })`) against `db`, binding `params` (an object for `:named`
|
|
127
|
+
* placeholders, an array for `:arg1..`). The method's raw arguments are NOT
|
|
128
|
+
* auto-bound in this form — `params` is the whole binding input. @Defaults,
|
|
129
|
+
* @Page, shaping, transform, and validation still apply.
|
|
130
|
+
*
|
|
131
|
+
* @Single @Query()
|
|
132
|
+
* async byEmail(db: Database, p: { email: string }): Promise<User | null> {
|
|
133
|
+
* return run(db, p);
|
|
134
|
+
* }
|
|
135
|
+
*
|
|
136
|
+
* @throws {DatabaseError} When binding fails, a named database cannot be
|
|
137
|
+
* resolved, or the driver rejects the statement. The original error is in
|
|
138
|
+
* `.cause`.
|
|
139
|
+
* @throws {SqlStackError} When called outside a @Query method, when passed
|
|
140
|
+
* `.toSQL()` output, or for shape/validation failures.
|
|
141
|
+
*/
|
|
142
|
+
export declare function run<T = unknown, P extends object = object>(db: RunDatabase | string, params: P & RejectCompiledSql<P>): Promise<T>;
|
|
143
|
+
/**
|
|
144
|
+
* Inside a @Query method: run the method's own SQL against `db` (a handle or
|
|
145
|
+
* a registered database name), binding the method's own arguments exactly as
|
|
146
|
+
* run() does — except that a leading database handle/name argument of the
|
|
147
|
+
* method is never bound.
|
|
148
|
+
*
|
|
149
|
+
* @throws {DatabaseError} When binding fails, a named database cannot be
|
|
150
|
+
* resolved, or the driver rejects the statement.
|
|
151
|
+
* @throws {SqlStackError} When called outside a @Query method, or for
|
|
152
|
+
* shape/validation failures.
|
|
153
|
+
*/
|
|
154
|
+
export declare function run<T = unknown, D extends RunDatabase | string = RunDatabase | string>(db: D & RejectSqlText<D>): Promise<T>;
|
|
155
|
+
/**
|
|
156
|
+
* Inside a @Query method: run the method's own SQL binding only `params` (an
|
|
157
|
+
* object for `:named`, an array for `:argN`) against the database run() would
|
|
158
|
+
* use: the method's leading database handle/name argument, else the
|
|
159
|
+
* decorator context.
|
|
160
|
+
*
|
|
161
|
+
* @throws {DatabaseError} When binding fails, the database cannot be
|
|
162
|
+
* resolved, or the driver rejects the statement.
|
|
163
|
+
* @throws {SqlStackError} When called outside a @Query method, when passed
|
|
164
|
+
* `.toSQL()` output, or for shape/validation failures.
|
|
165
|
+
*/
|
|
166
|
+
export declare function run<T = unknown, P extends object = object>(params: P & RejectCompiledSql<P>): Promise<T>;
|
|
167
|
+
/** @internal A database handle: any object exposing query(sql, params). */
|
|
168
|
+
export declare function isRunDatabaseHandle(value: unknown): value is RunDatabase;
|
|
169
|
+
/** @internal A database chosen for one run, plus the transaction it joins. */
|
|
170
|
+
export type RunTarget = {
|
|
171
|
+
readonly db: RunDatabase;
|
|
172
|
+
readonly tx: ActiveTransaction | undefined;
|
|
173
|
+
/** SQL resolver of the environment, when the target was resolved by name. */
|
|
174
|
+
readonly resolver: SqlResolver | undefined;
|
|
175
|
+
readonly byName: boolean;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* @internal Resolve run's database argument. A name goes through the active
|
|
179
|
+
* SqlStack (or legacy registry) and joins that entry's transaction — or,
|
|
180
|
+
* inside a @transaction scope with none open, opens one on first execution. A handle
|
|
181
|
+
* is used as-is — no registry lookup, so it works without any SqlStack — and
|
|
182
|
+
* behaves the same: it joins a transaction open in this flow on that same
|
|
183
|
+
* object, or, inside a @transaction scope with none open, opens one on the
|
|
184
|
+
* handle on first execution. Outside any scope a handle with no open
|
|
185
|
+
* transaction runs directly.
|
|
186
|
+
*/
|
|
187
|
+
export declare function resolveRunTarget(db: RunDatabase | string): Promise<RunTarget>;
|
|
188
|
+
/** @internal Run one bound statement on the target (inside its transaction, if any). */
|
|
189
|
+
export declare function executeOnTarget(target: RunTarget, boundSql: string, params: unknown[]): Promise<unknown>;
|
|
190
|
+
/**
|
|
191
|
+
* @internal Normalize a failure from run's argument-taking forms: errors that
|
|
192
|
+
* are already SqlStackError (DatabaseError, shape/validation errors) pass
|
|
193
|
+
* through; anything else becomes DatabaseError with the original in `.cause`.
|
|
194
|
+
*/
|
|
195
|
+
export declare function toRunError(err: unknown, sqlText: string): SqlStackError;
|
|
196
|
+
/** @internal Raw template text of a fragment, for error messages. */
|
|
197
|
+
export declare function fragmentText(fragment: SqlFragment): string;
|
|
198
|
+
/** @internal Compile a fragment for the dialect, wrapping macro errors. */
|
|
199
|
+
export declare function compileForRun(fragment: SqlFragment, dialect: Dialect): {
|
|
200
|
+
sql: string;
|
|
201
|
+
params: unknown[];
|
|
202
|
+
};
|
|
29
203
|
//# sourceMappingURL=run.d.ts.map
|
package/dist/cjs/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/run.js
CHANGED
|
@@ -2,8 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runStorage = void 0;
|
|
4
4
|
exports.run = run;
|
|
5
|
+
exports.isRunDatabaseHandle = isRunDatabaseHandle;
|
|
6
|
+
exports.resolveRunTarget = resolveRunTarget;
|
|
7
|
+
exports.executeOnTarget = executeOnTarget;
|
|
8
|
+
exports.toRunError = toRunError;
|
|
9
|
+
exports.fragmentText = fragmentText;
|
|
10
|
+
exports.compileForRun = compileForRun;
|
|
5
11
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
6
12
|
const errors_1 = require("./core/errors");
|
|
13
|
+
const sql_1 = require("./sql");
|
|
14
|
+
const runtime_1 = require("./runtime");
|
|
15
|
+
const transactions_1 = require("./transactions");
|
|
7
16
|
// Anchored on globalThis via Symbol.for so duplicated module instances
|
|
8
17
|
// (npm link, dual ESM/CJS loads) share one channel between the decorator
|
|
9
18
|
// and the run() the application imports.
|
|
@@ -13,26 +22,158 @@ if (!anchor[RUN_CHANNEL]) {
|
|
|
13
22
|
anchor[RUN_CHANNEL] = new node_async_hooks_1.AsyncLocalStorage();
|
|
14
23
|
}
|
|
15
24
|
exports.runStorage = anchor[RUN_CHANNEL];
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* Call it as the body of a @Query-decorated method in place of the legacy
|
|
19
|
-
* placeholder throw:
|
|
20
|
-
*
|
|
21
|
-
* @Query()
|
|
22
|
-
* async getUsers(active: boolean): Promise<User[]> {
|
|
23
|
-
* return run<User[]>();
|
|
24
|
-
* }
|
|
25
|
-
*
|
|
26
|
-
* Takes no arguments — the method's own arguments, database, SQL source,
|
|
27
|
-
* transaction, shaping, transform, and validation all come from the
|
|
28
|
-
* decorator context. The generic is a typing convenience only.
|
|
29
|
-
*/
|
|
30
|
-
async function run() {
|
|
25
|
+
async function run(...args) {
|
|
26
|
+
const invocation = parseRunArgs(args);
|
|
31
27
|
const ctx = exports.runStorage.getStore();
|
|
32
28
|
if (!ctx) {
|
|
33
|
-
|
|
29
|
+
if (invocation.kind === 'fragment' && invocation.db !== undefined) {
|
|
30
|
+
return executeFragment(invocation.db, invocation.fragment);
|
|
31
|
+
}
|
|
32
|
+
if (invocation.kind === 'default') {
|
|
33
|
+
throw new errors_1.SqlStackError('run() called outside a @Query method. It may only be invoked from the body of a @Query-decorated method.');
|
|
34
|
+
}
|
|
35
|
+
if (invocation.kind === 'fragment') {
|
|
36
|
+
throw new errors_1.SqlStackError('run(query) called outside a @Query method has no database. Pass one explicitly: run(db, query).');
|
|
37
|
+
}
|
|
38
|
+
if (invocation.kind === 'db') {
|
|
39
|
+
throw new errors_1.SqlStackError('run(db) called outside a @Query method has no SQL source. Pass an sql`` fragment instead: run(db, sql`...`).');
|
|
40
|
+
}
|
|
41
|
+
if (invocation.db === undefined) {
|
|
42
|
+
throw new errors_1.SqlStackError('run(params) called outside a @Query method has no SQL source or database. ' +
|
|
43
|
+
'Pass a database and an sql`` fragment instead: run(db, sql`...`).');
|
|
44
|
+
}
|
|
45
|
+
throw new errors_1.SqlStackError('run(db, params) called outside a @Query method has no SQL source. ' +
|
|
46
|
+
'Pass an sql`` fragment instead: run(db, sql`...`).');
|
|
47
|
+
}
|
|
48
|
+
if (invocation.kind !== 'default' && !ctx.invocations) {
|
|
49
|
+
throw new errors_1.SqlStackError('run(...) with arguments reached a @Query wrapper from an older sqlstack copy that cannot honour them. ' +
|
|
50
|
+
'Make sure a single sqlstack version is installed.');
|
|
34
51
|
}
|
|
35
52
|
ctx.ran = true;
|
|
36
|
-
return ctx.execute();
|
|
53
|
+
return invocation.kind === 'default' ? ctx.execute() : ctx.execute(invocation);
|
|
54
|
+
}
|
|
55
|
+
function parseRunArgs(args) {
|
|
56
|
+
if (args.length === 0)
|
|
57
|
+
return { kind: 'default' };
|
|
58
|
+
if (args.length === 1) {
|
|
59
|
+
const [query] = args;
|
|
60
|
+
if ((0, sql_1.isSqlFragment)(query))
|
|
61
|
+
return { kind: 'fragment', fragment: query };
|
|
62
|
+
if (typeof query === 'string') {
|
|
63
|
+
// A whitespace-free string is a database name: run(db).
|
|
64
|
+
if (isDatabaseNameText(query))
|
|
65
|
+
return { kind: 'db', db: query };
|
|
66
|
+
throw new errors_1.SqlStackError('run(query) does not accept SQL strings. Build the statement with the sql`` tag: run(sql`...`).');
|
|
67
|
+
}
|
|
68
|
+
if (isRunDatabaseHandle(query))
|
|
69
|
+
return { kind: 'db', db: query };
|
|
70
|
+
if (isCompiledSql(query)) {
|
|
71
|
+
throw new errors_1.SqlStackError('run(...) received the { sql, params } output of .toSQL(). Pass the sql`` fragment itself so run can ' +
|
|
72
|
+
'bind it for the target dialect: run(sql`...`).');
|
|
73
|
+
}
|
|
74
|
+
if (typeof query === 'object' && query !== null)
|
|
75
|
+
return { kind: 'params', params: query };
|
|
76
|
+
throw new errors_1.SqlStackError('run(x) requires an sql`` fragment, a params object/array, or a database handle/name.');
|
|
77
|
+
}
|
|
78
|
+
if (args.length === 2) {
|
|
79
|
+
const [db, second] = args;
|
|
80
|
+
assertRunDatabase(db);
|
|
81
|
+
if ((0, sql_1.isSqlFragment)(second))
|
|
82
|
+
return { kind: 'fragment', db, fragment: second };
|
|
83
|
+
if (typeof second === 'string') {
|
|
84
|
+
throw new errors_1.SqlStackError('run(db, query) does not accept SQL strings. Build the statement with the sql`` tag: run(db, sql`...`).');
|
|
85
|
+
}
|
|
86
|
+
if (isCompiledSql(second)) {
|
|
87
|
+
throw new errors_1.SqlStackError('run(db, ...) received the { sql, params } output of .toSQL(). Pass the sql`` fragment itself so run can ' +
|
|
88
|
+
'bind it for the target dialect: run(db, sql`...`).');
|
|
89
|
+
}
|
|
90
|
+
if (typeof second === 'object' && second !== null)
|
|
91
|
+
return { kind: 'params', db, params: second };
|
|
92
|
+
throw new errors_1.SqlStackError('run(db, x) requires an sql`` fragment or a params object/array as its second argument.');
|
|
93
|
+
}
|
|
94
|
+
throw new errors_1.SqlStackError(`run() accepts at most 2 arguments, got ${args.length}.`);
|
|
95
|
+
}
|
|
96
|
+
/** @internal A database handle: any object exposing query(sql, params). */
|
|
97
|
+
function isRunDatabaseHandle(value) {
|
|
98
|
+
return typeof value === 'object' && value !== null && typeof value.query === 'function';
|
|
99
|
+
}
|
|
100
|
+
function isDatabaseNameText(value) {
|
|
101
|
+
return value.length > 0 && !/\s/.test(value);
|
|
102
|
+
}
|
|
103
|
+
function assertRunDatabase(db) {
|
|
104
|
+
if (typeof db === 'string' && db.length > 0)
|
|
105
|
+
return;
|
|
106
|
+
if (typeof db === 'object' && db !== null && typeof db.query === 'function')
|
|
107
|
+
return;
|
|
108
|
+
throw new errors_1.SqlStackError('run(db, ...) requires a database handle with query(sql, params) or a registered database name as its first argument.');
|
|
109
|
+
}
|
|
110
|
+
function isCompiledSql(value) {
|
|
111
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
112
|
+
return false;
|
|
113
|
+
const keys = Object.keys(value);
|
|
114
|
+
const rec = value;
|
|
115
|
+
return keys.length === 2 && typeof rec.sql === 'string' && Array.isArray(rec.params);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @internal Resolve run's database argument. A name goes through the active
|
|
119
|
+
* SqlStack (or legacy registry) and joins that entry's transaction — or,
|
|
120
|
+
* inside a @transaction scope with none open, opens one on first execution. A handle
|
|
121
|
+
* is used as-is — no registry lookup, so it works without any SqlStack — and
|
|
122
|
+
* behaves the same: it joins a transaction open in this flow on that same
|
|
123
|
+
* object, or, inside a @transaction scope with none open, opens one on the
|
|
124
|
+
* handle on first execution. Outside any scope a handle with no open
|
|
125
|
+
* transaction runs directly.
|
|
126
|
+
*/
|
|
127
|
+
async function resolveRunTarget(db) {
|
|
128
|
+
if (typeof db === 'string') {
|
|
129
|
+
const { entry, resolver } = await (0, runtime_1.resolveExecution)(db);
|
|
130
|
+
return { db: entry.db, tx: (0, transactions_1.getTransactionTarget)(entry), resolver, byName: true };
|
|
131
|
+
}
|
|
132
|
+
return { db, tx: (0, transactions_1.getTransactionTargetForHandle)(db), resolver: undefined, byName: false };
|
|
133
|
+
}
|
|
134
|
+
/** @internal Run one bound statement on the target (inside its transaction, if any). */
|
|
135
|
+
async function executeOnTarget(target, boundSql, params) {
|
|
136
|
+
try {
|
|
137
|
+
return target.tx ? await target.tx.query(boundSql, params) : await target.db.query(boundSql, params);
|
|
138
|
+
}
|
|
139
|
+
catch (dbError) {
|
|
140
|
+
throw toDatabaseError(dbError, boundSql);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* @internal Normalize a failure from run's argument-taking forms: errors that
|
|
145
|
+
* are already SqlStackError (DatabaseError, shape/validation errors) pass
|
|
146
|
+
* through; anything else becomes DatabaseError with the original in `.cause`.
|
|
147
|
+
*/
|
|
148
|
+
function toRunError(err, sqlText) {
|
|
149
|
+
return err instanceof errors_1.SqlStackError ? err : toDatabaseError(err, sqlText);
|
|
150
|
+
}
|
|
151
|
+
function toDatabaseError(err, sqlText) {
|
|
152
|
+
const message = err?.message;
|
|
153
|
+
return new errors_1.DatabaseError(typeof message === 'string' && message ? message : String(err), sqlText, err instanceof Error ? err : undefined);
|
|
154
|
+
}
|
|
155
|
+
/** @internal Raw template text of a fragment, for error messages. */
|
|
156
|
+
function fragmentText(fragment) {
|
|
157
|
+
return fragment.strings.join('?');
|
|
158
|
+
}
|
|
159
|
+
/** @internal Compile a fragment for the dialect, wrapping macro errors. */
|
|
160
|
+
function compileForRun(fragment, dialect) {
|
|
161
|
+
try {
|
|
162
|
+
return (0, sql_1.compileFragment)(fragment, dialect);
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
throw toRunError(err, fragmentText(fragment));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async function executeFragment(db, fragment) {
|
|
169
|
+
let target;
|
|
170
|
+
try {
|
|
171
|
+
target = await resolveRunTarget(db);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
throw toRunError(err, fragmentText(fragment));
|
|
175
|
+
}
|
|
176
|
+
const { sql: boundSql, params } = compileForRun(fragment, target.db.dialect ?? 'sqlite');
|
|
177
|
+
return executeOnTarget(target, boundSql, params);
|
|
37
178
|
}
|
|
38
179
|
//# sourceMappingURL=run.js.map
|
package/dist/cjs/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":";;;AAuCA,kBASC;AAhDD,uDAAqD;AACrD,0CAA8C;AAc9C,uEAAuE;AACvE,yEAAyE;AACzE,yCAAyC;AACzC,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;AAC5D,MAAM,MAAM,GAAG,UAA0C,CAAC;AAC1D,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;IACzB,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,oCAAiB,EAAc,CAAC;AAC5D,CAAC;AACY,QAAA,UAAU,GAAG,MAAM,CAAC,WAAW,CAAkC,CAAC;AAE/E;;;;;;;;;;;;;GAaG;AACI,KAAK,UAAU,GAAG;IACvB,MAAM,GAAG,GAAG,kBAAU,CAAC,QAAQ,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,sBAAa,CACrB,0GAA0G,CAC3G,CAAC;IACJ,CAAC;IACD,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC;IACf,OAAO,GAAG,CAAC,OAAO,EAAgB,CAAC;AACrC,CAAC","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport { SqlStackError } from './core/errors';\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.\n */\nexport type RunContext = {\n execute: () => Promise<unknown>;\n ran: boolean;\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 in place of the legacy\n * placeholder throw:\n *\n * @Query()\n * async getUsers(active: boolean): Promise<User[]> {\n * return run<User[]>();\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. The generic is a typing convenience only.\n */\nexport async function run<T = any>(): Promise<T> {\n const ctx = runStorage.getStore();\n if (!ctx) {\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 ctx.ran = true;\n return ctx.execute() as Promise<T>;\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
|
@@ -20,6 +20,20 @@ export type ResolvedExecution = {
|
|
|
20
20
|
* Resolve the concrete database entry (and SQL resolver) for one execution.
|
|
21
21
|
*/
|
|
22
22
|
export declare function resolveExecution(dbName?: string): Promise<ResolvedExecution>;
|
|
23
|
+
/**
|
|
24
|
+
* @internal The SQL source resolver for one execution WITHOUT resolving a
|
|
25
|
+
* database — used when the caller supplied a database handle directly
|
|
26
|
+
* (`run(db, params)`). Same environment rules as resolveExecution: the
|
|
27
|
+
* active root's SqlStack resolver when an IoC environment is active (and an
|
|
28
|
+
* error when that environment has no SqlStack), else the legacy global one.
|
|
29
|
+
*/
|
|
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>;
|
|
23
37
|
/** @internal Resolve a legacy global-registry database as a DatabaseEntry. */
|
|
24
38
|
export declare function legacyEntry(dbName?: string): DatabaseEntry;
|
|
25
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;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
|
@@ -36,6 +36,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.__resetIocDetection = __resetIocDetection;
|
|
37
37
|
exports.activeSqlStack = activeSqlStack;
|
|
38
38
|
exports.resolveExecution = resolveExecution;
|
|
39
|
+
exports.resolveSqlResolver = resolveSqlResolver;
|
|
40
|
+
exports.isRegisteredDatabaseName = isRegisteredDatabaseName;
|
|
39
41
|
exports.legacyEntry = legacyEntry;
|
|
40
42
|
const stack_1 = require("./stack");
|
|
41
43
|
const registry_1 = require("./registry");
|
|
@@ -111,6 +113,34 @@ async function resolveExecution(dbName) {
|
|
|
111
113
|
viaStack: false,
|
|
112
114
|
};
|
|
113
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* @internal The SQL source resolver for one execution WITHOUT resolving a
|
|
118
|
+
* database — used when the caller supplied a database handle directly
|
|
119
|
+
* (`run(db, params)`). Same environment rules as resolveExecution: the
|
|
120
|
+
* active root's SqlStack resolver when an IoC environment is active (and an
|
|
121
|
+
* error when that environment has no SqlStack), else the legacy global one.
|
|
122
|
+
*/
|
|
123
|
+
async function resolveSqlResolver() {
|
|
124
|
+
const stack = await activeSqlStack();
|
|
125
|
+
return stack ? stack.resolver() : (0, resolver_1.getActiveResolver)();
|
|
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
|
+
}
|
|
114
144
|
// ---------------------------------------------------------------------------
|
|
115
145
|
// Legacy (deprecated) global-registry support
|
|
116
146
|
// ---------------------------------------------------------------------------
|