sqlstack 1.0.24 → 2.0.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 (52) hide show
  1. package/dist/cjs/adapters/mysql.d.ts.map +1 -1
  2. package/dist/cjs/adapters/mysql.js +3 -3
  3. package/dist/cjs/adapters/mysql.js.map +1 -1
  4. package/dist/cjs/adapters/pg.d.ts.map +1 -1
  5. package/dist/cjs/adapters/pg.js +3 -3
  6. package/dist/cjs/adapters/pg.js.map +1 -1
  7. package/dist/cjs/codegen/cli.d.ts +3 -0
  8. package/dist/cjs/codegen/cli.d.ts.map +1 -0
  9. package/dist/cjs/codegen/cli.js +50 -0
  10. package/dist/cjs/codegen/cli.js.map +1 -0
  11. package/dist/cjs/codegen/generateManifest.d.ts +60 -0
  12. package/dist/cjs/codegen/generateManifest.d.ts.map +1 -0
  13. package/dist/cjs/codegen/generateManifest.js +181 -0
  14. package/dist/cjs/codegen/generateManifest.js.map +1 -0
  15. package/dist/cjs/core/loadNodeModule.d.ts +17 -0
  16. package/dist/cjs/core/loadNodeModule.d.ts.map +1 -0
  17. package/dist/cjs/core/loadNodeModule.js +36 -0
  18. package/dist/cjs/core/loadNodeModule.js.map +1 -0
  19. package/dist/cjs/core/resolver.d.ts +81 -0
  20. package/dist/cjs/core/resolver.d.ts.map +1 -0
  21. package/dist/cjs/core/resolver.js +99 -0
  22. package/dist/cjs/core/resolver.js.map +1 -0
  23. package/dist/cjs/decorators/query.d.ts.map +1 -1
  24. package/dist/cjs/decorators/query.js +57 -4
  25. package/dist/cjs/decorators/query.js.map +1 -1
  26. package/dist/cjs/index.d.ts +3 -0
  27. package/dist/cjs/index.d.ts.map +1 -1
  28. package/dist/cjs/index.js +10 -1
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/sql.d.ts +11 -0
  31. package/dist/cjs/sql.d.ts.map +1 -0
  32. package/dist/cjs/sql.js +111 -0
  33. package/dist/cjs/sql.js.map +1 -0
  34. package/dist/esm/adapters/mysql.js +3 -3
  35. package/dist/esm/adapters/mysql.js.map +1 -1
  36. package/dist/esm/adapters/pg.js +3 -3
  37. package/dist/esm/adapters/pg.js.map +1 -1
  38. package/dist/esm/codegen/cli.js +48 -0
  39. package/dist/esm/codegen/cli.js.map +1 -0
  40. package/dist/esm/codegen/generateManifest.js +174 -0
  41. package/dist/esm/codegen/generateManifest.js.map +1 -0
  42. package/dist/esm/core/loadNodeModule.js +33 -0
  43. package/dist/esm/core/loadNodeModule.js.map +1 -0
  44. package/dist/esm/core/resolver.js +92 -0
  45. package/dist/esm/core/resolver.js.map +1 -0
  46. package/dist/esm/decorators/query.js +57 -4
  47. package/dist/esm/decorators/query.js.map +1 -1
  48. package/dist/esm/index.js +3 -0
  49. package/dist/esm/index.js.map +1 -1
  50. package/dist/esm/sql.js +106 -0
  51. package/dist/esm/sql.js.map +1 -0
  52. package/package.json +16 -7
package/dist/esm/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ // SQL Template Strings
2
+ export { sql, SqlFragment } from './sql.js';
1
3
  // Decorators
2
4
  export * from './decorators/queryBinder.js';
3
5
  export * from './decorators/query.js';
@@ -16,6 +18,7 @@ export * from './core/validator.js';
16
18
  // DTO Helper
17
19
  export * from './utils/dto.js';
18
20
  export { SqlStackDB } from './registry.js';
21
+ export { SqlStack, FsResolver, ManifestResolver, MANIFEST_DIALECT_EXT } from './core/resolver.js';
19
22
  // Legacy exports (kept for backward compatibility)
20
23
  export * from './binders/sqlBinder.js';
21
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAElC,eAAe;AACf,cAAc,gBAAgB,CAAC;AAE/B,WAAW;AACX,cAAc,YAAY,CAAC;AAE3B,wBAAwB;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,aAAa;AACb,cAAc,aAAa,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAY,MAAM,YAAY,CAAC;AAElD,mDAAmD;AACnD,cAAc,qBAAqB,CAAC","sourcesContent":["// Decorators\nexport * from './decorators/queryBinder';\nexport * from './decorators/query';\nexport * from './decorators/defaults';\nexport * from './decorators/resultShape';\nexport * from './decorators/validateResult';\nexport * from './decorators/transform';\nexport * from './decorators/page';\n\n// Transactions\nexport * from './transactions';\n\n// Adapters\nexport * from './adapters';\n\n// Errors and Validation\nexport * from './core/errors';\nexport * from './core/validator';\n\n// DTO Helper\nexport * from './utils/dto';\n\n// Database Registry and Types\nexport type { Dialect, WriteResult, PostgresWriteResult, QueryResult, Database } from './registry';\nexport { SqlStackDB, IStackDB } from './registry';\n\n// Legacy exports (kept for backward compatibility)\nexport * from './binders/sqlBinder';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEzC,aAAa;AACb,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAElC,eAAe;AACf,cAAc,gBAAgB,CAAC;AAE/B,WAAW;AACX,cAAc,YAAY,CAAC;AAE3B,wBAAwB;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,aAAa;AACb,cAAc,aAAa,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAY,MAAM,YAAY,CAAC;AAIlD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE/F,mDAAmD;AACnD,cAAc,qBAAqB,CAAC","sourcesContent":["// SQL Template Strings\nexport { sql, SqlFragment } from './sql';\n\n// Decorators\nexport * from './decorators/queryBinder';\nexport * from './decorators/query';\nexport * from './decorators/defaults';\nexport * from './decorators/resultShape';\nexport * from './decorators/validateResult';\nexport * from './decorators/transform';\nexport * from './decorators/page';\n\n// Transactions\nexport * from './transactions';\n\n// Adapters\nexport * from './adapters';\n\n// Errors and Validation\nexport * from './core/errors';\nexport * from './core/validator';\n\n// DTO Helper\nexport * from './utils/dto';\n\n// Database Registry and Types\nexport type { Dialect, WriteResult, PostgresWriteResult, QueryResult, Database } from './registry';\nexport { SqlStackDB, IStackDB } from './registry';\n\n// SQL Resolvers (v2): pluggable SQL source resolution\nexport type { SqlResolver, SqlManifest, SqlResolutionRequest, ManifestResolverOptions } from './core/resolver';\nexport { SqlStack, FsResolver, ManifestResolver, MANIFEST_DIALECT_EXT } from './core/resolver';\n\n// Legacy exports (kept for backward compatibility)\nexport * from './binders/sqlBinder';\n"]}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Tagged template literal for SQL queries with `?` placeholders.
3
+ *
4
+ * Usage:
5
+ * sql`SELECT * FROM users WHERE id = ${userId} AND status = ${status}`
6
+ * sql`INSERT INTO users :insert(${data})`
7
+ * sql`UPDATE users SET :update(${data}) WHERE id = ${id}`
8
+ * sql`SELECT * FROM users WHERE :filter(${criteria})`
9
+ * sql`INSERT INTO users :batch_insert(${rows})`
10
+ */
11
+ const MACRO_OPEN = /:(insert|update|filter|batch_insert)\s*\(\s*$/i;
12
+ const MACRO_CLOSE = /^\s*\)/;
13
+ export class SqlFragment {
14
+ constructor(strings, values) {
15
+ this.strings = strings;
16
+ this.values = values;
17
+ }
18
+ toSQL() {
19
+ const segments = [...this.strings];
20
+ const sqlParts = [];
21
+ const params = [];
22
+ for (let i = 0; i < segments.length; i++) {
23
+ if (i < this.values.length) {
24
+ const openMatch = segments[i].match(MACRO_OPEN);
25
+ const closeMatch = segments[i + 1]?.match(MACRO_CLOSE);
26
+ if (openMatch && closeMatch) {
27
+ // Binder macro: trim the macro syntax and expand
28
+ sqlParts.push(segments[i].slice(0, -openMatch[0].length));
29
+ segments[i + 1] = segments[i + 1].slice(closeMatch[0].length);
30
+ const { text, params: expanded } = expandMacro(openMatch[1].toLowerCase(), this.values[i]);
31
+ sqlParts.push(text);
32
+ params.push(...expanded);
33
+ }
34
+ else {
35
+ sqlParts.push(segments[i]);
36
+ sqlParts.push('?');
37
+ params.push(this.values[i]);
38
+ }
39
+ }
40
+ else {
41
+ sqlParts.push(segments[i]);
42
+ }
43
+ }
44
+ return { sql: sqlParts.join(''), params };
45
+ }
46
+ }
47
+ function expandMacro(type, value) {
48
+ switch (type) {
49
+ case 'insert': {
50
+ assertPlainObject(value, ':insert()');
51
+ const obj = value;
52
+ const keys = Object.keys(obj);
53
+ if (keys.length === 0)
54
+ throw new Error(':insert() requires at least one column');
55
+ const cols = keys.join(', ');
56
+ const placeholders = keys.map(() => '?').join(', ');
57
+ return { text: `(${cols}) VALUES (${placeholders})`, params: keys.map(k => obj[k]) };
58
+ }
59
+ case 'update': {
60
+ assertPlainObject(value, ':update()');
61
+ const entries = Object.entries(value).filter(([, v]) => v !== undefined);
62
+ if (entries.length === 0)
63
+ throw new Error(':update() requires at least one defined column');
64
+ return {
65
+ text: entries.map(([k]) => `${k} = ?`).join(', '),
66
+ params: entries.map(([, v]) => v),
67
+ };
68
+ }
69
+ case 'filter': {
70
+ assertPlainObject(value, ':filter()');
71
+ const entries = Object.entries(value).filter(([, v]) => v !== undefined);
72
+ if (entries.length === 0)
73
+ throw new Error(':filter() requires at least one defined condition');
74
+ return {
75
+ text: entries.map(([k]) => `${k} = ?`).join(' AND '),
76
+ params: entries.map(([, v]) => v),
77
+ };
78
+ }
79
+ case 'batch_insert': {
80
+ if (!Array.isArray(value) || value.length === 0) {
81
+ throw new Error(':batch_insert() requires a non-empty array of objects');
82
+ }
83
+ const keys = Object.keys(value[0]);
84
+ if (keys.length === 0)
85
+ throw new Error(':batch_insert() requires at least one column');
86
+ const cols = keys.join(', ');
87
+ const rowPlaceholder = `(${keys.map(() => '?').join(', ')})`;
88
+ const allPlaceholders = value.map(() => rowPlaceholder).join(', ');
89
+ return {
90
+ text: `(${cols}) VALUES ${allPlaceholders}`,
91
+ params: value.flatMap(row => keys.map(k => row[k])),
92
+ };
93
+ }
94
+ default:
95
+ throw new Error(`Unknown binder macro :${type}()`);
96
+ }
97
+ }
98
+ function assertPlainObject(value, label) {
99
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
100
+ throw new Error(`${label} in sql\`\` template requires a plain object`);
101
+ }
102
+ }
103
+ export function sql(strings, ...values) {
104
+ return new SqlFragment(strings, values);
105
+ }
106
+ //# sourceMappingURL=sql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.js","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tagged template literal for SQL queries with `?` placeholders.\n *\n * Usage:\n * sql`SELECT * FROM users WHERE id = ${userId} AND status = ${status}`\n * sql`INSERT INTO users :insert(${data})`\n * sql`UPDATE users SET :update(${data}) WHERE id = ${id}`\n * sql`SELECT * FROM users WHERE :filter(${criteria})`\n * sql`INSERT INTO users :batch_insert(${rows})`\n */\nconst MACRO_OPEN = /:(insert|update|filter|batch_insert)\\s*\\(\\s*$/i;\nconst MACRO_CLOSE = /^\\s*\\)/;\n\nexport class SqlFragment {\n constructor(\n public readonly strings: readonly string[],\n public readonly values: readonly unknown[],\n ) {}\n\n toSQL(): { sql: string; params: unknown[] } {\n const segments = [...this.strings];\n const sqlParts: string[] = [];\n const params: unknown[] = [];\n\n for (let i = 0; i < segments.length; i++) {\n if (i < this.values.length) {\n const openMatch = segments[i].match(MACRO_OPEN);\n const closeMatch = segments[i + 1]?.match(MACRO_CLOSE);\n\n if (openMatch && closeMatch) {\n // Binder macro: trim the macro syntax and expand\n sqlParts.push(segments[i].slice(0, -openMatch[0].length));\n segments[i + 1] = segments[i + 1].slice(closeMatch[0].length);\n\n const { text, params: expanded } = expandMacro(openMatch[1].toLowerCase(), this.values[i]);\n sqlParts.push(text);\n params.push(...expanded);\n } else {\n sqlParts.push(segments[i]);\n sqlParts.push('?');\n params.push(this.values[i]);\n }\n } else {\n sqlParts.push(segments[i]);\n }\n }\n\n return { sql: sqlParts.join(''), params };\n }\n}\n\nfunction expandMacro(type: string, value: unknown): { text: string; params: unknown[] } {\n switch (type) {\n case 'insert': {\n assertPlainObject(value, ':insert()');\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj);\n if (keys.length === 0) throw new Error(':insert() requires at least one column');\n const cols = keys.join(', ');\n const placeholders = keys.map(() => '?').join(', ');\n return { text: `(${cols}) VALUES (${placeholders})`, params: keys.map(k => obj[k]) };\n }\n case 'update': {\n assertPlainObject(value, ':update()');\n const entries = Object.entries(value as Record<string, unknown>).filter(([, v]) => v !== undefined);\n if (entries.length === 0) throw new Error(':update() requires at least one defined column');\n return {\n text: entries.map(([k]) => `${k} = ?`).join(', '),\n params: entries.map(([, v]) => v),\n };\n }\n case 'filter': {\n assertPlainObject(value, ':filter()');\n const entries = Object.entries(value as Record<string, unknown>).filter(([, v]) => v !== undefined);\n if (entries.length === 0) throw new Error(':filter() requires at least one defined condition');\n return {\n text: entries.map(([k]) => `${k} = ?`).join(' AND '),\n params: entries.map(([, v]) => v),\n };\n }\n case 'batch_insert': {\n if (!Array.isArray(value) || value.length === 0) {\n throw new Error(':batch_insert() requires a non-empty array of objects');\n }\n const keys = Object.keys(value[0]);\n if (keys.length === 0) throw new Error(':batch_insert() requires at least one column');\n const cols = keys.join(', ');\n const rowPlaceholder = `(${keys.map(() => '?').join(', ')})`;\n const allPlaceholders = value.map(() => rowPlaceholder).join(', ');\n return {\n text: `(${cols}) VALUES ${allPlaceholders}`,\n params: value.flatMap(row => keys.map(k => (row as Record<string, unknown>)[k])),\n };\n }\n default:\n throw new Error(`Unknown binder macro :${type}()`);\n }\n}\n\nfunction assertPlainObject(value: unknown, label: string): asserts value is Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} in sql\\`\\` template requires a plain object`);\n }\n}\n\nexport function sql(strings: TemplateStringsArray, ...values: unknown[]): SqlFragment {\n return new SqlFragment(strings, values);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqlstack",
3
- "version": "1.0.24",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -30,10 +30,18 @@
30
30
  "types": "./dist/cjs/core/errors.d.ts",
31
31
  "require": "./dist/cjs/core/errors.js",
32
32
  "import": "./dist/esm/core/errors.js"
33
+ },
34
+ "./codegen": {
35
+ "types": "./dist/cjs/codegen/generateManifest.d.ts",
36
+ "require": "./dist/cjs/codegen/generateManifest.js",
37
+ "import": "./dist/esm/codegen/generateManifest.js"
33
38
  }
34
39
  },
40
+ "bin": {
41
+ "sqlstack-codegen": "./dist/cjs/codegen/cli.js"
42
+ },
35
43
  "scripts": {
36
- "prepublish": "npm run build",
44
+ "prepublishOnly": "npm run build",
37
45
  "build": "npm-run-all clean build:cjs build:esm",
38
46
  "build:cjs": "tsc -p tsconfig.json",
39
47
  "build:esm": "tsc -p tsconfig.esm.json && node scripts/fix-esm-extensions.js && node scripts/create-esm-package.cjs",
@@ -56,6 +64,7 @@
56
64
  "better-sqlite3": "^12.3.0",
57
65
  "jest": "^29.7.0",
58
66
  "npm-run-all": "^4.1.5",
67
+ "pg": "^8.23.0",
59
68
  "rimraf": "^5.0.5",
60
69
  "ts-jest": "^29.2.5",
61
70
  "ts-node": "^10.9.2",
@@ -67,11 +76,11 @@
67
76
  "reflect-metadata": "^0.1.13"
68
77
  },
69
78
  "peerDependencies": {
70
- "sqlite": "^5.1.1",
71
- "better-sqlite3": "^9.6.0",
72
- "mysql2": "^3.14.4",
73
- "pg": "^8.16.3",
74
- "sqlite3": "^5.1.7"
79
+ "better-sqlite3": "*",
80
+ "mysql2": "*",
81
+ "pg": "*",
82
+ "sqlite": "*",
83
+ "sqlite3": "*"
75
84
  },
76
85
  "peerDependenciesMeta": {
77
86
  "better-sqlite3": {