@tablecraft/engine 0.1.1 → 0.1.2
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/LICENSE +21 -0
- package/dist/core/filterBuilder.d.ts +13 -2
- package/dist/core/filterBuilder.d.ts.map +1 -1
- package/dist/core/filterBuilder.js +123 -22
- package/dist/core/filterBuilder.js.map +1 -1
- package/dist/core/inputValidator.js +25 -1
- package/dist/core/inputValidator.js.map +1 -1
- package/dist/core/sortBuilder.d.ts +14 -1
- package/dist/core/sortBuilder.d.ts.map +1 -1
- package/dist/core/sortBuilder.js +77 -6
- package/dist/core/sortBuilder.js.map +1 -1
- package/dist/define.d.ts +34 -4
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +12 -1
- package/dist/define.js.map +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +21 -10
- package/dist/engine.js.map +1 -1
- package/dist/utils/operators.d.ts.map +1 -1
- package/dist/utils/operators.js +12 -2
- package/dist/utils/operators.js.map +1 -1
- package/dist/utils/requestParser.d.ts +11 -0
- package/dist/utils/requestParser.d.ts.map +1 -1
- package/dist/utils/requestParser.js +77 -2
- package/dist/utils/requestParser.js.map +1 -1
- package/dist/utils/responseFormatter.d.ts.map +1 -1
- package/dist/utils/responseFormatter.js +10 -2
- package/dist/utils/responseFormatter.js.map +1 -1
- package/package.json +9 -9
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TableCraft
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -11,12 +11,23 @@ export declare class FilterBuilder {
|
|
|
11
11
|
buildFilters(config: TableConfig, params: Record<string, FilterParam>): SQL | undefined;
|
|
12
12
|
/**
|
|
13
13
|
* Builds conditions for filters with type='static' (preset values in config).
|
|
14
|
+
* Supports both base columns and join columns.
|
|
14
15
|
*/
|
|
15
16
|
buildStaticFilters(config: TableConfig): SQL | undefined;
|
|
16
17
|
/**
|
|
17
|
-
* Resolves a column reference. Supports
|
|
18
|
-
*
|
|
18
|
+
* Resolves a column reference. Supports:
|
|
19
|
+
* 1. Direct column on the base table (only when isJoinField is false)
|
|
20
|
+
* 2. Dot-syntax for joined tables: "users.role"
|
|
21
|
+
* 3. Plain aliased name from a joined table: "role" (searched recursively through join configs)
|
|
22
|
+
*
|
|
23
|
+
* When `isJoinField` is true the base-column lookup is skipped entirely to prevent
|
|
24
|
+
* a base-schema column with the same name from silently shadowing a join column.
|
|
19
25
|
*/
|
|
20
26
|
private resolveColumn;
|
|
27
|
+
/**
|
|
28
|
+
* Searches join configs recursively for a column with the given plain name.
|
|
29
|
+
* Returns the drizzle Column from the joined table's schema.
|
|
30
|
+
*/
|
|
31
|
+
private resolveJoinColumn;
|
|
21
32
|
}
|
|
22
33
|
//# sourceMappingURL=filterBuilder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filterBuilder.d.ts","sourceRoot":"","sources":["../../src/core/filterBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,GAAG,EAGJ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"filterBuilder.d.ts","sourceRoot":"","sources":["../../src/core/filterBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,GAAG,EAGJ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAA4B,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAY9C,qBAAa,aAAa;IACZ,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEnD;;;OAGG;IACH,YAAY,CACV,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAClC,GAAG,GAAG,SAAS;IAuElB;;;OAGG;IACH,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG,GAAG,SAAS;IAkCxD;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAqCrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CA+B1B"}
|
|
@@ -17,7 +17,7 @@ export class FilterBuilder {
|
|
|
17
17
|
const table = this.schema[config.base];
|
|
18
18
|
if (!table)
|
|
19
19
|
return undefined;
|
|
20
|
-
const
|
|
20
|
+
const baseColumns = getTableColumns(table);
|
|
21
21
|
// Build a whitelist of filterable field names
|
|
22
22
|
const filterableFields = new Set();
|
|
23
23
|
// From explicit dynamic filter definitions
|
|
@@ -28,24 +28,34 @@ export class FilterBuilder {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
// From columns marked filterable (default true)
|
|
31
|
+
// From base columns marked filterable (default true)
|
|
32
32
|
for (const col of config.columns) {
|
|
33
33
|
if (col.filterable !== false) {
|
|
34
34
|
filterableFields.add(col.name);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
// From join columns marked filterable (recursive)
|
|
38
|
+
if (config.joins) {
|
|
39
|
+
collectFilterableJoinFields(config.joins, filterableFields);
|
|
40
|
+
}
|
|
37
41
|
const conditions = [];
|
|
38
42
|
for (const [field, param] of Object.entries(params)) {
|
|
39
43
|
// Security: reject fields not in the whitelist
|
|
40
44
|
if (!filterableFields.has(field))
|
|
41
45
|
continue;
|
|
42
|
-
//
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
46
|
+
// Determine whether this field is a join column
|
|
47
|
+
const isJoinField = isJoinColumn(config, field);
|
|
48
|
+
// Resolve the column — could be on the base table or a joined table.
|
|
49
|
+
// Pass isJoinField so that base-table columns can never shadow join columns.
|
|
50
|
+
const resolved = this.resolveColumn(config, baseColumns, field, isJoinField);
|
|
51
|
+
if (!resolved) {
|
|
52
|
+
console.warn(`[FilterBuilder] Could not resolve column "${field}" — filter skipped`);
|
|
48
53
|
continue;
|
|
54
|
+
}
|
|
55
|
+
const { column: col, colConfig } = resolved;
|
|
56
|
+
// Allow the config to override the db field name via colConfig.field
|
|
57
|
+
// (already handled inside resolveColumn, but colConfig is available for future use)
|
|
58
|
+
void colConfig;
|
|
49
59
|
// Check if value is a date preset
|
|
50
60
|
if (isDatePreset(param.value)) {
|
|
51
61
|
const presetCondition = buildDatePresetCondition(col, param.value);
|
|
@@ -61,6 +71,7 @@ export class FilterBuilder {
|
|
|
61
71
|
}
|
|
62
72
|
/**
|
|
63
73
|
* Builds conditions for filters with type='static' (preset values in config).
|
|
74
|
+
* Supports both base columns and join columns.
|
|
64
75
|
*/
|
|
65
76
|
buildStaticFilters(config) {
|
|
66
77
|
if (!config.filters)
|
|
@@ -68,15 +79,22 @@ export class FilterBuilder {
|
|
|
68
79
|
const table = this.schema[config.base];
|
|
69
80
|
if (!table)
|
|
70
81
|
return undefined;
|
|
71
|
-
const
|
|
82
|
+
const baseColumns = getTableColumns(table);
|
|
72
83
|
const conditions = [];
|
|
73
84
|
for (const filter of config.filters) {
|
|
74
85
|
if (filter.type !== 'static' || filter.value === undefined)
|
|
75
86
|
continue;
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
// Try base column first; fall back to join column
|
|
88
|
+
let col = baseColumns[filter.field];
|
|
89
|
+
if (!col) {
|
|
90
|
+
// Look in join columns (recursive)
|
|
91
|
+
const resolved = this.resolveJoinColumn(config, filter.field);
|
|
92
|
+
col = resolved?.column;
|
|
93
|
+
}
|
|
94
|
+
if (!col) {
|
|
95
|
+
console.warn(`[FilterBuilder] Static filter: could not resolve column "${filter.field}" — skipped`);
|
|
78
96
|
continue;
|
|
79
|
-
|
|
97
|
+
}
|
|
80
98
|
const op = filter.operator ?? 'eq';
|
|
81
99
|
const condition = applyOperator(op, col, filter.value);
|
|
82
100
|
if (condition)
|
|
@@ -85,28 +103,111 @@ export class FilterBuilder {
|
|
|
85
103
|
return conditions.length > 0 ? and(...conditions) : undefined;
|
|
86
104
|
}
|
|
87
105
|
/**
|
|
88
|
-
* Resolves a column reference. Supports
|
|
89
|
-
*
|
|
106
|
+
* Resolves a column reference. Supports:
|
|
107
|
+
* 1. Direct column on the base table (only when isJoinField is false)
|
|
108
|
+
* 2. Dot-syntax for joined tables: "users.role"
|
|
109
|
+
* 3. Plain aliased name from a joined table: "role" (searched recursively through join configs)
|
|
110
|
+
*
|
|
111
|
+
* When `isJoinField` is true the base-column lookup is skipped entirely to prevent
|
|
112
|
+
* a base-schema column with the same name from silently shadowing a join column.
|
|
90
113
|
*/
|
|
91
|
-
resolveColumn(config, baseColumns, field) {
|
|
92
|
-
//
|
|
93
|
-
if (baseColumns[field]) {
|
|
94
|
-
return baseColumns[field];
|
|
95
|
-
}
|
|
96
|
-
// Dot-syntax for joined tables: "orders.total"
|
|
114
|
+
resolveColumn(config, baseColumns, field, isJoinField) {
|
|
115
|
+
// Dot-syntax takes priority regardless of join vs base — it is explicit
|
|
97
116
|
if (field.includes('.')) {
|
|
98
117
|
const [tableName, colName] = field.split('.');
|
|
99
118
|
const joinedTable = this.schema[tableName];
|
|
100
119
|
if (!joinedTable)
|
|
101
120
|
return undefined;
|
|
102
|
-
// Verify this table is actually joined
|
|
121
|
+
// Verify this table is actually joined (security check)
|
|
103
122
|
const isJoined = config.joins?.some((j) => j.table === tableName || j.alias === tableName);
|
|
104
123
|
if (!isJoined)
|
|
105
124
|
return undefined;
|
|
106
125
|
const joinedCols = getTableColumns(joinedTable);
|
|
107
|
-
|
|
126
|
+
const column = joinedCols[colName];
|
|
127
|
+
return column ? { column, colConfig: undefined, fromJoin: true } : undefined;
|
|
128
|
+
}
|
|
129
|
+
// If this field belongs to a join, skip the base column entirely to avoid shadowing
|
|
130
|
+
if (!isJoinField) {
|
|
131
|
+
const baseColConfig = config.columns.find(c => c.name === field);
|
|
132
|
+
const dbFieldName = baseColConfig?.field ?? field;
|
|
133
|
+
const column = baseColumns[dbFieldName];
|
|
134
|
+
if (column) {
|
|
135
|
+
return { column, colConfig: baseColConfig, fromJoin: false };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Plain name — search join configs recursively
|
|
139
|
+
return this.resolveJoinColumn(config, field);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Searches join configs recursively for a column with the given plain name.
|
|
143
|
+
* Returns the drizzle Column from the joined table's schema.
|
|
144
|
+
*/
|
|
145
|
+
resolveJoinColumn(config, fieldName) {
|
|
146
|
+
if (!config.joins)
|
|
147
|
+
return undefined;
|
|
148
|
+
for (const join of config.joins) {
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
150
|
+
const joinColConfig = join.columns?.find((c) => c.name === fieldName);
|
|
151
|
+
if (joinColConfig) {
|
|
152
|
+
const joinedTable = this.schema[join.table];
|
|
153
|
+
if (!joinedTable)
|
|
154
|
+
continue;
|
|
155
|
+
const joinedCols = getTableColumns(joinedTable);
|
|
156
|
+
const dbCol = joinColConfig.field ?? fieldName;
|
|
157
|
+
const column = joinedCols[dbCol];
|
|
158
|
+
if (column)
|
|
159
|
+
return { column, colConfig: joinColConfig, fromJoin: true };
|
|
160
|
+
}
|
|
161
|
+
// Recurse into nested joins
|
|
162
|
+
if (join.joins) {
|
|
163
|
+
const nested = this.resolveJoinColumn({ joins: join.joins }, fieldName);
|
|
164
|
+
if (nested)
|
|
165
|
+
return nested;
|
|
166
|
+
}
|
|
108
167
|
}
|
|
109
168
|
return undefined;
|
|
110
169
|
}
|
|
111
170
|
}
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// Module-level helpers (pure, no `this` dependency)
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
/**
|
|
175
|
+
* Recursively populates `out` with filterable field names from all join configs.
|
|
176
|
+
*/
|
|
177
|
+
function collectFilterableJoinFields(joins, out) {
|
|
178
|
+
for (const join of joins) {
|
|
179
|
+
if (join.columns) {
|
|
180
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
181
|
+
for (const col of join.columns) {
|
|
182
|
+
if (col.filterable !== false) {
|
|
183
|
+
out.add(col.name);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (join.joins) {
|
|
188
|
+
collectFilterableJoinFields(join.joins, out);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Returns true if `fieldName` is defined in any join config (recursively).
|
|
194
|
+
* Used to prevent base-table columns from shadowing join columns.
|
|
195
|
+
*/
|
|
196
|
+
function isJoinColumn(config, fieldName) {
|
|
197
|
+
if (!config.joins)
|
|
198
|
+
return false;
|
|
199
|
+
return isJoinColumnInJoins(config.joins, fieldName);
|
|
200
|
+
}
|
|
201
|
+
function isJoinColumnInJoins(joins, fieldName) {
|
|
202
|
+
for (const join of joins) {
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
204
|
+
if (join.columns?.some((c) => c.name === fieldName)) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
if (join.joins && isJoinColumnInJoins(join.joins, fieldName)) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
112
213
|
//# sourceMappingURL=filterBuilder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filterBuilder.js","sourceRoot":"","sources":["../../src/core/filterBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,eAAe,EACf,GAAG,GACJ,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"filterBuilder.js","sourceRoot":"","sources":["../../src/core/filterBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -52,7 +52,10 @@ function validateValueType(field, colType, filter) {
|
|
|
52
52
|
// For array operators, validate each element
|
|
53
53
|
if (filter.operator === 'in' || filter.operator === 'notIn') {
|
|
54
54
|
if (!Array.isArray(value)) {
|
|
55
|
-
|
|
55
|
+
// Defensive: requestParser should have already wrapped scalars into arrays.
|
|
56
|
+
// If we still get a scalar here, it means someone called the engine directly
|
|
57
|
+
// without going through parseRequest — give a clear, actionable error.
|
|
58
|
+
throw new ValidationError(field, `array (for '${filter.operator}' operator). If passing a single value, wrap it in an array: [${JSON.stringify(value)}]`, value);
|
|
56
59
|
}
|
|
57
60
|
for (const item of value) {
|
|
58
61
|
validateSingleValue(field, colType, item);
|
|
@@ -105,12 +108,33 @@ function validateSortFields(params, config) {
|
|
|
105
108
|
if (!params.sort?.length)
|
|
106
109
|
return;
|
|
107
110
|
const sortable = new Set(config.columns.filter((c) => c.sortable).map((c) => c.name));
|
|
111
|
+
// Also collect sortable fields from joins (same pattern as FilterBuilder
|
|
112
|
+
// uses collectFilterableJoinFields for filterable fields)
|
|
113
|
+
collectSortableJoinFields(config.joins, sortable);
|
|
108
114
|
for (const s of params.sort) {
|
|
109
115
|
if (!sortable.has(s.field)) {
|
|
110
116
|
throw new FieldError(s.field, 'is not sortable. Sortable: ' + [...sortable].join(', '));
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
}
|
|
120
|
+
/** Recursively collects sortable column names from join configs. */
|
|
121
|
+
function collectSortableJoinFields(joins, sortable) {
|
|
122
|
+
if (!joins?.length)
|
|
123
|
+
return;
|
|
124
|
+
for (const join of joins) {
|
|
125
|
+
if (join.columns) {
|
|
126
|
+
for (const col of join.columns) {
|
|
127
|
+
if (col.sortable !== false) {
|
|
128
|
+
sortable.add(col.name);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Recurse into nested joins
|
|
133
|
+
if (join.joins) {
|
|
134
|
+
collectSortableJoinFields(join.joins, sortable);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
114
138
|
function isValidUUID(str) {
|
|
115
139
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str);
|
|
116
140
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputValidator.js","sourceRoot":"","sources":["../../src/core/inputValidator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"inputValidator.js","sourceRoot":"","sources":["../../src/core/inputValidator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAExD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAoB,EAAE,MAAmB;IACrE,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAoB,EAAE,MAAmB;IACrE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM;QAAE,OAAO;IAEnC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9D,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CAAC,KAAK,EAAE,6BAA6B,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;QACzD,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,UAAU,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAoB,EAAE,MAAmB;IACrE,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO;IAE5B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;IAClD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEjC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,EAAE,CAAC;gBACvE,OAAO,CAAC,IAAI,CAAC,8BAA8B,KAAK,8BAA8B,MAAM,CAAC,IAAI,aAAa,CAAC,CAAC;YAC1G,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,UAAU,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW;YAAE,SAAS;QAE9E,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,OAAe,EAAE,MAAmB;IAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAElD,6CAA6C;IAC7C,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,4EAA4E;YAC5E,6EAA6E;YAC7E,uEAAuE;YACvE,MAAM,IAAI,eAAe,CACvB,KAAK,EACL,eAAe,MAAM,CAAC,QAAQ,iEAAiE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EACvH,KAAK,CACN,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO;IACT,CAAC;IAED,oCAAoC;IACpC,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,qBAAqB,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAE,OAAe,EAAE,KAAc;IACzE,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YACpD,CAAC;YACD,MAAM;QAER,KAAK,SAAS;YACZ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;YACrD,CAAC;YACD,MAAM;QAER,KAAK,MAAM;YACT,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrD,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;YACxD,CAAC;YACD,MAAM;QAER,KAAK,MAAM;YACT,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;oBACvB,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;iBAAM,IAAI,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAClD,CAAC;YACD,MAAM;QAER,iCAAiC;IACnC,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAoB,EAAE,MAAmB;IACnE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM;QAAE,OAAO;IAEjC,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAC5D,CAAC;IAEF,yEAAyE;IACzE,0DAA0D;IAC1D,yBAAyB,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAElD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,6BAA6B,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,SAAS,yBAAyB,CAChC,KAA2B,EAC3B,QAAqB;IAErB,IAAI,CAAC,KAAK,EAAE,MAAM;QAAE,OAAO;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC/B,IAAI,GAAG,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;oBAC3B,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;QACD,4BAA4B;QAC5B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,yBAAyB,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,iEAAiE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrF,CAAC"}
|
|
@@ -7,8 +7,21 @@ export declare class SortBuilder {
|
|
|
7
7
|
/**
|
|
8
8
|
* Builds ORDER BY clauses from request params, falling back to defaults.
|
|
9
9
|
* Only allows sorting on columns marked sortable in the config.
|
|
10
|
+
*
|
|
11
|
+
* Supports:
|
|
12
|
+
* - Base-table columns
|
|
13
|
+
* - Join columns (resolved recursively through join configs)
|
|
14
|
+
* - Computed/raw-select SQL expressions (via the optional sqlExpressions map)
|
|
15
|
+
*
|
|
16
|
+
* @param sqlExpressions - Optional map of field name → SQL expression for
|
|
17
|
+
* computed/raw-select columns that don't exist as real Drizzle columns.
|
|
10
18
|
*/
|
|
11
|
-
buildSort(config: TableConfig, params?: SortParam[]): SQL[];
|
|
19
|
+
buildSort(config: TableConfig, params?: SortParam[], sqlExpressions?: Map<string, SQL>): SQL[];
|
|
20
|
+
/**
|
|
21
|
+
* Searches join configs recursively for a column with the given plain name.
|
|
22
|
+
* Returns the Drizzle Column from the joined table's schema.
|
|
23
|
+
*/
|
|
24
|
+
private resolveJoinColumn;
|
|
12
25
|
private getDefaultSort;
|
|
13
26
|
}
|
|
14
27
|
//# sourceMappingURL=sortBuilder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sortBuilder.d.ts","sourceRoot":"","sources":["../../src/core/sortBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,GAAG,EAKJ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"sortBuilder.d.ts","sourceRoot":"","sources":["../../src/core/sortBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,GAAG,EAKJ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAA4B,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,qBAAa,WAAW;IACV,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEnD;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE;IAkE9F;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,cAAc;CAQvB"}
|
package/dist/core/sortBuilder.js
CHANGED
|
@@ -7,22 +7,33 @@ export class SortBuilder {
|
|
|
7
7
|
/**
|
|
8
8
|
* Builds ORDER BY clauses from request params, falling back to defaults.
|
|
9
9
|
* Only allows sorting on columns marked sortable in the config.
|
|
10
|
+
*
|
|
11
|
+
* Supports:
|
|
12
|
+
* - Base-table columns
|
|
13
|
+
* - Join columns (resolved recursively through join configs)
|
|
14
|
+
* - Computed/raw-select SQL expressions (via the optional sqlExpressions map)
|
|
15
|
+
*
|
|
16
|
+
* @param sqlExpressions - Optional map of field name → SQL expression for
|
|
17
|
+
* computed/raw-select columns that don't exist as real Drizzle columns.
|
|
10
18
|
*/
|
|
11
|
-
buildSort(config, params) {
|
|
19
|
+
buildSort(config, params, sqlExpressions) {
|
|
12
20
|
const sortParams = params && params.length > 0 ? params : this.getDefaultSort(config);
|
|
13
21
|
if (!sortParams || sortParams.length === 0)
|
|
14
22
|
return [];
|
|
15
23
|
const table = this.schema[config.base];
|
|
16
24
|
if (!table)
|
|
17
25
|
return [];
|
|
18
|
-
const
|
|
19
|
-
// Build a whitelist of sortable fields
|
|
26
|
+
const baseColumns = getTableColumns(table);
|
|
27
|
+
// Build a whitelist of sortable fields from base columns AND join columns
|
|
20
28
|
const sortableFields = new Set();
|
|
21
29
|
for (const col of config.columns) {
|
|
22
30
|
if (col.sortable !== false) {
|
|
23
31
|
sortableFields.add(col.name);
|
|
24
32
|
}
|
|
25
33
|
}
|
|
34
|
+
if (config.joins) {
|
|
35
|
+
collectSortableJoinFields(config.joins, sortableFields);
|
|
36
|
+
}
|
|
26
37
|
const clauses = [];
|
|
27
38
|
for (const sp of sortParams) {
|
|
28
39
|
if (!sortableFields.has(sp.field))
|
|
@@ -30,6 +41,7 @@ export class SortBuilder {
|
|
|
30
41
|
const colConfig = config.columns.find(c => c.name === sp.field);
|
|
31
42
|
const dbFieldName = colConfig?.field ?? sp.field;
|
|
32
43
|
let col;
|
|
44
|
+
// 1. Dot-syntax: "users.email" → explicit table reference
|
|
33
45
|
if (dbFieldName.includes('.')) {
|
|
34
46
|
const [tableName, colName] = dbFieldName.split('.');
|
|
35
47
|
const joinedTable = this.schema[tableName];
|
|
@@ -38,14 +50,55 @@ export class SortBuilder {
|
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
52
|
else {
|
|
41
|
-
|
|
53
|
+
// 2. Try the base table first
|
|
54
|
+
col = baseColumns[dbFieldName];
|
|
55
|
+
}
|
|
56
|
+
if (col) {
|
|
57
|
+
clauses.push(sp.order === 'desc' ? desc(col) : asc(col));
|
|
58
|
+
continue;
|
|
42
59
|
}
|
|
43
|
-
|
|
60
|
+
// 3. Fallback: computed/raw-select SQL expressions
|
|
61
|
+
const sqlExpr = sqlExpressions?.get(sp.field) ?? sqlExpressions?.get(dbFieldName);
|
|
62
|
+
if (sqlExpr) {
|
|
63
|
+
clauses.push(sp.order === 'desc' ? desc(sqlExpr) : asc(sqlExpr));
|
|
44
64
|
continue;
|
|
45
|
-
|
|
65
|
+
}
|
|
66
|
+
// 4. Fallback: search join configs for this column name
|
|
67
|
+
const joinCol = this.resolveJoinColumn(config, sp.field);
|
|
68
|
+
if (joinCol) {
|
|
69
|
+
clauses.push(sp.order === 'desc' ? desc(joinCol) : asc(joinCol));
|
|
70
|
+
}
|
|
46
71
|
}
|
|
47
72
|
return clauses;
|
|
48
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Searches join configs recursively for a column with the given plain name.
|
|
76
|
+
* Returns the Drizzle Column from the joined table's schema.
|
|
77
|
+
*/
|
|
78
|
+
resolveJoinColumn(config, fieldName) {
|
|
79
|
+
if (!config.joins)
|
|
80
|
+
return undefined;
|
|
81
|
+
for (const join of config.joins) {
|
|
82
|
+
const joinColConfig = join.columns?.find((c) => c.name === fieldName);
|
|
83
|
+
if (joinColConfig) {
|
|
84
|
+
const joinedTable = this.schema[join.table];
|
|
85
|
+
if (!joinedTable)
|
|
86
|
+
continue;
|
|
87
|
+
const joinedCols = getTableColumns(joinedTable);
|
|
88
|
+
const dbCol = joinColConfig.field ?? fieldName;
|
|
89
|
+
const column = joinedCols[dbCol];
|
|
90
|
+
if (column)
|
|
91
|
+
return column;
|
|
92
|
+
}
|
|
93
|
+
// Recurse into nested joins
|
|
94
|
+
if (join.joins) {
|
|
95
|
+
const nested = this.resolveJoinColumn({ joins: join.joins }, fieldName);
|
|
96
|
+
if (nested)
|
|
97
|
+
return nested;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
49
102
|
getDefaultSort(config) {
|
|
50
103
|
if (!config.defaultSort || config.defaultSort.length === 0)
|
|
51
104
|
return undefined;
|
|
@@ -55,4 +108,22 @@ export class SortBuilder {
|
|
|
55
108
|
}));
|
|
56
109
|
}
|
|
57
110
|
}
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Module-level helpers
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
/** Recursively populates `out` with sortable field names from all join configs. */
|
|
115
|
+
function collectSortableJoinFields(joins, out) {
|
|
116
|
+
for (const join of joins) {
|
|
117
|
+
if (join.columns) {
|
|
118
|
+
for (const col of join.columns) {
|
|
119
|
+
if (col.sortable !== false) {
|
|
120
|
+
out.add(col.name);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (join.joins) {
|
|
125
|
+
collectSortableJoinFields(join.joins, out);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
58
129
|
//# sourceMappingURL=sortBuilder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sortBuilder.js","sourceRoot":"","sources":["../../src/core/sortBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EACf,GAAG,EACH,IAAI,GAEL,MAAM,aAAa,CAAC;AAIrB,MAAM,OAAO,WAAW;IACF;IAApB,YAAoB,MAA+B;QAA/B,WAAM,GAAN,MAAM,CAAyB;IAAG,CAAC;IAEvD
|
|
1
|
+
{"version":3,"file":"sortBuilder.js","sourceRoot":"","sources":["../../src/core/sortBuilder.ts"],"names":[],"mappings":"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"}
|
package/dist/define.d.ts
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
|
-
import { Table, SQL } from 'drizzle-orm';
|
|
1
|
+
import { Table, SQL, like, ilike, inArray, notInArray, between, notBetween, isNull, isNotNull, exists, notExists, and, or, not, sql } from 'drizzle-orm';
|
|
2
|
+
export declare const drizzleOperators: {
|
|
3
|
+
eq: import("drizzle-orm").BinaryOperator;
|
|
4
|
+
ne: import("drizzle-orm").BinaryOperator;
|
|
5
|
+
gt: import("drizzle-orm").BinaryOperator;
|
|
6
|
+
gte: import("drizzle-orm").BinaryOperator;
|
|
7
|
+
lt: import("drizzle-orm").BinaryOperator;
|
|
8
|
+
lte: import("drizzle-orm").BinaryOperator;
|
|
9
|
+
like: typeof like;
|
|
10
|
+
ilike: typeof ilike;
|
|
11
|
+
inArray: typeof inArray;
|
|
12
|
+
notInArray: typeof notInArray;
|
|
13
|
+
between: typeof between;
|
|
14
|
+
notBetween: typeof notBetween;
|
|
15
|
+
isNull: typeof isNull;
|
|
16
|
+
isNotNull: typeof isNotNull;
|
|
17
|
+
exists: typeof exists;
|
|
18
|
+
notExists: typeof notExists;
|
|
19
|
+
and: typeof and;
|
|
20
|
+
or: typeof or;
|
|
21
|
+
not: typeof not;
|
|
22
|
+
sql: typeof sql;
|
|
23
|
+
};
|
|
24
|
+
import { EngineParams, EngineContext } from './types/engine';
|
|
2
25
|
import { TableConfig, ColumnConfig, Operator, FilterExpression, ColumnFormat, DatePreset } from './types/table';
|
|
3
26
|
type InferColumns<T> = T extends {
|
|
4
27
|
_: {
|
|
@@ -14,11 +37,15 @@ export interface QuickOptions<T extends Table = Table> {
|
|
|
14
37
|
maxPageSize?: number;
|
|
15
38
|
labels?: Partial<Record<InferColumns<T>, string>>;
|
|
16
39
|
}
|
|
17
|
-
export interface RuntimeExtensions {
|
|
40
|
+
export interface RuntimeExtensions<T extends Table = Table> {
|
|
18
41
|
computedExpressions: Map<string, SQL>;
|
|
19
42
|
transforms: Map<string, (value: unknown) => unknown>;
|
|
20
43
|
rawSelects: Map<string, SQL>;
|
|
21
44
|
rawWheres: SQL[];
|
|
45
|
+
dynamicWheres: ((ctx: {
|
|
46
|
+
query: EngineParams;
|
|
47
|
+
context: EngineContext;
|
|
48
|
+
}, ops: typeof drizzleOperators, table: T) => SQL | undefined | Promise<SQL | undefined>)[];
|
|
22
49
|
rawJoins: SQL[];
|
|
23
50
|
rawOrderBys: SQL[];
|
|
24
51
|
ctes: Map<string, SQL>;
|
|
@@ -32,7 +59,7 @@ export interface RuntimeExtensions {
|
|
|
32
59
|
export declare class TableDefinitionBuilder<T extends Table = Table> {
|
|
33
60
|
_config: TableConfig;
|
|
34
61
|
_table: T;
|
|
35
|
-
_ext: RuntimeExtensions
|
|
62
|
+
_ext: RuntimeExtensions<T>;
|
|
36
63
|
constructor(table: T, config: TableConfig);
|
|
37
64
|
/** Set display format for a column */
|
|
38
65
|
format(column: InferColumns<T>, fmt: ColumnFormat): this;
|
|
@@ -131,7 +158,10 @@ export declare class TableDefinitionBuilder<T extends Table = Table> {
|
|
|
131
158
|
field: string;
|
|
132
159
|
op: Operator;
|
|
133
160
|
value: unknown;
|
|
134
|
-
}
|
|
161
|
+
} | ((ctx: {
|
|
162
|
+
query: EngineParams;
|
|
163
|
+
context: EngineContext;
|
|
164
|
+
}, ops: typeof drizzleOperators, table: T) => SQL | undefined | Promise<SQL | undefined>)): this;
|
|
135
165
|
dbTransform(column: InferColumns<T>, ...transforms: string[]): this;
|
|
136
166
|
jsTransform(column: InferColumns<T>, ...transforms: string[]): this;
|
|
137
167
|
transform(column: InferColumns<T>, fn: (value: unknown) => unknown): this;
|