sqlstack 1.0.6 → 1.0.8

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 (162) hide show
  1. package/dist/cjs/adapters/index.d.ts.map +1 -0
  2. package/dist/cjs/adapters/index.js.map +1 -0
  3. package/dist/cjs/adapters/mysql.d.ts.map +1 -0
  4. package/dist/cjs/adapters/mysql.js.map +1 -0
  5. package/dist/cjs/adapters/pg.d.ts.map +1 -0
  6. package/dist/cjs/adapters/pg.js.map +1 -0
  7. package/dist/cjs/adapters/sqlite.d.ts.map +1 -0
  8. package/dist/cjs/adapters/sqlite.js.map +1 -0
  9. package/dist/cjs/adapters/test.d.ts.map +1 -0
  10. package/dist/cjs/adapters/test.js.map +1 -0
  11. package/dist/cjs/binders/sqlBinder.d.ts.map +1 -0
  12. package/dist/cjs/binders/sqlBinder.js.map +1 -0
  13. package/dist/cjs/core/errors.d.ts.map +1 -0
  14. package/dist/cjs/core/errors.js.map +1 -0
  15. package/dist/cjs/core/fileResolution.d.ts.map +1 -0
  16. package/dist/cjs/core/fileResolution.js.map +1 -0
  17. package/dist/{core → cjs/core}/metadata.d.ts +4 -0
  18. package/dist/cjs/core/metadata.d.ts.map +1 -0
  19. package/dist/cjs/core/metadata.js.map +1 -0
  20. package/dist/cjs/core/validator.d.ts.map +1 -0
  21. package/dist/cjs/core/validator.js.map +1 -0
  22. package/dist/cjs/decorators/defaults.d.ts.map +1 -0
  23. package/dist/cjs/decorators/defaults.js.map +1 -0
  24. package/dist/cjs/decorators/page.d.ts +8 -0
  25. package/dist/cjs/decorators/page.d.ts.map +1 -0
  26. package/dist/cjs/decorators/page.js +11 -0
  27. package/dist/cjs/decorators/page.js.map +1 -0
  28. package/dist/cjs/decorators/query.d.ts.map +1 -0
  29. package/dist/cjs/decorators/query.js +281 -0
  30. package/dist/cjs/decorators/query.js.map +1 -0
  31. package/dist/cjs/decorators/queryBinder.d.ts.map +1 -0
  32. package/dist/cjs/decorators/queryBinder.js.map +1 -0
  33. package/dist/cjs/decorators/resultShape.d.ts.map +1 -0
  34. package/dist/cjs/decorators/resultShape.js.map +1 -0
  35. package/dist/cjs/decorators/transform.d.ts.map +1 -0
  36. package/dist/cjs/decorators/transform.js.map +1 -0
  37. package/dist/cjs/decorators/validateResult.d.ts.map +1 -0
  38. package/dist/cjs/decorators/validateResult.js.map +1 -0
  39. package/dist/cjs/index.d.ts +14 -0
  40. package/dist/cjs/index.d.ts.map +1 -0
  41. package/dist/{index.js → cjs/index.js} +1 -0
  42. package/dist/cjs/index.js.map +1 -0
  43. package/dist/cjs/registry.d.ts.map +1 -0
  44. package/dist/cjs/registry.js.map +1 -0
  45. package/dist/cjs/utils/dto.d.ts.map +1 -0
  46. package/dist/cjs/utils/dto.js.map +1 -0
  47. package/dist/esm/adapters/index.js +4 -0
  48. package/dist/esm/adapters/index.js.map +1 -0
  49. package/dist/esm/adapters/mysql.js +36 -0
  50. package/dist/esm/adapters/mysql.js.map +1 -0
  51. package/dist/esm/adapters/pg.js +67 -0
  52. package/dist/esm/adapters/pg.js.map +1 -0
  53. package/dist/esm/adapters/sqlite.js +141 -0
  54. package/dist/esm/adapters/sqlite.js.map +1 -0
  55. package/dist/esm/adapters/test.js +47 -0
  56. package/dist/esm/adapters/test.js.map +1 -0
  57. package/dist/esm/binders/sqlBinder.js +182 -0
  58. package/dist/esm/binders/sqlBinder.js.map +1 -0
  59. package/dist/esm/core/errors.js +25 -0
  60. package/dist/esm/core/errors.js.map +1 -0
  61. package/dist/esm/core/fileResolution.js +74 -0
  62. package/dist/esm/core/fileResolution.js.map +1 -0
  63. package/dist/esm/core/metadata.js +24 -0
  64. package/dist/esm/core/metadata.js.map +1 -0
  65. package/dist/esm/core/validator.js +57 -0
  66. package/dist/esm/core/validator.js.map +1 -0
  67. package/dist/esm/decorators/defaults.js +7 -0
  68. package/dist/esm/decorators/defaults.js.map +1 -0
  69. package/dist/esm/decorators/page.js +8 -0
  70. package/dist/esm/decorators/page.js.map +1 -0
  71. package/dist/esm/decorators/query.js +278 -0
  72. package/dist/esm/decorators/query.js.map +1 -0
  73. package/dist/esm/decorators/queryBinder.js +7 -0
  74. package/dist/esm/decorators/queryBinder.js.map +1 -0
  75. package/dist/esm/decorators/resultShape.js +14 -0
  76. package/dist/esm/decorators/resultShape.js.map +1 -0
  77. package/dist/esm/decorators/transform.js +8 -0
  78. package/dist/esm/decorators/transform.js.map +1 -0
  79. package/dist/esm/decorators/validateResult.js +8 -0
  80. package/dist/esm/decorators/validateResult.js.map +1 -0
  81. package/dist/{index.d.ts → esm/index.js} +2 -1
  82. package/dist/esm/index.js.map +1 -0
  83. package/dist/esm/package.json +3 -0
  84. package/dist/esm/registry.js +26 -0
  85. package/dist/esm/registry.js.map +1 -0
  86. package/dist/esm/utils/dto.js +129 -0
  87. package/dist/esm/utils/dto.js.map +1 -0
  88. package/package.json +21 -16
  89. package/readme.md +25 -0
  90. package/dist/adapters/index.d.ts.map +0 -1
  91. package/dist/adapters/index.js.map +0 -1
  92. package/dist/adapters/mysql.d.ts.map +0 -1
  93. package/dist/adapters/mysql.js.map +0 -1
  94. package/dist/adapters/pg.d.ts.map +0 -1
  95. package/dist/adapters/pg.js.map +0 -1
  96. package/dist/adapters/sqlite.d.ts.map +0 -1
  97. package/dist/adapters/sqlite.js.map +0 -1
  98. package/dist/adapters/test.d.ts.map +0 -1
  99. package/dist/adapters/test.js.map +0 -1
  100. package/dist/binders/sqlBinder.d.ts.map +0 -1
  101. package/dist/binders/sqlBinder.js.map +0 -1
  102. package/dist/core/errors.d.ts.map +0 -1
  103. package/dist/core/errors.js.map +0 -1
  104. package/dist/core/fileResolution.d.ts.map +0 -1
  105. package/dist/core/fileResolution.js.map +0 -1
  106. package/dist/core/metadata.d.ts.map +0 -1
  107. package/dist/core/metadata.js.map +0 -1
  108. package/dist/core/validator.d.ts.map +0 -1
  109. package/dist/core/validator.js.map +0 -1
  110. package/dist/decorators/defaults.d.ts.map +0 -1
  111. package/dist/decorators/defaults.js.map +0 -1
  112. package/dist/decorators/query.d.ts.map +0 -1
  113. package/dist/decorators/query.js +0 -106
  114. package/dist/decorators/query.js.map +0 -1
  115. package/dist/decorators/queryBinder.d.ts.map +0 -1
  116. package/dist/decorators/queryBinder.js.map +0 -1
  117. package/dist/decorators/resultShape.d.ts.map +0 -1
  118. package/dist/decorators/resultShape.js.map +0 -1
  119. package/dist/decorators/transform.d.ts.map +0 -1
  120. package/dist/decorators/transform.js.map +0 -1
  121. package/dist/decorators/validateResult.d.ts.map +0 -1
  122. package/dist/decorators/validateResult.js.map +0 -1
  123. package/dist/index.d.ts.map +0 -1
  124. package/dist/index.js.map +0 -1
  125. package/dist/registry.d.ts.map +0 -1
  126. package/dist/registry.js.map +0 -1
  127. package/dist/utils/dto.d.ts.map +0 -1
  128. package/dist/utils/dto.js.map +0 -1
  129. /package/dist/{adapters → cjs/adapters}/index.d.ts +0 -0
  130. /package/dist/{adapters → cjs/adapters}/index.js +0 -0
  131. /package/dist/{adapters → cjs/adapters}/mysql.d.ts +0 -0
  132. /package/dist/{adapters → cjs/adapters}/mysql.js +0 -0
  133. /package/dist/{adapters → cjs/adapters}/pg.d.ts +0 -0
  134. /package/dist/{adapters → cjs/adapters}/pg.js +0 -0
  135. /package/dist/{adapters → cjs/adapters}/sqlite.d.ts +0 -0
  136. /package/dist/{adapters → cjs/adapters}/sqlite.js +0 -0
  137. /package/dist/{adapters → cjs/adapters}/test.d.ts +0 -0
  138. /package/dist/{adapters → cjs/adapters}/test.js +0 -0
  139. /package/dist/{binders → cjs/binders}/sqlBinder.d.ts +0 -0
  140. /package/dist/{binders → cjs/binders}/sqlBinder.js +0 -0
  141. /package/dist/{core → cjs/core}/errors.d.ts +0 -0
  142. /package/dist/{core → cjs/core}/errors.js +0 -0
  143. /package/dist/{core → cjs/core}/fileResolution.d.ts +0 -0
  144. /package/dist/{core → cjs/core}/fileResolution.js +0 -0
  145. /package/dist/{core → cjs/core}/metadata.js +0 -0
  146. /package/dist/{core → cjs/core}/validator.d.ts +0 -0
  147. /package/dist/{core → cjs/core}/validator.js +0 -0
  148. /package/dist/{decorators → cjs/decorators}/defaults.d.ts +0 -0
  149. /package/dist/{decorators → cjs/decorators}/defaults.js +0 -0
  150. /package/dist/{decorators → cjs/decorators}/query.d.ts +0 -0
  151. /package/dist/{decorators → cjs/decorators}/queryBinder.d.ts +0 -0
  152. /package/dist/{decorators → cjs/decorators}/queryBinder.js +0 -0
  153. /package/dist/{decorators → cjs/decorators}/resultShape.d.ts +0 -0
  154. /package/dist/{decorators → cjs/decorators}/resultShape.js +0 -0
  155. /package/dist/{decorators → cjs/decorators}/transform.d.ts +0 -0
  156. /package/dist/{decorators → cjs/decorators}/transform.js +0 -0
  157. /package/dist/{decorators → cjs/decorators}/validateResult.d.ts +0 -0
  158. /package/dist/{decorators → cjs/decorators}/validateResult.js +0 -0
  159. /package/dist/{registry.d.ts → cjs/registry.d.ts} +0 -0
  160. /package/dist/{registry.js → cjs/registry.js} +0 -0
  161. /package/dist/{utils → cjs/utils}/dto.d.ts +0 -0
  162. /package/dist/{utils → cjs/utils}/dto.js +0 -0
@@ -1,106 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Query = Query;
4
- const metadata_1 = require("../core/metadata");
5
- const errors_1 = require("../core/errors");
6
- const validator_1 = require("../core/validator");
7
- const registry_1 = require("../registry");
8
- const sqlBinder_1 = require("../binders/sqlBinder");
9
- const fileResolution_1 = require("../core/fileResolution");
10
- function Query(arg) {
11
- return function (_target, prop, desc) {
12
- const options = typeof arg === 'string' ? undefined : arg;
13
- const rootArg = typeof arg === 'string' ? arg : undefined;
14
- // Store method-level db override if provided
15
- if (options?.db) {
16
- (0, metadata_1.setMethodLabels)(_target, prop, { db: options.db });
17
- }
18
- // Store inline SQL if provided
19
- if (options?.sql) {
20
- (0, metadata_1.setMethodLabels)(_target, prop, { source: { kind: 'inline', sql: options.sql } });
21
- }
22
- else {
23
- // FS-based resolution
24
- const { rootDir } = (0, fileResolution_1.coerceRootPath)(rootArg);
25
- const dir = rootDir ?? (0, fileResolution_1.guessDecoratorDir)();
26
- if (dir) {
27
- (0, metadata_1.setMethodLabels)(_target, prop, { source: { kind: 'fs', rootDir: dir } });
28
- }
29
- }
30
- const original = desc.value;
31
- desc.value = async function (...callArgs) {
32
- const labels = (0, metadata_1.getMethodLabels)(this, prop);
33
- const classLabels = (0, metadata_1.getClassLabels)(this);
34
- // 1) prepare args with defaults
35
- const rawInput = callArgs.length === 1 ? callArgs[0] : callArgs; // object or positional array
36
- // 2) choose database and dialect
37
- const dbName = labels.db ?? options?.db ?? classLabels?.db;
38
- const db = registry_1.SqlStackDB.get(dbName);
39
- const dialect = options?.dialect ?? db.dialect ?? 'sqlite';
40
- // 3) load SQL source (inline or fs)
41
- const sql = labels?.source?.kind === 'inline'
42
- ? labels.source.sql
43
- : labels?.source?.kind === 'fs'
44
- ? (0, fileResolution_1.resolveSqlFromFs)(labels.source.rootDir, String(prop), dialect).sql
45
- : undefined;
46
- if (!sql) {
47
- throw new errors_1.SqlStackError(`No SQL source provided for method ${String(prop)}. Use @Query() with a file/folder path or inline sql.`);
48
- }
49
- // 4) bind placeholders
50
- // Decide argument mode: positional if SQL contains :argN
51
- const hasPositional = /:arg[1-9][0-9]*/.test(sql);
52
- const args = hasPositional ? callArgs : applyDefaults(labels.defaults, rawInput);
53
- const binder = dialect === 'postgres' ? (0, sqlBinder_1.createPostgresBinder)() : dialect === 'mysql' ? (0, sqlBinder_1.createMysqlBinder)() : (0, sqlBinder_1.createSqliteBinder)();
54
- const { sql: boundSql, params } = binder.bind(sql, args);
55
- // 5) execute query via registry DB
56
- const out = await db.query(boundSql, params);
57
- // 6) If rows were returned (SELECT/CTE), shape + transform + validate
58
- if (Array.isArray(out)) {
59
- const shaped = applyShape(out, labels.shape);
60
- const transformed = labels.transform ? labels.transform(shaped) : shaped;
61
- // 7) validate result via JSON Schema, if provided
62
- if (labels.validateSchema && !(0, validator_1.isValidationDisabled)()) {
63
- if (Array.isArray(transformed)) {
64
- for (const row of transformed)
65
- (0, validator_1.validateOutput)(labels.validateSchema, row);
66
- }
67
- else if (transformed !== null && transformed !== undefined) {
68
- (0, validator_1.validateOutput)(labels.validateSchema, transformed);
69
- }
70
- }
71
- return transformed;
72
- }
73
- // Non-SELECT: return the write result as-is
74
- return out;
75
- };
76
- return desc;
77
- };
78
- }
79
- function applyDefaults(defaults, input) {
80
- if (!defaults)
81
- return input;
82
- if (Array.isArray(input))
83
- return input; // defaults only apply to named-object args
84
- return { ...defaults, ...(input || {}) };
85
- }
86
- function applyShape(rows, shape) {
87
- switch (shape) {
88
- case 'single':
89
- return rows.length > 0 ? rows[0] : null;
90
- case 'only':
91
- if (rows.length !== 1)
92
- throw new errors_1.ExactlyOneRowError(rows.length);
93
- return rows[0];
94
- case 'exist':
95
- if (rows.length < 1)
96
- throw new errors_1.NoRowsError();
97
- return rows[0];
98
- case 'none':
99
- if (rows.length > 0)
100
- throw new errors_1.RowsExistError(rows.length);
101
- return null;
102
- default:
103
- return rows;
104
- }
105
- }
106
- //# sourceMappingURL=query.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/decorators/query.ts"],"names":[],"mappings":"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","sourcesContent":["import { getClassLabels, getMethodLabels, setMethodLabels } from '../core/metadata';\nimport { SqlStackError, ExactlyOneRowError, NoRowsError, RowsExistError } from '../core/errors';\nimport { isValidationDisabled, validateOutput } from '../core/validator';\nimport { SqlStackDB } from '../registry';\nimport { createSqliteBinder, createMysqlBinder, createPostgresBinder } from '../binders/sqlBinder';\nimport { coerceRootPath, guessDecoratorDir, resolveSqlFromFs } from '../core/fileResolution';\n\ntype QueryOptions = {\n sql?: string; // optional inline SQL for testing; otherwise, future: load from file\n db?: string; // optional override DB name\n dialect?: 'sqlite' | 'mysql' | 'postgres';\n};\n\nexport function Query(arg?: string | QueryOptions) {\n return function (_target: any, prop: string | symbol, desc: PropertyDescriptor) {\n const options: QueryOptions | undefined = typeof arg === 'string' ? undefined : arg;\n const rootArg: string | undefined = typeof arg === 'string' ? arg : undefined;\n // Store method-level db override if provided\n if (options?.db) {\n setMethodLabels(_target, prop, { db: options.db });\n }\n // Store inline SQL if provided\n if (options?.sql) {\n setMethodLabels(_target, prop, { source: { kind: 'inline', sql: options.sql } });\n } else {\n // FS-based resolution\n const { rootDir } = coerceRootPath(rootArg);\n const dir = rootDir ?? guessDecoratorDir();\n if (dir) {\n setMethodLabels(_target, prop, { source: { kind: 'fs', rootDir: dir } });\n }\n }\n\n const original = desc.value;\n desc.value = async function (...callArgs: any[]) {\n const labels = getMethodLabels(this, prop);\n const classLabels = getClassLabels(this);\n\n // 1) prepare args with defaults\n const rawInput = callArgs.length === 1 ? callArgs[0] : callArgs; // object or positional array\n\n // 2) choose database and dialect\n const dbName = labels.db ?? options?.db ?? classLabels?.db;\n const db = SqlStackDB.get(dbName);\n const dialect = options?.dialect ?? db.dialect ?? 'sqlite';\n\n // 3) load SQL source (inline or fs)\n const sql = labels?.source?.kind === 'inline'\n ? labels.source.sql\n : labels?.source?.kind === 'fs'\n ? resolveSqlFromFs(labels.source.rootDir, String(prop), dialect).sql\n : undefined;\n if (!sql) {\n throw new SqlStackError(`No SQL source provided for method ${String(prop)}. Use @Query() with a file/folder path or inline sql.`);\n }\n\n // 4) bind placeholders\n // Decide argument mode: positional if SQL contains :argN\n const hasPositional = /:arg[1-9][0-9]*/.test(sql);\n const args = hasPositional ? callArgs : applyDefaults(labels.defaults, rawInput);\n const binder =\n dialect === 'postgres' ? createPostgresBinder() : dialect === 'mysql' ? createMysqlBinder() : createSqliteBinder();\n const { sql: boundSql, params } = binder.bind(sql, args as any);\n\n // 5) execute query via registry DB\n const out = await db.query(boundSql, params);\n\n // 6) If rows were returned (SELECT/CTE), shape + transform + validate\n if (Array.isArray(out)) {\n const shaped = applyShape(out, labels.shape);\n const transformed = labels.transform ? labels.transform(shaped) : shaped;\n\n // 7) validate result via JSON Schema, if provided\n if (labels.validateSchema && !isValidationDisabled()) {\n if (Array.isArray(transformed)) {\n for (const row of transformed) validateOutput(labels.validateSchema, row);\n } else if (transformed !== null && transformed !== undefined) {\n validateOutput(labels.validateSchema, transformed);\n }\n }\n return transformed;\n }\n\n // Non-SELECT: return the write result as-is\n return out;\n };\n\n return desc;\n };\n}\n\nfunction applyDefaults(defaults: Record<string, unknown> | undefined, input: any) {\n if (!defaults) return input;\n if (Array.isArray(input)) return input; // defaults only apply to named-object args\n return { ...defaults, ...(input || {}) };\n}\n\nfunction applyShape<T>(rows: T[], shape?: 'single' | 'only' | 'exist' | 'none'): any {\n switch (shape) {\n case 'single':\n return rows.length > 0 ? rows[0] : null;\n case 'only':\n if (rows.length !== 1) throw new ExactlyOneRowError(rows.length);\n return rows[0];\n case 'exist':\n if (rows.length < 1) throw new NoRowsError();\n return rows[0];\n case 'none':\n if (rows.length > 0) throw new RowsExistError(rows.length);\n return null;\n default:\n return rows;\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"queryBinder.d.ts","sourceRoot":"","sources":["../../src/decorators/queryBinder.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,IAClC,MAAM,QAAQ,UAGhC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"queryBinder.js","sourceRoot":"","sources":["../../src/decorators/queryBinder.ts"],"names":[],"mappings":";;AAEA,kCAIC;AAND,+CAAkD;AAElD,SAAgB,WAAW,CAAC,OAAyB;IACnD,OAAO,UAAU,IAAc;QAC7B,IAAA,yBAAc,EAAC,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { setClassLabels } from '../core/metadata';\n\nexport function QueryBinder(options?: { db?: string }) {\n return function (ctor: Function) {\n setClassLabels(ctor, { db: options?.db });\n };\n}\n\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"resultShape.d.ts","sourceRoot":"","sources":["../../src/decorators/resultShape.ts"],"names":[],"mappings":"AAEA,wBAAgB,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,QAExD;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,QAEtD;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,QAEvD;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,QAEtD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"resultShape.js","sourceRoot":"","sources":["../../src/decorators/resultShape.ts"],"names":[],"mappings":";;AAEA,wBAEC;AAED,oBAEC;AAED,sBAEC;AAED,oBAEC;AAhBD,+CAAmD;AAEnD,SAAgB,MAAM,CAAC,MAAW,EAAE,IAAqB;IACvD,IAAA,0BAAe,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,SAAgB,IAAI,CAAC,MAAW,EAAE,IAAqB;IACrD,IAAA,0BAAe,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,SAAgB,KAAK,CAAC,MAAW,EAAE,IAAqB;IACtD,IAAA,0BAAe,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,IAAI,CAAC,MAAW,EAAE,IAAqB;IACrD,IAAA,0BAAe,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import { setMethodLabels } from '../core/metadata';\n\nexport function Single(target: any, prop: string | symbol) {\n setMethodLabels(target, prop, { shape: 'single' });\n}\n\nexport function Only(target: any, prop: string | symbol) {\n setMethodLabels(target, prop, { shape: 'only' });\n}\n\nexport function Exist(target: any, prop: string | symbol) {\n setMethodLabels(target, prop, { shape: 'exist' });\n}\n\nexport function None(target: any, prop: string | symbol) {\n setMethodLabels(target, prop, { shape: 'none' });\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/decorators/transform.ts"],"names":[],"mappings":"AAGA,wBAAgB,SAAS,CAAC,GAAG,GAAG,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,IACtD,QAAQ,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,UAGpD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/decorators/transform.ts"],"names":[],"mappings":";;AAGA,8BAIC;AAPD,+CAAmD;AAEnD,8EAA8E;AAC9E,SAAgB,SAAS,CAAwB,EAAwB;IACvE,OAAO,UAAU,MAAW,EAAE,IAAqB;QACjD,IAAA,0BAAe,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAS,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { setMethodLabels } from '../core/metadata';\n\n// Transform operates on the shaped value (array of rows, single row, or null)\nexport function Transform<TIn = any, TOut = any>(fn: (value: TIn) => TOut) {\n return function (target: any, prop: string | symbol) {\n setMethodLabels(target, prop, { transform: fn as any });\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"validateResult.d.ts","sourceRoot":"","sources":["../../src/decorators/validateResult.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,IAC3B,QAAQ,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,UAGpD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"validateResult.js","sourceRoot":"","sources":["../../src/decorators/validateResult.ts"],"names":[],"mappings":";;AAGA,wCAIC;AAPD,+CAAmD;AAEnD,gCAAgC;AAChC,SAAgB,cAAc,CAAC,MAAe;IAC5C,OAAO,UAAU,MAAW,EAAE,IAAqB;QACjD,IAAA,0BAAe,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { setMethodLabels } from '../core/metadata';\n\n// Accept a JSON Schema directly\nexport function ValidateResult(schema: unknown) {\n return function (target: any, prop: string | symbol) {\n setMethodLabels(target, prop, { validateSchema: schema });\n };\n}\n\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,sDAAoC;AACpC,gDAA8B;AAC9B,mDAAiC;AACjC,6CAA2B;AAC3B,6CAA2B;AAC3B,2DAAyC;AACzC,qDAAmC;AACnC,wDAAsC;AACtC,2DAAyC;AACzC,8DAA4C;AAC5C,yDAAuC;AACvC,8CAA4B","sourcesContent":["export * from './binders/sqlBinder';\nexport * from './core/errors';\nexport * from './core/validator';\nexport * from './registry';\nexport * from './adapters';\nexport * from './decorators/queryBinder';\nexport * from './decorators/query';\nexport * from './decorators/defaults';\nexport * from './decorators/resultShape';\nexport * from './decorators/validateResult';\nexport * from './decorators/transform';\nexport * from './utils/dto';\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAGtD,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAGD,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IAEtD,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,GAAG,EAAE,GAAG,WAAW,GAAG,mBAAmB,CAAC;AAEpE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAE5D,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACnC;AAED,cAAM,QAAQ;IACZ,OAAO,CAAC,GAAG,CAA+B;IAC1C,OAAO,CAAC,WAAW,CAAC,CAAS;IAE7B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ;IAKnC,UAAU,CAAC,IAAI,EAAE,MAAM;IAMvB,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ;CAO7B;AAED,eAAO,MAAM,UAAU,UAAiB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":";;;AAwBA,MAAM,QAAQ;IAAd;QACU,QAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;IAqB5C,CAAC;IAlBC,QAAQ,CAAC,IAAY,EAAE,EAAY;QACjC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,IAAa;QACf,MAAM,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC;QACrC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACrD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;QAChE,OAAO,EAAE,CAAC;IACZ,CAAC;CACF;AAEY,QAAA,UAAU,GAAG,IAAI,QAAQ,EAAE,CAAC","sourcesContent":["export type Dialect = 'sqlite' | 'mysql' | 'postgres';\n\n// Result for non-SELECT statements across adapters\nexport interface WriteResult {\n rowsAffected: number;\n lastInsertId?: unknown;\n}\n\n// Postgres-specific extension when using RETURNING on write statements\nexport interface PostgresWriteResult extends WriteResult {\n // Only present when the SQL includes RETURNING and rows are returned\n returning?: any[];\n}\n\nexport type QueryResult = any[] | WriteResult | PostgresWriteResult;\n\nexport interface Database {\n dialect: Dialect;\n query(sql: string, params: unknown[]): Promise<QueryResult>;\n // Underlying driver connection or pool (driver-specific)\n conn: unknown;\n close: () => Promise<void> | void;\n}\n\nclass Registry {\n private map = new Map<string, Database>();\n private defaultName?: string;\n\n register(name: string, db: Database) {\n this.map.set(name, db);\n return this;\n }\n\n setDefault(name: string) {\n if (!this.map.has(name)) throw new Error(`No database registered under ${name}`);\n this.defaultName = name;\n return this;\n }\n\n get(name?: string): Database {\n const key = name ?? this.defaultName;\n if (!key) throw new Error('No default database set');\n const db = this.map.get(key);\n if (!db) throw new Error(`No database registered under ${key}`);\n return db;\n }\n}\n\nexport const SqlStackDB = new Registry();\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dto.d.ts","sourceRoot":"","sources":["../../src/utils/dto.ts"],"names":[],"mappings":"AAAA,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE9B,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,CAAC,aAAa,EAAE,MAAM,GAAG,GAAG,CAAC;CAC9B,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,iGAAiG;IACjG,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AA6CF;;GAEG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,UAAe,IAkE7B,MAAM,EAAE,EAAE,sBAerC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dto.js","sourceRoot":"","sources":["../../src/utils/dto.ts"],"names":[],"mappings":"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","sourcesContent":["type KV = Record<string, any>;\n\nexport type NodeSpec = {\n id?: string;\n name?: string;\n // nested collections: { [collectionKey]: NodeSpec }\n [collectionKey: string]: any;\n};\n\ntype DTOOptions = {\n /** If true, return a single root (or null). If false, return an array of roots. Default: true */\n single?: boolean;\n};\n\nconst CHILD_INDEX = Symbol('childIndex');\n\nfunction setDeep(obj: KV, path: string, value: any) {\n const parts = path.split('.');\n let cur: any = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const k = parts[i]!;\n if (cur[k] == null || typeof cur[k] !== 'object') cur[k] = {};\n cur = cur[k];\n }\n cur[parts[parts.length - 1]!] = value;\n}\n\nfunction childCollections(spec: NodeSpec): Array<[string, NodeSpec]> {\n const out: Array<[string, NodeSpec]> = [];\n for (const key of Object.keys(spec)) {\n if (key === 'id' || key === 'name') continue;\n const val = (spec as any)[key];\n if (val && typeof val === 'object' && !Array.isArray(val)) out.push([key, val as NodeSpec]);\n }\n return out;\n}\n\nfunction ensureChildInfra(node: KV, collectionKey: string) {\n if (!node[collectionKey]) node[collectionKey] = [];\n if (!(node as any)[CHILD_INDEX]) (node as any)[CHILD_INDEX] = {} as Record<string, Map<any, KV>>;\n const idxBag = (node as any)[CHILD_INDEX] as Record<string, Map<any, KV>>;\n if (!idxBag[collectionKey]) idxBag[collectionKey] = new Map<any, KV>();\n return { arr: node[collectionKey] as KV[], index: idxBag[collectionKey] as Map<any, KV> };\n}\n\nfunction stripMeta(node: KV) {\n if (node && typeof node === 'object') {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete (node as any)[CHILD_INDEX];\n for (const k of Object.keys(node)) {\n const v = node[k];\n if (Array.isArray(v)) v.forEach(stripMeta);\n }\n }\n return node;\n}\n\n/**\n * Build a rows→tree transformer from a nested spec.\n */\nexport function DTO(spec: NodeSpec, opts: DTOOptions = {}) {\n const single = opts.single ?? false;\n type IndexMap = Map<any, KV>;\n const mappingsCache = new WeakMap<NodeSpec, Array<[string, string]>>();\n\n function getMappings(levelSpec: NodeSpec): Array<[string, string]> {\n const cached = mappingsCache.get(levelSpec);\n if (cached) return cached;\n const out: Array<[string, string]> = [];\n for (const [k, v] of Object.entries(levelSpec)) {\n if (typeof v === 'string') out.push([k, v]);\n }\n // Ensure stable ordering so identity is independent of spec key order\n out.sort((a, b) => (a[0] as string).localeCompare(b[0] as string));\n mappingsCache.set(levelSpec, out);\n return out;\n }\n\n function computeKey(levelSpec: NodeSpec, row: KV): any {\n const mappings = getMappings(levelSpec);\n if (mappings.length === 0) return undefined;\n const pairs = mappings.map(([, source]) => row[source]);\n // If all mapping values are null/undefined, skip\n if (pairs.every((v) => v === null || v === undefined)) return undefined;\n // Stable composite key: include source keys with values\n const composite = mappings.map(([, source], i) => [source, pairs[i]] as [string, any]);\n return JSON.stringify(composite);\n }\n\n function upsertAtLevel(rowsIndex: IndexMap, rowsOut: KV[], levelSpec: NodeSpec, row: KV) {\n const nodeKey = computeKey(levelSpec, row);\n if (nodeKey == null) return null;\n\n let node = rowsIndex.get(nodeKey);\n if (!node) {\n node = {};\n for (const [target, source] of getMappings(levelSpec)) {\n if (source in row) setDeep(node, target, (row as any)[source]);\n }\n rowsIndex.set(nodeKey, node);\n rowsOut.push(node);\n }\n return node;\n }\n\n function descend(parent: KV, levelSpec: NodeSpec, row: KV) {\n for (const [collectionKey, childSpec] of childCollections(levelSpec)) {\n const childKey = computeKey(childSpec, row);\n if (childKey == null) continue; // skip this branch for this row\n\n const { arr, index } = ensureChildInfra(parent, collectionKey);\n let child = index.get(childKey);\n if (!child) {\n child = {};\n for (const [target, source] of getMappings(childSpec)) {\n if (source in row) setDeep(child, target, (row as any)[source]);\n }\n index.set(childKey, child);\n arr.push(child);\n }\n\n // Recurse further for this child (it may host its own collections)\n descend(child, childSpec, row);\n }\n }\n\n return function transform(rows: KV[]) {\n if (!rows || rows.length === 0) return single ? null : [];\n\n const roots: KV[] = [];\n const rootIndex: IndexMap = new Map();\n\n for (const row of rows) {\n const root = upsertAtLevel(rootIndex, roots, spec, row);\n if (!root) continue;\n descend(root, spec, row);\n }\n\n roots.forEach(stripMeta);\n return single ? roots[0] ?? null : roots;\n };\n}\n"]}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes