sqlstack 1.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.
- package/dist/adapters/index.d.ts +4 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +10 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/mysql.d.ts +3 -0
- package/dist/adapters/mysql.d.ts.map +1 -0
- package/dist/adapters/mysql.js +21 -0
- package/dist/adapters/mysql.js.map +1 -0
- package/dist/adapters/pg.d.ts +3 -0
- package/dist/adapters/pg.d.ts.map +1 -0
- package/dist/adapters/pg.js +20 -0
- package/dist/adapters/pg.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +3 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +64 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/adapters/test.d.ts +3 -0
- package/dist/adapters/test.d.ts.map +1 -0
- package/dist/adapters/test.js +47 -0
- package/dist/adapters/test.js.map +1 -0
- package/dist/binders/sqlBinder.d.ts +14 -0
- package/dist/binders/sqlBinder.d.ts.map +1 -0
- package/dist/binders/sqlBinder.js +189 -0
- package/dist/binders/sqlBinder.js.map +1 -0
- package/dist/core/errors.d.ts +13 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +32 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/fileResolution.d.ts +11 -0
- package/dist/core/fileResolution.d.ts.map +1 -0
- package/dist/core/fileResolution.js +82 -0
- package/dist/core/fileResolution.js.map +1 -0
- package/dist/core/metadata.d.ts +26 -0
- package/dist/core/metadata.d.ts.map +1 -0
- package/dist/core/metadata.js +31 -0
- package/dist/core/metadata.js.map +1 -0
- package/dist/core/validator.d.ts +8 -0
- package/dist/core/validator.d.ts.map +1 -0
- package/dist/core/validator.js +66 -0
- package/dist/core/validator.js.map +1 -0
- package/dist/decorators/defaults.d.ts +2 -0
- package/dist/decorators/defaults.d.ts.map +1 -0
- package/dist/decorators/defaults.js +10 -0
- package/dist/decorators/defaults.js.map +1 -0
- package/dist/decorators/query.d.ts +8 -0
- package/dist/decorators/query.d.ts.map +1 -0
- package/dist/decorators/query.js +101 -0
- package/dist/decorators/query.js.map +1 -0
- package/dist/decorators/queryBinder.d.ts +4 -0
- package/dist/decorators/queryBinder.d.ts.map +1 -0
- package/dist/decorators/queryBinder.js +10 -0
- package/dist/decorators/queryBinder.js.map +1 -0
- package/dist/decorators/resultShape.d.ts +5 -0
- package/dist/decorators/resultShape.d.ts.map +1 -0
- package/dist/decorators/resultShape.js +20 -0
- package/dist/decorators/resultShape.js.map +1 -0
- package/dist/decorators/validateResult.d.ts +2 -0
- package/dist/decorators/validateResult.d.ts.map +1 -0
- package/dist/decorators/validateResult.js +11 -0
- package/dist/decorators/validateResult.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +16 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +29 -0
- package/dist/registry.js.map +1 -0
- package/package.json +86 -0
- package/readme.md +376 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveSqlFromFs = resolveSqlFromFs;
|
|
7
|
+
exports.coerceRootPath = coerceRootPath;
|
|
8
|
+
exports.guessDecoratorDir = guessDecoratorDir;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const DIALECT_EXT = {
|
|
12
|
+
postgres: 'pg',
|
|
13
|
+
mysql: 'mysql',
|
|
14
|
+
sqlite: 'sqlite',
|
|
15
|
+
};
|
|
16
|
+
const contentCache = new Map();
|
|
17
|
+
const pathCache = new Map();
|
|
18
|
+
function key(root, method, dialect) {
|
|
19
|
+
return `${root}::${method}::${dialect}`;
|
|
20
|
+
}
|
|
21
|
+
function resolveSqlFromFs(rootDir, methodName, dialect) {
|
|
22
|
+
const k = key(rootDir, methodName, dialect);
|
|
23
|
+
const tried = [];
|
|
24
|
+
const ext = DIALECT_EXT[dialect];
|
|
25
|
+
const dialectPath = path_1.default.join(rootDir, `${methodName}.${ext}.sql`);
|
|
26
|
+
const genericPath = path_1.default.join(rootDir, `${methodName}.sql`);
|
|
27
|
+
// Cached path
|
|
28
|
+
let chosen = pathCache.get(k);
|
|
29
|
+
if (!chosen) {
|
|
30
|
+
if (fs_1.default.existsSync(dialectPath)) {
|
|
31
|
+
chosen = dialectPath;
|
|
32
|
+
}
|
|
33
|
+
else if (fs_1.default.existsSync(genericPath)) {
|
|
34
|
+
chosen = genericPath;
|
|
35
|
+
}
|
|
36
|
+
if (chosen)
|
|
37
|
+
pathCache.set(k, chosen);
|
|
38
|
+
}
|
|
39
|
+
if (!chosen) {
|
|
40
|
+
tried.push(dialectPath, genericPath);
|
|
41
|
+
throw new Error(`sqlstack: SQL file not found for ${methodName}\ntried: ${tried.join(', ')}`);
|
|
42
|
+
}
|
|
43
|
+
// Cached content
|
|
44
|
+
let sql = contentCache.get(chosen);
|
|
45
|
+
if (!sql) {
|
|
46
|
+
sql = fs_1.default.readFileSync(chosen, 'utf8');
|
|
47
|
+
contentCache.set(chosen, sql);
|
|
48
|
+
}
|
|
49
|
+
return { sql, tried: [chosen] };
|
|
50
|
+
}
|
|
51
|
+
function coerceRootPath(input) {
|
|
52
|
+
if (!input)
|
|
53
|
+
return {};
|
|
54
|
+
const stat = fs_1.default.existsSync(input) ? fs_1.default.statSync(input) : undefined;
|
|
55
|
+
if (stat?.isDirectory())
|
|
56
|
+
return { rootDir: input, from: 'folder' };
|
|
57
|
+
if (stat?.isFile())
|
|
58
|
+
return { rootDir: path_1.default.dirname(input), from: 'file' };
|
|
59
|
+
// If not found, treat as folder hint anyway
|
|
60
|
+
return { rootDir: input, from: 'folder' };
|
|
61
|
+
}
|
|
62
|
+
function guessDecoratorDir() {
|
|
63
|
+
const err = new Error();
|
|
64
|
+
const stack = (err.stack || '').split('\n').slice(2);
|
|
65
|
+
for (const line of stack) {
|
|
66
|
+
const m = line.match(/\((.*?):\d+:\d+\)/) || line.match(/at (.*?):\d+:\d+/);
|
|
67
|
+
const file = m?.[1];
|
|
68
|
+
if (!file)
|
|
69
|
+
continue;
|
|
70
|
+
if (file.includes('node_modules'))
|
|
71
|
+
continue;
|
|
72
|
+
if (file.endsWith('.ts') || file.endsWith('.js')) {
|
|
73
|
+
try {
|
|
74
|
+
const dir = path_1.default.dirname(file);
|
|
75
|
+
return dir;
|
|
76
|
+
}
|
|
77
|
+
catch { }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=fileResolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileResolution.js","sourceRoot":"","sources":["../../src/core/fileResolution.ts"],"names":[],"mappings":";;;;;AAiBA,4CAgCC;AAED,wCAOC;AAED,8CAgBC;AA5ED,4CAAoB;AACpB,gDAAwB;AAGxB,MAAM,WAAW,GAA4B;IAC3C,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC/C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE5C,SAAS,GAAG,CAAC,IAAY,EAAE,MAAc,EAAE,OAAgB;IACzD,OAAO,GAAG,IAAI,KAAK,MAAM,KAAK,OAAO,EAAE,CAAC;AAC1C,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAe,EAAE,UAAkB,EAAE,OAAgB;IACpF,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,UAAU,IAAI,GAAG,MAAM,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,UAAU,MAAM,CAAC,CAAC;IAE5D,cAAc;IACd,IAAI,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,IAAI,YAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,WAAW,CAAC;QACvB,CAAC;aAAM,IAAI,YAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACtC,MAAM,GAAG,WAAW,CAAC;QACvB,CAAC;QACD,IAAI,MAAM;YAAE,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,oCAAoC,UAAU,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7E,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,IAAI,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;AAClC,CAAC;AAED,SAAgB,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,IAAI,GAAG,YAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,IAAI,IAAI,EAAE,WAAW,EAAE;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACnE,IAAI,IAAI,EAAE,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,EAAE,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1E,4CAA4C;IAC5C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5C,CAAC;AAED,SAAgB,iBAAiB;IAC/B,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC5E,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;YAAE,SAAS;QAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC/B,OAAO,GAAG,CAAC;YACb,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport type { Dialect } from '../registry';\n\nconst DIALECT_EXT: Record<Dialect, string> = {\n postgres: 'pg',\n mysql: 'mysql',\n sqlite: 'sqlite',\n};\n\nconst contentCache = new Map<string, string>();\nconst pathCache = new Map<string, string>();\n\nfunction key(root: string, method: string, dialect: Dialect): string {\n return `${root}::${method}::${dialect}`;\n}\n\nexport function resolveSqlFromFs(rootDir: string, methodName: string, dialect: Dialect): { sql: string; tried: string[] } {\n const k = key(rootDir, methodName, dialect);\n const tried: string[] = [];\n const ext = DIALECT_EXT[dialect];\n const dialectPath = path.join(rootDir, `${methodName}.${ext}.sql`);\n const genericPath = path.join(rootDir, `${methodName}.sql`);\n\n // Cached path\n let chosen = pathCache.get(k);\n if (!chosen) {\n if (fs.existsSync(dialectPath)) {\n chosen = dialectPath;\n } else if (fs.existsSync(genericPath)) {\n chosen = genericPath;\n }\n if (chosen) pathCache.set(k, chosen);\n }\n\n if (!chosen) {\n tried.push(dialectPath, genericPath);\n throw new Error(\n `sqlstack: SQL file not found for ${methodName}\\ntried: ${tried.join(', ')}`\n );\n }\n\n // Cached content\n let sql = contentCache.get(chosen);\n if (!sql) {\n sql = fs.readFileSync(chosen, 'utf8');\n contentCache.set(chosen, sql);\n }\n return { sql, tried: [chosen] };\n}\n\nexport function coerceRootPath(input?: string): { rootDir?: string; from?: 'file' | 'folder' } {\n if (!input) return {};\n const stat = fs.existsSync(input) ? fs.statSync(input) : undefined;\n if (stat?.isDirectory()) return { rootDir: input, from: 'folder' };\n if (stat?.isFile()) return { rootDir: path.dirname(input), from: 'file' };\n // If not found, treat as folder hint anyway\n return { rootDir: input, from: 'folder' };\n}\n\nexport function guessDecoratorDir(): string | undefined {\n const err = new Error();\n const stack = (err.stack || '').split('\\n').slice(2);\n for (const line of stack) {\n const m = line.match(/\\((.*?):\\d+:\\d+\\)/) || line.match(/at (.*?):\\d+:\\d+/);\n const file = m?.[1];\n if (!file) continue;\n if (file.includes('node_modules')) continue;\n if (file.endsWith('.ts') || file.endsWith('.js')) {\n try {\n const dir = path.dirname(file);\n return dir;\n } catch {}\n }\n }\n return undefined;\n}\n\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type MethodLabels = {
|
|
2
|
+
defaults?: Record<string, unknown>;
|
|
3
|
+
shape?: 'single' | 'only' | 'exist' | 'none';
|
|
4
|
+
validateSchema?: unknown;
|
|
5
|
+
source?: {
|
|
6
|
+
kind: 'inline';
|
|
7
|
+
sql: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'fs';
|
|
10
|
+
rootDir: string;
|
|
11
|
+
};
|
|
12
|
+
db?: string;
|
|
13
|
+
};
|
|
14
|
+
export type ClassLabels = {
|
|
15
|
+
db?: string;
|
|
16
|
+
};
|
|
17
|
+
export type MetaShape = {
|
|
18
|
+
class?: ClassLabels;
|
|
19
|
+
methods: Record<string | symbol, MethodLabels>;
|
|
20
|
+
};
|
|
21
|
+
export declare function getMeta(target: any): MetaShape;
|
|
22
|
+
export declare function setMethodLabels(target: any, prop: string | symbol, patch: Partial<MethodLabels>): void;
|
|
23
|
+
export declare function getMethodLabels(instance: any, prop: string | symbol): MethodLabels;
|
|
24
|
+
export declare function setClassLabels(ctor: any, patch: Partial<ClassLabels>): void;
|
|
25
|
+
export declare function getClassLabels(instance: any): ClassLabels | undefined;
|
|
26
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/core/metadata.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,YAAY,CAAC,CAAC;CAChD,CAAC;AAEF,wBAAgB,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,CAK9C;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,QAG/F;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,CAGlF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,QAGpE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,WAAW,GAAG,SAAS,CAGrE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMeta = getMeta;
|
|
4
|
+
exports.setMethodLabels = setMethodLabels;
|
|
5
|
+
exports.getMethodLabels = getMethodLabels;
|
|
6
|
+
exports.setClassLabels = setClassLabels;
|
|
7
|
+
exports.getClassLabels = getClassLabels;
|
|
8
|
+
const META = Symbol.for('sqlstack:meta');
|
|
9
|
+
function getMeta(target) {
|
|
10
|
+
if (!target[META]) {
|
|
11
|
+
target[META] = { methods: {} };
|
|
12
|
+
}
|
|
13
|
+
return target[META];
|
|
14
|
+
}
|
|
15
|
+
function setMethodLabels(target, prop, patch) {
|
|
16
|
+
const meta = getMeta(target);
|
|
17
|
+
meta.methods[prop] = { ...(meta.methods[prop] || {}), ...patch };
|
|
18
|
+
}
|
|
19
|
+
function getMethodLabels(instance, prop) {
|
|
20
|
+
const meta = getMeta(Object.getPrototypeOf(instance));
|
|
21
|
+
return meta.methods[prop] || {};
|
|
22
|
+
}
|
|
23
|
+
function setClassLabels(ctor, patch) {
|
|
24
|
+
const meta = getMeta(ctor.prototype);
|
|
25
|
+
meta.class = { ...(meta.class || {}), ...patch };
|
|
26
|
+
}
|
|
27
|
+
function getClassLabels(instance) {
|
|
28
|
+
const meta = getMeta(Object.getPrototypeOf(instance));
|
|
29
|
+
return meta.class;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/core/metadata.ts"],"names":[],"mappings":";;AAmBA,0BAKC;AAED,0CAGC;AAED,0CAGC;AAED,wCAGC;AAED,wCAGC;AA5CD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AAmBzC,SAAgB,OAAO,CAAC,MAAW;IACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAe,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAgB,eAAe,CAAC,MAAW,EAAE,IAAqB,EAAE,KAA4B;IAC9F,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;AACnE,CAAC;AAED,SAAgB,eAAe,CAAC,QAAa,EAAE,IAAqB;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC;AAED,SAAgB,cAAc,CAAC,IAAS,EAAE,KAA2B;IACnE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;AACnD,CAAC;AAED,SAAgB,cAAc,CAAC,QAAa;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,KAAK,CAAC;AACpB,CAAC","sourcesContent":["const META = Symbol.for('sqlstack:meta');\n\nexport type MethodLabels = {\n defaults?: Record<string, unknown>;\n shape?: 'single' | 'only' | 'exist' | 'none';\n validateSchema?: unknown;\n source?: { kind: 'inline'; sql: string } | { kind: 'fs'; rootDir: string };\n db?: string;\n};\n\nexport type ClassLabels = {\n db?: string;\n};\n\nexport type MetaShape = {\n class?: ClassLabels;\n methods: Record<string | symbol, MethodLabels>;\n};\n\nexport function getMeta(target: any): MetaShape {\n if (!target[META]) {\n target[META] = { methods: {} } as MetaShape;\n }\n return target[META];\n}\n\nexport function setMethodLabels(target: any, prop: string | symbol, patch: Partial<MethodLabels>) {\n const meta = getMeta(target);\n meta.methods[prop] = { ...(meta.methods[prop] || {}), ...patch };\n}\n\nexport function getMethodLabels(instance: any, prop: string | symbol): MethodLabels {\n const meta = getMeta(Object.getPrototypeOf(instance));\n return meta.methods[prop] || {};\n}\n\nexport function setClassLabels(ctor: any, patch: Partial<ClassLabels>) {\n const meta = getMeta(ctor.prototype);\n meta.class = { ...(meta.class || {}), ...patch };\n}\n\nexport function getClassLabels(instance: any): ClassLabels | undefined {\n const meta = getMeta(Object.getPrototypeOf(instance));\n return meta.class;\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SqlStackError } from './errors';
|
|
2
|
+
export declare class ValidationError extends SqlStackError {
|
|
3
|
+
details: string;
|
|
4
|
+
constructor(details: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function validateOutput(schema: any, data: any): void;
|
|
7
|
+
export declare function isValidationDisabled(): boolean;
|
|
8
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,qBAAa,eAAgB,SAAQ,aAAa;IAC7B,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;CAInC;AAkBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,QAOpD;AAgBD,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ValidationError = void 0;
|
|
7
|
+
exports.validateOutput = validateOutput;
|
|
8
|
+
exports.isValidationDisabled = isValidationDisabled;
|
|
9
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
10
|
+
const ajv_formats_1 = __importDefault(require("ajv-formats"));
|
|
11
|
+
const errors_1 = require("./errors");
|
|
12
|
+
class ValidationError extends errors_1.SqlStackError {
|
|
13
|
+
constructor(details) {
|
|
14
|
+
super(`Validation failed: ${details}`);
|
|
15
|
+
this.details = details;
|
|
16
|
+
this.name = 'ValidationError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.ValidationError = ValidationError;
|
|
20
|
+
const ajv = new ajv_1.default({ allErrors: true, strict: false });
|
|
21
|
+
(0, ajv_formats_1.default)(ajv);
|
|
22
|
+
const cache = new WeakMap();
|
|
23
|
+
function getValidator(schema) {
|
|
24
|
+
if (schema && typeof schema === 'object') {
|
|
25
|
+
const existing = cache.get(schema);
|
|
26
|
+
if (existing)
|
|
27
|
+
return existing;
|
|
28
|
+
const compiled = ajv.compile(schema);
|
|
29
|
+
cache.set(schema, compiled);
|
|
30
|
+
return compiled;
|
|
31
|
+
}
|
|
32
|
+
throw new ValidationError('Invalid schema');
|
|
33
|
+
}
|
|
34
|
+
function validateOutput(schema, data) {
|
|
35
|
+
const validate = getValidator(schema);
|
|
36
|
+
const ok = validate(data);
|
|
37
|
+
if (!ok) {
|
|
38
|
+
const msg = ajv.errorsText(validate.errors, { dataVar: 'result' });
|
|
39
|
+
throw new ValidationError(msg);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function isTruthyEnv(value) {
|
|
43
|
+
if (!value)
|
|
44
|
+
return false;
|
|
45
|
+
switch (value.toLowerCase()) {
|
|
46
|
+
case '1':
|
|
47
|
+
case 'true':
|
|
48
|
+
case 'yes':
|
|
49
|
+
case 'on':
|
|
50
|
+
return true;
|
|
51
|
+
default:
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// SQLSTACK_DISABLE_VALIDATION: when truthy, validation is skipped.
|
|
56
|
+
function isValidationDisabled() {
|
|
57
|
+
// Highest priority: explicit enable wins (even in production)
|
|
58
|
+
if (isTruthyEnv(process.env.SQLSTACK_ENABLE_VALIDATION))
|
|
59
|
+
return false;
|
|
60
|
+
// Next: explicit disable
|
|
61
|
+
if (isTruthyEnv(process.env.SQLSTACK_DISABLE_VALIDATION))
|
|
62
|
+
return true;
|
|
63
|
+
// Default: enabled in all environments
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":";;;;;;AA2BA,wCAOC;AAgBD,oDAOC;AAzDD,8CAAwC;AACxC,8DAAqC;AACrC,qCAAyC;AAEzC,MAAa,eAAgB,SAAQ,sBAAa;IAChD,YAAmB,OAAe;QAChC,KAAK,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAC;QADtB,YAAO,GAAP,OAAO,CAAQ;QAEhC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AALD,0CAKC;AAED,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AACxD,IAAA,qBAAU,EAAC,GAAG,CAAC,CAAC;AAEhB,MAAM,KAAK,GAAG,IAAI,OAAO,EAAsC,CAAC;AAEhE,SAAS,YAAY,CAAC,MAAW;IAC/B,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,MAAgB,CAAC,CAAC;QAC7C,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,CAAC,GAAG,CAAC,MAAgB,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,eAAe,CAAC,gBAAgB,CAAC,CAAC;AAC9C,CAAC;AAED,SAAgB,cAAc,CAAC,MAAW,EAAE,IAAS;IACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,MAA+B,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5F,MAAM,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAyB;IAC5C,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,QAAQ,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5B,KAAK,GAAG,CAAC;QACT,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK,CAAC;QACX,KAAK,IAAI;YACP,OAAO,IAAI,CAAC;QACd;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,SAAgB,oBAAoB;IAClC,8DAA8D;IAC9D,IAAI,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,yBAAyB;IACzB,IAAI,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,uCAAuC;IACvC,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import Ajv, { DefinedError } from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { SqlStackError } from './errors';\n\nexport class ValidationError extends SqlStackError {\n constructor(public details: string) {\n super(`Validation failed: ${details}`);\n this.name = 'ValidationError';\n }\n}\n\nconst ajv = new Ajv({ allErrors: true, strict: false });\naddFormats(ajv);\n\nconst cache = new WeakMap<object, ReturnType<Ajv['compile']>>();\n\nfunction getValidator(schema: any) {\n if (schema && typeof schema === 'object') {\n const existing = cache.get(schema as object);\n if (existing) return existing;\n const compiled = ajv.compile(schema);\n cache.set(schema as object, compiled);\n return compiled;\n }\n throw new ValidationError('Invalid schema');\n}\n\nexport function validateOutput(schema: any, data: any) {\n const validate = getValidator(schema);\n const ok = validate(data);\n if (!ok) {\n const msg = ajv.errorsText(validate.errors as DefinedError[] | null, { dataVar: 'result' });\n throw new ValidationError(msg);\n }\n}\n\nfunction isTruthyEnv(value: string | undefined): boolean {\n if (!value) return false;\n switch (value.toLowerCase()) {\n case '1':\n case 'true':\n case 'yes':\n case 'on':\n return true;\n default:\n return false;\n }\n}\n\n// SQLSTACK_DISABLE_VALIDATION: when truthy, validation is skipped.\nexport function isValidationDisabled(): boolean {\n // Highest priority: explicit enable wins (even in production)\n if (isTruthyEnv(process.env.SQLSTACK_ENABLE_VALIDATION)) return false;\n // Next: explicit disable\n if (isTruthyEnv(process.env.SQLSTACK_DISABLE_VALIDATION)) return true;\n // Default: enabled in all environments\n return false;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/decorators/defaults.ts"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACrC,SAAS,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,UAGrD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Defaults = Defaults;
|
|
4
|
+
const metadata_1 = require("../core/metadata");
|
|
5
|
+
function Defaults(values) {
|
|
6
|
+
return function (_target, prop) {
|
|
7
|
+
(0, metadata_1.setMethodLabels)(_target, prop, { defaults: { ...(values || {}) } });
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/decorators/defaults.ts"],"names":[],"mappings":";;AAEA,4BAIC;AAND,+CAAmD;AAEnD,SAAgB,QAAQ,CAAC,MAA+B;IACtD,OAAO,UAAU,OAAY,EAAE,IAAqB;QAClD,IAAA,0BAAe,EAAC,OAAO,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { setMethodLabels } from '../core/metadata';\n\nexport function Defaults(values: Record<string, unknown>) {\n return function (_target: any, prop: string | symbol) {\n setMethodLabels(_target, prop, { defaults: { ...(values || {}) } });\n };\n}\n\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type QueryOptions = {
|
|
2
|
+
sql?: string;
|
|
3
|
+
db?: string;
|
|
4
|
+
dialect?: 'sqlite' | 'mysql' | 'postgres';
|
|
5
|
+
};
|
|
6
|
+
export declare function Query(arg?: string | QueryOptions): (_target: any, prop: string | symbol, desc: PropertyDescriptor) => PropertyDescriptor;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/decorators/query.ts"],"names":[],"mappings":"AAOA,KAAK,YAAY,GAAG;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;CAC3C,CAAC;AAEF,wBAAgB,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY,IAC9B,SAAS,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,kBAAkB,wBAsE/E"}
|
|
@@ -0,0 +1,101 @@
|
|
|
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 rows = await db.query(boundSql, params);
|
|
57
|
+
// 6) shape result
|
|
58
|
+
const shaped = applyShape(rows, labels.shape);
|
|
59
|
+
// 7) validate result via JSON Schema, if provided
|
|
60
|
+
if (labels.validateSchema && !(0, validator_1.isValidationDisabled)()) {
|
|
61
|
+
if (Array.isArray(shaped)) {
|
|
62
|
+
for (const row of shaped)
|
|
63
|
+
(0, validator_1.validateOutput)(labels.validateSchema, row);
|
|
64
|
+
}
|
|
65
|
+
else if (shaped !== null && shaped !== undefined) {
|
|
66
|
+
(0, validator_1.validateOutput)(labels.validateSchema, shaped);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return shaped;
|
|
70
|
+
};
|
|
71
|
+
return desc;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function applyDefaults(defaults, input) {
|
|
75
|
+
if (!defaults)
|
|
76
|
+
return input;
|
|
77
|
+
if (Array.isArray(input))
|
|
78
|
+
return input; // defaults only apply to named-object args
|
|
79
|
+
return { ...defaults, ...(input || {}) };
|
|
80
|
+
}
|
|
81
|
+
function applyShape(rows, shape) {
|
|
82
|
+
switch (shape) {
|
|
83
|
+
case 'single':
|
|
84
|
+
return rows.length > 0 ? rows[0] : null;
|
|
85
|
+
case 'only':
|
|
86
|
+
if (rows.length !== 1)
|
|
87
|
+
throw new errors_1.ExactlyOneRowError(rows.length);
|
|
88
|
+
return rows[0];
|
|
89
|
+
case 'exist':
|
|
90
|
+
if (rows.length < 1)
|
|
91
|
+
throw new errors_1.NoRowsError();
|
|
92
|
+
return rows[0];
|
|
93
|
+
case 'none':
|
|
94
|
+
if (rows.length > 0)
|
|
95
|
+
throw new errors_1.RowsExistError(rows.length);
|
|
96
|
+
return null;
|
|
97
|
+
default:
|
|
98
|
+
return rows;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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 rows = await db.query(boundSql, params);\n\n // 6) shape result\n const shaped = applyShape(rows, labels.shape);\n\n // 7) validate result via JSON Schema, if provided\n if (labels.validateSchema && !isValidationDisabled()) {\n if (Array.isArray(shaped)) {\n for (const row of shaped) validateOutput(labels.validateSchema, row);\n } else if (shaped !== null && shaped !== undefined) {\n validateOutput(labels.validateSchema, shaped);\n }\n }\n\n return shaped;\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"]}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryBinder = QueryBinder;
|
|
4
|
+
const metadata_1 = require("../core/metadata");
|
|
5
|
+
function QueryBinder(options) {
|
|
6
|
+
return function (ctor) {
|
|
7
|
+
(0, metadata_1.setClassLabels)(ctor, { db: options?.db });
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=queryBinder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function Single(target: any, prop: string | symbol): void;
|
|
2
|
+
export declare function Only(target: any, prop: string | symbol): void;
|
|
3
|
+
export declare function Exist(target: any, prop: string | symbol): void;
|
|
4
|
+
export declare function None(target: any, prop: string | symbol): void;
|
|
5
|
+
//# sourceMappingURL=resultShape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Single = Single;
|
|
4
|
+
exports.Only = Only;
|
|
5
|
+
exports.Exist = Exist;
|
|
6
|
+
exports.None = None;
|
|
7
|
+
const metadata_1 = require("../core/metadata");
|
|
8
|
+
function Single(target, prop) {
|
|
9
|
+
(0, metadata_1.setMethodLabels)(target, prop, { shape: 'single' });
|
|
10
|
+
}
|
|
11
|
+
function Only(target, prop) {
|
|
12
|
+
(0, metadata_1.setMethodLabels)(target, prop, { shape: 'only' });
|
|
13
|
+
}
|
|
14
|
+
function Exist(target, prop) {
|
|
15
|
+
(0, metadata_1.setMethodLabels)(target, prop, { shape: 'exist' });
|
|
16
|
+
}
|
|
17
|
+
function None(target, prop) {
|
|
18
|
+
(0, metadata_1.setMethodLabels)(target, prop, { shape: 'none' });
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=resultShape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"]}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValidateResult = ValidateResult;
|
|
4
|
+
const metadata_1 = require("../core/metadata");
|
|
5
|
+
// Accept a JSON Schema directly
|
|
6
|
+
function ValidateResult(schema) {
|
|
7
|
+
return function (target, prop) {
|
|
8
|
+
(0, metadata_1.setMethodLabels)(target, prop, { validateSchema: schema });
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=validateResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './binders/sqlBinder';
|
|
2
|
+
export * from './core/errors';
|
|
3
|
+
export * from './core/validator';
|
|
4
|
+
export * from './registry';
|
|
5
|
+
export * from './adapters';
|
|
6
|
+
export * from './decorators/queryBinder';
|
|
7
|
+
export * from './decorators/query';
|
|
8
|
+
export * from './decorators/defaults';
|
|
9
|
+
export * from './decorators/resultShape';
|
|
10
|
+
export * from './decorators/validateResult';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./binders/sqlBinder"), exports);
|
|
18
|
+
__exportStar(require("./core/errors"), exports);
|
|
19
|
+
__exportStar(require("./core/validator"), exports);
|
|
20
|
+
__exportStar(require("./registry"), exports);
|
|
21
|
+
__exportStar(require("./adapters"), exports);
|
|
22
|
+
__exportStar(require("./decorators/queryBinder"), exports);
|
|
23
|
+
__exportStar(require("./decorators/query"), exports);
|
|
24
|
+
__exportStar(require("./decorators/defaults"), exports);
|
|
25
|
+
__exportStar(require("./decorators/resultShape"), exports);
|
|
26
|
+
__exportStar(require("./decorators/validateResult"), exports);
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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","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';\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type Dialect = 'sqlite' | 'mysql' | 'postgres';
|
|
2
|
+
export interface Database {
|
|
3
|
+
dialect: Dialect;
|
|
4
|
+
query(sql: string, params: unknown[]): Promise<any[]>;
|
|
5
|
+
close?: () => Promise<void> | void;
|
|
6
|
+
}
|
|
7
|
+
declare class Registry {
|
|
8
|
+
private map;
|
|
9
|
+
private defaultName?;
|
|
10
|
+
register(name: string, db: Database): this;
|
|
11
|
+
setDefault(name: string): this;
|
|
12
|
+
get(name?: string): Database;
|
|
13
|
+
}
|
|
14
|
+
export declare const SqlStackDB: Registry;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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;AAEtD,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpC;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"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqlStackDB = void 0;
|
|
4
|
+
class Registry {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.map = new Map();
|
|
7
|
+
}
|
|
8
|
+
register(name, db) {
|
|
9
|
+
this.map.set(name, db);
|
|
10
|
+
return this;
|
|
11
|
+
}
|
|
12
|
+
setDefault(name) {
|
|
13
|
+
if (!this.map.has(name))
|
|
14
|
+
throw new Error(`No database registered under ${name}`);
|
|
15
|
+
this.defaultName = name;
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
get(name) {
|
|
19
|
+
const key = name ?? this.defaultName;
|
|
20
|
+
if (!key)
|
|
21
|
+
throw new Error('No default database set');
|
|
22
|
+
const db = this.map.get(key);
|
|
23
|
+
if (!db)
|
|
24
|
+
throw new Error(`No database registered under ${key}`);
|
|
25
|
+
return db;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.SqlStackDB = new Registry();
|
|
29
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":";;;AAQA,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\nexport interface Database {\n dialect: Dialect;\n query(sql: string, params: unknown[]): Promise<any[]>;\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"]}
|