@tablecraft/engine 0.1.3 → 0.1.5
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/core/cursorPagination.d.ts +8 -2
- package/dist/core/cursorPagination.d.ts.map +1 -1
- package/dist/core/cursorPagination.js +85 -15
- package/dist/core/cursorPagination.js.map +1 -1
- package/dist/core/fieldSelector.d.ts.map +1 -1
- package/dist/core/fieldSelector.js +7 -1
- package/dist/core/fieldSelector.js.map +1 -1
- package/dist/core/filterBuilder.d.ts +1 -1
- package/dist/core/filterBuilder.d.ts.map +1 -1
- package/dist/core/filterBuilder.js +22 -54
- package/dist/core/filterBuilder.js.map +1 -1
- package/dist/core/inputValidator.d.ts.map +1 -1
- package/dist/core/inputValidator.js +19 -30
- package/dist/core/inputValidator.js.map +1 -1
- package/dist/core/metadataBuilder.d.ts.map +1 -1
- package/dist/core/metadataBuilder.js +9 -4
- package/dist/core/metadataBuilder.js.map +1 -1
- package/dist/core/sortBuilder.d.ts +5 -0
- package/dist/core/sortBuilder.d.ts.map +1 -1
- package/dist/core/sortBuilder.js +47 -32
- package/dist/core/sortBuilder.js.map +1 -1
- package/dist/core/subqueryBuilder.d.ts +7 -1
- package/dist/core/subqueryBuilder.d.ts.map +1 -1
- package/dist/core/subqueryBuilder.js +25 -7
- package/dist/core/subqueryBuilder.js.map +1 -1
- package/dist/define.d.ts +9 -0
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +47 -10
- package/dist/define.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +30 -4
- package/dist/engine.js.map +1 -1
- package/dist/types/engine.d.ts +1 -1
- package/dist/types/engine.d.ts.map +1 -1
- package/dist/utils/joinUtils.d.ts +15 -0
- package/dist/utils/joinUtils.d.ts.map +1 -0
- package/dist/utils/joinUtils.js +63 -0
- package/dist/utils/joinUtils.js.map +1 -0
- package/dist/utils/operators.d.ts.map +1 -1
- package/dist/utils/operators.js +0 -3
- package/dist/utils/operators.js.map +1 -1
- package/dist/utils/requestParser.d.ts.map +1 -1
- package/dist/utils/requestParser.js +28 -4
- package/dist/utils/requestParser.js.map +1 -1
- package/package.json +9 -9
- package/LICENSE +0 -21
|
@@ -11,10 +11,14 @@ export interface CursorMeta {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Cursor-based pagination.
|
|
14
|
-
* Uses the sort column
|
|
14
|
+
* Uses the sort column values as the cursor instead of OFFSET.
|
|
15
15
|
* O(1) performance regardless of page depth.
|
|
16
16
|
*
|
|
17
17
|
* Cursor format: base64({ field: value, field2: value2 })
|
|
18
|
+
*
|
|
19
|
+
* Multi-column sort: the WHERE clause uses ALL sort fields in a
|
|
20
|
+
* row-value comparison to avoid duplicate/skipped rows when rows
|
|
21
|
+
* share the same primary sort value.
|
|
18
22
|
*/
|
|
19
23
|
export declare class CursorPaginationBuilder {
|
|
20
24
|
private schema;
|
|
@@ -22,9 +26,11 @@ export declare class CursorPaginationBuilder {
|
|
|
22
26
|
/**
|
|
23
27
|
* Decodes a cursor string and builds WHERE + ORDER BY for the next page.
|
|
24
28
|
*/
|
|
25
|
-
build(config: TableConfig, cursor: string | undefined, pageSize: number, sort?: SortConfig[]): CursorResult;
|
|
29
|
+
build(config: TableConfig, cursor: string | undefined, pageSize: number, sort?: SortConfig[], sqlExpressions?: Map<string, SQL>): CursorResult;
|
|
26
30
|
/**
|
|
27
31
|
* From the fetched data (with 1 extra row), determine next cursor.
|
|
32
|
+
* The cursor encodes ALL sort field values from the last row so the
|
|
33
|
+
* compound WHERE condition can be reconstructed on the next request.
|
|
28
34
|
*/
|
|
29
35
|
buildMeta(data: Record<string, unknown>[], pageSize: number, sort?: SortConfig[]): {
|
|
30
36
|
data: Record<string, unknown>[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursorPagination.d.ts","sourceRoot":"","sources":["../../src/core/cursorPagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,GAAG,
|
|
1
|
+
{"version":3,"file":"cursorPagination.d.ts","sourceRoot":"","sources":["../../src/core/cursorPagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,GAAG,EAAmD,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGzD,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,GAAG,GAAG,SAAS,CAAC;IAChC,OAAO,EAAE,GAAG,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,uBAAuB;IACtB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEnD;;OAEG;IACH,KAAK,CACH,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,UAAU,EAAE,EACnB,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAChC,YAAY;IA2Gf;;;;OAIG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,UAAU,EAAE,GAClB;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE;CAuBzD;AAID,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAO3E"}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getTableColumns, gt, lt, eq, and, or, asc, desc } from 'drizzle-orm';
|
|
2
|
+
import { FieldError } from '../errors';
|
|
2
3
|
/**
|
|
3
4
|
* Cursor-based pagination.
|
|
4
|
-
* Uses the sort column
|
|
5
|
+
* Uses the sort column values as the cursor instead of OFFSET.
|
|
5
6
|
* O(1) performance regardless of page depth.
|
|
6
7
|
*
|
|
7
8
|
* Cursor format: base64({ field: value, field2: value2 })
|
|
9
|
+
*
|
|
10
|
+
* Multi-column sort: the WHERE clause uses ALL sort fields in a
|
|
11
|
+
* row-value comparison to avoid duplicate/skipped rows when rows
|
|
12
|
+
* share the same primary sort value.
|
|
8
13
|
*/
|
|
9
14
|
export class CursorPaginationBuilder {
|
|
10
15
|
schema;
|
|
@@ -14,7 +19,7 @@ export class CursorPaginationBuilder {
|
|
|
14
19
|
/**
|
|
15
20
|
* Decodes a cursor string and builds WHERE + ORDER BY for the next page.
|
|
16
21
|
*/
|
|
17
|
-
build(config, cursor, pageSize, sort) {
|
|
22
|
+
build(config, cursor, pageSize, sort, sqlExpressions) {
|
|
18
23
|
const table = this.schema[config.base];
|
|
19
24
|
if (!table) {
|
|
20
25
|
return { whereCondition: undefined, orderBy: [], limit: pageSize + 1 };
|
|
@@ -26,24 +31,80 @@ export class CursorPaginationBuilder {
|
|
|
26
31
|
: config.defaultSort?.length
|
|
27
32
|
? config.defaultSort
|
|
28
33
|
: [{ field: 'id', order: 'asc' }];
|
|
29
|
-
// Build ORDER BY
|
|
34
|
+
// Build ORDER BY — throw a FieldError for unknown fields instead of
|
|
35
|
+
// injecting unvalidated raw SQL identifiers.
|
|
30
36
|
const orderBy = sortFields.map((s) => {
|
|
31
37
|
const col = columns[s.field];
|
|
32
|
-
if (
|
|
33
|
-
return s.order === 'desc' ? desc(
|
|
34
|
-
|
|
38
|
+
if (col) {
|
|
39
|
+
return s.order === 'desc' ? desc(col) : asc(col);
|
|
40
|
+
}
|
|
41
|
+
if (sqlExpressions?.has(s.field)) {
|
|
42
|
+
const expr = sqlExpressions.get(s.field);
|
|
43
|
+
return s.order === 'desc' ? desc(expr) : asc(expr);
|
|
44
|
+
}
|
|
45
|
+
// Previously fell back to sql.identifier(s.field) — an unvalidated raw
|
|
46
|
+
// SQL identifier that bypasses all whitelist checks. Throw instead so
|
|
47
|
+
// the developer gets a clear, actionable error rather than a DB crash.
|
|
48
|
+
throw new FieldError(s.field, `cannot be used for cursor pagination: not a known column or SQL expression`);
|
|
35
49
|
});
|
|
36
50
|
// Decode cursor and build WHERE
|
|
51
|
+
// Uses ALL sort fields (compound cursor) so that rows sharing the same
|
|
52
|
+
// primary sort value are not duplicated or skipped across pages.
|
|
53
|
+
//
|
|
54
|
+
// For ORDER BY col1 ASC, col2 ASC with cursor (v1, v2), the correct
|
|
55
|
+
// continuation is a lexicographic OR-expansion:
|
|
56
|
+
//
|
|
57
|
+
// (col1 > v1)
|
|
58
|
+
// OR (col1 = v1 AND col2 > v2)
|
|
59
|
+
// OR (col1 = v1 AND col2 = v2 AND col3 > v3)
|
|
60
|
+
// ...
|
|
61
|
+
//
|
|
62
|
+
// A flat AND (col1 > v1 AND col2 > v2) is WRONG — it would skip rows
|
|
63
|
+
// where col1 = v1 and col2 > v2 (same primary sort value, later secondary).
|
|
37
64
|
let whereCondition;
|
|
38
65
|
if (cursor) {
|
|
39
66
|
const decoded = decodeCursor(cursor);
|
|
40
67
|
if (decoded && sortFields.length > 0) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
68
|
+
// Collect resolvable sort fields from base columns OR sqlExpressions
|
|
69
|
+
// (computed/subquery sort fields can participate in cursor continuation)
|
|
70
|
+
const resolvable = sortFields
|
|
71
|
+
.map((s) => {
|
|
72
|
+
const col = columns[s.field];
|
|
73
|
+
const expr = sqlExpressions?.get(s.field);
|
|
74
|
+
return { s, col, expr };
|
|
75
|
+
})
|
|
76
|
+
.filter(({ s, col, expr }) => (col !== undefined || expr !== undefined) && decoded[s.field] != null);
|
|
77
|
+
if (resolvable.length === 1) {
|
|
78
|
+
// Single field — simple gt/lt
|
|
79
|
+
const { s, col, expr } = resolvable[0];
|
|
80
|
+
const target = col ?? expr;
|
|
81
|
+
whereCondition = s.order === 'desc'
|
|
82
|
+
? lt(target, decoded[s.field])
|
|
83
|
+
: gt(target, decoded[s.field]);
|
|
84
|
+
}
|
|
85
|
+
else if (resolvable.length > 1) {
|
|
86
|
+
// Multi-field: build the lexicographic OR-expansion
|
|
87
|
+
// Each "arm" of the OR is: (prefix equality conditions) AND (advance condition)
|
|
88
|
+
const orArms = [];
|
|
89
|
+
for (let i = 0; i < resolvable.length; i++) {
|
|
90
|
+
const { s, col, expr } = resolvable[i];
|
|
91
|
+
const target = col ?? expr;
|
|
92
|
+
const advance = s.order === 'desc'
|
|
93
|
+
? lt(target, decoded[s.field])
|
|
94
|
+
: gt(target, decoded[s.field]);
|
|
95
|
+
if (i === 0) {
|
|
96
|
+
// First arm: just the advance condition on col1
|
|
97
|
+
orArms.push(advance);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Remaining arms: prefix equality on cols 0..i-1, advance on col i
|
|
101
|
+
const prefixEqs = resolvable
|
|
102
|
+
.slice(0, i)
|
|
103
|
+
.map(({ s: ps, col: pc, expr: pe }) => eq(pc ?? pe, decoded[ps.field]));
|
|
104
|
+
orArms.push(and(...prefixEqs, advance));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
whereCondition = or(...orArms);
|
|
47
108
|
}
|
|
48
109
|
}
|
|
49
110
|
}
|
|
@@ -56,6 +117,8 @@ export class CursorPaginationBuilder {
|
|
|
56
117
|
}
|
|
57
118
|
/**
|
|
58
119
|
* From the fetched data (with 1 extra row), determine next cursor.
|
|
120
|
+
* The cursor encodes ALL sort field values from the last row so the
|
|
121
|
+
* compound WHERE condition can be reconstructed on the next request.
|
|
59
122
|
*/
|
|
60
123
|
buildMeta(data, pageSize, sort) {
|
|
61
124
|
const hasMore = data.length > pageSize;
|
|
@@ -63,8 +126,15 @@ export class CursorPaginationBuilder {
|
|
|
63
126
|
let nextCursor = null;
|
|
64
127
|
if (hasMore && trimmed.length > 0) {
|
|
65
128
|
const lastRow = trimmed[trimmed.length - 1];
|
|
66
|
-
|
|
67
|
-
|
|
129
|
+
// Encode ALL sort field values so the compound cursor WHERE is complete
|
|
130
|
+
const sortFields = sort?.length ? sort : [{ field: 'id', order: 'asc' }];
|
|
131
|
+
const cursorValues = {};
|
|
132
|
+
for (const s of sortFields) {
|
|
133
|
+
if (lastRow[s.field] != null) {
|
|
134
|
+
cursorValues[s.field] = lastRow[s.field];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
nextCursor = encodeCursor(cursorValues);
|
|
68
138
|
}
|
|
69
139
|
return {
|
|
70
140
|
data: trimmed,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursorPagination.js","sourceRoot":"","sources":["../../src/core/cursorPagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,
|
|
1
|
+
{"version":3,"file":"cursorPagination.js","sourceRoot":"","sources":["../../src/core/cursorPagination.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fieldSelector.d.ts","sourceRoot":"","sources":["../../src/core/fieldSelector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"fieldSelector.d.ts","sourceRoot":"","sources":["../../src/core/fieldSelector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C;;;GAGG;AACH,qBAAa,aAAa;IACxB;;;OAGG;IACH,mBAAmB,CACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC,EACvC,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS,EACrC,MAAM,EAAE,WAAW,GAClB,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC;IAiC/B;;;OAGG;IACH,oBAAoB,CAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS,GACpC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;CAe7B"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { collectSelectableJoinFields } from '../utils/joinUtils';
|
|
1
2
|
/**
|
|
2
3
|
* Filters the selection to only include requested fields.
|
|
3
4
|
* Supports `?select=id,name,email` from URL.
|
|
@@ -10,8 +11,13 @@ export class FieldSelector {
|
|
|
10
11
|
applyFieldSelection(selection, requestedFields, config) {
|
|
11
12
|
if (!requestedFields?.length)
|
|
12
13
|
return selection;
|
|
13
|
-
// Build a whitelist of allowed (non-hidden) fields
|
|
14
|
+
// Build a whitelist of allowed (non-hidden) fields — base columns first
|
|
14
15
|
const allowed = new Set(config.columns.filter((c) => !c.hidden).map((c) => c.name));
|
|
16
|
+
// Also allow selectable fields from joined tables so that
|
|
17
|
+
// ?select=joinColumn correctly includes them in the SQL selection.
|
|
18
|
+
if (config.joins?.length) {
|
|
19
|
+
collectSelectableJoinFields(config.joins, allowed);
|
|
20
|
+
}
|
|
15
21
|
const filtered = {};
|
|
16
22
|
for (const field of requestedFields) {
|
|
17
23
|
if (allowed.has(field) && selection[field]) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fieldSelector.js","sourceRoot":"","sources":["../../src/core/fieldSelector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fieldSelector.js","sourceRoot":"","sources":["../../src/core/fieldSelector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEjE;;;GAGG;AACH,MAAM,OAAO,aAAa;IACxB;;;OAGG;IACH,mBAAmB,CACjB,SAAuC,EACvC,eAAqC,EACrC,MAAmB;QAEnB,IAAI,CAAC,eAAe,EAAE,MAAM;YAAE,OAAO,SAAS,CAAC;QAE/C,wEAAwE;QACxE,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAC3D,CAAC;QAEF,0DAA0D;QAC1D,mEAAmE;QACnE,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YACzB,2BAA2B,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,QAAQ,GAAiC,EAAE,CAAC;QAElD,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,QAAQ,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAC1D,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC3B,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,CAAC;IAED;;;OAGG;IACH,oBAAoB,CAClB,IAA+B,EAC/B,eAAqC;QAErC,IAAI,CAAC,eAAe,EAAE,MAAM;YAAE,OAAO,IAAI,CAAC;QAE1C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;QAE1C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACtB,MAAM,QAAQ,GAA4B,EAAE,CAAC;YAC7C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;gBAC7B,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;oBACjB,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -8,7 +8,7 @@ export declare class FilterBuilder {
|
|
|
8
8
|
* Builds dynamic WHERE conditions from user-provided filter params.
|
|
9
9
|
* Only allows filtering on columns explicitly marked as filterable.
|
|
10
10
|
*/
|
|
11
|
-
buildFilters(config: TableConfig, params: Record<string, FilterParam>): SQL | undefined;
|
|
11
|
+
buildFilters(config: TableConfig, params: Record<string, FilterParam | FilterParam[]>): SQL | undefined;
|
|
12
12
|
/**
|
|
13
13
|
* Builds conditions for filters with type='static' (preset values in config).
|
|
14
14
|
* Supports both base columns and join columns.
|
|
@@ -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,EAA4B,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
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;AAa9C,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,GAAG,WAAW,EAAE,CAAC,GAClD,GAAG,GAAG,SAAS;IA0ElB;;;OAGG;IACH,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG,GAAG,SAAS;IA6BxD;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAqCrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CA+B1B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getTableColumns, and, } from 'drizzle-orm';
|
|
2
2
|
import { applyOperator } from '../utils/operators';
|
|
3
3
|
import { isDatePreset, buildDatePresetCondition } from './datePresets';
|
|
4
|
+
import { collectFilterableJoinFields, isJoinColumnInJoins } from '../utils/joinUtils';
|
|
4
5
|
export class FilterBuilder {
|
|
5
6
|
schema;
|
|
6
7
|
constructor(schema) {
|
|
@@ -35,16 +36,20 @@ export class FilterBuilder {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
// From join columns marked filterable (recursive)
|
|
39
|
+
const joinFields = new Set();
|
|
38
40
|
if (config.joins) {
|
|
39
|
-
collectFilterableJoinFields(config.joins,
|
|
41
|
+
collectFilterableJoinFields(config.joins, joinFields);
|
|
42
|
+
for (const jf of joinFields) {
|
|
43
|
+
filterableFields.add(jf);
|
|
44
|
+
}
|
|
40
45
|
}
|
|
41
46
|
const conditions = [];
|
|
42
|
-
for (const [field,
|
|
47
|
+
for (const [field, paramOrParams] of Object.entries(params)) {
|
|
43
48
|
// Security: reject fields not in the whitelist
|
|
44
49
|
if (!filterableFields.has(field))
|
|
45
50
|
continue;
|
|
46
|
-
// Determine whether this field is a join column
|
|
47
|
-
const isJoinField =
|
|
51
|
+
// Determine whether this field is a join column using the Set
|
|
52
|
+
const isJoinField = joinFields.has(field);
|
|
48
53
|
// Resolve the column — could be on the base table or a joined table.
|
|
49
54
|
// Pass isJoinField so that base-table columns can never shadow join columns.
|
|
50
55
|
const resolved = this.resolveColumn(config, baseColumns, field, isJoinField);
|
|
@@ -53,16 +58,19 @@ export class FilterBuilder {
|
|
|
53
58
|
continue;
|
|
54
59
|
}
|
|
55
60
|
const { column: col } = resolved;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
const paramsList = Array.isArray(paramOrParams) ? paramOrParams : [paramOrParams];
|
|
62
|
+
for (const param of paramsList) {
|
|
63
|
+
// Check if value is a date preset
|
|
64
|
+
if (isDatePreset(param.value)) {
|
|
65
|
+
const presetCondition = buildDatePresetCondition(col, param.value);
|
|
66
|
+
if (presetCondition)
|
|
67
|
+
conditions.push(presetCondition);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const condition = applyOperator(param.operator, col, param.value);
|
|
71
|
+
if (condition)
|
|
72
|
+
conditions.push(condition);
|
|
62
73
|
}
|
|
63
|
-
const condition = applyOperator(param.operator, col, param.value);
|
|
64
|
-
if (condition)
|
|
65
|
-
conditions.push(condition);
|
|
66
74
|
}
|
|
67
75
|
return conditions.length > 0 ? and(...conditions) : undefined;
|
|
68
76
|
}
|
|
@@ -81,7 +89,7 @@ export class FilterBuilder {
|
|
|
81
89
|
for (const filter of config.filters) {
|
|
82
90
|
if (filter.type !== 'static' || filter.value === undefined)
|
|
83
91
|
continue;
|
|
84
|
-
const isJoinField =
|
|
92
|
+
const isJoinField = isJoinColumnInJoins(config.joins ?? [], filter.field);
|
|
85
93
|
const resolved = this.resolveColumn(config, baseColumns, filter.field, isJoinField);
|
|
86
94
|
if (!resolved) {
|
|
87
95
|
console.warn(`[FilterBuilder] Static filter: could not resolve column "${filter.field}" — skipped`);
|
|
@@ -161,44 +169,4 @@ export class FilterBuilder {
|
|
|
161
169
|
return undefined;
|
|
162
170
|
}
|
|
163
171
|
}
|
|
164
|
-
// ---------------------------------------------------------------------------
|
|
165
|
-
// Module-level helpers (pure, no `this` dependency)
|
|
166
|
-
// ---------------------------------------------------------------------------
|
|
167
|
-
/**
|
|
168
|
-
* Recursively populates `out` with filterable field names from all join configs.
|
|
169
|
-
*/
|
|
170
|
-
function collectFilterableJoinFields(joins, out) {
|
|
171
|
-
for (const join of joins) {
|
|
172
|
-
if (join.columns) {
|
|
173
|
-
for (const col of join.columns) {
|
|
174
|
-
if (col.filterable !== false) {
|
|
175
|
-
out.add(col.name);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (join.joins) {
|
|
180
|
-
collectFilterableJoinFields(join.joins, out);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Returns true if `fieldName` is defined in any join config (recursively).
|
|
186
|
-
* Used to prevent base-table columns from shadowing join columns.
|
|
187
|
-
*/
|
|
188
|
-
function isJoinColumn(config, fieldName) {
|
|
189
|
-
if (!config.joins)
|
|
190
|
-
return false;
|
|
191
|
-
return isJoinColumnInJoins(config.joins, fieldName);
|
|
192
|
-
}
|
|
193
|
-
function isJoinColumnInJoins(joins, fieldName) {
|
|
194
|
-
for (const join of joins) {
|
|
195
|
-
if (join.columns?.some(c => c.name === fieldName)) {
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
if (join.joins && isJoinColumnInJoins(join.joins, fieldName)) {
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return false;
|
|
203
|
-
}
|
|
204
172
|
//# 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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputValidator.d.ts","sourceRoot":"","sources":["../../src/core/inputValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgB,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAe,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"inputValidator.d.ts","sourceRoot":"","sources":["../../src/core/inputValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgB,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAe,MAAM,iBAAiB,CAAC;AAI5D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAI7E"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ValidationError, FieldError } from '../errors';
|
|
2
|
+
import { collectSortableJoinFields, collectSelectableJoinFields } from '../utils/joinUtils';
|
|
2
3
|
/**
|
|
3
4
|
* Validates request params against the table config BEFORE hitting the database.
|
|
4
5
|
* Catches type mismatches, invalid fields, and bad values early.
|
|
@@ -11,14 +12,15 @@ export function validateInput(params, config) {
|
|
|
11
12
|
function validateSelectFields(params, config) {
|
|
12
13
|
if (!params.select?.length)
|
|
13
14
|
return;
|
|
14
|
-
|
|
15
|
+
// Build valid set from base columns (non-hidden only)
|
|
16
|
+
const validNames = new Set(config.columns.filter((c) => !c.hidden).map((c) => c.name));
|
|
17
|
+
// Also allow selectable fields from joined tables
|
|
18
|
+
if (config.joins?.length) {
|
|
19
|
+
collectSelectableJoinFields(config.joins, validNames);
|
|
20
|
+
}
|
|
15
21
|
for (const field of params.select) {
|
|
16
22
|
if (!validNames.has(field)) {
|
|
17
|
-
throw new FieldError(field, 'does not exist. Available: ' + [...validNames].join(', '));
|
|
18
|
-
}
|
|
19
|
-
const col = config.columns.find((c) => c.name === field);
|
|
20
|
-
if (col?.hidden) {
|
|
21
|
-
throw new FieldError(field, 'is not accessible');
|
|
23
|
+
throw new FieldError(field, 'does not exist or is not accessible. Available: ' + [...validNames].join(', '));
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -29,7 +31,7 @@ function validateFilterValues(params, config) {
|
|
|
29
31
|
for (const col of config.columns) {
|
|
30
32
|
columnMap.set(col.name, col);
|
|
31
33
|
}
|
|
32
|
-
for (const [field,
|
|
34
|
+
for (const [field, filterOrFilters] of Object.entries(params.filters)) {
|
|
33
35
|
const col = columnMap.get(field);
|
|
34
36
|
if (!col) {
|
|
35
37
|
if (typeof process !== 'undefined' && process.env?.NODE_ENV !== 'test') {
|
|
@@ -40,9 +42,12 @@ function validateFilterValues(params, config) {
|
|
|
40
42
|
if (!col.filterable) {
|
|
41
43
|
throw new FieldError(field, 'is not filterable');
|
|
42
44
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const filters = Array.isArray(filterOrFilters) ? filterOrFilters : [filterOrFilters];
|
|
46
|
+
for (const filter of filters) {
|
|
47
|
+
if (filter.operator === 'isNull' || filter.operator === 'isNotNull')
|
|
48
|
+
continue;
|
|
49
|
+
validateValueType(field, col.type, filter);
|
|
50
|
+
}
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
function validateValueType(field, colType, filter) {
|
|
@@ -107,34 +112,18 @@ function validateSingleValue(field, colType, value) {
|
|
|
107
112
|
function validateSortFields(params, config) {
|
|
108
113
|
if (!params.sort?.length)
|
|
109
114
|
return;
|
|
110
|
-
const sortable = new Set(config.columns.filter((c) => c.sortable).map((c) => c.name));
|
|
115
|
+
const sortable = new Set(config.columns.filter((c) => c.sortable !== false).map((c) => c.name));
|
|
111
116
|
// Also collect sortable fields from joins (same pattern as FilterBuilder
|
|
112
117
|
// uses collectFilterableJoinFields for filterable fields)
|
|
113
|
-
|
|
118
|
+
if (config.joins?.length) {
|
|
119
|
+
collectSortableJoinFields(config.joins, sortable);
|
|
120
|
+
}
|
|
114
121
|
for (const s of params.sort) {
|
|
115
122
|
if (!sortable.has(s.field)) {
|
|
116
123
|
throw new FieldError(s.field, 'is not sortable. Sortable: ' + [...sortable].join(', '));
|
|
117
124
|
}
|
|
118
125
|
}
|
|
119
126
|
}
|
|
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
|
-
}
|
|
138
127
|
function isValidUUID(str) {
|
|
139
128
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str);
|
|
140
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputValidator.js","sourceRoot":"","sources":["../../src/core/inputValidator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"inputValidator.js","sourceRoot":"","sources":["../../src/core/inputValidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataBuilder.d.ts","sourceRoot":"","sources":["../../src/core/metadataBuilder.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"metadataBuilder.d.ts","sourceRoot":"","sources":["../../src/core/metadataBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,15 +22,20 @@ export function buildMetadata(config, context) {
|
|
|
22
22
|
if (config.subqueries) {
|
|
23
23
|
for (const sub of config.subqueries) {
|
|
24
24
|
// Subqueries produce a virtual column with the alias name
|
|
25
|
-
// Only add if not already in allColumns (
|
|
25
|
+
// Only add if not already in allColumns (define.ts builder always pre-populates
|
|
26
|
+
// via .subquery(), but raw TableConfig JSON objects bypass the builder).
|
|
26
27
|
if (!allColumns.some(c => c.name === sub.alias)) {
|
|
28
|
+
// 'first' mode returns row_to_json() — non-scalar JSON object.
|
|
29
|
+
// 'count' returns integer, 'exists' returns boolean.
|
|
30
|
+
// filterable: false matches define.ts to keep both paths consistent.
|
|
31
|
+
const subqueryType = sub.type === 'exists' ? 'boolean' : sub.type === 'count' ? 'number' : 'json';
|
|
27
32
|
allColumns.push({
|
|
28
33
|
name: sub.alias,
|
|
29
|
-
type:
|
|
34
|
+
type: subqueryType,
|
|
30
35
|
label: sub.alias,
|
|
31
36
|
hidden: false,
|
|
32
|
-
sortable:
|
|
33
|
-
filterable:
|
|
37
|
+
sortable: sub.type !== 'first',
|
|
38
|
+
filterable: false,
|
|
34
39
|
computed: true,
|
|
35
40
|
_source: 'subquery',
|
|
36
41
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataBuilder.js","sourceRoot":"","sources":["../../src/core/metadataBuilder.ts"],"names":[],"mappings":"AA+EA;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAmB,EACnB,OAAuB;IAEvB,MAAM,SAAS,GAAG,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;IAE7C,8CAA8C;IAE9C,MAAM,UAAU,GAAiE,EAAE,CAAC;IAEpF,0EAA0E;IAC1E,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjC,UAAU,CAAC,IAAI,CAAC;YACd,GAAG,GAAG;YACN,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM;SACrC,CAAC,CAAC;IACZ,CAAC;IAED,mDAAmD;IACnD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,2BAA2B,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IAED,8BAA8B;IAC9B,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACpC,0DAA0D;YAC1D,
|
|
1
|
+
{"version":3,"file":"metadataBuilder.js","sourceRoot":"","sources":["../../src/core/metadataBuilder.ts"],"names":[],"mappings":"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"}
|