@kuindji/typed-sql 0.1.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 (208) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -0
  3. package/dist/builder/assemble.d.ts +13 -0
  4. package/dist/builder/assemble.d.ts.map +1 -0
  5. package/dist/builder/assemble.js +86 -0
  6. package/dist/builder/assemble.js.map +1 -0
  7. package/dist/builder/condition-tree.d.ts +27 -0
  8. package/dist/builder/condition-tree.d.ts.map +1 -0
  9. package/dist/builder/condition-tree.js +91 -0
  10. package/dist/builder/condition-tree.js.map +1 -0
  11. package/dist/builder/conditional-sql.d.ts +80 -0
  12. package/dist/builder/conditional-sql.d.ts.map +1 -0
  13. package/dist/builder/conditional-sql.js +88 -0
  14. package/dist/builder/conditional-sql.js.map +1 -0
  15. package/dist/builder/db.d.ts +76 -0
  16. package/dist/builder/db.d.ts.map +1 -0
  17. package/dist/builder/db.js +12 -0
  18. package/dist/builder/db.js.map +1 -0
  19. package/dist/builder/delete.d.ts +39 -0
  20. package/dist/builder/delete.d.ts.map +1 -0
  21. package/dist/builder/delete.js +33 -0
  22. package/dist/builder/delete.js.map +1 -0
  23. package/dist/builder/extract-params.d.ts +97 -0
  24. package/dist/builder/extract-params.d.ts.map +1 -0
  25. package/dist/builder/extract-params.js +2 -0
  26. package/dist/builder/extract-params.js.map +1 -0
  27. package/dist/builder/index.d.ts +23 -0
  28. package/dist/builder/index.d.ts.map +1 -0
  29. package/dist/builder/index.js +14 -0
  30. package/dist/builder/index.js.map +1 -0
  31. package/dist/builder/insert.d.ts +51 -0
  32. package/dist/builder/insert.d.ts.map +1 -0
  33. package/dist/builder/insert.js +39 -0
  34. package/dist/builder/insert.js.map +1 -0
  35. package/dist/builder/mutate.d.ts +28 -0
  36. package/dist/builder/mutate.d.ts.map +1 -0
  37. package/dist/builder/mutate.js +17 -0
  38. package/dist/builder/mutate.js.map +1 -0
  39. package/dist/builder/params.d.ts +22 -0
  40. package/dist/builder/params.d.ts.map +1 -0
  41. package/dist/builder/params.js +65 -0
  42. package/dist/builder/params.js.map +1 -0
  43. package/dist/builder/return-type.d.ts +39 -0
  44. package/dist/builder/return-type.d.ts.map +1 -0
  45. package/dist/builder/return-type.js +2 -0
  46. package/dist/builder/return-type.js.map +1 -0
  47. package/dist/builder/scanner.d.ts +49 -0
  48. package/dist/builder/scanner.d.ts.map +1 -0
  49. package/dist/builder/scanner.js +240 -0
  50. package/dist/builder/scanner.js.map +1 -0
  51. package/dist/builder/select.d.ts +76 -0
  52. package/dist/builder/select.d.ts.map +1 -0
  53. package/dist/builder/select.js +240 -0
  54. package/dist/builder/select.js.map +1 -0
  55. package/dist/builder/sql-tag.d.ts +319 -0
  56. package/dist/builder/sql-tag.d.ts.map +1 -0
  57. package/dist/builder/sql-tag.js +3 -0
  58. package/dist/builder/sql-tag.js.map +1 -0
  59. package/dist/builder/sql.d.ts +17 -0
  60. package/dist/builder/sql.d.ts.map +1 -0
  61. package/dist/builder/sql.js +36 -0
  62. package/dist/builder/sql.js.map +1 -0
  63. package/dist/builder/state.d.ts +53 -0
  64. package/dist/builder/state.d.ts.map +1 -0
  65. package/dist/builder/state.js +18 -0
  66. package/dist/builder/state.js.map +1 -0
  67. package/dist/builder/update.d.ts +60 -0
  68. package/dist/builder/update.d.ts.map +1 -0
  69. package/dist/builder/update.js +40 -0
  70. package/dist/builder/update.js.map +1 -0
  71. package/dist/builder/write-assemble.d.ts +5 -0
  72. package/dist/builder/write-assemble.d.ts.map +1 -0
  73. package/dist/builder/write-assemble.js +57 -0
  74. package/dist/builder/write-assemble.js.map +1 -0
  75. package/dist/builder/write-state.d.ts +39 -0
  76. package/dist/builder/write-state.d.ts.map +1 -0
  77. package/dist/builder/write-state.js +6 -0
  78. package/dist/builder/write-state.js.map +1 -0
  79. package/dist/builder/write-tag.d.ts +91 -0
  80. package/dist/builder/write-tag.d.ts.map +1 -0
  81. package/dist/builder/write-tag.js +2 -0
  82. package/dist/builder/write-tag.js.map +1 -0
  83. package/dist/columns.d.ts +33 -0
  84. package/dist/columns.d.ts.map +1 -0
  85. package/dist/columns.js +2 -0
  86. package/dist/columns.js.map +1 -0
  87. package/dist/expressions.d.ts +71 -0
  88. package/dist/expressions.d.ts.map +1 -0
  89. package/dist/expressions.js +2 -0
  90. package/dist/expressions.js.map +1 -0
  91. package/dist/index.d.ts +22 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +5 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/parsing/extract.d.ts +47 -0
  96. package/dist/parsing/extract.d.ts.map +1 -0
  97. package/dist/parsing/extract.js +2 -0
  98. package/dist/parsing/extract.js.map +1 -0
  99. package/dist/parsing/normalize.d.ts +44 -0
  100. package/dist/parsing/normalize.d.ts.map +1 -0
  101. package/dist/parsing/normalize.js +2 -0
  102. package/dist/parsing/normalize.js.map +1 -0
  103. package/dist/parsing/pg-literals.d.ts +37 -0
  104. package/dist/parsing/pg-literals.d.ts.map +1 -0
  105. package/dist/parsing/pg-literals.js +2 -0
  106. package/dist/parsing/pg-literals.js.map +1 -0
  107. package/dist/parsing/split.d.ts +100 -0
  108. package/dist/parsing/split.d.ts.map +1 -0
  109. package/dist/parsing/split.js +2 -0
  110. package/dist/parsing/split.js.map +1 -0
  111. package/dist/parsing/string-utils.d.ts +29 -0
  112. package/dist/parsing/string-utils.d.ts.map +1 -0
  113. package/dist/parsing/string-utils.js +2 -0
  114. package/dist/parsing/string-utils.js.map +1 -0
  115. package/dist/parsing/tokenize.d.ts +27 -0
  116. package/dist/parsing/tokenize.d.ts.map +1 -0
  117. package/dist/parsing/tokenize.js +2 -0
  118. package/dist/parsing/tokenize.js.map +1 -0
  119. package/dist/parsing.d.ts +7 -0
  120. package/dist/parsing.d.ts.map +1 -0
  121. package/dist/parsing.js +9 -0
  122. package/dist/parsing.js.map +1 -0
  123. package/dist/partial.d.ts +30 -0
  124. package/dist/partial.d.ts.map +1 -0
  125. package/dist/partial.js +10 -0
  126. package/dist/partial.js.map +1 -0
  127. package/dist/schema.d.ts +28 -0
  128. package/dist/schema.d.ts.map +1 -0
  129. package/dist/schema.js +2 -0
  130. package/dist/schema.js.map +1 -0
  131. package/dist/tables.d.ts +34 -0
  132. package/dist/tables.d.ts.map +1 -0
  133. package/dist/tables.js +2 -0
  134. package/dist/tables.js.map +1 -0
  135. package/dist/utils.d.ts +13 -0
  136. package/dist/utils.d.ts.map +1 -0
  137. package/dist/utils.js +3 -0
  138. package/dist/utils.js.map +1 -0
  139. package/dist/validation/cte.d.ts +54 -0
  140. package/dist/validation/cte.d.ts.map +1 -0
  141. package/dist/validation/cte.js +2 -0
  142. package/dist/validation/cte.js.map +1 -0
  143. package/dist/validation/dispatch.d.ts +31 -0
  144. package/dist/validation/dispatch.d.ts.map +1 -0
  145. package/dist/validation/dispatch.js +2 -0
  146. package/dist/validation/dispatch.js.map +1 -0
  147. package/dist/validation/joins.d.ts +16 -0
  148. package/dist/validation/joins.d.ts.map +1 -0
  149. package/dist/validation/joins.js +2 -0
  150. package/dist/validation/joins.js.map +1 -0
  151. package/dist/validation/return-derived.d.ts +67 -0
  152. package/dist/validation/return-derived.d.ts.map +1 -0
  153. package/dist/validation/return-derived.js +5 -0
  154. package/dist/validation/return-derived.js.map +1 -0
  155. package/dist/validation/return-types.d.ts +41 -0
  156. package/dist/validation/return-types.d.ts.map +1 -0
  157. package/dist/validation/return-types.js +2 -0
  158. package/dist/validation/return-types.js.map +1 -0
  159. package/dist/validation/validate-columns.d.ts +63 -0
  160. package/dist/validation/validate-columns.d.ts.map +1 -0
  161. package/dist/validation/validate-columns.js +2 -0
  162. package/dist/validation/validate-columns.js.map +1 -0
  163. package/dist/validation.d.ts +7 -0
  164. package/dist/validation.d.ts.map +1 -0
  165. package/dist/validation.js +9 -0
  166. package/dist/validation.js.map +1 -0
  167. package/package.json +64 -0
  168. package/src/builder/assemble.ts +100 -0
  169. package/src/builder/condition-tree.ts +162 -0
  170. package/src/builder/conditional-sql.ts +325 -0
  171. package/src/builder/db.ts +281 -0
  172. package/src/builder/delete.ts +57 -0
  173. package/src/builder/extract-params.ts +507 -0
  174. package/src/builder/index.ts +58 -0
  175. package/src/builder/insert.ts +75 -0
  176. package/src/builder/mutate.ts +55 -0
  177. package/src/builder/params.ts +95 -0
  178. package/src/builder/return-type.ts +66 -0
  179. package/src/builder/scanner.ts +254 -0
  180. package/src/builder/select.ts +470 -0
  181. package/src/builder/sql-tag.ts +422 -0
  182. package/src/builder/sql.ts +51 -0
  183. package/src/builder/state.ts +55 -0
  184. package/src/builder/update.ts +77 -0
  185. package/src/builder/write-assemble.ts +52 -0
  186. package/src/builder/write-state.ts +43 -0
  187. package/src/builder/write-tag.ts +119 -0
  188. package/src/columns.ts +336 -0
  189. package/src/expressions.ts +745 -0
  190. package/src/index.ts +81 -0
  191. package/src/parsing/extract.ts +260 -0
  192. package/src/parsing/normalize.ts +243 -0
  193. package/src/parsing/pg-literals.ts +289 -0
  194. package/src/parsing/split.ts +288 -0
  195. package/src/parsing/string-utils.ts +172 -0
  196. package/src/parsing/tokenize.ts +321 -0
  197. package/src/parsing.ts +8 -0
  198. package/src/partial.ts +241 -0
  199. package/src/schema.ts +130 -0
  200. package/src/tables.ts +278 -0
  201. package/src/utils.ts +43 -0
  202. package/src/validation/cte.ts +198 -0
  203. package/src/validation/dispatch.ts +312 -0
  204. package/src/validation/joins.ts +198 -0
  205. package/src/validation/return-derived.ts +253 -0
  206. package/src/validation/return-types.ts +271 -0
  207. package/src/validation/validate-columns.ts +489 -0
  208. package/src/validation.ts +8 -0
@@ -0,0 +1,39 @@
1
+ import { assembleInsertSQL } from "./write-assemble.js";
2
+ import { EMPTY_INSERT_STATE } from "./write-state.js";
3
+ import { assertAllProvided, collectScanned, expandScanned, } from "./scanner.js";
4
+ class InsertImpl {
5
+ st;
6
+ constructor(st) {
7
+ this.st = st;
8
+ }
9
+ next(st) { return new InsertImpl(st); }
10
+ into(table) { return this.next({ ...this.st, table }); }
11
+ // Store the explicit column list / SELECT body for the INSERT...SELECT form.
12
+ columns(cols) { return this.next({ ...this.st, columns: cols }); }
13
+ fromSelect(q) { return this.next({ ...this.st, fromSelect: q }); }
14
+ value(col, text) {
15
+ return this.next({ ...this.st, values: [...this.st.values, { col, text }] });
16
+ }
17
+ valueIf(cond, col, text) {
18
+ return cond ? this.value(col, text) : this.next(this.st);
19
+ }
20
+ onConflict(clause) { return this.next({ ...this.st, conflict: clause }); }
21
+ returning(cols) { return this.next({ ...this.st, returning: cols }); }
22
+ withParams(params) {
23
+ return this.next({ ...this.st, namedParams: { ...this.st.namedParams, ...params } });
24
+ }
25
+ toString() {
26
+ const sql = assembleInsertSQL(this.st);
27
+ assertAllProvided(sql, this.st.namedParams);
28
+ return expandScanned(sql, this.st.namedParams);
29
+ }
30
+ getParams() {
31
+ const sql = assembleInsertSQL(this.st);
32
+ assertAllProvided(sql, this.st.namedParams);
33
+ return collectScanned(sql, this.st.namedParams);
34
+ }
35
+ }
36
+ export function createInsertQuery() {
37
+ return new InsertImpl(EMPTY_INSERT_STATE);
38
+ }
39
+ //# sourceMappingURL=insert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insert.js","sourceRoot":"","sources":["../../src/builder/insert.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAA2B,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EACH,iBAAiB,EAAE,cAAc,EAAE,aAAa,GACnD,MAAM,cAAc,CAAC;AA8BtB,MAAM,UAAU;IACiB;IAA7B,YAA6B,EAAsB;QAAtB,OAAE,GAAF,EAAE,CAAoB;IAAG,CAAC;IAC/C,IAAI,CAAC,EAAsB,IAAS,OAAO,IAAI,UAAU,CAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC,KAAa,IAAS,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,6EAA6E;IAC7E,OAAO,CAAC,IAAY,IAAS,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/E,UAAU,CAAC,CAAS,IAAS,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/E,KAAK,CAAC,GAAW,EAAE,IAAY;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,CAAC,IAAa,EAAE,GAAW,EAAE,IAAY;QAC5C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,UAAU,CAAC,MAAc,IAAS,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACvF,SAAS,CAAC,IAAY,IAAS,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACnF,UAAU,CAAC,MAAwC;QAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,QAAQ;QACJ,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvC,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;QAC5C,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC;IACD,SAAS;QACL,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvC,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;QAC5C,OAAO,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;CACJ;AAQD,MAAM,UAAU,iBAAiB;IAC7B,OAAO,IAAI,UAAU,CAAoB,kBAAkB,CAAqD,CAAC;AACrH,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { DatabaseSchema } from "../schema.js";
2
+ import type { ExtractParams, ExtractReturning } from "./extract-params.js";
3
+ import { type DriverParamValue } from "./scanner.js";
4
+ /** Driver contract: returns the RETURNING rows, or [] for a no-RETURNING mutation. */
5
+ export type MutationHandler = (sql: string, params: DriverParamValue[]) => Promise<unknown[]>;
6
+ /** Row type a bound builder / createSql object yields. */
7
+ export type MutationReturnType<B> = B extends {
8
+ readonly __returning?: infer R;
9
+ } ? R : {};
10
+ /**
11
+ * Minimal structural shape both `BoundWrite` (builders) and `BoundSql`
12
+ * (`createSql`) satisfy. Used as the object-overload constraint instead of the
13
+ * deep `BoundWrite<S, any> | BoundSql<any, S>` union — matching a value against
14
+ * that union forces TS to compare the phantom `__returning` types of both arms,
15
+ * which recurses without bound. A shallow structural constraint avoids that; the
16
+ * row type is still derived from the value's own `__returning` via
17
+ * `MutationReturnType<B>`.
18
+ */
19
+ interface Executable {
20
+ toString(): string;
21
+ getParams(): ReadonlyArray<DriverParamValue>;
22
+ }
23
+ export declare function createMutateFn<S extends DatabaseSchema>(handler: MutationHandler): {
24
+ <B extends Executable>(query: B): Promise<MutationReturnType<B>[]>;
25
+ <Q extends string>(query: Q, params: ExtractParams<Q, S>): Promise<ExtractReturning<Q, S>[]>;
26
+ };
27
+ export {};
28
+ //# sourceMappingURL=mutate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutate.d.ts","sourceRoot":"","sources":["../../src/builder/mutate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErE,sFAAsF;AACtF,MAAM,MAAM,eAAe,GAAG,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,gBAAgB,EAAE,KACzB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAExB,0DAA0D;AAC1D,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAC5B,CAAC,SAAS;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,EAAE,CAAC;AAE1D;;;;;;;;GAQG;AACH,UAAU,UAAU;IAChB,QAAQ,IAAI,MAAM,CAAC;IACnB,SAAS,IAAI,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAChD;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,cAAc,EAAE,OAAO,EAAE,eAAe;KAE7D,CAAC,SAAS,UAAU,SACzB,CAAC,GACT,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;KAEnB,CAAC,SAAS,MAAM,SACrB,CAAC,UACA,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;EAgBvC"}
@@ -0,0 +1,17 @@
1
+ import { prepareScanned } from "./scanner.js";
2
+ export function createMutateFn(handler) {
3
+ // async so a prep-time / assembly throw (missing live placeholder, empty
4
+ // INSERT/SET, etc.) surfaces as a rejected promise rather than a synchronous
5
+ // throw — consistent with the promise-returning executor contract.
6
+ async function mutate(query, params) {
7
+ if (typeof query === "string") {
8
+ const { sql, values } = prepareScanned(query, params ?? {});
9
+ return handler(sql, values);
10
+ }
11
+ const sql = query.toString(); // already expanded + live-checked
12
+ const values = [...query.getParams()];
13
+ return handler(sql, values);
14
+ }
15
+ return mutate;
16
+ }
17
+ //# sourceMappingURL=mutate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutate.js","sourceRoot":"","sources":["../../src/builder/mutate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAyB,MAAM,cAAc,CAAC;AA0BrE,MAAM,UAAU,cAAc,CAA2B,OAAwB;IAW7E,yEAAyE;IACzE,6EAA6E;IAC7E,mEAAmE;IACnE,KAAK,UAAU,MAAM,CAAC,KAA0B,EAAE,MAAyC;QACvF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;YAC5D,OAAO,OAAO,CAAC,GAAG,EAAE,MAAM,CAAiB,CAAC;QAChD,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAiB,kCAAkC;QAChF,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QACtC,OAAO,OAAO,CAAC,GAAG,EAAE,MAAM,CAAiB,CAAC;IAChD,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** Runtime parameter value type supported by query builders. */
2
+ export type QueryParamValue = string | number | boolean | null;
3
+ /**
4
+ * Input parameter value type — allows arrays (expanded to multiple
5
+ * placeholders, e.g. :ids with [1,2,3] → "$1, $2, $3") and undefined
6
+ * (throws at runtime only if the param is actually used).
7
+ *
8
+ * Array expansion is BUILDER-ONLY. Conditional SQL keeps a scalar-only
9
+ * signature (see conditional-sql.ts) for parity with the old package.
10
+ */
11
+ export type QueryParamInput = QueryParamValue | readonly QueryParamValue[] | undefined;
12
+ /**
13
+ * Replace :name placeholders with $n positional placeholders, ordered by
14
+ * first appearance. Array values expand to consecutive placeholders.
15
+ */
16
+ export declare function expandNamedParams(sql: string, params: Record<string, QueryParamInput>): string;
17
+ /**
18
+ * Flattened param values in placeholder order. Throws if a used param's
19
+ * value is undefined.
20
+ */
21
+ export declare function collectParamValues(sql: string, params: Record<string, QueryParamInput>): QueryParamValue[];
22
+ //# sourceMappingURL=params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/builder/params.ts"],"names":[],"mappings":"AAEA,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GACrB,eAAe,GACf,SAAS,eAAe,EAAE,GAC1B,SAAS,CAAC;AAwBhB;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GACxC,MAAM,CAoBR;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GACxC,eAAe,EAAE,CAkBnB"}
@@ -0,0 +1,65 @@
1
+ // src/builder/params.ts
2
+ // Ported verbatim from OLD: trailing negative lookahead stops a short param
3
+ // (:te) from clobbering a longer one (:text). Matching the second colon of a
4
+ // ::cast is intentional parity (pinned by params.test.ts).
5
+ const PARAM_REGEX = /:([a-zA-Z_][a-zA-Z0-9_]*)(?![a-zA-Z0-9_])/g;
6
+ /** Param names in order of first appearance that are present in `params`. */
7
+ function usedParamNames(sql, params) {
8
+ const used = [];
9
+ let match;
10
+ PARAM_REGEX.lastIndex = 0;
11
+ while ((match = PARAM_REGEX.exec(sql)) !== null) {
12
+ const name = match[1];
13
+ if (name in params && !used.includes(name)) {
14
+ used.push(name);
15
+ }
16
+ }
17
+ return used;
18
+ }
19
+ /**
20
+ * Replace :name placeholders with $n positional placeholders, ordered by
21
+ * first appearance. Array values expand to consecutive placeholders.
22
+ */
23
+ export function expandNamedParams(sql, params) {
24
+ const used = usedParamNames(sql, params);
25
+ let out = sql;
26
+ let position = 1;
27
+ for (const name of used) {
28
+ const value = params[name];
29
+ const regex = new RegExp(`:${name}(?![a-zA-Z0-9_])`, "g");
30
+ if (Array.isArray(value)) {
31
+ const placeholders = value
32
+ .map((_, i) => `$${position + i}`)
33
+ .join(", ");
34
+ out = out.replace(regex, placeholders);
35
+ position += value.length;
36
+ }
37
+ else {
38
+ out = out.replace(regex, `$${position}`);
39
+ position++;
40
+ }
41
+ }
42
+ return out;
43
+ }
44
+ /**
45
+ * Flattened param values in placeholder order. Throws if a used param's
46
+ * value is undefined.
47
+ */
48
+ export function collectParamValues(sql, params) {
49
+ const used = usedParamNames(sql, params);
50
+ const result = [];
51
+ for (const name of used) {
52
+ const value = params[name];
53
+ if (value === undefined) {
54
+ throw new Error(`Query parameter ":${name}" is used but its value is undefined`);
55
+ }
56
+ if (Array.isArray(value)) {
57
+ result.push(...value);
58
+ }
59
+ else {
60
+ result.push(value);
61
+ }
62
+ }
63
+ return result;
64
+ }
65
+ //# sourceMappingURL=params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/builder/params.ts"],"names":[],"mappings":"AAAA,wBAAwB;AAkBxB,4EAA4E;AAC5E,6EAA6E;AAC7E,2DAA2D;AAC3D,MAAM,WAAW,GAAG,4CAA4C,CAAC;AAEjE,6EAA6E;AAC7E,SAAS,cAAc,CACnB,GAAW,EACX,MAAuC;IAEvC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAA6B,CAAC;IAClC,WAAW,CAAC,SAAS,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC7B,GAAW,EACX,MAAuC;IAEvC,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACzC,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,kBAAkB,EAAE,GAAG,CAAC,CAAC;QAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,YAAY,GAAG,KAAK;iBACrB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;iBACjC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;YACvC,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;QAC7B,CAAC;aACI,CAAC;YACF,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC,CAAC;YACzC,QAAQ,EAAE,CAAC;QACf,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAC9B,GAAW,EACX,MAAuC;IAEvC,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACX,qBAAqB,IAAI,sCAAsC,CAClE,CAAC;QACN,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QAC1B,CAAC;aACI,CAAC;YACF,MAAM,CAAC,IAAI,CAAC,KAAwB,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { DatabaseSchema } from "../schema.js";
2
+ import type { GetReturnType } from "../index.js";
3
+ import type { BuildSQL, SqlTag, SelFrag } from "./sql-tag.js";
4
+ /** Type-level canonical SQL: the maximal query (all select fragments present). */
5
+ export type BuilderSQLFor<Sql extends SqlTag> = BuildSQL<Sql, "max">;
6
+ /** True iff some select fragment is unconditional. */
7
+ type HasUncond<List extends readonly SelFrag[]> = List extends readonly [infer H extends SelFrag, ...infer R extends readonly SelFrag[]] ? H["cond"] extends false ? true : HasUncond<R> : false;
8
+ /** True iff NO select fragment is conditional (req-list === max-list). */
9
+ type AllUncond<List extends readonly SelFrag[]> = List extends readonly [infer H extends SelFrag, ...infer R extends readonly SelFrag[]] ? H["cond"] extends false ? AllUncond<R> : false : true;
10
+ type Partition<Row, ReqRow> = {
11
+ [K in keyof Row as K extends keyof ReqRow ? K : never]: Row[K];
12
+ } & {
13
+ [K in keyof Row as K extends keyof ReqRow ? never : K]?: Row[K];
14
+ };
15
+ /**
16
+ * Required/optional partition over GetReturnType of MaxSQL / ReqSQL / ScopeSQL.
17
+ * - allUncond: every selected column is unconditional, so the req-list and the
18
+ * max-list are identical and every key is required. Skip the second parse and
19
+ * the Partition entirely — both are pure overhead here, and parsing a very
20
+ * wide SELECT twice can cross TS's instantiation limit (TS2589).
21
+ * - hasUncond (but some conditional): Row = GetReturnType<MaxSQL>;
22
+ * ReqRow = GetReturnType<ReqSQL>; partition keys: required iff in ReqRow.
23
+ * - else (no unconditional select → all-false runtime path is SELECT *):
24
+ * Partial<GetReturnType<MaxSQL> & GetReturnType<ScopeSQL>>.
25
+ */
26
+ export type BuilderReturnTypeFor<Schema extends DatabaseSchema, Sql extends SqlTag> = HasUncond<Sql["selects"]> extends true ? AllUncond<Sql["selects"]> extends true ? GetReturnType<BuildSQL<Sql, "max">, Schema> : GetReturnType<BuildSQL<Sql, "max">, Schema> extends infer Row ? GetReturnType<BuildSQL<Sql, "req">, Schema> extends infer ReqRow ? Partition<Row, ReqRow> : Row : {} : Partial<GetReturnType<BuildSQL<Sql, "max">, Schema> & GetReturnType<BuildSQL<Sql, "scope">, Schema>>;
27
+ /** Brand carried by toBrandedString(); not used at runtime. */
28
+ export interface BuilderResultBrand<Schema extends DatabaseSchema, Sql extends SqlTag> {
29
+ readonly __schema?: Schema;
30
+ readonly __sql?: Sql;
31
+ }
32
+ import type { SelectQueryBuilder } from "./select.js";
33
+ /** Extract the Sql tag from a builder type. */
34
+ export type SqlOf<B> = B extends SelectQueryBuilder<any, infer Sql extends SqlTag> ? Sql : never;
35
+ type SchemaOf<B> = B extends SelectQueryBuilder<infer S extends DatabaseSchema, any> ? S : never;
36
+ export type BuilderSQL<B> = BuilderSQLFor<SqlOf<B>>;
37
+ export type BuilderReturnType<B> = BuilderReturnTypeFor<SchemaOf<B>, SqlOf<B>>;
38
+ export {};
39
+ //# sourceMappingURL=return-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-type.d.ts","sourceRoot":"","sources":["../../src/builder/return-type.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=return-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-type.js","sourceRoot":"","sources":["../../src/builder/return-type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Value domain at the typed boundary (spec §6.5). Default `unknown` accepts
3
+ * scalars, branded scalars, arrays, dates, and JSON/object columns. The driver
4
+ * adapter is responsible for serialization.
5
+ */
6
+ export type DriverParamValue = unknown;
7
+ /** One real `:name` occurrence found by the scanner. */
8
+ export interface PlaceholderOccurrence {
9
+ /** Param name without leading ":" and without any `::cast` suffix. */
10
+ readonly name: string;
11
+ /** True iff this occurrence sits directly inside an `IN (...)` / `NOT IN (...)` group. */
12
+ readonly inExpansion: boolean;
13
+ /** Index of the ":" in the source SQL. */
14
+ readonly start: number;
15
+ /** Index just past the last char of the name. */
16
+ readonly end: number;
17
+ }
18
+ /**
19
+ * Scan `sql` and return every real placeholder occurrence, skipping string
20
+ * literals (single-quote + dollar-quote), `--` line comments, and block
21
+ * comments, and treating `::type` casts as non-placeholders. Tracks, per paren
22
+ * group, whether the group opened immediately after `in` / `not in`, so each
23
+ * occurrence carries an accurate `inExpansion` flag (spec §6.3/§6.5).
24
+ */
25
+ export declare function scanPlaceholders(sql: string): PlaceholderOccurrence[];
26
+ /**
27
+ * Replace `:name` with `$n` (first-appearance order; repeats reuse the same
28
+ * `$n`). Only IN-list occurrences with an array value expand to multiple slots;
29
+ * every other value (including array-VALUED columns and JSON objects) is a
30
+ * single slot. Driven entirely by the shared scanner (spec §6.5).
31
+ */
32
+ export declare function expandScanned(sql: string, params: Record<string, DriverParamValue>): string;
33
+ /**
34
+ * Flattened param values in placeholder order. IN-list arrays are spread; all
35
+ * other values pass through as one entry. Throws if a used value is undefined.
36
+ */
37
+ export declare function collectScanned(sql: string, params: Record<string, DriverParamValue>): DriverParamValue[];
38
+ /**
39
+ * Live-placeholder check (spec §6.3): throw for any real placeholder in the
40
+ * assembled SQL whose name is absent from `params`. Conditional fragments that
41
+ * were excluded contribute no placeholder, so they never trip this.
42
+ */
43
+ export declare function assertAllProvided(sql: string, params: Record<string, DriverParamValue>): void;
44
+ /** One-shot: live-check then return `{ sql: expanded, values }`. */
45
+ export declare function prepareScanned(sql: string, params: Record<string, DriverParamValue>): {
46
+ sql: string;
47
+ values: DriverParamValue[];
48
+ };
49
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/builder/scanner.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEvC,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IAClC,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACxB;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAgHrE;AA2BD;;;;;GAKG;AACH,wBAAgB,aAAa,CACzB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACzC,MAAM,CAyBR;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACzC,gBAAgB,EAAE,CAepB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACzC,IAAI,CAMN;AAED,oEAAoE;AACpE,wBAAgB,cAAc,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACzC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAG7C"}
@@ -0,0 +1,240 @@
1
+ // src/builder/scanner.ts
2
+ const isIdentStart = (c) => /[a-zA-Z_]/.test(c);
3
+ const isIdentChar = (c) => /[a-zA-Z0-9_]/.test(c);
4
+ /**
5
+ * Scan `sql` and return every real placeholder occurrence, skipping string
6
+ * literals (single-quote + dollar-quote), `--` line comments, and block
7
+ * comments, and treating `::type` casts as non-placeholders. Tracks, per paren
8
+ * group, whether the group opened immediately after `in` / `not in`, so each
9
+ * occurrence carries an accurate `inExpansion` flag (spec §6.3/§6.5).
10
+ */
11
+ export function scanPlaceholders(sql) {
12
+ const out = [];
13
+ // Stack of paren contexts: true = this "(" opened right after IN / NOT IN.
14
+ const parenStack = [];
15
+ let i = 0;
16
+ const n = sql.length;
17
+ // Returns true if the run of word chars ending just before `idx` (skipping
18
+ // trailing whitespace) is `in`, optionally preceded by `not`.
19
+ const opensInList = (idx) => {
20
+ let j = idx - 1;
21
+ while (j >= 0 && /\s/.test(sql[j]))
22
+ j--;
23
+ let end = j + 1;
24
+ while (j >= 0 && isIdentChar(sql[j]))
25
+ j--;
26
+ const w1 = sql.slice(j + 1, end).toLowerCase();
27
+ return w1 === "in";
28
+ };
29
+ while (i < n) {
30
+ const c = sql[i];
31
+ // -- line comment
32
+ if (c === "-" && sql[i + 1] === "-") {
33
+ i += 2;
34
+ while (i < n && sql[i] !== "\n")
35
+ i++;
36
+ continue;
37
+ }
38
+ // /* block comment */
39
+ if (c === "/" && sql[i + 1] === "*") {
40
+ i += 2;
41
+ while (i < n && !(sql[i] === "*" && sql[i + 1] === "/"))
42
+ i++;
43
+ i += 2;
44
+ continue;
45
+ }
46
+ // double-quoted identifier (with "" escape) — a `:name`-looking run
47
+ // inside a quoted identifier (`"tenant:region"`) is part of the name,
48
+ // not a placeholder.
49
+ if (c === '"') {
50
+ i++;
51
+ while (i < n) {
52
+ if (sql[i] === '"' && sql[i + 1] === '"') {
53
+ i += 2;
54
+ continue;
55
+ }
56
+ if (sql[i] === '"') {
57
+ i++;
58
+ break;
59
+ }
60
+ i++;
61
+ }
62
+ continue;
63
+ }
64
+ // PostgreSQL escape string E'...' — backslash escapes are active, so a
65
+ // `\'` (and the usual `''`) escapes a quote rather than closing the
66
+ // literal. A bare `'` scan would mis-read `\'` as the terminator and leak
67
+ // any `:name` that follows back into the placeholder stream. The `E` must
68
+ // be a standalone string prefix, not the tail of an identifier.
69
+ if ((c === "E" || c === "e") && sql[i + 1] === "'" &&
70
+ !(i > 0 && isIdentChar(sql[i - 1]))) {
71
+ i += 2; // skip the `E` and the opening quote
72
+ while (i < n) {
73
+ if (sql[i] === "\\") {
74
+ i += 2;
75
+ continue;
76
+ } // backslash escapes next char
77
+ if (sql[i] === "'" && sql[i + 1] === "'") {
78
+ i += 2;
79
+ continue;
80
+ }
81
+ if (sql[i] === "'") {
82
+ i++;
83
+ break;
84
+ }
85
+ i++;
86
+ }
87
+ continue;
88
+ }
89
+ // single-quoted string (with '' escape)
90
+ if (c === "'") {
91
+ i++;
92
+ while (i < n) {
93
+ if (sql[i] === "'" && sql[i + 1] === "'") {
94
+ i += 2;
95
+ continue;
96
+ }
97
+ if (sql[i] === "'") {
98
+ i++;
99
+ break;
100
+ }
101
+ i++;
102
+ }
103
+ continue;
104
+ }
105
+ // dollar-quoted string: $tag$ ... $tag$
106
+ if (c === "$") {
107
+ const m = /^\$([a-zA-Z_]\w*)?\$/.exec(sql.slice(i));
108
+ if (m) {
109
+ const tag = m[0];
110
+ const close = sql.indexOf(tag, i + tag.length);
111
+ i = close === -1 ? n : close + tag.length;
112
+ continue;
113
+ }
114
+ }
115
+ // parens — track IN-list context
116
+ if (c === "(") {
117
+ parenStack.push(opensInList(i));
118
+ i++;
119
+ continue;
120
+ }
121
+ if (c === ")") {
122
+ parenStack.pop();
123
+ i++;
124
+ continue;
125
+ }
126
+ // cast `::` — skip both colons, never a placeholder
127
+ if (c === ":" && sql[i + 1] === ":") {
128
+ i += 2;
129
+ continue;
130
+ }
131
+ // placeholder `:name`
132
+ if (c === ":" && isIdentStart(sql[i + 1] ?? "")) {
133
+ const start = i;
134
+ i++;
135
+ const from = i;
136
+ while (i < n && isIdentChar(sql[i]))
137
+ i++;
138
+ const name = sql.slice(from, i);
139
+ const inExpansion = parenStack.length > 0 && parenStack[parenStack.length - 1];
140
+ out.push({ name, inExpansion, start, end: i });
141
+ continue;
142
+ }
143
+ i++;
144
+ }
145
+ return out;
146
+ }
147
+ /** Ordered unique names (first appearance) with their merged expansion flag. */
148
+ function uniqueNames(occ) {
149
+ const order = [];
150
+ const expand = new Map();
151
+ const seenNonExpand = new Map();
152
+ for (const o of occ) {
153
+ if (!order.includes(o.name))
154
+ order.push(o.name);
155
+ if (o.inExpansion)
156
+ expand.set(o.name, true);
157
+ else
158
+ seenNonExpand.set(o.name, true);
159
+ }
160
+ // Mixed IN / non-IN reuse is unsound (spec §6.5) — one value cannot be both
161
+ // N positional slots and one slot.
162
+ for (const name of order) {
163
+ if (expand.get(name) && seenNonExpand.get(name)) {
164
+ throw new Error(`Query parameter ":${name}" is used in mixed IN and non-IN positions; ` +
165
+ `a name cannot be both an expanded IN list and a scalar.`);
166
+ }
167
+ }
168
+ return order.map(name => ({ name, inExpansion: expand.get(name) ?? false }));
169
+ }
170
+ /**
171
+ * Replace `:name` with `$n` (first-appearance order; repeats reuse the same
172
+ * `$n`). Only IN-list occurrences with an array value expand to multiple slots;
173
+ * every other value (including array-VALUED columns and JSON objects) is a
174
+ * single slot. Driven entirely by the shared scanner (spec §6.5).
175
+ */
176
+ export function expandScanned(sql, params) {
177
+ const occ = scanPlaceholders(sql);
178
+ const names = uniqueNames(occ).filter(u => u.name in params);
179
+ // Assign starting positions in appearance order.
180
+ const startPos = new Map();
181
+ let pos = 1;
182
+ for (const u of names) {
183
+ startPos.set(u.name, pos);
184
+ const v = params[u.name];
185
+ pos += u.inExpansion && Array.isArray(v) ? v.length : 1;
186
+ }
187
+ // Rewrite right-to-left so indices stay valid; skip occurrences whose name
188
+ // isn't supplied (left as a literal — caught by assertAllProvided when live).
189
+ let out = sql;
190
+ for (let k = occ.length - 1; k >= 0; k--) {
191
+ const o = occ[k];
192
+ if (!(o.name in params))
193
+ continue;
194
+ const p = startPos.get(o.name);
195
+ const v = params[o.name];
196
+ const replacement = o.inExpansion && Array.isArray(v)
197
+ ? v.map((_, idx) => `$${p + idx}`).join(", ")
198
+ : `$${p}`;
199
+ out = out.slice(0, o.start) + replacement + out.slice(o.end);
200
+ }
201
+ return out;
202
+ }
203
+ /**
204
+ * Flattened param values in placeholder order. IN-list arrays are spread; all
205
+ * other values pass through as one entry. Throws if a used value is undefined.
206
+ */
207
+ export function collectScanned(sql, params) {
208
+ const occ = scanPlaceholders(sql);
209
+ const names = uniqueNames(occ).filter(u => u.name in params);
210
+ const result = [];
211
+ for (const u of names) {
212
+ const v = params[u.name];
213
+ if (v === undefined) {
214
+ throw new Error(`Query parameter ":${u.name}" is used but its value is undefined`);
215
+ }
216
+ if (u.inExpansion && Array.isArray(v))
217
+ result.push(...v);
218
+ else
219
+ result.push(v);
220
+ }
221
+ return result;
222
+ }
223
+ /**
224
+ * Live-placeholder check (spec §6.3): throw for any real placeholder in the
225
+ * assembled SQL whose name is absent from `params`. Conditional fragments that
226
+ * were excluded contribute no placeholder, so they never trip this.
227
+ */
228
+ export function assertAllProvided(sql, params) {
229
+ for (const o of scanPlaceholders(sql)) {
230
+ if (!(o.name in params)) {
231
+ throw new Error(`Missing value for query parameter ":${o.name}"`);
232
+ }
233
+ }
234
+ }
235
+ /** One-shot: live-check then return `{ sql: expanded, values }`. */
236
+ export function prepareScanned(sql, params) {
237
+ assertAllProvided(sql, params);
238
+ return { sql: expandScanned(sql, params), values: collectScanned(sql, params) };
239
+ }
240
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/builder/scanner.ts"],"names":[],"mappings":"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"}