litedbmodel 2.0.2 → 2.2.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.
Files changed (193) hide show
  1. package/README.md +7 -0
  2. package/dist/DBConditions.d.ts.map +1 -1
  3. package/dist/DBConditions.js +16 -1
  4. package/dist/DBConditions.js.map +1 -1
  5. package/dist/DBHandler.d.ts.map +1 -1
  6. package/dist/DBHandler.js +6 -0
  7. package/dist/DBHandler.js.map +1 -1
  8. package/dist/DBModel.d.ts +84 -2
  9. package/dist/DBModel.d.ts.map +1 -1
  10. package/dist/DBModel.js +312 -29
  11. package/dist/DBModel.js.map +1 -1
  12. package/dist/decorators.d.ts +52 -0
  13. package/dist/decorators.d.ts.map +1 -1
  14. package/dist/decorators.js +127 -24
  15. package/dist/decorators.js.map +1 -1
  16. package/dist/drivers/mysql.d.ts.map +1 -1
  17. package/dist/drivers/mysql.js +12 -2
  18. package/dist/drivers/mysql.js.map +1 -1
  19. package/dist/drivers/postgres.d.ts.map +1 -1
  20. package/dist/drivers/postgres.js +13 -2
  21. package/dist/drivers/postgres.js.map +1 -1
  22. package/dist/drivers/sqlite.d.ts +2 -0
  23. package/dist/drivers/sqlite.d.ts.map +1 -1
  24. package/dist/drivers/sqlite.js +49 -4
  25. package/dist/drivers/sqlite.js.map +1 -1
  26. package/dist/index.cjs +10741 -0
  27. package/dist/index.d.cts +1 -0
  28. package/dist/scp/coltype.d.ts +108 -0
  29. package/dist/scp/coltype.d.ts.map +1 -1
  30. package/dist/scp/coltype.js +293 -6
  31. package/dist/scp/coltype.js.map +1 -1
  32. package/dist/scp/connection-routing.d.ts +312 -0
  33. package/dist/scp/connection-routing.d.ts.map +1 -0
  34. package/dist/scp/connection-routing.js +394 -0
  35. package/dist/scp/connection-routing.js.map +1 -0
  36. package/dist/scp/dbmodel-runtime.d.ts +101 -0
  37. package/dist/scp/dbmodel-runtime.d.ts.map +1 -0
  38. package/dist/scp/dbmodel-runtime.js +174 -0
  39. package/dist/scp/dbmodel-runtime.js.map +1 -0
  40. package/dist/scp/decorator-adapter.d.ts +196 -0
  41. package/dist/scp/decorator-adapter.d.ts.map +1 -0
  42. package/dist/scp/decorator-adapter.js +286 -0
  43. package/dist/scp/decorator-adapter.js.map +1 -0
  44. package/dist/scp/emit/emitter.d.ts +108 -0
  45. package/dist/scp/emit/emitter.d.ts.map +1 -0
  46. package/dist/scp/emit/emitter.js +782 -0
  47. package/dist/scp/emit/emitter.js.map +1 -0
  48. package/dist/scp/emit/endpoint.d.ts +248 -0
  49. package/dist/scp/emit/endpoint.d.ts.map +1 -0
  50. package/dist/scp/emit/endpoint.js +20 -0
  51. package/dist/scp/emit/endpoint.js.map +1 -0
  52. package/dist/scp/emit/index.d.ts +11 -0
  53. package/dist/scp/emit/index.d.ts.map +1 -0
  54. package/dist/scp/emit/index.js +13 -0
  55. package/dist/scp/emit/index.js.map +1 -0
  56. package/dist/scp/errors.d.ts +45 -1
  57. package/dist/scp/errors.d.ts.map +1 -1
  58. package/dist/scp/errors.js +47 -1
  59. package/dist/scp/errors.js.map +1 -1
  60. package/dist/scp/exec-context.d.ts +390 -0
  61. package/dist/scp/exec-context.d.ts.map +1 -0
  62. package/dist/scp/exec-context.js +540 -0
  63. package/dist/scp/exec-context.js.map +1 -0
  64. package/dist/scp/grouping.d.ts +32 -0
  65. package/dist/scp/grouping.d.ts.map +1 -0
  66. package/dist/scp/grouping.js +0 -0
  67. package/dist/scp/grouping.js.map +1 -0
  68. package/dist/scp/index.cjs +6432 -17579
  69. package/dist/scp/index.d.cts +1 -0
  70. package/dist/scp/index.d.mts +1 -0
  71. package/dist/scp/index.d.ts +51 -52
  72. package/dist/scp/index.d.ts.map +1 -1
  73. package/dist/scp/index.js +189 -152
  74. package/dist/scp/index.js.map +1 -1
  75. package/dist/scp/index.mjs +6067 -3659
  76. package/dist/scp/leaf-transport.d.ts +50 -0
  77. package/dist/scp/leaf-transport.d.ts.map +1 -0
  78. package/dist/scp/leaf-transport.js +92 -0
  79. package/dist/scp/leaf-transport.js.map +1 -0
  80. package/dist/scp/leaves.d.ts +174 -0
  81. package/dist/scp/leaves.d.ts.map +1 -0
  82. package/dist/scp/leaves.js +287 -0
  83. package/dist/scp/leaves.js.map +1 -0
  84. package/dist/scp/limit-config.d.ts +118 -0
  85. package/dist/scp/limit-config.d.ts.map +1 -0
  86. package/dist/scp/limit-config.js +126 -0
  87. package/dist/scp/limit-config.js.map +1 -0
  88. package/dist/scp/makesql/compile-relation.d.ts +49 -23
  89. package/dist/scp/makesql/compile-relation.d.ts.map +1 -1
  90. package/dist/scp/makesql/compile-relation.js +101 -76
  91. package/dist/scp/makesql/compile-relation.js.map +1 -1
  92. package/dist/scp/makesql/compile-select.d.ts +45 -10
  93. package/dist/scp/makesql/compile-select.d.ts.map +1 -1
  94. package/dist/scp/makesql/compile-select.js +50 -10
  95. package/dist/scp/makesql/compile-select.js.map +1 -1
  96. package/dist/scp/makesql/handler.d.ts +1 -1
  97. package/dist/scp/makesql/handler.d.ts.map +1 -1
  98. package/dist/scp/makesql/index.d.ts +7 -10
  99. package/dist/scp/makesql/index.d.ts.map +1 -1
  100. package/dist/scp/makesql/index.js +19 -30
  101. package/dist/scp/makesql/index.js.map +1 -1
  102. package/dist/scp/makesql/json-array.d.ts +65 -0
  103. package/dist/scp/makesql/json-array.d.ts.map +1 -1
  104. package/dist/scp/makesql/json-array.js +99 -10
  105. package/dist/scp/makesql/json-array.js.map +1 -1
  106. package/dist/scp/makesql/json-batch.d.ts.map +1 -1
  107. package/dist/scp/makesql/json-batch.js +21 -19
  108. package/dist/scp/makesql/json-batch.js.map +1 -1
  109. package/dist/scp/makesql/makesql.d.ts +1 -1
  110. package/dist/scp/makesql/makesql.d.ts.map +1 -1
  111. package/dist/scp/makesql/mysql-returning.d.ts +93 -0
  112. package/dist/scp/makesql/mysql-returning.d.ts.map +1 -0
  113. package/dist/scp/makesql/mysql-returning.js +215 -0
  114. package/dist/scp/makesql/mysql-returning.js.map +1 -0
  115. package/dist/scp/makesql/outtype.d.ts +75 -34
  116. package/dist/scp/makesql/outtype.d.ts.map +1 -1
  117. package/dist/scp/makesql/outtype.js +91 -118
  118. package/dist/scp/makesql/outtype.js.map +1 -1
  119. package/dist/scp/makesql/pool-executor.d.ts +135 -13
  120. package/dist/scp/makesql/pool-executor.d.ts.map +1 -1
  121. package/dist/scp/makesql/pool-executor.js +229 -21
  122. package/dist/scp/makesql/pool-executor.js.map +1 -1
  123. package/dist/scp/makesql/tx.d.ts +107 -22
  124. package/dist/scp/makesql/tx.d.ts.map +1 -1
  125. package/dist/scp/makesql/tx.js +451 -97
  126. package/dist/scp/makesql/tx.js.map +1 -1
  127. package/dist/scp/makesql/writeouttype.d.ts +7 -8
  128. package/dist/scp/makesql/writeouttype.d.ts.map +1 -1
  129. package/dist/scp/makesql/writeouttype.js +8 -7
  130. package/dist/scp/makesql/writeouttype.js.map +1 -1
  131. package/dist/scp/middleware.d.ts +287 -0
  132. package/dist/scp/middleware.d.ts.map +1 -0
  133. package/dist/scp/middleware.js +358 -0
  134. package/dist/scp/middleware.js.map +1 -0
  135. package/dist/scp/relation.d.ts +80 -9
  136. package/dist/scp/relation.d.ts.map +1 -1
  137. package/dist/scp/relation.js +198 -78
  138. package/dist/scp/relation.js.map +1 -1
  139. package/dist/scp/tx-options.d.ts +136 -0
  140. package/dist/scp/tx-options.d.ts.map +1 -0
  141. package/dist/scp/tx-options.js +184 -0
  142. package/dist/scp/tx-options.js.map +1 -0
  143. package/dist/scp/write-bundle.d.ts +131 -0
  144. package/dist/scp/write-bundle.d.ts.map +1 -0
  145. package/dist/scp/write-bundle.js +160 -0
  146. package/dist/scp/write-bundle.js.map +1 -0
  147. package/dist/types.d.ts +7 -0
  148. package/dist/types.d.ts.map +1 -1
  149. package/dist/types.js.map +1 -1
  150. package/docs/BENCHMARK.md +58 -56
  151. package/docs/benchmark-chart.svg +166 -166
  152. package/docs/design/phase-a-execution-context.md +139 -0
  153. package/package.json +16 -9
  154. package/dist/scp/authoring-sql.d.ts +0 -134
  155. package/dist/scp/authoring-sql.d.ts.map +0 -1
  156. package/dist/scp/authoring-sql.js +0 -191
  157. package/dist/scp/authoring-sql.js.map +0 -1
  158. package/dist/scp/authoring.d.ts +0 -155
  159. package/dist/scp/authoring.d.ts.map +0 -1
  160. package/dist/scp/authoring.js +0 -162
  161. package/dist/scp/authoring.js.map +0 -1
  162. package/dist/scp/catalog.d.ts +0 -94
  163. package/dist/scp/catalog.d.ts.map +0 -1
  164. package/dist/scp/catalog.js +0 -234
  165. package/dist/scp/catalog.js.map +0 -1
  166. package/dist/scp/codegen.d.ts +0 -189
  167. package/dist/scp/codegen.d.ts.map +0 -1
  168. package/dist/scp/codegen.js +0 -421
  169. package/dist/scp/codegen.js.map +0 -1
  170. package/dist/scp/find-filter-guard.d.ts +0 -68
  171. package/dist/scp/find-filter-guard.d.ts.map +0 -1
  172. package/dist/scp/find-filter-guard.js +0 -88
  173. package/dist/scp/find-filter-guard.js.map +0 -1
  174. package/dist/scp/guard.d.ts +0 -43
  175. package/dist/scp/guard.d.ts.map +0 -1
  176. package/dist/scp/guard.js +0 -134
  177. package/dist/scp/guard.js.map +0 -1
  178. package/dist/scp/makesql/authoring-compile.d.ts +0 -90
  179. package/dist/scp/makesql/authoring-compile.d.ts.map +0 -1
  180. package/dist/scp/makesql/authoring-compile.js +0 -494
  181. package/dist/scp/makesql/authoring-compile.js.map +0 -1
  182. package/dist/scp/makesql/ir.d.ts +0 -42
  183. package/dist/scp/makesql/ir.d.ts.map +0 -1
  184. package/dist/scp/makesql/ir.js +0 -66
  185. package/dist/scp/makesql/ir.js.map +0 -1
  186. package/dist/scp/makesql/static-bundle.d.ts +0 -187
  187. package/dist/scp/makesql/static-bundle.d.ts.map +0 -1
  188. package/dist/scp/makesql/static-bundle.js +0 -1113
  189. package/dist/scp/makesql/static-bundle.js.map +0 -1
  190. package/dist/scp/runtime.d.ts +0 -242
  191. package/dist/scp/runtime.d.ts.map +0 -1
  192. package/dist/scp/runtime.js +0 -400
  193. package/dist/scp/runtime.js.map +0 -1
@@ -0,0 +1,358 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP — the **middleware layer** (Phase D / #92).
4
+ *
5
+ * This module is the **API REFERENCE** for Phase D — the 4 native ports (rust #93 / go #94 / py #95
6
+ * / php #96) mirror THIS contract exactly: the registration surface (`use` / `createMiddleware`), the
7
+ * SQL-level `execute(next, sql, params)` chain contract + APPLIED ORDER, the method-level hook shape
8
+ * + op-kind dispatch, the standard {@link Logger} middleware, and the raw {@link rawExecute} /
9
+ * {@link rawQuery} API that goes THROUGH the exec-context seam (so middleware + connection routing +
10
+ * transaction all still apply). It builds ON the Phase A {@link import('./exec-context').ExecutionContext}
11
+ * seam (the empty {@link import('./exec-context').MiddlewareChain} hook Phase A reserved) — it does
12
+ * NOT restructure the seam; it makes the reserved hook real.
13
+ *
14
+ * ## The two hook levels (design §4)
15
+ *
16
+ * 1. **SQL-level `execute` hook** — `(sql, params, next) => T`. Wraps EVERY statement that funnels
17
+ * through the central seam ({@link import('./exec-context').execute} / `run` / their async +
18
+ * safeIntegers twins), so read, write, tx-control (BEGIN/COMMIT/ROLLBACK), and relation-batch
19
+ * SQL are ALL intercepted. A middleware can observe / rewrite (`next(sql', params')`) / time /
20
+ * short-circuit (return without calling `next`). This is the seam's `MiddlewareChain` folded
21
+ * around the connection-resolve terminal.
22
+ * 2. **method-level hook** — at the ORM operation boundary, keyed by the operation KIND
23
+ * (`find`/`findOne`/`findById`/`count`/`create`/`createMany`/`update`/`updateMany`/`delete`/
24
+ * `query`). In v2 the "methods" map onto the read (`executeBundle`) / write (`executeTransactionBundle`)
25
+ * operations tagged with their {@link MethodKind}; {@link runMethod} folds the matching method
26
+ * hooks around the operation. A method hook runs before/after (around) the whole operation and
27
+ * can rewrite its args / short-circuit its result.
28
+ *
29
+ * ## Registration + APPLIED ORDER (the 5-language contract — v1 `DBModel.use` parity)
30
+ *
31
+ * `use(mw)` appends to an ordered stack and returns an un-register fn (`DBModel.use` :414). The stack
32
+ * is folded so the FIRST-registered middleware is the OUTERMOST wrapper: given `use(A); use(B)`, a
33
+ * statement runs `A.before → B.before → «execute» → B.after → A.after`. This holds identically for the
34
+ * SQL-level chain ({@link MiddlewareChain.wrap}) and the method-level chain ({@link runMethod}) — the
35
+ * fold walks the stack from LAST to FIRST building `next`, so index 0 ends up outermost. This ORDER is
36
+ * the normative contract the ports reproduce.
37
+ *
38
+ * ## Per-execution-scope isolation (NOT a serializing process global) — design §4 last line
39
+ *
40
+ * A middleware binds to the EXECUTION SCOPE, so concurrent requests/contexts never see each other's
41
+ * middleware or per-request state. TS uses `AsyncLocalStorage` (as v1 does): {@link withMiddlewareScope}
42
+ * runs a callback with an ISOLATED registry copy; every middleware STATE object is likewise ALS-scoped
43
+ * (a fresh per-scope instance via {@link MiddlewareHandle.state}). Two concurrent `withMiddlewareScope`
44
+ * bodies each mutate their OWN registry + state, never a shared global slot — so N concurrent requests
45
+ * do not serialize on one registry (the bug a process-global stack would cause). Absent an explicit
46
+ * scope, `use` mutates a process-global default stack (the app-startup registration path). The native
47
+ * ports translate the ALS: rust = `task_local!`, go = a value on `context.Context`, py = `contextvars`,
48
+ * php = an explicit registry arg (1 request = 1 process ⇒ no concurrency to isolate).
49
+ *
50
+ * NB: native registration (design §4 "native 側でも登録可"): each runtime exposes its own
51
+ * `register_middleware(mw)` appending to its ctx chain; the CHAIN CONTRACT + ORDER above is shared, the
52
+ * middleware BODY is that language's closure/impl. TS is the reference for the shape.
53
+ */
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.Registry = void 0;
56
+ exports.currentRegistry = currentRegistry;
57
+ exports.withMiddlewareScope = withMiddlewareScope;
58
+ exports.activeSqlMiddlewares = activeSqlMiddlewares;
59
+ exports.register = register;
60
+ exports.use = use;
61
+ exports.createMiddleware = createMiddleware;
62
+ exports.runMethod = runMethod;
63
+ exports.Logger = Logger;
64
+ exports.rawExecute = rawExecute;
65
+ exports.rawExecuteAsync = rawExecuteAsync;
66
+ exports.rawQuery = rawQuery;
67
+ exports.rawQueryAsync = rawQueryAsync;
68
+ exports.clearMiddlewares = clearMiddlewares;
69
+ const node_async_hooks_1 = require("node:async_hooks");
70
+ // ── The middleware registry (the ordered stack + ambient isolation) ────────────
71
+ /**
72
+ * The ordered middleware stack. `use` appends (first-registered = outermost, §order), returning an
73
+ * un-register fn. `sqlHooks()` / `methodHooks(kind)` return the folded-order slices the seam +
74
+ * {@link runMethod} consume. A {@link Registry} is EITHER the process-global default (app-startup
75
+ * registration) OR a per-execution-scope copy pushed by {@link withMiddlewareScope} (concurrent
76
+ * isolation) — the two share this class; only their lifetime differs.
77
+ */
78
+ class Registry {
79
+ stack = [];
80
+ /**
81
+ * Per-scope STATE instances, keyed by the state-owning token a {@link createMiddleware} descriptor
82
+ * carries. Because the Registry is itself per-execution-scope ({@link withMiddlewareScope} pushes a
83
+ * COPY), the state map is scope-local too — so a middleware's per-request state is isolated across
84
+ * concurrent scopes WITHOUT leaking (the `enterWith`-leak trap). A fresh scope's copy starts with an
85
+ * EMPTY state map (states are NOT copied), so each scope lazily builds its own fresh state instances.
86
+ */
87
+ states = new Map();
88
+ /** The current scope's state for `token`, lazily created via `fresh` on first access (v1 getCurrentContext). */
89
+ stateFor(token, fresh) {
90
+ let s = this.states.get(token);
91
+ if (s === undefined) {
92
+ s = fresh();
93
+ this.states.set(token, s);
94
+ }
95
+ return s;
96
+ }
97
+ /** Reset `token`'s state in this scope to a fresh instance (testing convenience). */
98
+ resetStateFor(token, fresh) {
99
+ this.states.set(token, fresh());
100
+ }
101
+ /** Register `mw` (appended ⇒ outermost). Returns an idempotent un-register fn. */
102
+ use(mw) {
103
+ this.stack.push(mw);
104
+ return () => {
105
+ const i = this.stack.indexOf(mw);
106
+ if (i !== -1)
107
+ this.stack.splice(i, 1);
108
+ };
109
+ }
110
+ /** Remove `mw` (v1 `removeMiddleware`). Returns whether it was present. */
111
+ remove(mw) {
112
+ const i = this.stack.indexOf(mw);
113
+ if (i === -1)
114
+ return false;
115
+ this.stack.splice(i, 1);
116
+ return true;
117
+ }
118
+ /** Drop every registration (v1 `clearMiddlewares` — testing). */
119
+ clear() {
120
+ this.stack = [];
121
+ }
122
+ /** The registered descriptors, registration order (index 0 = first = outermost). */
123
+ all() {
124
+ return this.stack;
125
+ }
126
+ /** The SQL-level hooks (registration order), for the {@link MiddlewareChain} fold. */
127
+ sqlHooks() {
128
+ const out = [];
129
+ for (const mw of this.stack)
130
+ if (mw.sql !== undefined)
131
+ out.push(mw.sql);
132
+ return out;
133
+ }
134
+ /** The method hooks for `kind` (registration order), for the {@link runMethod} fold. */
135
+ methodHooks(kind) {
136
+ const out = [];
137
+ for (const mw of this.stack) {
138
+ const h = mw.methods?.[kind];
139
+ if (h !== undefined)
140
+ out.push(h);
141
+ }
142
+ return out;
143
+ }
144
+ /** A shallow COPY (used to seed an isolated per-scope registry that starts from the global set). */
145
+ copy() {
146
+ const r = new Registry();
147
+ r.stack = [...this.stack];
148
+ return r;
149
+ }
150
+ }
151
+ exports.Registry = Registry;
152
+ /** The process-global default registry (app-startup `use` with no explicit scope). */
153
+ const globalRegistry = new Registry();
154
+ /** The per-execution-scope registry override (ALS): present ⇒ `use`/reads target THIS scope's copy. */
155
+ const registryScope = new node_async_hooks_1.AsyncLocalStorage();
156
+ /** The registry the current execution scope resolves to: the ALS override, else the global default. */
157
+ function currentRegistry() {
158
+ return registryScope.getStore() ?? globalRegistry;
159
+ }
160
+ /**
161
+ * Run `fn` with an ISOLATED middleware registry (concurrent-request isolation, design §4). The scope
162
+ * seeds a COPY of the currently-visible registry (so app-wide registrations remain in effect), and any
163
+ * `use` / per-request state inside `fn` mutates ONLY this scope — two concurrent `withMiddlewareScope`
164
+ * bodies never see each other's middleware. `seed` lets a caller start from an EMPTY registry instead
165
+ * (`inherit: false`). The native ports run their task-local / contextvar / `context.Context` /
166
+ * explicit-arg equivalent.
167
+ */
168
+ function withMiddlewareScope(fn, opts = {}) {
169
+ const seed = opts.inherit === false ? new Registry() : currentRegistry().copy();
170
+ return registryScope.run(seed, fn);
171
+ }
172
+ /**
173
+ * The LIVE SQL-level middleware stack of the current execution scope — the
174
+ * {@link import('./exec-context').MiddlewareStackSource} the ctx factories give their
175
+ * {@link import('./exec-context').MiddlewareChain}. Resolved at EACH `wrap`, so registration after ctx
176
+ * construction, and per-scope registries, are both honored. Empty ⇒ the seam is a byte-identical
177
+ * passthrough.
178
+ */
179
+ function activeSqlMiddlewares() {
180
+ return currentRegistry().sqlHooks();
181
+ }
182
+ // ── Registration surface (v1 `DBModel.use` / `createMiddleware` parity) ────────
183
+ /**
184
+ * Register a middleware descriptor on the CURRENT scope's registry (the ambient per-scope one inside
185
+ * {@link withMiddlewareScope}, else the process-global default). Returns an un-register fn (v1
186
+ * `DBModel.use` :414). This is the low-level surface; app code usually registers a
187
+ * {@link createMiddleware} handle via {@link use}.
188
+ */
189
+ function register(mw) {
190
+ return currentRegistry().use(mw);
191
+ }
192
+ /** Register a {@link createMiddleware} handle (or a raw descriptor) — v1 `DBModel.use`. */
193
+ function use(mw) {
194
+ const descriptor = 'descriptor' in mw ? mw.descriptor : mw;
195
+ return register(descriptor);
196
+ }
197
+ /** The op-kind method-hook config keys (in registration-independent order). */
198
+ const METHOD_KINDS = [
199
+ 'find', 'findOne', 'findById', 'count', 'create', 'createMany', 'update', 'updateMany', 'delete', 'query',
200
+ ];
201
+ /**
202
+ * Build a {@link MiddlewareHandle} from a v1-shaped {@link MiddlewareConfig} (v1 `createMiddleware`
203
+ * parity). Each hook body's `this` is the CURRENT execution scope's state instance (a fresh
204
+ * `structuredClone` of `config.state` per scope, ALS-isolated). The `execute` hook is adapted from the
205
+ * v1 `(next, sql, params)` order to the seam's `(sql, params, next)` order, so a v1 hook body ports
206
+ * unchanged. Method hooks pass through in the v1 `(model, next, ...args)` shape.
207
+ */
208
+ function createMiddleware(config) {
209
+ // Per-scope state: keyed on THIS unique token in the CURRENT scope's registry. Because the registry
210
+ // is itself per-execution-scope ({@link withMiddlewareScope} pushes a fresh copy with an empty state
211
+ // map), each scope lazily builds its OWN state instance — isolated across concurrent scopes with no
212
+ // `enterWith` leak (v1's per-subclass AsyncLocalStorage, but scope-tied to the registry). First
213
+ // access in a scope deep-copies the initial state (v1 `structuredClone`).
214
+ const token = {};
215
+ const freshState = () => (config.state !== undefined ? structuredClone(config.state) : {});
216
+ const state = () => currentRegistry().stateFor(token, freshState);
217
+ // SQL-level hook: adapt v1 (next, sql, params) → seam (sql, params, next); bind `this` to the state.
218
+ const sql = config.execute
219
+ ? (s, p, next) => config.execute
220
+ .call(state(), (ns, np) => next(ns, np ?? []), s, p)
221
+ : undefined;
222
+ const methods = {};
223
+ for (const kind of METHOD_KINDS) {
224
+ const fn = config[kind];
225
+ if (fn !== undefined) {
226
+ methods[kind] = (model, next, ...args) => fn.call(state(), model, next, ...args);
227
+ }
228
+ }
229
+ const descriptor = {
230
+ ...(sql !== undefined ? { sql } : {}),
231
+ ...(Object.keys(methods).length > 0 ? { methods } : {}),
232
+ };
233
+ return {
234
+ descriptor,
235
+ state,
236
+ resetState: () => currentRegistry().resetStateFor(token, freshState),
237
+ };
238
+ }
239
+ // ── Method-level dispatch (design §4 level 2) — the operation boundary fold ─────
240
+ /**
241
+ * Run an ORM operation of KIND `kind` through the current scope's method hooks, then execute `core`.
242
+ * The hooks fold first-registered-outermost (§order), each getting `(model, next, ...args)`; a hook may
243
+ * rewrite `args`, time `next`, or short-circuit. Empty hooks for this kind ⇒ `core(...args)` verbatim
244
+ * (byte-identical — no method registered = the operation runs untouched). This is the v2 equivalent of
245
+ * v1 `DBModel._applyMiddleware`: the runtime calls it at the read (`executeBundle`) / write
246
+ * (`executeTransactionBundle`) boundary with the op tagged by its {@link MethodKind}.
247
+ *
248
+ * @param kind the operation kind (how a method hook distinguishes read vs. write vs. find/create/…).
249
+ * @param model the operation's model/target descriptor (opaque; passed to each hook).
250
+ * @param core the actual operation, taking the (possibly hook-rewritten) args.
251
+ * @param args the operation's arguments.
252
+ */
253
+ function runMethod(kind, model, core, args) {
254
+ const hooks = currentRegistry().methodHooks(kind);
255
+ if (hooks.length === 0)
256
+ return core(...args); // fast path: no method hook for this kind
257
+ let next = (...a) => core(...a);
258
+ for (let i = hooks.length - 1; i >= 0; i--) {
259
+ const hook = hooks[i];
260
+ const inner = next;
261
+ next = (...a) => hook(model, inner, ...a);
262
+ }
263
+ return next(...args);
264
+ }
265
+ /**
266
+ * The standard **Logger middleware** (design §4, v1 `StatisticsMiddleware`/`Logger` parity): a
267
+ * SQL-level {@link SqlHook} that records the SQL, its params, and the wall-clock ms each statement
268
+ * takes. Every statement through the seam — read, write, tx-control, relation-batch — is logged (it is
269
+ * an `execute`-level hook). Register it with {@link use}: `use(Logger({ sink }))`. Timing brackets the
270
+ * `next` call, so it measures the connection execute (chain remainder included), NOT just the log call.
271
+ *
272
+ * The per-scope log history lives on the handle's `state().entries` (v1 `getCurrentContext().getLogs()`),
273
+ * so concurrent requests each collect their OWN entries (ALS-isolated). The port agents build the same
274
+ * shape: a scope-local list + an `execute` hook timing `next`.
275
+ */
276
+ function Logger(options = {}) {
277
+ const now = options.now ?? Date.now;
278
+ return createMiddleware({
279
+ state: { entries: [] },
280
+ // Works on BOTH the sync (`Rows`/`RunInfo`) and async (`Promise<…>`) seams: `next` may return a
281
+ // value or a thenable, so timing/recording is done in a completion callback that handles either —
282
+ // NOT an `async`/`await` (which would coerce the sync seam's value into a Promise, breaking the
283
+ // synchronous conformance path). `this` is the per-scope state (isolated log history).
284
+ execute: function (next, sql, params) {
285
+ const entries = this.entries;
286
+ const started = now();
287
+ const record = () => {
288
+ const entry = { sql, params, durationMs: now() - started };
289
+ entries.push(entry);
290
+ if (options.sink !== undefined)
291
+ options.sink(entry);
292
+ if (options.console === true) {
293
+ console.log(`[scp] ${sql} (${entry.durationMs}ms) params=${JSON.stringify(params)}`);
294
+ }
295
+ };
296
+ const result = next(sql, params);
297
+ if (result !== null && typeof result === 'object' && typeof result.then === 'function') {
298
+ return result.then((v) => { record(); return v; }, (e) => { record(); throw e; });
299
+ }
300
+ record();
301
+ return result;
302
+ },
303
+ });
304
+ }
305
+ // ── D3: raw execute / query THROUGH the seam ───────────────────────────────────
306
+ //
307
+ // A public raw statement API that goes through the exec-context seam, so a registered SQL-level
308
+ // middleware sees it AND connection routing / an ambient transaction still apply (design §4 D3). It is
309
+ // a thin front over the seam's `execute`/`run` (sync) or `executeAsync`/`runAsync` (async) — the SAME
310
+ // central point every ORM-generated statement uses. `rawQuery` is `rawExecute` tagged as a `query`
311
+ // operation kind (so a `query` method hook fires), matching v1 `DBModel.query` → `execute`.
312
+ const exec_context_1 = require("./exec-context");
313
+ /** Does `sql` return rows (SELECT / …RETURNING / WITH…SELECT / SHOW / PRAGMA / VALUES)? */
314
+ function returnsRows(sql) {
315
+ return /^\s*(select|with|show|pragma|values|explain|table)\b/i.test(sql) || /\breturning\b/i.test(sql);
316
+ }
317
+ /**
318
+ * Raw **synchronous** `execute(sql, params)` THROUGH the seam (design §4 D3): a registered SQL-level
319
+ * middleware intercepts it, connection routing resolves the connection, and an ambient transaction (if
320
+ * the ctx is tx-scoped) applies — because it is the SAME `execute`/`run` seam the ORM uses, not a
321
+ * direct driver call. A row-returning statement runs `execute`; a non-returning one runs `run`.
322
+ * `write` forces the write intent (writer routing / tx connection) for a row-returning write.
323
+ */
324
+ function rawExecute(ctx, sql, params = [], opts = {}) {
325
+ if (returnsRows(sql)) {
326
+ const rows = (0, exec_context_1.execute)(ctx, sql, params, { write: opts.write ?? false });
327
+ return { rows, rowCount: rows.length };
328
+ }
329
+ const info = (0, exec_context_1.run)(ctx, sql, params);
330
+ return { rows: [], rowCount: info.changes };
331
+ }
332
+ /** Raw **async** `execute(sql, params)` THROUGH the async seam — the live PG / MySQL twin of {@link rawExecute}. */
333
+ async function rawExecuteAsync(ctx, sql, params = [], opts = {}) {
334
+ if (returnsRows(sql)) {
335
+ const rows = await (0, exec_context_1.executeAsync)(ctx, sql, params, { write: opts.write ?? false });
336
+ return { rows, rowCount: rows.length };
337
+ }
338
+ const info = await (0, exec_context_1.runAsync)(ctx, sql, params);
339
+ return { rows: [], rowCount: info.changes };
340
+ }
341
+ /**
342
+ * Raw **synchronous** `query(sql, params)` — {@link rawExecute} tagged as a `query` operation, so a
343
+ * `query` method hook fires (then its SQL flows through the same seam + `execute` hooks, exactly as v1
344
+ * `DBModel.query` calls `DBModel.execute`). Returns the row list.
345
+ */
346
+ function rawQuery(ctx, sql, params = []) {
347
+ return runMethod('query', undefined, async () => rawExecute(ctx, sql, params).rows, [sql, params]);
348
+ }
349
+ /** Raw **async** `query(sql, params)` — the live PG / MySQL twin of {@link rawQuery}. */
350
+ function rawQueryAsync(ctx, sql, params = []) {
351
+ return runMethod('query', undefined, async () => (await rawExecuteAsync(ctx, sql, params)).rows, [sql, params]);
352
+ }
353
+ // ── Reset / testing helpers ────────────────────────────────────────────────────
354
+ /** Clear the process-global registry (testing; a per-scope registry is dropped when its scope exits). */
355
+ function clearMiddlewares() {
356
+ globalRegistry.clear();
357
+ }
358
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/scp/middleware.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,9 @@
26
26
  * - **Lazy** (`await post.author`): a prototype getter fires the SAME op over the sibling set.
27
27
  */
28
28
  import { type Dialect } from './makesql/handler';
29
+ import { type ExecutionContext } from './exec-context';
30
+ import { type MaterializeClass, type ColumnTypeResolver } from './coltype';
31
+ import { type RelationGuard } from './limit-config';
29
32
  /** A read relation cardinality (v1 parity). `belongsTo`/`hasOne` are single; `hasMany` many. */
30
33
  export type RelationKind = 'belongsTo' | 'hasMany' | 'hasOne';
31
34
  /**
@@ -57,8 +60,26 @@ export interface RelationDecl {
57
60
  readonly order?: string;
58
61
  /** Optional per-parent row limit (`hasMany` only). */
59
62
  readonly limit?: number;
63
+ /**
64
+ * Per-relation hard-limit override (Phase E-2, epic #74; v1 `@hasMany({ hardLimit })`): the
65
+ * batch-total cap for THIS relation, winning over the global `hasManyHardLimit`. `null` DISABLES
66
+ * the check for this relation even when the global is set; `undefined` ⇒ use the global. `hasMany`
67
+ * only (a single-cardinality relation fetches at most one child per parent). A relation with an
68
+ * intrinsic per-parent {@link limit} window skips the batch-total check regardless (its fanout is
69
+ * already bounded). See {@link import('./limit-config').resolveHasManyHardLimit}.
70
+ */
71
+ readonly hardLimit?: number | null;
60
72
  /** The target SQL dialect the batch SELECT is compiled for (default `'sqlite'`). */
61
73
  readonly dialect?: Dialect;
74
+ /**
75
+ * CHAINED relations (nested `with`, e.g. users→posts→comments): the relations declared ON THIS
76
+ * relation's CHILD rows — a grandchild batch keyed by this relation's own result rows (level ≥ 3).
77
+ * Each is a normal {@link RelationDecl} whose parent is THIS relation's target table. The batch stays
78
+ * N+1-free per level (one query per depth): a per-language codegen lowers the chain as a batched map
79
+ * off the parent relation's node; the runtime resolves the flattened child keys once per level. Absent
80
+ * for a leaf (2-level) relation — additive, so existing single-level relations are byte-unchanged.
81
+ */
82
+ readonly childRelations?: readonly RelationDecl[];
62
83
  /**
63
84
  * CROSS-DB relations (V0 R1): the NAME of the connection the batch SELECT must execute against —
64
85
  * the TARGET model's DB, which may differ from the parent's (v1 `LazyRelation.ts:236` runs a
@@ -97,12 +118,46 @@ export interface RelationOp {
97
118
  */
98
119
  readonly connection?: string;
99
120
  /**
100
- * The batched child SELECT as STATIC makeSQL text. Single-key: ONE `?` binds the deduped
101
- * parent-key set (PG `= ANY(?::t[])` / MySQL·SQLite single-JSON). Composite: PG binds ONE array
102
- * param PER key column (`unnest(?::t1[], ?::t2[])`); MySQL·SQLite bind ONE JSON array-of-tuples
103
- * param. Value-length-independent either way, so `sql` is fixed.
121
+ * The batched child SELECT as STATIC makeSQL text. ONE `?` binds the deduped parent-key set on
122
+ * every dialect and arity: single-key as the scalar set (PG `= ANY(?::t[])` / MySQL·SQLite
123
+ * single-JSON), composite as the ONE array-of-tuples JSON param every dialect expands server-side
124
+ * (PG `json_array_elements`, MySQL `JSON_TABLE`, SQLite `json_each`). Value-length-independent, so
125
+ * `sql` is fixed — and the key set is exactly the ONE array the `pluck` leaf yields.
104
126
  */
105
127
  readonly sql: string;
128
+ /**
129
+ * The child (target) table + projected columns (issue #59) — carried for diagnostics + as the
130
+ * basis of the baked `materializers` map. Additive/optional.
131
+ */
132
+ readonly targetTable?: string;
133
+ readonly select?: readonly string[];
134
+ /**
135
+ * CHAINED relations (nested `with`): the COMPILED grandchild relation ops keyed off THIS relation's
136
+ * child rows (level ≥ 3). Present iff the decl carried {@link RelationDecl.childRelations}. A codegen
137
+ * lowering injects each as a batched map off this relation's node (N+1-free per level); the mode-2
138
+ * flat-batch runtime does not recurse into it (single-level). Additive — absent for leaf relations.
139
+ */
140
+ readonly childRelations?: readonly RelationOp[];
141
+ /**
142
+ * The child columns' STATIC materialize classes (issue #59): `column → MaterializeClass`, baked
143
+ * at compile from the model's DDL resolver (only non-passthrough entries). The relation batch runs
144
+ * these over its child rows so a BIGINT/DATE/BOOLEAN child de-boxes identically to the primary
145
+ * read — with ZERO per-read DB introspection. Absent ⇒ the child rows stay raw (no schema).
146
+ */
147
+ readonly materializers?: Readonly<Record<string, MaterializeClass>>;
148
+ /**
149
+ * Hard-limit runaway cap (Phase E-2, epic #74; v1 `_selectForRelation` `hasManyHardLimit`): the
150
+ * effective per-batch row cap RESOLVED at compile (per-relation override → global). When the batch
151
+ * fetches MORE than this TOTAL, {@link import('./errors').LimitExceededError} is raised
152
+ * (`context: 'relation'`, EXACT count) — by {@link runRelationOp} on the typed-object / lazy
153
+ * surface, and by the `executeSQL` leaf on the CODEGEN surface, where the emitter bakes this cap
154
+ * into the child fetch's `guard` port (the raw child rows are only visible there, before `group`).
155
+ * BOTH read it through {@link relationGuard} + `assertRelationHardLimit`, so neither the cap nor the
156
+ * error identity can drift between surfaces or languages. Absent ⇒ no check (disabled, or a relation
157
+ * with an intrinsic per-parent `limit` window whose fanout is already bounded).
158
+ * See {@link import('./limit-config').resolveHasManyHardLimit}.
159
+ */
160
+ readonly hardLimit?: number;
106
161
  }
107
162
  /** The reserved input head the relation batch query binds its deduped key array to. */
108
163
  export declare const RELATION_KEYS_HEAD = "__keys";
@@ -114,15 +169,30 @@ export declare const RELATION_KEYS_HEAD = "__keys";
114
169
  * LATERAL (PG) / ROW_NUMBER (MySQL·SQLite) form. The SQL text is FIXED (the array binds as one
115
170
  * param regardless of length), so it needs no per-input recompile.
116
171
  */
117
- export declare function compileRelationOp(decl: RelationDecl): RelationOp;
172
+ export declare function compileRelationOp(decl: RelationDecl, resolveColumnType?: ColumnTypeResolver): RelationOp;
118
173
  /** A minimal read-only driver surface (`prepare(sql).all(...params)`), the SQLite `Database`. */
119
174
  export interface RelationDriver {
120
175
  prepare(sql: string): {
121
176
  all(...params: unknown[]): unknown[];
177
+ safeIntegers?(v: boolean): unknown;
122
178
  };
123
179
  }
180
+ /** A relation batch runs against either a raw {@link RelationDriver} or a full {@link ExecutionContext}. */
181
+ export type RelationTarget = RelationDriver | ExecutionContext;
124
182
  /** The child rows grouped for a batch: parent-key value (stringified) → child rows. */
125
183
  export type RelationBatch = Map<string, Record<string, unknown>[]>;
184
+ /** The ordered PARENT key columns of an op (single-key → 1-element list; composite → the tuple). */
185
+ export declare function parentKeyCols(op: RelationOp): readonly string[];
186
+ /** The ordered CHILD key columns of an op (single-key → 1-element list; composite → the tuple). */
187
+ export declare function targetKeyCols(op: RelationOp): readonly string[];
188
+ /**
189
+ * The op's RELATION RUNAWAY GUARD, or `null` when it baked none (disabled, or an intrinsic per-parent
190
+ * `limit` window whose fanout is already bounded). The ONE projection of a compiled op onto the
191
+ * {@link RelationGuard} record — read by BOTH consumers of the cap: {@link runRelationOp} (the
192
+ * typed-object / lazy batch) and the emitter, which bakes this record into the generated child fetch's
193
+ * `guard` port so the leaf enforces the SAME resolved cap. Nothing downstream re-derives it.
194
+ */
195
+ export declare function relationGuard(op: RelationOp): RelationGuard | null;
126
196
  /**
127
197
  * Run ONE {@link RelationOp} for a set of parent rows: dedup the parent-key tuples, render the
128
198
  * STATIC batch SELECT once (dialect placeholder form) resolving the deferred PG array cast(s) from
@@ -133,16 +203,17 @@ export type RelationBatch = Map<string, Record<string, unknown>[]>;
133
203
  * Returns `{ sql, keys, batch }` (`keys` = the deduped parent-key tuples). An empty key set issues
134
204
  * NO query (the correct empty-set behavior — the membership over no keys selects nothing).
135
205
  */
136
- export declare function runRelationOp(op: RelationOp, parents: readonly Record<string, unknown>[], db: RelationDriver): {
206
+ export declare function runRelationOp(op: RelationOp, parents: readonly Record<string, unknown>[], db: RelationTarget): {
137
207
  sql: string;
138
208
  keys: unknown[][];
139
209
  batch: RelationBatch;
140
210
  };
141
211
  /**
142
212
  * Distribute a resolved {@link RelationBatch} onto ONE parent per the relation cardinality:
143
- * `hasMany` → the child list (`[]` when none); `belongsTo`/`hasOne` → the single child (or
144
- * `null`). Keyed by the parent's key-tuple identity. `null`/`[]` is the declared cardinality's
145
- * empty representation, not an ad-hoc default.
213
+ * `hasMany` → the child list (`[]` when none); `belongsTo`/`hasOne` → the single child (or `null`).
214
+ * A thin consumer over the shared grouping SSoT ({@link attachToParent}) — the SAME core the eager
215
+ * `group` leaf uses (no duplicated grouping). `null`/`[]` is the declared cardinality's empty
216
+ * representation, not an ad-hoc default.
146
217
  */
147
218
  export declare function distributeToParent(op: RelationOp, parent: Record<string, unknown>, batch: RelationBatch): Record<string, unknown>[] | Record<string, unknown> | null;
148
219
  //# sourceMappingURL=relation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"relation.d.ts","sourceRoot":"","sources":["../../src/scp/relation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relation.d.ts","sourceRoot":"","sources":["../../src/scp/relation.ts"],"names":[],"mappings":"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"}