@tablecraft/engine 0.1.0-beta.1
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/src/__tests__/inputValidator.test.d.ts +2 -0
- package/dist/src/__tests__/inputValidator.test.d.ts.map +1 -0
- package/dist/src/__tests__/inputValidator.test.js +205 -0
- package/dist/src/__tests__/inputValidator.test.js.map +1 -0
- package/dist/src/__tests__/metadataBuilder.test.d.ts +2 -0
- package/dist/src/__tests__/metadataBuilder.test.d.ts.map +1 -0
- package/dist/src/__tests__/metadataBuilder.test.js +221 -0
- package/dist/src/__tests__/metadataBuilder.test.js.map +1 -0
- package/dist/src/core/aggregationBuilder.d.ts +17 -0
- package/dist/src/core/aggregationBuilder.d.ts.map +1 -0
- package/dist/src/core/aggregationBuilder.js +81 -0
- package/dist/src/core/aggregationBuilder.js.map +1 -0
- package/dist/src/core/cursorPagination.d.ts +36 -0
- package/dist/src/core/cursorPagination.d.ts.map +1 -0
- package/dist/src/core/cursorPagination.js +88 -0
- package/dist/src/core/cursorPagination.js.map +1 -0
- package/dist/src/core/datePresets.d.ts +19 -0
- package/dist/src/core/datePresets.d.ts.map +1 -0
- package/dist/src/core/datePresets.js +96 -0
- package/dist/src/core/datePresets.js.map +1 -0
- package/dist/src/core/dialect.d.ts +17 -0
- package/dist/src/core/dialect.d.ts.map +1 -0
- package/dist/src/core/dialect.js +60 -0
- package/dist/src/core/dialect.js.map +1 -0
- package/dist/src/core/fieldSelector.d.ts +19 -0
- package/dist/src/core/fieldSelector.d.ts.map +1 -0
- package/dist/src/core/fieldSelector.js +49 -0
- package/dist/src/core/fieldSelector.js.map +1 -0
- package/dist/src/core/filterBuilder.d.ts +22 -0
- package/dist/src/core/filterBuilder.d.ts.map +1 -0
- package/dist/src/core/filterBuilder.js +112 -0
- package/dist/src/core/filterBuilder.js.map +1 -0
- package/dist/src/core/filterGroupBuilder.d.ts +28 -0
- package/dist/src/core/filterGroupBuilder.d.ts.map +1 -0
- package/dist/src/core/filterGroupBuilder.js +73 -0
- package/dist/src/core/filterGroupBuilder.js.map +1 -0
- package/dist/src/core/groupByBuilder.d.ts +23 -0
- package/dist/src/core/groupByBuilder.d.ts.map +1 -0
- package/dist/src/core/groupByBuilder.js +127 -0
- package/dist/src/core/groupByBuilder.js.map +1 -0
- package/dist/src/core/inputValidator.d.ts +8 -0
- package/dist/src/core/inputValidator.d.ts.map +1 -0
- package/dist/src/core/inputValidator.js +117 -0
- package/dist/src/core/inputValidator.js.map +1 -0
- package/dist/src/core/metadataBuilder.d.ts +91 -0
- package/dist/src/core/metadataBuilder.d.ts.map +1 -0
- package/dist/src/core/metadataBuilder.js +220 -0
- package/dist/src/core/metadataBuilder.js.map +1 -0
- package/dist/src/core/paginationBuilder.d.ts +20 -0
- package/dist/src/core/paginationBuilder.d.ts.map +1 -0
- package/dist/src/core/paginationBuilder.js +42 -0
- package/dist/src/core/paginationBuilder.js.map +1 -0
- package/dist/src/core/queryBuilder.d.ts +20 -0
- package/dist/src/core/queryBuilder.d.ts.map +1 -0
- package/dist/src/core/queryBuilder.js +163 -0
- package/dist/src/core/queryBuilder.js.map +1 -0
- package/dist/src/core/recursiveBuilder.d.ts +25 -0
- package/dist/src/core/recursiveBuilder.d.ts.map +1 -0
- package/dist/src/core/recursiveBuilder.js +86 -0
- package/dist/src/core/recursiveBuilder.js.map +1 -0
- package/dist/src/core/relationBuilder.d.ts +19 -0
- package/dist/src/core/relationBuilder.d.ts.map +1 -0
- package/dist/src/core/relationBuilder.js +118 -0
- package/dist/src/core/relationBuilder.js.map +1 -0
- package/dist/src/core/roleFilter.d.ts +11 -0
- package/dist/src/core/roleFilter.d.ts.map +1 -0
- package/dist/src/core/roleFilter.js +24 -0
- package/dist/src/core/roleFilter.js.map +1 -0
- package/dist/src/core/searchBuilder.d.ts +17 -0
- package/dist/src/core/searchBuilder.d.ts.map +1 -0
- package/dist/src/core/searchBuilder.js +71 -0
- package/dist/src/core/searchBuilder.js.map +1 -0
- package/dist/src/core/softDelete.d.ts +12 -0
- package/dist/src/core/softDelete.d.ts.map +1 -0
- package/dist/src/core/softDelete.js +29 -0
- package/dist/src/core/softDelete.js.map +1 -0
- package/dist/src/core/sortBuilder.d.ts +14 -0
- package/dist/src/core/sortBuilder.d.ts.map +1 -0
- package/dist/src/core/sortBuilder.js +58 -0
- package/dist/src/core/sortBuilder.js.map +1 -0
- package/dist/src/core/subqueryBuilder.d.ts +13 -0
- package/dist/src/core/subqueryBuilder.d.ts.map +1 -0
- package/dist/src/core/subqueryBuilder.js +47 -0
- package/dist/src/core/subqueryBuilder.js.map +1 -0
- package/dist/src/core/validator.d.ts +18 -0
- package/dist/src/core/validator.d.ts.map +1 -0
- package/dist/src/core/validator.js +88 -0
- package/dist/src/core/validator.js.map +1 -0
- package/dist/src/define.d.ts +274 -0
- package/dist/src/define.d.ts.map +1 -0
- package/dist/src/define.js +690 -0
- package/dist/src/define.js.map +1 -0
- package/dist/src/engine.d.ts +17 -0
- package/dist/src/engine.d.ts.map +1 -0
- package/dist/src/engine.js +429 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/errors.d.ts +53 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +80 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +37 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +41 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/types/engine.d.ts +92 -0
- package/dist/src/types/engine.d.ts.map +1 -0
- package/dist/src/types/engine.js +2 -0
- package/dist/src/types/engine.js.map +1 -0
- package/dist/src/types/table.d.ts +867 -0
- package/dist/src/types/table.d.ts.map +1 -0
- package/dist/src/types/table.js +198 -0
- package/dist/src/types/table.js.map +1 -0
- package/dist/src/utils/adapterUtils.d.ts +16 -0
- package/dist/src/utils/adapterUtils.d.ts.map +1 -0
- package/dist/src/utils/adapterUtils.js +28 -0
- package/dist/src/utils/adapterUtils.js.map +1 -0
- package/dist/src/utils/codegen.d.ts +7 -0
- package/dist/src/utils/codegen.d.ts.map +1 -0
- package/dist/src/utils/codegen.js +126 -0
- package/dist/src/utils/codegen.js.map +1 -0
- package/dist/src/utils/export.d.ts +15 -0
- package/dist/src/utils/export.d.ts.map +1 -0
- package/dist/src/utils/export.js +42 -0
- package/dist/src/utils/export.js.map +1 -0
- package/dist/src/utils/introspect.d.ts +32 -0
- package/dist/src/utils/introspect.d.ts.map +1 -0
- package/dist/src/utils/introspect.js +174 -0
- package/dist/src/utils/introspect.js.map +1 -0
- package/dist/src/utils/openapi.d.ts +6 -0
- package/dist/src/utils/openapi.d.ts.map +1 -0
- package/dist/src/utils/openapi.js +138 -0
- package/dist/src/utils/openapi.js.map +1 -0
- package/dist/src/utils/operators.d.ts +8 -0
- package/dist/src/utils/operators.d.ts.map +1 -0
- package/dist/src/utils/operators.js +70 -0
- package/dist/src/utils/operators.js.map +1 -0
- package/dist/src/utils/requestParser.d.ts +18 -0
- package/dist/src/utils/requestParser.d.ts.map +1 -0
- package/dist/src/utils/requestParser.js +126 -0
- package/dist/src/utils/requestParser.js.map +1 -0
- package/dist/src/utils/responseFormatter.d.ts +12 -0
- package/dist/src/utils/responseFormatter.d.ts.map +1 -0
- package/dist/src/utils/responseFormatter.js +106 -0
- package/dist/src/utils/responseFormatter.js.map +1 -0
- package/dist/src/utils/typedSql.d.ts +70 -0
- package/dist/src/utils/typedSql.d.ts.map +1 -0
- package/dist/src/utils/typedSql.js +102 -0
- package/dist/src/utils/typedSql.js.map +1 -0
- package/dist/test/columnMeta.test.d.ts +2 -0
- package/dist/test/columnMeta.test.d.ts.map +1 -0
- package/dist/test/columnMeta.test.js +92 -0
- package/dist/test/columnMeta.test.js.map +1 -0
- package/dist/test/core/aggregationBuilder.test.d.ts +2 -0
- package/dist/test/core/aggregationBuilder.test.d.ts.map +1 -0
- package/dist/test/core/aggregationBuilder.test.js +64 -0
- package/dist/test/core/aggregationBuilder.test.js.map +1 -0
- package/dist/test/core/filterBuilder.test.d.ts +2 -0
- package/dist/test/core/filterBuilder.test.d.ts.map +1 -0
- package/dist/test/core/filterBuilder.test.js +80 -0
- package/dist/test/core/filterBuilder.test.js.map +1 -0
- package/dist/test/core/paginationBuilder.test.d.ts +2 -0
- package/dist/test/core/paginationBuilder.test.d.ts.map +1 -0
- package/dist/test/core/paginationBuilder.test.js +63 -0
- package/dist/test/core/paginationBuilder.test.js.map +1 -0
- package/dist/test/core/queryBuilder.test.d.ts +2 -0
- package/dist/test/core/queryBuilder.test.d.ts.map +1 -0
- package/dist/test/core/queryBuilder.test.js +92 -0
- package/dist/test/core/queryBuilder.test.js.map +1 -0
- package/dist/test/core/searchBuilder.test.d.ts +2 -0
- package/dist/test/core/searchBuilder.test.d.ts.map +1 -0
- package/dist/test/core/searchBuilder.test.js +68 -0
- package/dist/test/core/searchBuilder.test.js.map +1 -0
- package/dist/test/core/softDelete.test.d.ts +2 -0
- package/dist/test/core/softDelete.test.d.ts.map +1 -0
- package/dist/test/core/softDelete.test.js +60 -0
- package/dist/test/core/softDelete.test.js.map +1 -0
- package/dist/test/core/sortBuilder.test.d.ts +2 -0
- package/dist/test/core/sortBuilder.test.d.ts.map +1 -0
- package/dist/test/core/sortBuilder.test.js +59 -0
- package/dist/test/core/sortBuilder.test.js.map +1 -0
- package/dist/test/core/subqueryBuilder.test.d.ts +2 -0
- package/dist/test/core/subqueryBuilder.test.d.ts.map +1 -0
- package/dist/test/core/subqueryBuilder.test.js +48 -0
- package/dist/test/core/subqueryBuilder.test.js.map +1 -0
- package/dist/test/core/validator.test.d.ts +2 -0
- package/dist/test/core/validator.test.d.ts.map +1 -0
- package/dist/test/core/validator.test.js +81 -0
- package/dist/test/core/validator.test.js.map +1 -0
- package/dist/test/datePresets.test.d.ts +2 -0
- package/dist/test/datePresets.test.d.ts.map +1 -0
- package/dist/test/datePresets.test.js +57 -0
- package/dist/test/datePresets.test.js.map +1 -0
- package/dist/test/errors.test.d.ts +2 -0
- package/dist/test/errors.test.d.ts.map +1 -0
- package/dist/test/errors.test.js +62 -0
- package/dist/test/errors.test.js.map +1 -0
- package/dist/test/inputValidator.test.d.ts +2 -0
- package/dist/test/inputValidator.test.d.ts.map +1 -0
- package/dist/test/inputValidator.test.js +60 -0
- package/dist/test/inputValidator.test.js.map +1 -0
- package/dist/test/metadata.test.d.ts +2 -0
- package/dist/test/metadata.test.d.ts.map +1 -0
- package/dist/test/metadata.test.js +285 -0
- package/dist/test/metadata.test.js.map +1 -0
- package/dist/test/metadataComplete.test.d.ts +2 -0
- package/dist/test/metadataComplete.test.d.ts.map +1 -0
- package/dist/test/metadataComplete.test.js +113 -0
- package/dist/test/metadataComplete.test.js.map +1 -0
- package/dist/test/roleFilter.test.d.ts +2 -0
- package/dist/test/roleFilter.test.d.ts.map +1 -0
- package/dist/test/roleFilter.test.js +53 -0
- package/dist/test/roleFilter.test.js.map +1 -0
- package/dist/test/typedSql.test.d.ts +2 -0
- package/dist/test/typedSql.test.d.ts.map +1 -0
- package/dist/test/typedSql.test.js +63 -0
- package/dist/test/typedSql.test.js.map +1 -0
- package/dist/test/utils/codegen.test.d.ts +2 -0
- package/dist/test/utils/codegen.test.d.ts.map +1 -0
- package/dist/test/utils/codegen.test.js +65 -0
- package/dist/test/utils/codegen.test.js.map +1 -0
- package/dist/test/utils/export.test.d.ts +2 -0
- package/dist/test/utils/export.test.d.ts.map +1 -0
- package/dist/test/utils/export.test.js +54 -0
- package/dist/test/utils/export.test.js.map +1 -0
- package/dist/test/utils/openapi.test.d.ts +2 -0
- package/dist/test/utils/openapi.test.d.ts.map +1 -0
- package/dist/test/utils/openapi.test.js +65 -0
- package/dist/test/utils/openapi.test.js.map +1 -0
- package/dist/test/utils/requestParser.test.d.ts +2 -0
- package/dist/test/utils/requestParser.test.d.ts.map +1 -0
- package/dist/test/utils/requestParser.test.js +89 -0
- package/dist/test/utils/requestParser.test.js.map +1 -0
- package/dist/test/utils/responseFormatter.test.d.ts +2 -0
- package/dist/test/utils/responseFormatter.test.d.ts.map +1 -0
- package/dist/test/utils/responseFormatter.test.js +79 -0
- package/dist/test/utils/responseFormatter.test.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// ---- Built-in JS transforms ----
|
|
2
|
+
const builtInTransforms = {
|
|
3
|
+
uppercase: (v) => (typeof v === 'string' ? v.toUpperCase() : v),
|
|
4
|
+
lowercase: (v) => (typeof v === 'string' ? v.toLowerCase() : v),
|
|
5
|
+
trim: (v) => (typeof v === 'string' ? v.trim() : v),
|
|
6
|
+
toString: (v) => (v == null ? '' : String(v)),
|
|
7
|
+
toNumber: (v) => (v == null ? 0 : Number(v)),
|
|
8
|
+
toBoolean: (v) => Boolean(v),
|
|
9
|
+
formatDate: (v) => {
|
|
10
|
+
if (v instanceof Date)
|
|
11
|
+
return v.toISOString();
|
|
12
|
+
if (typeof v === 'string' || typeof v === 'number') {
|
|
13
|
+
const d = new Date(v);
|
|
14
|
+
return Number.isNaN(d.getTime()) ? v : d.toISOString();
|
|
15
|
+
}
|
|
16
|
+
return v;
|
|
17
|
+
},
|
|
18
|
+
formatCurrency: (v) => {
|
|
19
|
+
if (typeof v === 'number') {
|
|
20
|
+
return new Intl.NumberFormat('en-US', {
|
|
21
|
+
style: 'currency',
|
|
22
|
+
currency: 'USD',
|
|
23
|
+
}).format(v);
|
|
24
|
+
}
|
|
25
|
+
return v;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A registry so consumers can add custom JS transforms.
|
|
30
|
+
*/
|
|
31
|
+
const customTransforms = new Map();
|
|
32
|
+
export function registerTransform(name, fn) {
|
|
33
|
+
customTransforms.set(name, fn);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Applies all jsTransform functions defined on each column config to the data rows.
|
|
37
|
+
*/
|
|
38
|
+
export function applyJsTransforms(data, config) {
|
|
39
|
+
// Index columns that have jsTransform
|
|
40
|
+
const transformMap = new Map();
|
|
41
|
+
for (const col of config.columns) {
|
|
42
|
+
if (!col.jsTransform || col.jsTransform.length === 0)
|
|
43
|
+
continue;
|
|
44
|
+
const fns = [];
|
|
45
|
+
for (const tName of col.jsTransform) {
|
|
46
|
+
// Check for slice(start,end) style parameterised transforms
|
|
47
|
+
const paramMatch = /^(\w+)\((.+)\)$/.exec(tName);
|
|
48
|
+
if (paramMatch) {
|
|
49
|
+
const fnName = paramMatch[1];
|
|
50
|
+
const args = paramMatch[2].split(',').map((a) => a.trim());
|
|
51
|
+
if (fnName === 'slice' && args.length === 2) {
|
|
52
|
+
const start = parseInt(args[0], 10);
|
|
53
|
+
const end = parseInt(args[1], 10);
|
|
54
|
+
fns.push((v) => typeof v === 'string' ? v.slice(start, end) : v);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const fn = customTransforms.get(tName) ?? builtInTransforms[tName];
|
|
59
|
+
if (fn)
|
|
60
|
+
fns.push(fn);
|
|
61
|
+
}
|
|
62
|
+
if (fns.length > 0) {
|
|
63
|
+
transformMap.set(col.name, fns);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (transformMap.size === 0)
|
|
67
|
+
return data;
|
|
68
|
+
return data.map((row) => {
|
|
69
|
+
const newRow = { ...row };
|
|
70
|
+
for (const [field, fns] of transformMap) {
|
|
71
|
+
if (field in newRow) {
|
|
72
|
+
let val = newRow[field];
|
|
73
|
+
for (const fn of fns) {
|
|
74
|
+
val = fn(val);
|
|
75
|
+
}
|
|
76
|
+
newRow[field] = val;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return newRow;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Builds a complete EngineResult, applying jsTransform and stripping hidden columns.
|
|
84
|
+
*/
|
|
85
|
+
export function formatResponse(data, meta, config, aggregations) {
|
|
86
|
+
// 1. Strip hidden columns from data (defense in depth — select should omit them)
|
|
87
|
+
const hiddenFields = new Set(config.columns.filter((c) => c.hidden).map((c) => c.name));
|
|
88
|
+
let processed = data;
|
|
89
|
+
if (hiddenFields.size > 0) {
|
|
90
|
+
processed = processed.map((row) => {
|
|
91
|
+
const r = { ...row };
|
|
92
|
+
for (const h of hiddenFields) {
|
|
93
|
+
delete r[h];
|
|
94
|
+
}
|
|
95
|
+
return r;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// 2. Apply JS transforms
|
|
99
|
+
processed = applyJsTransforms(processed, config);
|
|
100
|
+
return {
|
|
101
|
+
data: processed,
|
|
102
|
+
meta,
|
|
103
|
+
...(aggregations && { aggregations }),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=responseFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseFormatter.js","sourceRoot":"","sources":["../../../src/utils/responseFormatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Table, Column, SQL } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* Type-safe column reference helper.
|
|
4
|
+
* Use when you need a column ref outside of Drizzle's sql tag.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const col = column(s.orders, 'total'); // ← TypeScript autocomplete + validation
|
|
9
|
+
* const col = column(s.orders, 'typo'); // ← TypeScript ERROR
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function column<T extends Table>(table: T, name: T extends {
|
|
13
|
+
_: {
|
|
14
|
+
columns: infer C;
|
|
15
|
+
};
|
|
16
|
+
} ? keyof C & string : string): Column;
|
|
17
|
+
/**
|
|
18
|
+
* Type-safe CASE WHEN builder.
|
|
19
|
+
* Avoids writing raw SQL for the most common pattern.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const statusLabel = caseWhen(s.orders.status, {
|
|
24
|
+
* 1: 'success',
|
|
25
|
+
* 2: 'failed',
|
|
26
|
+
* 3: 'partial',
|
|
27
|
+
* }, 'unknown');
|
|
28
|
+
* // → CASE WHEN status = 1 THEN 'success' WHEN status = 2 THEN 'failed' ... END
|
|
29
|
+
*
|
|
30
|
+
* defineTable(s.orders).computed('statusLabel', statusLabel, { type: 'string' });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function caseWhen<T>(col: Column, mapping: Record<string | number, T>, fallback?: T): SQL;
|
|
34
|
+
/**
|
|
35
|
+
* Type-safe COALESCE.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const name = coalesce(s.users.nickname, s.users.name, sql`'Anonymous'`);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function coalesce(...values: (Column | SQL | string | number)[]): SQL;
|
|
43
|
+
/**
|
|
44
|
+
* Type-safe CONCAT.
|
|
45
|
+
*/
|
|
46
|
+
export declare function concat(...values: (Column | SQL | string)[]): SQL;
|
|
47
|
+
/**
|
|
48
|
+
* Type-safe date truncation.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const month = dateTrunc('month', s.orders.createdAt);
|
|
53
|
+
* defineTable(s.orders).groupBy('createdAt') // or use as computed
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function dateTrunc(precision: 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute', col: Column): SQL;
|
|
57
|
+
/**
|
|
58
|
+
* Type-safe interval.
|
|
59
|
+
*/
|
|
60
|
+
export declare function interval(value: number, unit: 'days' | 'hours' | 'minutes' | 'months' | 'years'): SQL;
|
|
61
|
+
/**
|
|
62
|
+
* Type-safe NOW() - interval shorthand.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* .rawWhere(sql`${s.orders.createdAt} > ${ago(30, 'days')}`)
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare function ago(value: number, unit: 'days' | 'hours' | 'minutes' | 'months' | 'years'): SQL;
|
|
70
|
+
//# sourceMappingURL=typedSql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typedSql.d.ts","sourceRoot":"","sources":["../../../src/utils/typedSql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAwB,MAAM,aAAa,CAAC;AAEvE;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,KAAK,EACpC,KAAK,EAAE,CAAC,EACR,IAAI,EAAE,CAAC,SAAS;IAAE,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,GACtE,MAAM,CAOR;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,EACnC,QAAQ,CAAC,EAAE,CAAC,GACX,GAAG,CAeL;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,GAAG,CAO3E;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,EAAE,GAAG,GAAG,CAGhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACvB,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,EAChE,GAAG,EAAE,MAAM,GACV,GAAG,CAEL;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,GAAG,CAEpG;AAED;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,GAAG,CAE/F"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { sql, getTableColumns } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* Type-safe column reference helper.
|
|
4
|
+
* Use when you need a column ref outside of Drizzle's sql tag.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const col = column(s.orders, 'total'); // ← TypeScript autocomplete + validation
|
|
9
|
+
* const col = column(s.orders, 'typo'); // ← TypeScript ERROR
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function column(table, name) {
|
|
13
|
+
const columns = getTableColumns(table);
|
|
14
|
+
const col = columns[name];
|
|
15
|
+
if (!col) {
|
|
16
|
+
throw new Error(`Column '${name}' does not exist on table`);
|
|
17
|
+
}
|
|
18
|
+
return col;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Type-safe CASE WHEN builder.
|
|
22
|
+
* Avoids writing raw SQL for the most common pattern.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const statusLabel = caseWhen(s.orders.status, {
|
|
27
|
+
* 1: 'success',
|
|
28
|
+
* 2: 'failed',
|
|
29
|
+
* 3: 'partial',
|
|
30
|
+
* }, 'unknown');
|
|
31
|
+
* // → CASE WHEN status = 1 THEN 'success' WHEN status = 2 THEN 'failed' ... END
|
|
32
|
+
*
|
|
33
|
+
* defineTable(s.orders).computed('statusLabel', statusLabel, { type: 'string' });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function caseWhen(col, mapping, fallback) {
|
|
37
|
+
const parts = [];
|
|
38
|
+
for (const [value, result] of Object.entries(mapping)) {
|
|
39
|
+
const v = isNaN(Number(value)) ? value : Number(value);
|
|
40
|
+
parts.push(sql `WHEN ${col} = ${v} THEN ${result}`);
|
|
41
|
+
}
|
|
42
|
+
const caseParts = sql.join(parts, sql ` `);
|
|
43
|
+
if (fallback !== undefined) {
|
|
44
|
+
return sql `CASE ${caseParts} ELSE ${fallback} END`;
|
|
45
|
+
}
|
|
46
|
+
return sql `CASE ${caseParts} END`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Type-safe COALESCE.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const name = coalesce(s.users.nickname, s.users.name, sql`'Anonymous'`);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export function coalesce(...values) {
|
|
57
|
+
const parts = values.map(v => {
|
|
58
|
+
if (typeof v === 'string')
|
|
59
|
+
return sql `${v}`;
|
|
60
|
+
if (typeof v === 'number')
|
|
61
|
+
return sql `${v}`;
|
|
62
|
+
return v;
|
|
63
|
+
});
|
|
64
|
+
return sql `COALESCE(${sql.join(parts, sql `, `)})`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Type-safe CONCAT.
|
|
68
|
+
*/
|
|
69
|
+
export function concat(...values) {
|
|
70
|
+
const parts = values.map(v => typeof v === 'string' ? sql `${v}` : v);
|
|
71
|
+
return sql `CONCAT(${sql.join(parts, sql `, `)})`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Type-safe date truncation.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* const month = dateTrunc('month', s.orders.createdAt);
|
|
79
|
+
* defineTable(s.orders).groupBy('createdAt') // or use as computed
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function dateTrunc(precision, col) {
|
|
83
|
+
return sql `DATE_TRUNC(${precision}, ${col})`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Type-safe interval.
|
|
87
|
+
*/
|
|
88
|
+
export function interval(value, unit) {
|
|
89
|
+
return sql `INTERVAL '${sql.raw(String(value))} ${sql.raw(unit)}'`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Type-safe NOW() - interval shorthand.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* .rawWhere(sql`${s.orders.createdAt} > ${ago(30, 'days')}`)
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export function ago(value, unit) {
|
|
100
|
+
return sql `NOW() - ${interval(value, unit)}`;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=typedSql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typedSql.js","sourceRoot":"","sources":["../../../src/utils/typedSql.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columnMeta.test.d.ts","sourceRoot":"","sources":["../../test/columnMeta.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { defineTable } from '../src/define';
|
|
3
|
+
import { sql } from 'drizzle-orm';
|
|
4
|
+
import { pgTable, uuid, varchar, integer, timestamp } from 'drizzle-orm/pg-core';
|
|
5
|
+
const orders = pgTable('orders', {
|
|
6
|
+
id: uuid('id').primaryKey(),
|
|
7
|
+
total: integer('total'),
|
|
8
|
+
cost: integer('cost'),
|
|
9
|
+
status: varchar('status', { length: 50 }),
|
|
10
|
+
createdAt: timestamp('created_at'),
|
|
11
|
+
});
|
|
12
|
+
describe('columnMeta', () => {
|
|
13
|
+
it('should set metadata on existing column', () => {
|
|
14
|
+
const config = defineTable(orders)
|
|
15
|
+
.columnMeta('total', {
|
|
16
|
+
label: 'Order Total',
|
|
17
|
+
format: 'currency',
|
|
18
|
+
align: 'right',
|
|
19
|
+
width: 150,
|
|
20
|
+
})
|
|
21
|
+
.toConfig();
|
|
22
|
+
const col = config.columns.find((c) => c.name === 'total');
|
|
23
|
+
expect(col.label).toBe('Order Total');
|
|
24
|
+
expect(col.format).toBe('currency');
|
|
25
|
+
expect(col.align).toBe('right');
|
|
26
|
+
expect(col.width).toBe(150);
|
|
27
|
+
});
|
|
28
|
+
it('should create placeholder for non-existent column', () => {
|
|
29
|
+
const config = defineTable(orders)
|
|
30
|
+
.columnMeta('profitMargin', {
|
|
31
|
+
type: 'number',
|
|
32
|
+
label: 'Profit Margin',
|
|
33
|
+
format: 'percent',
|
|
34
|
+
sortable: true,
|
|
35
|
+
})
|
|
36
|
+
.toConfig();
|
|
37
|
+
const col = config.columns.find((c) => c.name === 'profitMargin');
|
|
38
|
+
expect(col).toBeDefined();
|
|
39
|
+
expect(col.type).toBe('number');
|
|
40
|
+
expect(col.label).toBe('Profit Margin');
|
|
41
|
+
expect(col.sortable).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
it('should set visibleTo', () => {
|
|
44
|
+
const config = defineTable(orders)
|
|
45
|
+
.columnMeta('cost', {
|
|
46
|
+
visibleTo: ['admin', 'finance'],
|
|
47
|
+
})
|
|
48
|
+
.toConfig();
|
|
49
|
+
const col = config.columns.find((c) => c.name === 'cost');
|
|
50
|
+
expect(col.visibleTo).toEqual(['admin', 'finance']);
|
|
51
|
+
});
|
|
52
|
+
it('should set options', () => {
|
|
53
|
+
const config = defineTable(orders)
|
|
54
|
+
.columnMeta('status', {
|
|
55
|
+
options: [
|
|
56
|
+
{ value: 'active', label: 'Active', color: 'green' },
|
|
57
|
+
{ value: 'inactive', label: 'Inactive', color: 'gray' },
|
|
58
|
+
],
|
|
59
|
+
})
|
|
60
|
+
.toConfig();
|
|
61
|
+
const col = config.columns.find((c) => c.name === 'status');
|
|
62
|
+
expect(col.options).toHaveLength(2);
|
|
63
|
+
});
|
|
64
|
+
it('should work with rawSelect', () => {
|
|
65
|
+
const builder = defineTable(orders)
|
|
66
|
+
.rawSelect('profit', sql `${orders.total} - ${orders.cost}`, {
|
|
67
|
+
type: 'number',
|
|
68
|
+
label: 'Profit',
|
|
69
|
+
format: 'currency',
|
|
70
|
+
sortable: true,
|
|
71
|
+
});
|
|
72
|
+
const config = builder.toConfig();
|
|
73
|
+
// Metadata on config
|
|
74
|
+
const col = config.columns.find((c) => c.name === 'profit');
|
|
75
|
+
expect(col).toBeDefined();
|
|
76
|
+
expect(col.type).toBe('number');
|
|
77
|
+
expect(col.label).toBe('Profit');
|
|
78
|
+
expect(col.format).toBe('currency');
|
|
79
|
+
expect(col.sortable).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it('should merge with existing column metadata', () => {
|
|
82
|
+
const config = defineTable(orders)
|
|
83
|
+
.format('total', 'currency')
|
|
84
|
+
.columnMeta('total', { width: 150, minWidth: 100 })
|
|
85
|
+
.toConfig();
|
|
86
|
+
const col = config.columns.find((c) => c.name === 'total');
|
|
87
|
+
expect(col.format).toBe('currency'); // preserved from .format()
|
|
88
|
+
expect(col.width).toBe(150); // added by .columnMeta()
|
|
89
|
+
expect(col.minWidth).toBe(100);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=columnMeta.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columnMeta.test.js","sourceRoot":"","sources":["../../test/columnMeta.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregationBuilder.test.d.ts","sourceRoot":"","sources":["../../../test/core/aggregationBuilder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { pgTable, integer, text } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { AggregationBuilder } from '../../src/core/aggregationBuilder';
|
|
4
|
+
const users = pgTable('users', {
|
|
5
|
+
id: integer('id').primaryKey(),
|
|
6
|
+
age: integer('age'),
|
|
7
|
+
score: integer('score'),
|
|
8
|
+
name: text('name')
|
|
9
|
+
});
|
|
10
|
+
const schema = { users };
|
|
11
|
+
describe('AggregationBuilder', () => {
|
|
12
|
+
const config = {
|
|
13
|
+
name: 'users',
|
|
14
|
+
base: 'users',
|
|
15
|
+
columns: [
|
|
16
|
+
{ name: 'id', type: 'number', hidden: false, sortable: true, filterable: true },
|
|
17
|
+
{ name: 'age', type: 'number', hidden: false, sortable: true, filterable: true },
|
|
18
|
+
{ name: 'score', type: 'number', hidden: false, sortable: true, filterable: true },
|
|
19
|
+
{ name: 'name', type: 'string', hidden: false, sortable: true, filterable: true }
|
|
20
|
+
],
|
|
21
|
+
aggregations: [
|
|
22
|
+
{ alias: 'totalScore', type: 'sum', field: 'score' },
|
|
23
|
+
{ alias: 'avgAge', type: 'avg', field: 'age' },
|
|
24
|
+
{ alias: 'userCount', type: 'count', field: 'id' },
|
|
25
|
+
{ alias: 'maxScore', type: 'max', field: 'score' },
|
|
26
|
+
{ alias: 'minAge', type: 'min', field: 'age' }
|
|
27
|
+
]
|
|
28
|
+
};
|
|
29
|
+
const builder = new AggregationBuilder(schema);
|
|
30
|
+
describe('buildAggregations', () => {
|
|
31
|
+
it('should build aggregation map', () => {
|
|
32
|
+
const result = builder.buildAggregations(config);
|
|
33
|
+
expect(result).toBeDefined();
|
|
34
|
+
expect(Object.keys(result)).toHaveLength(5);
|
|
35
|
+
expect(result['totalScore']).toBeDefined();
|
|
36
|
+
expect(result['avgAge']).toBeDefined();
|
|
37
|
+
});
|
|
38
|
+
it('should return undefined if no aggregations configured', () => {
|
|
39
|
+
const noAggConfig = { ...config, aggregations: [] };
|
|
40
|
+
const result = builder.buildAggregations(noAggConfig);
|
|
41
|
+
expect(result).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
it('should ignore aggregations on unknown columns', () => {
|
|
44
|
+
const badConfig = {
|
|
45
|
+
...config,
|
|
46
|
+
aggregations: [{ alias: 'x', type: 'sum', field: 'unknown' }]
|
|
47
|
+
};
|
|
48
|
+
const result = builder.buildAggregations(badConfig);
|
|
49
|
+
expect(result).toBeUndefined();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('buildAggregationSelect', () => {
|
|
53
|
+
it('should always include _totalCount', () => {
|
|
54
|
+
const result = builder.buildAggregationSelect({ ...config, aggregations: [] });
|
|
55
|
+
expect(result._totalCount).toBeDefined();
|
|
56
|
+
});
|
|
57
|
+
it('should include configured aggregations', () => {
|
|
58
|
+
const result = builder.buildAggregationSelect(config);
|
|
59
|
+
expect(result.totalScore).toBeDefined();
|
|
60
|
+
expect(result._totalCount).toBeDefined();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=aggregationBuilder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregationBuilder.test.js","sourceRoot":"","sources":["../../../test/core/aggregationBuilder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filterBuilder.test.d.ts","sourceRoot":"","sources":["../../../test/core/filterBuilder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { pgTable, text, integer, boolean } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { FilterBuilder } from '../../src/core/filterBuilder';
|
|
4
|
+
// Mock Schema
|
|
5
|
+
const users = pgTable('users', {
|
|
6
|
+
id: integer('id').primaryKey(),
|
|
7
|
+
name: text('name'),
|
|
8
|
+
email: text('email'),
|
|
9
|
+
status: text('status'),
|
|
10
|
+
role: text('role'),
|
|
11
|
+
age: integer('age'),
|
|
12
|
+
archived: boolean('archived')
|
|
13
|
+
});
|
|
14
|
+
const schema = { users };
|
|
15
|
+
describe('FilterBuilder', () => {
|
|
16
|
+
const config = {
|
|
17
|
+
name: 'users',
|
|
18
|
+
base: 'users',
|
|
19
|
+
columns: [
|
|
20
|
+
{ name: 'id', type: 'number', sortable: true, hidden: false, filterable: true },
|
|
21
|
+
{ name: 'name', type: 'string', sortable: true, hidden: false, filterable: true },
|
|
22
|
+
{ name: 'email', type: 'string', sortable: true, hidden: false, filterable: true },
|
|
23
|
+
{ name: 'status', type: 'string', filterable: true, hidden: false, sortable: true },
|
|
24
|
+
{ name: 'age', type: 'number', filterable: true, hidden: false, sortable: true },
|
|
25
|
+
{ name: 'role', type: 'string', filterable: false, hidden: false, sortable: true } // Not filterable
|
|
26
|
+
],
|
|
27
|
+
filters: [
|
|
28
|
+
{ field: 'status', operator: 'eq', type: 'dynamic' },
|
|
29
|
+
{ field: 'age', operator: 'gte', type: 'dynamic' },
|
|
30
|
+
{ field: 'archived', operator: 'eq', value: false, type: 'static' } // Static filter
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
const builder = new FilterBuilder(schema);
|
|
34
|
+
describe('buildFilters', () => {
|
|
35
|
+
it('should build filter conditions from valid params', () => {
|
|
36
|
+
const params = {
|
|
37
|
+
status: { operator: 'eq', value: 'active' },
|
|
38
|
+
age: { operator: 'gte', value: 18 }
|
|
39
|
+
};
|
|
40
|
+
const conditions = builder.buildFilters(config, params);
|
|
41
|
+
expect(conditions).toBeDefined();
|
|
42
|
+
// We can't easily inspect the SQL object structure deeply without internal knowledge,
|
|
43
|
+
// but we can check it returns something.
|
|
44
|
+
// Drizzle's `and` returns an object.
|
|
45
|
+
});
|
|
46
|
+
it('should ignore filters for columns not marked as filterable', () => {
|
|
47
|
+
const params = {
|
|
48
|
+
role: { operator: 'eq', value: 'admin' }
|
|
49
|
+
};
|
|
50
|
+
const conditions = builder.buildFilters(config, params);
|
|
51
|
+
expect(conditions).toBeUndefined();
|
|
52
|
+
});
|
|
53
|
+
it('should ignore filters for unknown columns', () => {
|
|
54
|
+
const params = {
|
|
55
|
+
unknown: { operator: 'eq', value: 'something' }
|
|
56
|
+
};
|
|
57
|
+
const conditions = builder.buildFilters(config, params);
|
|
58
|
+
expect(conditions).toBeUndefined();
|
|
59
|
+
});
|
|
60
|
+
it('should return undefined for empty params', () => {
|
|
61
|
+
const conditions = builder.buildFilters(config, {});
|
|
62
|
+
expect(conditions).toBeUndefined();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('buildStaticFilters', () => {
|
|
66
|
+
it('should build static filters from config', () => {
|
|
67
|
+
const conditions = builder.buildStaticFilters(config);
|
|
68
|
+
expect(conditions).toBeDefined();
|
|
69
|
+
});
|
|
70
|
+
it('should return undefined if no static filters', () => {
|
|
71
|
+
const noStaticConfig = {
|
|
72
|
+
...config,
|
|
73
|
+
filters: []
|
|
74
|
+
};
|
|
75
|
+
const conditions = builder.buildStaticFilters(noStaticConfig);
|
|
76
|
+
expect(conditions).toBeUndefined();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=filterBuilder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filterBuilder.test.js","sourceRoot":"","sources":["../../../test/core/filterBuilder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginationBuilder.test.d.ts","sourceRoot":"","sources":["../../../test/core/paginationBuilder.test.ts"],"names":[],"mappings":""}
|