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,139 @@
1
+ # Phase A 設計: ExecutionContext + 中央 execute/query seam + 接続コンテキスト + 並行 tx 修正
2
+
3
+ **対象**: litedbmodel v2 → beta(v1 parity)Epic #74 の基盤フェーズ。tx(#69)・middleware(#70)・reader/writer/複数DB(#72)・config(#72) の全てがこの上に載る。**5 native 言語(TS/rust/go/py/php)共通契約**。設計参照: v1 TS(`AsyncLocalStorage`)・v1 rust(`litedbmodel.rs` `PoolTransaction`)・graphddb。
4
+
5
+ ---
6
+
7
+ ## 1. 現状(seam の素地と欠落)
8
+
9
+ 全 5 runtime が共通形:
10
+ - `executeBundle(bundle, input, driver/db)` … read(TS `executeBundle`→`executeReadGraph`、go `ExecuteBundle`、py `execute_bundle`、php `Runtime::executeBundle`、rust `execute_bundle`)
11
+ - `executeTransactionBundle(bundle, input, driver/db)` … write/tx
12
+ - SQL 実行は `driver.prepare(sql).all()/run()`(go は `db.Query/Exec`、php は `PDO`)
13
+
14
+ **欠落**:
15
+ - 全 SQL が通る**中央 seam が無い**(各所で driver を直接叩く)→ middleware 挿入点が無い。
16
+ - **接続コンテキストが無い**(driver を生で渡すだけ)→ tx スコープ・reader/writer・複数DB ルーティングを表現できない。
17
+ - **tx が driver グローバル単一スロット**(rust `writer: Mutex<Option>`、py `driver.py:369` 等)→ **並行 tx 汚染バグ**。
18
+
19
+ ---
20
+
21
+ ## 2. 中核設計: `ExecutionContext` を driver の代わりに通す
22
+
23
+ `executeBundle`/`executeTransactionBundle`/relation walker が受け取るのを **生 driver → `ExecutionContext`(以下 ctx)** に変える。ctx が保持するもの:
24
+
25
+ 1. **接続プロバイダ**(`connectionFor(intent)`): この文にどの接続を使うかを解決(tx所有 / reader / writer-sticky / named-DB)。
26
+ 2. **middleware chain**: 全 SQL をラップするフック列。
27
+ 3. **設定**(timeout/limits 等、Phase C/E で拡張)。
28
+
29
+ **中央 seam(5 言語共通の 2 関数)**:
30
+ ```
31
+ execute(ctx, sql, params) -> Rows // read(SELECT)
32
+ run(ctx, sql, params) -> RunInfo // write(INSERT/UPDATE/DELETE, BEGIN/COMMIT)
33
+ ```
34
+ 両関数の中身(共通契約):
35
+ ```
36
+ seam(ctx, sql, params, intent):
37
+ return ctx.middleware.wrap(sql, params, (sql, params) => # ① middleware chain
38
+ conn = ctx.connectionFor(intent) # ② 接続解決(tx/reader/writer/db)
39
+ return conn.exec(sql, params) # ③ 実行(唯一の driver 接点)
40
+ )
41
+ ```
42
+ → **全 SQL がこの 1 点を通る**。middleware も接続解決もここに集約。既存の `driver.prepare().all()` 直呼びを全て `execute/run(ctx, …)` に置換。
43
+
44
+ ---
45
+
46
+ ## 3. 接続コンテキストモデル(per-execution・言語別)
47
+
48
+ **原則: 接続は「実行スコープ」が所有する。driver グローバルスロットは廃止。並行実行(HTTP req/tx)は各自別接続。**
49
+
50
+ `connectionFor(intent)` の解決優先順位(v1 準拠、`DBModel.ts:313` の順):
51
+ 1. **アクティブ tx の接続**(tx スコープ内なら必ずその接続)
52
+ 2. **withWriter スコープ** / **writer-sticky**(直近 tx 後 `writerStickyDuration` 内の read は writer へ)
53
+ 3. **read=reader pool / write=writer pool**(reader/writer 分離時)
54
+ 4. **named-DB ルーティング**(model→connection、複数DB時)→ 対象 DB の pool
55
+
56
+ 言語別の「実行スコープ所有」実装:
57
+ | 言語 | ctx 伝播 | tx 接続所有 |
58
+ |---|---|---|
59
+ | **TS** | `AsyncLocalStorage<Ctx>`(v1 と同じ、非同期境界を跨ぐ) | tx が接続を ALS に束ねる(v1 `txContext.run`) |
60
+ | **rust** | ctx を**引数で明示 thread**(or `tokio::task_local`)。current-thread runtime(v1rs 準拠、block_on 軽量化) | `PoolTransaction`(接続所有ハンドル、v1 rust `handler.rs`)を ctx が保持 |
61
+ | **go** | `context.Context` に ctx を載せる | `*sql.Tx`(接続所有)を ctx が保持 |
62
+ | **py** | `contextvars.ContextVar<Ctx>` | tx 接続を contextvar に束ねる |
63
+ | **php** | ctx を**明示引数**(PHP は 1 req 1 プロセスで並行 tx 無し、但し接続所有は同契約) | tx が PDO 接続を ctx 内で所有 |
64
+
65
+ **tx の per-execution 所有(並行 tx バグ根治)**:
66
+ ```
67
+ withTransaction(ctx, opts, fn) -> R:
68
+ conn = pool(writer, targetDB).acquire() # tx 専用に 1 接続取得
69
+ txctx = ctx.withConnection(conn, tx=true) # スコープに束ねる(ALS/task-local/owned)
70
+ conn.exec(BEGIN [ISOLATION opts.isolation])
71
+ try: r = fn(txctx) # fn 内の全 SQL は connectionFor→この conn
72
+ conn.exec(COMMIT); return r
73
+ except: conn.exec(ROLLBACK); (retry? #69-B3); raise
74
+ finally: pool.release(conn) [or destroy if bad #69-B4]
75
+ ```
76
+ → **並行 tx は各々別 conn を所有**。driver グローバル `writer` スロット(rust:431 等)を**全言語で撤去**。
77
+
78
+ ---
79
+
80
+ ## 4. Middleware hook 機構(5言語共通・TS定義主・native登録可)
81
+
82
+ **ctx が middleware chain を保持**、中央 seam(§2 ①)が全 SQL をラップ。2 レベル:
83
+ - **SQL-level `execute` フック**(全 SQL 横取り)= 中央 seam に組込。**5言語全部**に hook 点あり。
84
+ - **method-level フック**(find?/create?/update?…)= ORM メソッド入口でラップ(decorator model は TS、native は該当メソッド境界)。
85
+
86
+ **登録**:
87
+ - **TS が主**(v1 `DBModel.use(MiddlewareClass)` 相当)。middleware chain を構築。
88
+ - **native 側でも登録可**: rust/go/py/php 各 runtime に `register_middleware(mw)` API を設け、その言語の ctx chain に append。
89
+ - chain の**契約(`execute(next, sql, params)`)と適用順は 5 言語共通**。
90
+
91
+ middleware は ctx(実行スコープ)に紐づく → per-request/context 分離(v1 ALS と同じ)。
92
+
93
+ ---
94
+
95
+ ## 5. seam 契約(共通シェイプ・言語別実装の型)
96
+
97
+ 疑似型(各言語に写す):
98
+ ```
99
+ interface ExecutionContext {
100
+ connectionFor(intent: { write: bool, db?: string }): Connection
101
+ readonly middleware: MiddlewareChain
102
+ withConnection(conn, tx: bool): ExecutionContext // tx スコープ派生
103
+ // config(timeout/limit)は Phase C/E で追加
104
+ }
105
+ interface Connection { exec(sql, params): Rows | RunInfo } // 唯一の driver 接点
106
+ interface MiddlewareChain { wrap(sql, params, next): result }
107
+ execute(ctx, sql, params): Rows
108
+ run(ctx, sql, params): RunInfo
109
+ withTransaction(ctx, opts, fn): R
110
+ ```
111
+ - 既存 `executeBundle(bundle, input, driver)` は `executeBundle(bundle, input, ctx)` に。呼び出し側は `ctx = Context.forDriver(driver)`(単一DB・middleware無し時は薄いラッパ=後方互換)。
112
+ - relation walker / tx walker は `driver.prepare().all()` を `execute/run(ctx, …)` に置換。
113
+
114
+ ---
115
+
116
+ ## 6. 移行と後方互換
117
+
118
+ - **既存の単純パス**(bench/conformance が driver 直渡し)は `Context.forDriver(driver)`(reader=writer=同 pool・middleware 空・単一DB)で**挙動不変**。conformance/livedb は byte 不変で通す。
119
+ - Phase A は「seam + ctx + tx所有 + 並行tx修正」まで。reader/writer(§3-2/3)・複数DB(§3-4)・middleware 登録 API・config は **B/C/D で ctx を拡張**(本設計の ctx がその受け皿)。
120
+ - **並行 tx 隔離テスト**(#69 AC)を Phase A の完了条件に含める(現行 fail→修正で green、全言語・実 DB)。
121
+
122
+ ---
123
+
124
+ ## 7. Phase A の完了条件(AC)
125
+
126
+ - [ ] 中央 `execute/run(ctx, …)` seam を 5 言語に実装、全 SQL(read/write/tx/relation)がそこを通る(直 driver 呼び出しゼロを grep で担保)。
127
+ - [ ] `ExecutionContext` + per-execution 接続所有(tx が接続をスコープ所有)。driver グローバル tx スロット全言語撤去。
128
+ - [ ] **並行 tx 隔離テスト green**(同一プロセス・共有 runtime で N tx 同時、混入なし・原子性保持、実 PG/MySQL、全言語)。現行コードで fail することも実証。
129
+ - [ ] middleware chain 挿入点を seam に用意(空 chain で挙動不変。登録 API 実体は #70/Phase D)。
130
+ - [ ] conformance/livedb/unit/bench 全 green・byte 不変(後方互換ラッパ経由)、全ゲート native ARM。
131
+ - [ ] 独立監査(並行 tx の隔離を mutation で実証)。
132
+
133
+ ---
134
+
135
+ ## 8. 要判断(sign-off 前に確認したい)
136
+
137
+ 1. **rust の ctx 伝播**: 明示引数 thread か `tokio::task_local` か(前者は型安全・後者は v1 TS の ALS に近い)。→ 提案: **明示引数**(rust らしく静的・所有明確)。
138
+ 2. **current-thread runtime 化**(rust、block_on 軽量化・v1rs 準拠)を Phase A に含めるか(perf にも効く)。→ 提案: 含める。
139
+ 3. **seam の粒度**: statement 単位(各 SQL)で middleware/接続解決。read-graph の serial 連鎖は同一 tx/接続スコープを共有(§3)。並列 read fan-out は別接続(既存 bc#23 維持)。→ 確認。
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "litedbmodel",
3
- "version": "2.0.2",
3
+ "version": "2.2.0",
4
4
  "description": "A lightweight TypeScript ORM for PostgreSQL, MySQL, and SQLite with Active Record pattern",
5
- "main": "dist/index.js",
5
+ "main": "dist/index.cjs",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
8
8
  ".": {
9
9
  "types": "./dist/index.d.ts",
10
- "default": "./dist/index.js"
10
+ "default": "./dist/index.cjs"
11
11
  },
12
12
  "./drivers": {
13
13
  "types": "./dist/drivers/index.d.ts",
@@ -35,6 +35,8 @@
35
35
  "test": "vitest run",
36
36
  "test:unit": "vitest run test/unit",
37
37
  "test:integration": "TEST_DB_HOST=localhost vitest run test/integration",
38
+ "parity:capture": "TEST_DB_HOST=localhost TEST_DB_PORT=5433 vitest run test/parity/v1-sql-golden.test.ts",
39
+ "parity:scp": "vitest run test/parity/v2-scp-parity.test.ts",
38
40
  "test:watch": "vitest",
39
41
  "test:coverage": "vitest run --coverage",
40
42
  "lint": "eslint src",
@@ -49,17 +51,19 @@
49
51
  "sync:versions": "node scripts/sync-versions.mjs",
50
52
  "sync:versions:check": "node scripts/sync-versions.mjs --check",
51
53
  "deps:check": "node scripts/check-no-local-deps.mjs",
54
+ "gates:check": "node scripts/check-reachable-test-gates.mjs",
55
+ "pkg:check": "node scripts/check-package-entrypoints.mjs",
52
56
  "vendor:bc-php": "node scripts/vendor-behavior-contracts-php.mjs",
53
57
  "vendor:bc-php:check": "node scripts/vendor-behavior-contracts-php.mjs --check",
54
58
  "conformance:gen": "vitest run --config conformance/vitest.config.ts",
55
59
  "conformance:gen:livedb": "vitest run --config conformance/vitest.livedb.config.ts",
56
- "conformance:vectors": "npm run build:scp && tsx conformance/vectors-runner.ts",
57
- "conformance:run": "npm run build:scp && tsx conformance/vectors-run.ts",
58
- "conformance:codegen": "npm run build:scp && tsx conformance/codegen/codegen-runner.ts",
60
+ "conformance:check:livedb": "LIVEDB_GEN_MODE=check vitest run --config conformance/vitest.livedb.config.ts",
59
61
  "conformance:livedb": "tsx conformance/livedb-run.ts",
60
62
  "docker:livedb:up": "docker compose -f docker-compose.test.yml -f docker-compose.livedb.yml up -d postgres mysql",
61
63
  "docker:livedb:down": "docker compose -f docker-compose.test.yml -f docker-compose.livedb.yml down -v",
62
- "conformance:livedb:docker": "npm run docker:livedb:up && sleep 5 && npm run conformance:gen:livedb && npm run conformance:livedb; e=$?; npm run docker:livedb:down; exit $e"
64
+ "conformance:livedb:docker": "npm run docker:livedb:up && sleep 5 && npm run conformance:gen:livedb && npm run conformance:livedb; e=$?; npm run docker:livedb:down; exit $e",
65
+ "native:gen": "bash benchmark/crosslang/gen-native.sh generate",
66
+ "bench:codegen:drift": "bash benchmark/crosslang/gen-native.sh check"
63
67
  },
64
68
  "keywords": [
65
69
  "orm",
@@ -80,7 +84,7 @@
80
84
  "url": "git+https://github.com/foo-ogawa/litedbmodel.git"
81
85
  },
82
86
  "dependencies": {
83
- "behavior-contracts": "^0.5.0",
87
+ "behavior-contracts": "^0.11.17",
84
88
  "reflect-metadata": "^0.2.2"
85
89
  },
86
90
  "devDependencies": {
@@ -123,6 +127,9 @@
123
127
  "node": ">=18.0.0"
124
128
  },
125
129
  "overrides": {
126
- "js-yaml": "^4.2.0"
130
+ "js-yaml": "4.3.0",
131
+ "linkify-it": "5.0.2",
132
+ "postcss": "8.5.24",
133
+ "brace-expansion": "5.0.8"
127
134
  }
128
135
  }
@@ -1,134 +0,0 @@
1
- /**
2
- * litedbmodel v2 SCP — SQL WHERE authoring helpers (WS3, #23).
3
- *
4
- * These are thin, closed-set wrappers over behavior-contracts' expression builders that
5
- * make a WHERE fragment tree authorable in the `SemanticBehavior` / eager surface while
6
- * emitting ONLY bc's closed-set Expression IR (no invented opcode — the hard rule). The
7
- * {@link import('./bridge').compileNode} Backend-Compile bridge decodes exactly these
8
- * closed-set encodings back into WS1's fragment `Condition[]`:
9
- *
10
- * - {@link whereEq} → `{eq:[<colRef>, <value>]}` → `col = ?`
11
- * - {@link whereNe}/{@link whereLt}/… → `{ne|lt|le|gt|ge:[<colRef>, v]}` → `col <op> ?`
12
- * - {@link whereIsNull} → `{eq:[<colRef>, null]}` → `col IS NULL`
13
- * - {@link whereIn} → `{eq:[{ref:[IN_SENTINEL, col]}, <arr>]}` → `col IN (?, …)`
14
- *
15
- * A SKIP-optional condition is authored with bc's `when(cond, () => <whereX(...)>)`, which
16
- * bc lowers to `{cond:[cond, <member>, null]}` — the bridge reads that as a `skipWhen`
17
- * guard (dynamic-expansion spec §2). Nested AND/OR groups are authored with bc's `and` /
18
- * `or` over these members.
19
- *
20
- * The column argument is a RECORDED reference (`$.author_id`, or a wire field `$p.foo`):
21
- * its ref-path last segment is the physical column name (spec §7). The value argument is a
22
- * recorded reference, a literal, or any closed-set builder expression (`coalesce`, `add`, …).
23
- */
24
- import { type Recorded } from 'behavior-contracts';
25
- /** A recorded `$`-reference (column or value) or a literal value usable in a builder. */
26
- type Operand = Recorded | unknown;
27
- /**
28
- * The sentinel ref-path heads that mark the ADDITIVE where-primitives (V0 R2/R3) so the live
29
- * compile (`static-bundle.lowerWhereMember`) can decode them into the EXACT v1 `ConditionObject`
30
- * and drive the ORIGINAL `DBConditions.compile()` for byte-true text — never a hand-roll. Each is
31
- * encoded with the closed-set `eq(<sentinel ref>, <value>)` shape (the SAME trick {@link whereIn}
32
- * uses for IN-lists), so no opcode outside bc's closed set is invented. Structural metadata (the
33
- * column name, the SQL cast type, the LIKE keyword, the tuple column list, the subquery text)
34
- * rides as extra STRING segments in the sentinel ref path; the runtime value operands ride as the
35
- * `eq` RHS and are deferred as value-specs 1:1 with the placeholders in the v1-produced text.
36
- */
37
- export declare const BETWEEN_SENTINEL = "@between";
38
- export declare const LIKE_SENTINEL = "@like";
39
- export declare const CAST_SENTINEL = "@cast";
40
- export declare const DYNAMIC_SENTINEL = "@dynamic";
41
- export declare const IMMEDIATE_SENTINEL = "@immediate";
42
- export declare const TUPLE_SENTINEL = "@tuple";
43
- export declare const SUBQUERY_SENTINEL = "@subquery";
44
- export declare const EXISTS_SENTINEL = "@exists";
45
- /** `col = value` — equality fragment (`{eq:[colRef, value]}`). */
46
- export declare function whereEq(col: Recorded, value: Operand): Recorded;
47
- /** `col <> value` — inequality fragment. */
48
- export declare function whereNe(col: Recorded, value: Operand): Recorded;
49
- /** `col < value`. */
50
- export declare function whereLt(col: Recorded, value: Operand): Recorded;
51
- /** `col <= value`. */
52
- export declare function whereLe(col: Recorded, value: Operand): Recorded;
53
- /** `col > value`. */
54
- export declare function whereGt(col: Recorded, value: Operand): Recorded;
55
- /** `col >= value`. */
56
- export declare function whereGe(col: Recorded, value: Operand): Recorded;
57
- /** `col IS NULL` — encoded as `eq(col, null)` (v1 parity; bridge maps null-RHS → IS NULL). */
58
- export declare function whereIsNull(col: Recorded): Recorded;
59
- /**
60
- * `col IN (?, …)` — encoded as `eq(<IN-sentinel col>, value)`. `col` MUST be the IN-sentinel
61
- * reference built by {@link inColumn} (its ref-path head is {@link IN_SENTINEL}); `value` is
62
- * the array-valued reference/expression whose `?` expands to `(?, ?, …)` at render time
63
- * (dynamic-expansion spec §5). Using the sentinel keeps IN expressible with only the
64
- * closed-set `eq` + `ref` operators.
65
- */
66
- export declare function whereIn(col: Recorded, value: Operand): Recorded;
67
- /**
68
- * Build the IN-list column reference for {@link whereIn}: `$[IN_SENTINEL][name]` — a
69
- * recorded ref whose path is `[IN_SENTINEL, name]`. The bridge strips the sentinel head and
70
- * treats `name` as the physical column (a membership fragment, not an equality).
71
- */
72
- export declare function inColumn($: Recorded, name: string): Recorded;
73
- /**
74
- * `col BETWEEN ? AND ?` (V0 R3). Encoded `eq($[@between][col], [lo, hi])`; the live compile builds
75
- * the v1 custom-op `ConditionObject` `{'<col> BETWEEN ? AND ?': [lo, hi]}` and defers both bounds.
76
- * `lo`/`hi` are recorded refs or literals.
77
- */
78
- export declare function whereBetween($: Recorded, col: string, lo: Operand, hi: Operand): Recorded;
79
- /**
80
- * `col LIKE ?` (V0 R3). Encoded `eq($[@like][col], pattern)` → v1 `{'<col> LIKE ?': pattern}`.
81
- * The pattern is a recorded ref or literal.
82
- */
83
- export declare function whereLike($: Recorded, col: string, pattern: Operand): Recorded;
84
- /**
85
- * `col ILIKE ?` (V0 R3, PG case-insensitive; on MySQL/SQLite v1 emits the raw `ILIKE` keyword —
86
- * this reproduces v1 verbatim, not a portability rewrite). Encoded `eq($[@like][col][ILIKE], p)`.
87
- */
88
- export declare function whereILike($: Recorded, col: string, pattern: Operand): Recorded;
89
- /**
90
- * `col <op> ?::type` (V0 R3, dialect-gated cast — `dbCast`). Encoded
91
- * `eq($[@cast][col][type][op], value)`; the live compile drives v1 `dbCast(value, type, op)` so the
92
- * PG `::type` cast (and the MySQL/SQLite no-cast) is byte-true. `op` defaults to `=`.
93
- */
94
- export declare function whereCast($: Recorded, col: string, sqlType: string, value: Operand, op?: string): Recorded;
95
- /**
96
- * `col = fn(?)` (V0 R3, `dbDynamic`) — a function-call template with `?` placeholders bound to the
97
- * value list. Encoded `eq($[@dynamic][col][template], values)`; drives v1 `dbDynamic(template, vals)`.
98
- * `template` is the raw function SQL (e.g. `to_tsvector('en', ?)`).
99
- */
100
- export declare function whereDynamic($: Recorded, col: string, template: string, values: Operand): Recorded;
101
- /**
102
- * `col = <sql>` (V0 R3, `dbImmediate` — an inline SQL expression, NO bound param, e.g. `NOW()`).
103
- * Encoded `eq($[@immediate][col][sql], null)`; drives v1 `dbImmediate(sql)`. No value-spec.
104
- */
105
- export declare function whereImmediate($: Recorded, col: string, sql: string): Recorded;
106
- /**
107
- * `(a, b, …) IN ((?, ?), …)` (V0 R3, `dbTupleIn` composite membership). Encoded
108
- * `eq($[@tuple][a][b]…, tuples)` where `tuples` is an array-of-tuples value; drives v1
109
- * `dbTupleIn(columns, tuples)`. `columns` is the tuple column list.
110
- */
111
- export declare function whereTupleIn($: Recorded, columns: readonly string[], tuples: Operand): Recorded;
112
- /**
113
- * `lhs IN (SELECT …)` / `lhs NOT IN (SELECT …)` (V0 R2). The subquery is authored as a NESTED
114
- * makeSQL Fragment carried in the param slot (spec §2 補足): `sub` is a `{ sql, params? }` where
115
- * `sql` is the inner SELECT text (already dialect-tuned, v1-sourced) and `params` its bound
116
- * value-specs. Encoded `eq($[@subquery][lhsCol][kw], sub)`; the live compile splices the inner
117
- * `sql` into the v1 `DBSubquery`-shaped predicate `<lhs> <kw> (<sub.sql>)` and appends `sub.params`.
118
- */
119
- export declare function whereInSubquery($: Recorded, lhs: string, sub: {
120
- sql: string;
121
- params?: readonly Operand[];
122
- }, not?: boolean): Recorded;
123
- /**
124
- * `EXISTS (SELECT 1 …)` / `NOT EXISTS (…)` (V0 R2). Like {@link whereInSubquery}, the correlated
125
- * subquery rides as a nested makeSQL Fragment in the param slot: `sub.sql` is the inner
126
- * `SELECT 1 FROM … WHERE …` (correlation refs already rendered as literal column paths, v1-sourced).
127
- * Encoded `eq($[@exists][kw], sub)`; the live compile emits `<kw> (<sub.sql>)` + `sub.params`.
128
- */
129
- export declare function whereExists($: Recorded, sub: {
130
- sql: string;
131
- params?: readonly Operand[];
132
- }, not?: boolean): Recorded;
133
- export {};
134
- //# sourceMappingURL=authoring-sql.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"authoring-sql.d.ts","sourceRoot":"","sources":["../../src/scp/authoring-sql.ts"],"names":[],"mappings":"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"}
@@ -1,191 +0,0 @@
1
- "use strict";
2
- /**
3
- * litedbmodel v2 SCP — SQL WHERE authoring helpers (WS3, #23).
4
- *
5
- * These are thin, closed-set wrappers over behavior-contracts' expression builders that
6
- * make a WHERE fragment tree authorable in the `SemanticBehavior` / eager surface while
7
- * emitting ONLY bc's closed-set Expression IR (no invented opcode — the hard rule). The
8
- * {@link import('./bridge').compileNode} Backend-Compile bridge decodes exactly these
9
- * closed-set encodings back into WS1's fragment `Condition[]`:
10
- *
11
- * - {@link whereEq} → `{eq:[<colRef>, <value>]}` → `col = ?`
12
- * - {@link whereNe}/{@link whereLt}/… → `{ne|lt|le|gt|ge:[<colRef>, v]}` → `col <op> ?`
13
- * - {@link whereIsNull} → `{eq:[<colRef>, null]}` → `col IS NULL`
14
- * - {@link whereIn} → `{eq:[{ref:[IN_SENTINEL, col]}, <arr>]}` → `col IN (?, …)`
15
- *
16
- * A SKIP-optional condition is authored with bc's `when(cond, () => <whereX(...)>)`, which
17
- * bc lowers to `{cond:[cond, <member>, null]}` — the bridge reads that as a `skipWhen`
18
- * guard (dynamic-expansion spec §2). Nested AND/OR groups are authored with bc's `and` /
19
- * `or` over these members.
20
- *
21
- * The column argument is a RECORDED reference (`$.author_id`, or a wire field `$p.foo`):
22
- * its ref-path last segment is the physical column name (spec §7). The value argument is a
23
- * recorded reference, a literal, or any closed-set builder expression (`coalesce`, `add`, …).
24
- */
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.EXISTS_SENTINEL = exports.SUBQUERY_SENTINEL = exports.TUPLE_SENTINEL = exports.IMMEDIATE_SENTINEL = exports.DYNAMIC_SENTINEL = exports.CAST_SENTINEL = exports.LIKE_SENTINEL = exports.BETWEEN_SENTINEL = void 0;
27
- exports.whereEq = whereEq;
28
- exports.whereNe = whereNe;
29
- exports.whereLt = whereLt;
30
- exports.whereLe = whereLe;
31
- exports.whereGt = whereGt;
32
- exports.whereGe = whereGe;
33
- exports.whereIsNull = whereIsNull;
34
- exports.whereIn = whereIn;
35
- exports.inColumn = inColumn;
36
- exports.whereBetween = whereBetween;
37
- exports.whereLike = whereLike;
38
- exports.whereILike = whereILike;
39
- exports.whereCast = whereCast;
40
- exports.whereDynamic = whereDynamic;
41
- exports.whereImmediate = whereImmediate;
42
- exports.whereTupleIn = whereTupleIn;
43
- exports.whereInSubquery = whereInSubquery;
44
- exports.whereExists = whereExists;
45
- const behavior_contracts_1 = require("behavior-contracts");
46
- const makesql_1 = require("./makesql");
47
- /**
48
- * The sentinel ref-path heads that mark the ADDITIVE where-primitives (V0 R2/R3) so the live
49
- * compile (`static-bundle.lowerWhereMember`) can decode them into the EXACT v1 `ConditionObject`
50
- * and drive the ORIGINAL `DBConditions.compile()` for byte-true text — never a hand-roll. Each is
51
- * encoded with the closed-set `eq(<sentinel ref>, <value>)` shape (the SAME trick {@link whereIn}
52
- * uses for IN-lists), so no opcode outside bc's closed set is invented. Structural metadata (the
53
- * column name, the SQL cast type, the LIKE keyword, the tuple column list, the subquery text)
54
- * rides as extra STRING segments in the sentinel ref path; the runtime value operands ride as the
55
- * `eq` RHS and are deferred as value-specs 1:1 with the placeholders in the v1-produced text.
56
- */
57
- exports.BETWEEN_SENTINEL = '@between';
58
- exports.LIKE_SENTINEL = '@like';
59
- exports.CAST_SENTINEL = '@cast';
60
- exports.DYNAMIC_SENTINEL = '@dynamic';
61
- exports.IMMEDIATE_SENTINEL = '@immediate';
62
- exports.TUPLE_SENTINEL = '@tuple';
63
- exports.SUBQUERY_SENTINEL = '@subquery';
64
- exports.EXISTS_SENTINEL = '@exists';
65
- /** Build a sentinel column ref: `$[HEAD][seg0][seg1]…` → a recorded ref with that path. */
66
- function sentinelRef($, head, segs) {
67
- let node = $[head];
68
- for (const s of segs)
69
- node = node[s];
70
- return node;
71
- }
72
- /** `col = value` — equality fragment (`{eq:[colRef, value]}`). */
73
- function whereEq(col, value) {
74
- return (0, behavior_contracts_1.eq)(col, value);
75
- }
76
- /** `col <> value` — inequality fragment. */
77
- function whereNe(col, value) {
78
- return (0, behavior_contracts_1.ne)(col, value);
79
- }
80
- /** `col < value`. */
81
- function whereLt(col, value) {
82
- return (0, behavior_contracts_1.lt)(col, value);
83
- }
84
- /** `col <= value`. */
85
- function whereLe(col, value) {
86
- return (0, behavior_contracts_1.le)(col, value);
87
- }
88
- /** `col > value`. */
89
- function whereGt(col, value) {
90
- return (0, behavior_contracts_1.gt)(col, value);
91
- }
92
- /** `col >= value`. */
93
- function whereGe(col, value) {
94
- return (0, behavior_contracts_1.ge)(col, value);
95
- }
96
- /** `col IS NULL` — encoded as `eq(col, null)` (v1 parity; bridge maps null-RHS → IS NULL). */
97
- function whereIsNull(col) {
98
- return (0, behavior_contracts_1.eq)(col, null);
99
- }
100
- /**
101
- * `col IN (?, …)` — encoded as `eq(<IN-sentinel col>, value)`. `col` MUST be the IN-sentinel
102
- * reference built by {@link inColumn} (its ref-path head is {@link IN_SENTINEL}); `value` is
103
- * the array-valued reference/expression whose `?` expands to `(?, ?, …)` at render time
104
- * (dynamic-expansion spec §5). Using the sentinel keeps IN expressible with only the
105
- * closed-set `eq` + `ref` operators.
106
- */
107
- function whereIn(col, value) {
108
- return (0, behavior_contracts_1.eq)(col, value);
109
- }
110
- /**
111
- * Build the IN-list column reference for {@link whereIn}: `$[IN_SENTINEL][name]` — a
112
- * recorded ref whose path is `[IN_SENTINEL, name]`. The bridge strips the sentinel head and
113
- * treats `name` as the physical column (a membership fragment, not an equality).
114
- */
115
- function inColumn($, name) {
116
- return $[makesql_1.IN_SENTINEL][name];
117
- }
118
- // ── Additive where-primitives (V0 R2/R3) — all v1-sourced at compile, live-reachable ──────────
119
- /**
120
- * `col BETWEEN ? AND ?` (V0 R3). Encoded `eq($[@between][col], [lo, hi])`; the live compile builds
121
- * the v1 custom-op `ConditionObject` `{'<col> BETWEEN ? AND ?': [lo, hi]}` and defers both bounds.
122
- * `lo`/`hi` are recorded refs or literals.
123
- */
124
- function whereBetween($, col, lo, hi) {
125
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.BETWEEN_SENTINEL, [col]), [lo, hi]);
126
- }
127
- /**
128
- * `col LIKE ?` (V0 R3). Encoded `eq($[@like][col], pattern)` → v1 `{'<col> LIKE ?': pattern}`.
129
- * The pattern is a recorded ref or literal.
130
- */
131
- function whereLike($, col, pattern) {
132
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.LIKE_SENTINEL, [col, 'LIKE']), pattern);
133
- }
134
- /**
135
- * `col ILIKE ?` (V0 R3, PG case-insensitive; on MySQL/SQLite v1 emits the raw `ILIKE` keyword —
136
- * this reproduces v1 verbatim, not a portability rewrite). Encoded `eq($[@like][col][ILIKE], p)`.
137
- */
138
- function whereILike($, col, pattern) {
139
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.LIKE_SENTINEL, [col, 'ILIKE']), pattern);
140
- }
141
- /**
142
- * `col <op> ?::type` (V0 R3, dialect-gated cast — `dbCast`). Encoded
143
- * `eq($[@cast][col][type][op], value)`; the live compile drives v1 `dbCast(value, type, op)` so the
144
- * PG `::type` cast (and the MySQL/SQLite no-cast) is byte-true. `op` defaults to `=`.
145
- */
146
- function whereCast($, col, sqlType, value, op = '=') {
147
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.CAST_SENTINEL, [col, sqlType, op]), value);
148
- }
149
- /**
150
- * `col = fn(?)` (V0 R3, `dbDynamic`) — a function-call template with `?` placeholders bound to the
151
- * value list. Encoded `eq($[@dynamic][col][template], values)`; drives v1 `dbDynamic(template, vals)`.
152
- * `template` is the raw function SQL (e.g. `to_tsvector('en', ?)`).
153
- */
154
- function whereDynamic($, col, template, values) {
155
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.DYNAMIC_SENTINEL, [col, template]), values);
156
- }
157
- /**
158
- * `col = <sql>` (V0 R3, `dbImmediate` — an inline SQL expression, NO bound param, e.g. `NOW()`).
159
- * Encoded `eq($[@immediate][col][sql], null)`; drives v1 `dbImmediate(sql)`. No value-spec.
160
- */
161
- function whereImmediate($, col, sql) {
162
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.IMMEDIATE_SENTINEL, [col, sql]), null);
163
- }
164
- /**
165
- * `(a, b, …) IN ((?, ?), …)` (V0 R3, `dbTupleIn` composite membership). Encoded
166
- * `eq($[@tuple][a][b]…, tuples)` where `tuples` is an array-of-tuples value; drives v1
167
- * `dbTupleIn(columns, tuples)`. `columns` is the tuple column list.
168
- */
169
- function whereTupleIn($, columns, tuples) {
170
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.TUPLE_SENTINEL, columns), tuples);
171
- }
172
- /**
173
- * `lhs IN (SELECT …)` / `lhs NOT IN (SELECT …)` (V0 R2). The subquery is authored as a NESTED
174
- * makeSQL Fragment carried in the param slot (spec §2 補足): `sub` is a `{ sql, params? }` where
175
- * `sql` is the inner SELECT text (already dialect-tuned, v1-sourced) and `params` its bound
176
- * value-specs. Encoded `eq($[@subquery][lhsCol][kw], sub)`; the live compile splices the inner
177
- * `sql` into the v1 `DBSubquery`-shaped predicate `<lhs> <kw> (<sub.sql>)` and appends `sub.params`.
178
- */
179
- function whereInSubquery($, lhs, sub, not = false) {
180
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.SUBQUERY_SENTINEL, [lhs, not ? 'NOT IN' : 'IN']), sub);
181
- }
182
- /**
183
- * `EXISTS (SELECT 1 …)` / `NOT EXISTS (…)` (V0 R2). Like {@link whereInSubquery}, the correlated
184
- * subquery rides as a nested makeSQL Fragment in the param slot: `sub.sql` is the inner
185
- * `SELECT 1 FROM … WHERE …` (correlation refs already rendered as literal column paths, v1-sourced).
186
- * Encoded `eq($[@exists][kw], sub)`; the live compile emits `<kw> (<sub.sql>)` + `sub.params`.
187
- */
188
- function whereExists($, sub, not = false) {
189
- return (0, behavior_contracts_1.eq)(sentinelRef($, exports.EXISTS_SENTINEL, [not ? 'NOT EXISTS' : 'EXISTS']), sub);
190
- }
191
- //# sourceMappingURL=authoring-sql.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"authoring-sql.js","sourceRoot":"","sources":["../../src/scp/authoring-sql.ts"],"names":[],"mappings":"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"}