@proofkit/fmodata 0.1.0-alpha.8 → 0.1.0-beta.23
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.md +21 -0
- package/README.md +651 -449
- package/dist/esm/client/batch-builder.d.ts +10 -9
- package/dist/esm/client/batch-builder.js +119 -56
- package/dist/esm/client/batch-builder.js.map +1 -1
- package/dist/esm/client/batch-request.js +16 -21
- package/dist/esm/client/batch-request.js.map +1 -1
- package/dist/esm/client/builders/default-select.d.ts +10 -0
- package/dist/esm/client/builders/default-select.js +41 -0
- package/dist/esm/client/builders/default-select.js.map +1 -0
- package/dist/esm/client/builders/expand-builder.d.ts +45 -0
- package/dist/esm/client/builders/expand-builder.js +185 -0
- package/dist/esm/client/builders/expand-builder.js.map +1 -0
- package/dist/esm/client/builders/index.d.ts +9 -0
- package/dist/esm/client/builders/query-string-builder.d.ts +18 -0
- package/dist/esm/client/builders/query-string-builder.js +21 -0
- package/dist/esm/client/builders/query-string-builder.js.map +1 -0
- package/dist/esm/client/builders/response-processor.d.ts +43 -0
- package/dist/esm/client/builders/response-processor.js +175 -0
- package/dist/esm/client/builders/response-processor.js.map +1 -0
- package/dist/esm/client/builders/select-mixin.d.ts +25 -0
- package/dist/esm/client/builders/select-mixin.js +28 -0
- package/dist/esm/client/builders/select-mixin.js.map +1 -0
- package/dist/esm/client/builders/select-utils.d.ts +18 -0
- package/dist/esm/client/builders/select-utils.js +30 -0
- package/dist/esm/client/builders/select-utils.js.map +1 -0
- package/dist/esm/client/builders/shared-types.d.ts +40 -0
- package/dist/esm/client/builders/table-utils.d.ts +35 -0
- package/dist/esm/client/builders/table-utils.js +44 -0
- package/dist/esm/client/builders/table-utils.js.map +1 -0
- package/dist/esm/client/database.d.ts +34 -22
- package/dist/esm/client/database.js +48 -84
- package/dist/esm/client/database.js.map +1 -1
- package/dist/esm/client/delete-builder.d.ts +25 -30
- package/dist/esm/client/delete-builder.js +45 -30
- package/dist/esm/client/delete-builder.js.map +1 -1
- package/dist/esm/client/entity-set.d.ts +35 -43
- package/dist/esm/client/entity-set.js +110 -52
- package/dist/esm/client/entity-set.js.map +1 -1
- package/dist/esm/client/error-parser.d.ts +12 -0
- package/dist/esm/client/error-parser.js +25 -0
- package/dist/esm/client/error-parser.js.map +1 -0
- package/dist/esm/client/filemaker-odata.d.ts +26 -7
- package/dist/esm/client/filemaker-odata.js +65 -42
- package/dist/esm/client/filemaker-odata.js.map +1 -1
- package/dist/esm/client/insert-builder.d.ts +19 -24
- package/dist/esm/client/insert-builder.js +94 -58
- package/dist/esm/client/insert-builder.js.map +1 -1
- package/dist/esm/client/query/expand-builder.d.ts +35 -0
- package/dist/esm/client/query/index.d.ts +4 -0
- package/dist/esm/client/query/query-builder.d.ts +132 -0
- package/dist/esm/client/query/query-builder.js +456 -0
- package/dist/esm/client/query/query-builder.js.map +1 -0
- package/dist/esm/client/query/response-processor.d.ts +25 -0
- package/dist/esm/client/query/types.d.ts +77 -0
- package/dist/esm/client/query/url-builder.d.ts +71 -0
- package/dist/esm/client/query/url-builder.js +100 -0
- package/dist/esm/client/query/url-builder.js.map +1 -0
- package/dist/esm/client/query-builder.d.ts +2 -115
- package/dist/esm/client/record-builder.d.ts +108 -36
- package/dist/esm/client/record-builder.js +284 -119
- package/dist/esm/client/record-builder.js.map +1 -1
- package/dist/esm/client/response-processor.d.ts +4 -9
- package/dist/esm/client/sanitize-json.d.ts +35 -0
- package/dist/esm/client/sanitize-json.js +27 -0
- package/dist/esm/client/sanitize-json.js.map +1 -0
- package/dist/esm/client/schema-manager.d.ts +5 -5
- package/dist/esm/client/schema-manager.js +45 -31
- package/dist/esm/client/schema-manager.js.map +1 -1
- package/dist/esm/client/update-builder.d.ts +34 -40
- package/dist/esm/client/update-builder.js +99 -58
- package/dist/esm/client/update-builder.js.map +1 -1
- package/dist/esm/client/webhook-builder.d.ts +126 -0
- package/dist/esm/client/webhook-builder.js +189 -0
- package/dist/esm/client/webhook-builder.js.map +1 -0
- package/dist/esm/errors.d.ts +19 -2
- package/dist/esm/errors.js +39 -4
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +10 -8
- package/dist/esm/index.js +40 -10
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logger.d.ts +47 -0
- package/dist/esm/logger.js +69 -0
- package/dist/esm/logger.js.map +1 -0
- package/dist/esm/logger.test.d.ts +1 -0
- package/dist/esm/orm/column.d.ts +62 -0
- package/dist/esm/orm/column.js +63 -0
- package/dist/esm/orm/column.js.map +1 -0
- package/dist/esm/orm/field-builders.d.ts +164 -0
- package/dist/esm/orm/field-builders.js +158 -0
- package/dist/esm/orm/field-builders.js.map +1 -0
- package/dist/esm/orm/index.d.ts +5 -0
- package/dist/esm/orm/operators.d.ts +173 -0
- package/dist/esm/orm/operators.js +260 -0
- package/dist/esm/orm/operators.js.map +1 -0
- package/dist/esm/orm/table.d.ts +355 -0
- package/dist/esm/orm/table.js +202 -0
- package/dist/esm/orm/table.js.map +1 -0
- package/dist/esm/transform.d.ts +20 -21
- package/dist/esm/transform.js +44 -45
- package/dist/esm/transform.js.map +1 -1
- package/dist/esm/types.d.ts +96 -30
- package/dist/esm/types.js +7 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/validation.d.ts +22 -12
- package/dist/esm/validation.js +132 -85
- package/dist/esm/validation.js.map +1 -1
- package/package.json +28 -20
- package/src/client/batch-builder.ts +153 -89
- package/src/client/batch-request.ts +25 -41
- package/src/client/builders/default-select.ts +75 -0
- package/src/client/builders/expand-builder.ts +246 -0
- package/src/client/builders/index.ts +11 -0
- package/src/client/builders/query-string-builder.ts +46 -0
- package/src/client/builders/response-processor.ts +279 -0
- package/src/client/builders/select-mixin.ts +65 -0
- package/src/client/builders/select-utils.ts +59 -0
- package/src/client/builders/shared-types.ts +45 -0
- package/src/client/builders/table-utils.ts +83 -0
- package/src/client/database.ts +89 -183
- package/src/client/delete-builder.ts +74 -84
- package/src/client/entity-set.ts +266 -293
- package/src/client/error-parser.ts +41 -0
- package/src/client/filemaker-odata.ts +98 -66
- package/src/client/insert-builder.ts +157 -118
- package/src/client/query/expand-builder.ts +160 -0
- package/src/client/query/index.ts +14 -0
- package/src/client/query/query-builder.ts +729 -0
- package/src/client/query/response-processor.ts +226 -0
- package/src/client/query/types.ts +126 -0
- package/src/client/query/url-builder.ts +151 -0
- package/src/client/query-builder.ts +10 -1455
- package/src/client/record-builder.ts +575 -240
- package/src/client/response-processor.ts +15 -42
- package/src/client/sanitize-json.ts +64 -0
- package/src/client/schema-manager.ts +61 -76
- package/src/client/update-builder.ts +161 -143
- package/src/client/webhook-builder.ts +265 -0
- package/src/errors.ts +49 -16
- package/src/index.ts +99 -54
- package/src/logger.test.ts +34 -0
- package/src/logger.ts +116 -0
- package/src/orm/column.ts +106 -0
- package/src/orm/field-builders.ts +250 -0
- package/src/orm/index.ts +61 -0
- package/src/orm/operators.ts +473 -0
- package/src/orm/table.ts +741 -0
- package/src/transform.ts +90 -70
- package/src/types.ts +154 -113
- package/src/validation.ts +200 -115
- package/dist/esm/client/base-table.d.ts +0 -125
- package/dist/esm/client/base-table.js +0 -57
- package/dist/esm/client/base-table.js.map +0 -1
- package/dist/esm/client/query-builder.js +0 -896
- package/dist/esm/client/query-builder.js.map +0 -1
- package/dist/esm/client/table-occurrence.d.ts +0 -72
- package/dist/esm/client/table-occurrence.js +0 -74
- package/dist/esm/client/table-occurrence.js.map +0 -1
- package/dist/esm/filter-types.d.ts +0 -76
- package/src/client/base-table.ts +0 -166
- package/src/client/query-builder.ts.bak +0 -1457
- package/src/client/table-occurrence.ts +0 -175
- package/src/filter-types.ts +0 -97
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { needsFieldQuoting } from "../client/builders/select-utils.js";
|
|
5
|
+
import { isColumn } from "./column.js";
|
|
6
|
+
class FilterExpression {
|
|
7
|
+
// biome-ignore lint/suspicious/noExplicitAny: Operands can be Column, FilterExpression, or any value type
|
|
8
|
+
constructor(operator, operands) {
|
|
9
|
+
__publicField(this, "operator");
|
|
10
|
+
// biome-ignore lint/suspicious/noExplicitAny: Operands can be Column, FilterExpression, or any value type
|
|
11
|
+
__publicField(this, "operands");
|
|
12
|
+
this.operator = operator;
|
|
13
|
+
this.operands = operands;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Convert this expression to OData filter syntax.
|
|
17
|
+
* @internal Used by QueryBuilder
|
|
18
|
+
*/
|
|
19
|
+
toODataFilter(useEntityIds) {
|
|
20
|
+
switch (this.operator) {
|
|
21
|
+
// Comparison operators
|
|
22
|
+
case "eq":
|
|
23
|
+
return this._binaryOp("eq", useEntityIds);
|
|
24
|
+
case "ne":
|
|
25
|
+
return this._binaryOp("ne", useEntityIds);
|
|
26
|
+
case "gt":
|
|
27
|
+
return this._binaryOp("gt", useEntityIds);
|
|
28
|
+
case "gte":
|
|
29
|
+
return this._binaryOp("ge", useEntityIds);
|
|
30
|
+
case "lt":
|
|
31
|
+
return this._binaryOp("lt", useEntityIds);
|
|
32
|
+
case "lte":
|
|
33
|
+
return this._binaryOp("le", useEntityIds);
|
|
34
|
+
case "in":
|
|
35
|
+
return this._inOp(useEntityIds);
|
|
36
|
+
case "notIn":
|
|
37
|
+
return this._notInOp(useEntityIds);
|
|
38
|
+
// String operators
|
|
39
|
+
case "contains":
|
|
40
|
+
return this._functionOp("contains", useEntityIds);
|
|
41
|
+
case "startsWith":
|
|
42
|
+
return this._functionOp("startswith", useEntityIds);
|
|
43
|
+
case "endsWith":
|
|
44
|
+
return this._functionOp("endswith", useEntityIds);
|
|
45
|
+
// Null checks
|
|
46
|
+
case "isNull":
|
|
47
|
+
return this._isNullOp(useEntityIds);
|
|
48
|
+
case "isNotNull":
|
|
49
|
+
return this._isNotNullOp(useEntityIds);
|
|
50
|
+
// Logical operators
|
|
51
|
+
case "and":
|
|
52
|
+
return this._logicalOp("and", useEntityIds);
|
|
53
|
+
case "or":
|
|
54
|
+
return this._logicalOp("or", useEntityIds);
|
|
55
|
+
case "not":
|
|
56
|
+
return this._notOp(useEntityIds);
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(`Unknown operator: ${this.operator}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
_binaryOp(op, useEntityIds) {
|
|
62
|
+
const [left, right] = this.operands;
|
|
63
|
+
let columnForValue;
|
|
64
|
+
if (isColumn(left) && !isColumn(right)) {
|
|
65
|
+
columnForValue = left;
|
|
66
|
+
} else if (isColumn(right) && !isColumn(left)) {
|
|
67
|
+
columnForValue = right;
|
|
68
|
+
} else {
|
|
69
|
+
columnForValue = void 0;
|
|
70
|
+
}
|
|
71
|
+
const leftStr = this._operandToString(left, useEntityIds, columnForValue);
|
|
72
|
+
const rightStr = this._operandToString(right, useEntityIds, columnForValue);
|
|
73
|
+
return `${leftStr} ${op} ${rightStr}`;
|
|
74
|
+
}
|
|
75
|
+
_functionOp(fnName, useEntityIds) {
|
|
76
|
+
const [column, value] = this.operands;
|
|
77
|
+
const columnInstance = isColumn(column) ? column : void 0;
|
|
78
|
+
const columnStr = this._operandToString(column, useEntityIds);
|
|
79
|
+
const valueStr = this._operandToString(value, useEntityIds, columnInstance);
|
|
80
|
+
return `${fnName}(${columnStr}, ${valueStr})`;
|
|
81
|
+
}
|
|
82
|
+
_inOp(useEntityIds) {
|
|
83
|
+
const [column, values] = this.operands;
|
|
84
|
+
const columnInstance = isColumn(column) ? column : void 0;
|
|
85
|
+
const columnStr = this._operandToString(column, useEntityIds);
|
|
86
|
+
const valuesStr = values.map((v) => this._operandToString(v, useEntityIds, columnInstance)).join(", ");
|
|
87
|
+
return `${columnStr} in (${valuesStr})`;
|
|
88
|
+
}
|
|
89
|
+
_notInOp(useEntityIds) {
|
|
90
|
+
const [column, values] = this.operands;
|
|
91
|
+
const columnInstance = isColumn(column) ? column : void 0;
|
|
92
|
+
const columnStr = this._operandToString(column, useEntityIds);
|
|
93
|
+
const valuesStr = values.map((v) => this._operandToString(v, useEntityIds, columnInstance)).join(", ");
|
|
94
|
+
return `not (${columnStr} in (${valuesStr}))`;
|
|
95
|
+
}
|
|
96
|
+
_isNullOp(useEntityIds) {
|
|
97
|
+
const [column] = this.operands;
|
|
98
|
+
const columnStr = this._operandToString(column, useEntityIds);
|
|
99
|
+
return `${columnStr} eq null`;
|
|
100
|
+
}
|
|
101
|
+
_isNotNullOp(useEntityIds) {
|
|
102
|
+
const [column] = this.operands;
|
|
103
|
+
const columnStr = this._operandToString(column, useEntityIds);
|
|
104
|
+
return `${columnStr} ne null`;
|
|
105
|
+
}
|
|
106
|
+
_logicalOp(op, useEntityIds) {
|
|
107
|
+
const expressions = this.operands.map((expr) => {
|
|
108
|
+
if (expr instanceof FilterExpression) {
|
|
109
|
+
const innerExpr = expr.toODataFilter(useEntityIds);
|
|
110
|
+
if (expr.operator === "and" || expr.operator === "or") {
|
|
111
|
+
return `(${innerExpr})`;
|
|
112
|
+
}
|
|
113
|
+
return innerExpr;
|
|
114
|
+
}
|
|
115
|
+
throw new Error("Logical operators require FilterExpression operands");
|
|
116
|
+
});
|
|
117
|
+
return expressions.join(` ${op} `);
|
|
118
|
+
}
|
|
119
|
+
_notOp(useEntityIds) {
|
|
120
|
+
const [expr] = this.operands;
|
|
121
|
+
if (expr instanceof FilterExpression) {
|
|
122
|
+
return `not (${expr.toODataFilter(useEntityIds)})`;
|
|
123
|
+
}
|
|
124
|
+
throw new Error("NOT operator requires a FilterExpression operand");
|
|
125
|
+
}
|
|
126
|
+
_operandToString(operand, useEntityIds, column) {
|
|
127
|
+
if (isColumn(operand)) {
|
|
128
|
+
const fieldIdentifier = operand.getFieldIdentifier(useEntityIds);
|
|
129
|
+
return needsFieldQuoting(fieldIdentifier) ? `"${fieldIdentifier}"` : fieldIdentifier;
|
|
130
|
+
}
|
|
131
|
+
let value = operand;
|
|
132
|
+
if (column == null ? void 0 : column.inputValidator) {
|
|
133
|
+
try {
|
|
134
|
+
const result = column.inputValidator["~standard"].validate(value);
|
|
135
|
+
if (result instanceof Promise) {
|
|
136
|
+
value = operand;
|
|
137
|
+
} else if ("issues" in result && result.issues) {
|
|
138
|
+
value = operand;
|
|
139
|
+
} else if ("value" in result) {
|
|
140
|
+
value = result.value;
|
|
141
|
+
}
|
|
142
|
+
} catch (_error) {
|
|
143
|
+
value = operand;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (typeof value === "string") {
|
|
147
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
148
|
+
}
|
|
149
|
+
if (value === null || value === void 0) {
|
|
150
|
+
return "null";
|
|
151
|
+
}
|
|
152
|
+
if (value instanceof Date) {
|
|
153
|
+
return value.toISOString();
|
|
154
|
+
}
|
|
155
|
+
return String(value);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function eq(column, value) {
|
|
159
|
+
return new FilterExpression("eq", [column, value]);
|
|
160
|
+
}
|
|
161
|
+
function ne(column, value) {
|
|
162
|
+
return new FilterExpression("ne", [column, value]);
|
|
163
|
+
}
|
|
164
|
+
function gt(column, value) {
|
|
165
|
+
return new FilterExpression("gt", [column, value]);
|
|
166
|
+
}
|
|
167
|
+
function gte(column, value) {
|
|
168
|
+
return new FilterExpression("gte", [column, value]);
|
|
169
|
+
}
|
|
170
|
+
function lt(column, value) {
|
|
171
|
+
return new FilterExpression("lt", [column, value]);
|
|
172
|
+
}
|
|
173
|
+
function lte(column, value) {
|
|
174
|
+
return new FilterExpression("lte", [column, value]);
|
|
175
|
+
}
|
|
176
|
+
function contains(column, value) {
|
|
177
|
+
return new FilterExpression("contains", [column, value]);
|
|
178
|
+
}
|
|
179
|
+
function startsWith(column, value) {
|
|
180
|
+
return new FilterExpression("startsWith", [column, value]);
|
|
181
|
+
}
|
|
182
|
+
function endsWith(column, value) {
|
|
183
|
+
return new FilterExpression("endsWith", [column, value]);
|
|
184
|
+
}
|
|
185
|
+
function inArray(column, values) {
|
|
186
|
+
return new FilterExpression("in", [column, values]);
|
|
187
|
+
}
|
|
188
|
+
function notInArray(column, values) {
|
|
189
|
+
return new FilterExpression("notIn", [column, values]);
|
|
190
|
+
}
|
|
191
|
+
function isNull(column) {
|
|
192
|
+
return new FilterExpression("isNull", [column]);
|
|
193
|
+
}
|
|
194
|
+
function isNotNull(column) {
|
|
195
|
+
return new FilterExpression("isNotNull", [column]);
|
|
196
|
+
}
|
|
197
|
+
function and(...expressions) {
|
|
198
|
+
if (expressions.length === 0) {
|
|
199
|
+
throw new Error("AND operator requires at least one expression");
|
|
200
|
+
}
|
|
201
|
+
if (expressions.length === 1 && expressions[0] !== void 0) {
|
|
202
|
+
return expressions[0];
|
|
203
|
+
}
|
|
204
|
+
return new FilterExpression("and", expressions);
|
|
205
|
+
}
|
|
206
|
+
function or(...expressions) {
|
|
207
|
+
if (expressions.length === 0) {
|
|
208
|
+
throw new Error("OR operator requires at least one expression");
|
|
209
|
+
}
|
|
210
|
+
if (expressions.length === 1 && expressions[0] !== void 0) {
|
|
211
|
+
return expressions[0];
|
|
212
|
+
}
|
|
213
|
+
return new FilterExpression("or", expressions);
|
|
214
|
+
}
|
|
215
|
+
function not(expression) {
|
|
216
|
+
return new FilterExpression("not", [expression]);
|
|
217
|
+
}
|
|
218
|
+
class OrderByExpression {
|
|
219
|
+
// biome-ignore lint/suspicious/noExplicitAny: Generic constraint accepting any Column configuration
|
|
220
|
+
constructor(column, direction) {
|
|
221
|
+
// biome-ignore lint/suspicious/noExplicitAny: Generic constraint accepting any Column configuration
|
|
222
|
+
__publicField(this, "column");
|
|
223
|
+
__publicField(this, "direction");
|
|
224
|
+
this.column = column;
|
|
225
|
+
this.direction = direction;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function isOrderByExpression(value) {
|
|
229
|
+
return value instanceof OrderByExpression;
|
|
230
|
+
}
|
|
231
|
+
function asc(column) {
|
|
232
|
+
return new OrderByExpression(column, "asc");
|
|
233
|
+
}
|
|
234
|
+
function desc(column) {
|
|
235
|
+
return new OrderByExpression(column, "desc");
|
|
236
|
+
}
|
|
237
|
+
export {
|
|
238
|
+
FilterExpression,
|
|
239
|
+
OrderByExpression,
|
|
240
|
+
and,
|
|
241
|
+
asc,
|
|
242
|
+
contains,
|
|
243
|
+
desc,
|
|
244
|
+
endsWith,
|
|
245
|
+
eq,
|
|
246
|
+
gt,
|
|
247
|
+
gte,
|
|
248
|
+
inArray,
|
|
249
|
+
isNotNull,
|
|
250
|
+
isNull,
|
|
251
|
+
isOrderByExpression,
|
|
252
|
+
lt,
|
|
253
|
+
lte,
|
|
254
|
+
ne,
|
|
255
|
+
not,
|
|
256
|
+
notInArray,
|
|
257
|
+
or,
|
|
258
|
+
startsWith
|
|
259
|
+
};
|
|
260
|
+
//# sourceMappingURL=operators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.js","sources":["../../../src/orm/operators.ts"],"sourcesContent":["import { needsFieldQuoting } from \"../client/builders/select-utils\";\nimport type { Column } from \"./column\";\nimport { isColumn } from \"./column\";\n\n/**\n * FilterExpression represents a filter condition that can be used in where() clauses.\n * Internal representation of operator expressions that get converted to OData filter syntax.\n */\nexport class FilterExpression {\n readonly operator: string;\n // biome-ignore lint/suspicious/noExplicitAny: Operands can be Column, FilterExpression, or any value type\n readonly operands: (Column | any | FilterExpression)[];\n\n // biome-ignore lint/suspicious/noExplicitAny: Operands can be Column, FilterExpression, or any value type\n constructor(operator: string, operands: (Column | any | FilterExpression)[]) {\n this.operator = operator;\n this.operands = operands;\n }\n\n /**\n * Convert this expression to OData filter syntax.\n * @internal Used by QueryBuilder\n */\n toODataFilter(useEntityIds?: boolean): string {\n switch (this.operator) {\n // Comparison operators\n case \"eq\":\n return this._binaryOp(\"eq\", useEntityIds);\n case \"ne\":\n return this._binaryOp(\"ne\", useEntityIds);\n case \"gt\":\n return this._binaryOp(\"gt\", useEntityIds);\n case \"gte\":\n return this._binaryOp(\"ge\", useEntityIds);\n case \"lt\":\n return this._binaryOp(\"lt\", useEntityIds);\n case \"lte\":\n return this._binaryOp(\"le\", useEntityIds);\n case \"in\":\n return this._inOp(useEntityIds);\n case \"notIn\":\n return this._notInOp(useEntityIds);\n\n // String operators\n case \"contains\":\n return this._functionOp(\"contains\", useEntityIds);\n case \"startsWith\":\n return this._functionOp(\"startswith\", useEntityIds);\n case \"endsWith\":\n return this._functionOp(\"endswith\", useEntityIds);\n\n // Null checks\n case \"isNull\":\n return this._isNullOp(useEntityIds);\n case \"isNotNull\":\n return this._isNotNullOp(useEntityIds);\n\n // Logical operators\n case \"and\":\n return this._logicalOp(\"and\", useEntityIds);\n case \"or\":\n return this._logicalOp(\"or\", useEntityIds);\n case \"not\":\n return this._notOp(useEntityIds);\n\n default:\n throw new Error(`Unknown operator: ${this.operator}`);\n }\n }\n\n private _binaryOp(op: string, useEntityIds?: boolean): string {\n const [left, right] = this.operands;\n // For binary ops, the column is typically the first operand and value is the second\n // But we also support column-to-column comparisons, so check both\n let columnForValue: typeof left | typeof right | undefined;\n if (isColumn(left) && !isColumn(right)) {\n columnForValue = left;\n } else if (isColumn(right) && !isColumn(left)) {\n columnForValue = right;\n } else {\n columnForValue = undefined;\n }\n const leftStr = this._operandToString(left, useEntityIds, columnForValue);\n const rightStr = this._operandToString(right, useEntityIds, columnForValue);\n return `${leftStr} ${op} ${rightStr}`;\n }\n\n private _functionOp(fnName: string, useEntityIds?: boolean): string {\n const [column, value] = this.operands;\n const columnInstance = isColumn(column) ? column : undefined;\n const columnStr = this._operandToString(column, useEntityIds);\n const valueStr = this._operandToString(value, useEntityIds, columnInstance);\n return `${fnName}(${columnStr}, ${valueStr})`;\n }\n\n private _inOp(useEntityIds?: boolean): string {\n const [column, values] = this.operands;\n const columnInstance = isColumn(column) ? column : undefined;\n const columnStr = this._operandToString(column, useEntityIds);\n // biome-ignore lint/suspicious/noExplicitAny: Dynamic array of values from user input\n const valuesStr = (values as any[]).map((v) => this._operandToString(v, useEntityIds, columnInstance)).join(\", \");\n return `${columnStr} in (${valuesStr})`;\n }\n\n private _notInOp(useEntityIds?: boolean): string {\n const [column, values] = this.operands;\n const columnInstance = isColumn(column) ? column : undefined;\n const columnStr = this._operandToString(column, useEntityIds);\n // biome-ignore lint/suspicious/noExplicitAny: Dynamic array of values from user input\n const valuesStr = (values as any[]).map((v) => this._operandToString(v, useEntityIds, columnInstance)).join(\", \");\n return `not (${columnStr} in (${valuesStr}))`;\n }\n\n private _isNullOp(useEntityIds?: boolean): string {\n const [column] = this.operands;\n const columnStr = this._operandToString(column, useEntityIds);\n return `${columnStr} eq null`;\n }\n\n private _isNotNullOp(useEntityIds?: boolean): string {\n const [column] = this.operands;\n const columnStr = this._operandToString(column, useEntityIds);\n return `${columnStr} ne null`;\n }\n\n private _logicalOp(op: string, useEntityIds?: boolean): string {\n const expressions = this.operands.map((expr) => {\n if (expr instanceof FilterExpression) {\n const innerExpr = expr.toODataFilter(useEntityIds);\n // Wrap in parens if it's a logical expression to ensure precedence\n if (expr.operator === \"and\" || expr.operator === \"or\") {\n return `(${innerExpr})`;\n }\n return innerExpr;\n }\n throw new Error(\"Logical operators require FilterExpression operands\");\n });\n return expressions.join(` ${op} `);\n }\n\n private _notOp(useEntityIds?: boolean): string {\n const [expr] = this.operands;\n if (expr instanceof FilterExpression) {\n return `not (${expr.toODataFilter(useEntityIds)})`;\n }\n throw new Error(\"NOT operator requires a FilterExpression operand\");\n }\n\n private _operandToString(\n // biome-ignore lint/suspicious/noExplicitAny: Operand can be Column, FilterExpression, or any value type\n operand: any,\n useEntityIds?: boolean, // biome-ignore lint/suspicious/noExplicitAny: Generic constraint accepting any Column configuration\n column?: Column<any, any, any, any>,\n ): string {\n if (isColumn(operand)) {\n const fieldIdentifier = operand.getFieldIdentifier(useEntityIds);\n // Quote field names in OData filters per FileMaker OData API requirements\n return needsFieldQuoting(fieldIdentifier) ? `\"${fieldIdentifier}\"` : fieldIdentifier;\n }\n\n // If we have a column with an input validator, apply it to transform the value\n let value = operand;\n if (column?.inputValidator) {\n try {\n const result = column.inputValidator[\"~standard\"].validate(value);\n // Handle async validators (though they shouldn't be async for filters)\n if (result instanceof Promise) {\n // For filters, we can't use async validators, so skip transformation\n // This is a limitation - async validators won't work in filters\n value = operand;\n } else if (\"issues\" in result && result.issues) {\n // Validation failed, use original value\n value = operand;\n } else if (\"value\" in result) {\n // Validation succeeded, use transformed value\n value = result.value;\n }\n } catch (_error) {\n // If validation throws, use the original value (will likely cause a query error)\n // This maintains backward compatibility and allows the server to handle validation\n value = operand;\n }\n }\n\n if (typeof value === \"string\") {\n return `'${value.replace(/'/g, \"''\")}'`; // Escape single quotes\n }\n if (value === null || value === undefined) {\n return \"null\";\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n return String(value);\n }\n}\n\n// ============================================================================\n// Comparison Operators\n// ============================================================================\n\n/**\n * Equal operator - checks if column equals a value or another column.\n *\n * @example\n * eq(users.name, \"John\") // name equals \"John\"\n * eq(users.id, contacts.id_user) // cross-table comparison\n */\nexport function eq<TOutput, TInput>(\n column1: Column<TOutput, TInput>,\n column2: Column<TOutput, TInput> | NoInfer<TInput>,\n): FilterExpression;\n// biome-ignore lint/suspicious/noExplicitAny: Implementation signature for overloads\nexport function eq(column: Column, value: any): FilterExpression {\n return new FilterExpression(\"eq\", [column, value]);\n}\n\n/**\n * Not equal operator - checks if column does not equal a value or another column.\n *\n * @example\n * ne(users.status, \"inactive\") // status not equal to \"inactive\"\n * ne(users.id, contacts.id_user) // cross-table comparison\n */\nexport function ne<TOutput, TInput>(\n column1: Column<TOutput, TInput>,\n column2: Column<TOutput, TInput> | NoInfer<TInput>,\n): FilterExpression;\n// biome-ignore lint/suspicious/noExplicitAny: Implementation signature for overloads\nexport function ne(column: Column, value: any): FilterExpression {\n return new FilterExpression(\"ne\", [column, value]);\n}\n\n/**\n * Greater than operator - checks if column is greater than a value.\n *\n * @example\n * gt(users.age, 18) // age greater than 18\n */\nexport function gt<TOutput extends number | string | Date | null, TInput>(\n column: Column<TOutput, TInput>,\n value: NoInfer<TInput>,\n): FilterExpression {\n return new FilterExpression(\"gt\", [column, value]);\n}\n\n/**\n * Greater than or equal operator - checks if column is >= a value.\n *\n * @example\n * gte(users.age, 18) // age >= 18\n */\nexport function gte<TOutput extends number | string | Date | null, TInput>(\n column: Column<TOutput, TInput>,\n value: NoInfer<TInput>,\n): FilterExpression {\n return new FilterExpression(\"gte\", [column, value]);\n}\n\n/**\n * Less than operator - checks if column is less than a value.\n *\n * @example\n * lt(users.age, 65) // age less than 65\n */\nexport function lt<TOutput extends number | string | Date | null, TInput>(\n column: Column<TOutput, TInput>,\n value: NoInfer<TInput>,\n): FilterExpression {\n return new FilterExpression(\"lt\", [column, value]);\n}\n\n/**\n * Less than or equal operator - checks if column is <= a value.\n *\n * @example\n * lte(users.age, 65) // age <= 65\n */\nexport function lte<TOutput extends number | string | Date | null, TInput>(\n column: Column<TOutput, TInput>,\n value: NoInfer<TInput>,\n): FilterExpression {\n return new FilterExpression(\"lte\", [column, value]);\n}\n\n// ============================================================================\n// String Operators\n// ============================================================================\n\n/**\n * Contains operator - checks if a string column contains a substring.\n *\n * @example\n * contains(users.name, \"John\") // name contains \"John\"\n */\nexport function contains<TOutput, TInput>(column: Column<TOutput, TInput>, value: NoInfer<TInput>): FilterExpression {\n return new FilterExpression(\"contains\", [column, value]);\n}\n\n/**\n * Starts with operator - checks if a string column starts with a prefix.\n *\n * @example\n * startsWith(users.email, \"admin\") // email starts with \"admin\"\n */\nexport function startsWith<TOutput, TInput>(column: Column<TOutput, TInput>, value: NoInfer<TInput>): FilterExpression {\n return new FilterExpression(\"startsWith\", [column, value]);\n}\n\n/**\n * Ends with operator - checks if a string column ends with a suffix.\n *\n * @example\n * endsWith(users.email, \"@example.com\") // email ends with \"@example.com\"\n */\nexport function endsWith<TOutput, TInput>(column: Column<TOutput, TInput>, value: NoInfer<TInput>): FilterExpression {\n return new FilterExpression(\"endsWith\", [column, value]);\n}\n\n// ============================================================================\n// Array Operators\n// ============================================================================\n\n/**\n * In array operator - checks if column value is in an array of values.\n *\n * @example\n * inArray(users.status, [\"active\", \"pending\"]) // status is \"active\" or \"pending\"\n */\nexport function inArray<TOutput, TInput>(column: Column<TOutput, TInput>, values: NoInfer<TInput>[]): FilterExpression {\n return new FilterExpression(\"in\", [column, values]);\n}\n\n/**\n * Not in array operator - checks if column value is not in an array of values.\n *\n * @example\n * notInArray(users.status, [\"deleted\", \"banned\"]) // status is neither \"deleted\" nor \"banned\"\n */\nexport function notInArray<TOutput, TInput>(\n column: Column<TOutput, TInput>,\n values: NoInfer<TInput>[],\n): FilterExpression {\n return new FilterExpression(\"notIn\", [column, values]);\n}\n\n// ============================================================================\n// Null Check Operators\n// ============================================================================\n\n/**\n * Is null operator - checks if column value is null.\n *\n * @example\n * isNull(users.deletedAt) // deletedAt is null\n */\nexport function isNull<TOutput, TInput>(column: Column<TOutput, TInput>): FilterExpression {\n return new FilterExpression(\"isNull\", [column]);\n}\n\n/**\n * Is not null operator - checks if column value is not null.\n *\n * @example\n * isNotNull(users.email) // email is not null\n */\nexport function isNotNull<TOutput, TInput>(column: Column<TOutput, TInput>): FilterExpression {\n return new FilterExpression(\"isNotNull\", [column]);\n}\n\n// ============================================================================\n// Logical Operators\n// ============================================================================\n\n/**\n * AND operator - combines multiple filter expressions with logical AND.\n * All expressions must be true for the record to match.\n *\n * @example\n * and(\n * eq(users.active, true),\n * gt(users.age, 18)\n * ) // active is true AND age > 18\n */\nexport function and(...expressions: FilterExpression[]): FilterExpression {\n if (expressions.length === 0) {\n throw new Error(\"AND operator requires at least one expression\");\n }\n if (expressions.length === 1 && expressions[0] !== undefined) {\n return expressions[0];\n }\n return new FilterExpression(\"and\", expressions);\n}\n\n/**\n * OR operator - combines multiple filter expressions with logical OR.\n * At least one expression must be true for the record to match.\n *\n * @example\n * or(\n * eq(users.role, \"admin\"),\n * eq(users.role, \"moderator\")\n * ) // role is \"admin\" OR \"moderator\"\n */\nexport function or(...expressions: FilterExpression[]): FilterExpression {\n if (expressions.length === 0) {\n throw new Error(\"OR operator requires at least one expression\");\n }\n if (expressions.length === 1 && expressions[0] !== undefined) {\n return expressions[0];\n }\n return new FilterExpression(\"or\", expressions);\n}\n\n/**\n * NOT operator - negates a filter expression.\n *\n * @example\n * not(eq(users.status, \"deleted\")) // status is NOT \"deleted\"\n */\nexport function not(expression: FilterExpression): FilterExpression {\n return new FilterExpression(\"not\", [expression]);\n}\n\n// ============================================================================\n// OrderBy Operators\n// ============================================================================\n\n/**\n * OrderByExpression represents a sort order specification for a column.\n * Used in orderBy() clauses to provide type-safe sorting with direction.\n */\nexport class OrderByExpression<TableName extends string = string> {\n // biome-ignore lint/suspicious/noExplicitAny: Generic constraint accepting any Column configuration\n readonly column: Column<any, any, TableName>;\n readonly direction: \"asc\" | \"desc\";\n\n // biome-ignore lint/suspicious/noExplicitAny: Generic constraint accepting any Column configuration\n constructor(column: Column<any, any, TableName>, direction: \"asc\" | \"desc\") {\n this.column = column;\n this.direction = direction;\n }\n}\n\n/**\n * Type guard to check if a value is an OrderByExpression instance.\n */\n// biome-ignore lint/suspicious/noExplicitAny: Type guard accepting any value type\nexport function isOrderByExpression(value: any): value is OrderByExpression {\n return value instanceof OrderByExpression;\n}\n\n/**\n * Ascending order operator - sorts a column in ascending order.\n *\n * @example\n * asc(users.name) // Sort by name ascending\n */\n// biome-ignore lint/suspicious/noExplicitAny: Generic constraint accepting any Column configuration\nexport function asc<TableName extends string>(column: Column<any, any, TableName>): OrderByExpression<TableName> {\n return new OrderByExpression(column, \"asc\");\n}\n\n/**\n * Descending order operator - sorts a column in descending order.\n *\n * @example\n * desc(users.age) // Sort by age descending\n */\n// biome-ignore lint/suspicious/noExplicitAny: Generic constraint accepting any Column configuration\nexport function desc<TableName extends string>(column: Column<any, any, TableName>): OrderByExpression<TableName> {\n return new OrderByExpression(column, \"desc\");\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import { Column } from './column.js';
|
|
3
|
+
import { ContainerDbType, FieldBuilder, FieldBuilder as FieldBuilderType } from './field-builders.js';
|
|
4
|
+
/**
|
|
5
|
+
* Extract the output type from a FieldBuilder.
|
|
6
|
+
* This is what you get when reading from the database.
|
|
7
|
+
*
|
|
8
|
+
* This type extracts the TOutput type parameter, which is set by readValidator()
|
|
9
|
+
* and represents the transformed/validated output type.
|
|
10
|
+
*/
|
|
11
|
+
export type InferFieldOutput<F> = F extends FieldBuilder<infer TOutput, any, any, any> ? TOutput : never;
|
|
12
|
+
/**
|
|
13
|
+
* Extract the input type from a FieldBuilder.
|
|
14
|
+
* This is what you pass when writing to the database.
|
|
15
|
+
*
|
|
16
|
+
* This type extracts the TInput type parameter, which is set by writeValidator()
|
|
17
|
+
* and represents the transformed/validated input type.
|
|
18
|
+
*/
|
|
19
|
+
type InferFieldInput<F> = F extends FieldBuilder<any, infer TInput, any, any> ? TInput : never;
|
|
20
|
+
/**
|
|
21
|
+
* Build a schema type from field builders (output/read types).
|
|
22
|
+
*/
|
|
23
|
+
type InferSchemaFromFields<TFields extends Record<string, FieldBuilder<any, any, any, any>>> = {
|
|
24
|
+
[K in keyof TFields]: InferFieldOutput<TFields[K]>;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Build an input schema type from field builders (input/write types).
|
|
28
|
+
* Used for insert and update operations.
|
|
29
|
+
*/
|
|
30
|
+
type InferInputSchemaFromFields<TFields extends Record<string, FieldBuilder<any, any, any, any>>> = {
|
|
31
|
+
[K in keyof TFields]: InferFieldInput<TFields[K]>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Check if a field is a container field by inspecting its TDbType.
|
|
35
|
+
* Container fields have a branded TDbType that extends ContainerDbType.
|
|
36
|
+
*/
|
|
37
|
+
type IsContainerField<F> = F extends FieldBuilder<any, any, infer TDbType, any> ? NonNullable<TDbType> extends ContainerDbType ? true : false : false;
|
|
38
|
+
/**
|
|
39
|
+
* Extract only selectable (non-container) field keys from a fields record.
|
|
40
|
+
* Container fields are excluded because they cannot be selected via $select in FileMaker OData.
|
|
41
|
+
*/
|
|
42
|
+
type SelectableFieldKeys<TFields extends Record<string, FieldBuilder<any, any, any, any>>> = {
|
|
43
|
+
[K in keyof TFields]: IsContainerField<TFields[K]> extends true ? never : K;
|
|
44
|
+
}[keyof TFields];
|
|
45
|
+
/**
|
|
46
|
+
* Internal Symbols for table properties (hidden from IDE autocomplete).
|
|
47
|
+
* These are used to store internal configuration that shouldn't be visible
|
|
48
|
+
* when users access table columns.
|
|
49
|
+
* @internal - Not exported from public API, only accessible via FMTable.Symbol
|
|
50
|
+
*/
|
|
51
|
+
declare const FMTableName: unique symbol;
|
|
52
|
+
declare const FMTableEntityId: unique symbol;
|
|
53
|
+
declare const FMTableSchema: unique symbol;
|
|
54
|
+
declare const FMTableFields: unique symbol;
|
|
55
|
+
declare const FMTableNavigationPaths: unique symbol;
|
|
56
|
+
declare const FMTableDefaultSelect: unique symbol;
|
|
57
|
+
declare const FMTableBaseTableConfig: unique symbol;
|
|
58
|
+
declare const FMTableUseEntityIds: unique symbol;
|
|
59
|
+
declare const FMTableComment: unique symbol;
|
|
60
|
+
/**
|
|
61
|
+
* Base table class with Symbol-based internal properties.
|
|
62
|
+
* This follows the Drizzle ORM pattern where internal configuration
|
|
63
|
+
* is stored via Symbols, keeping it hidden from IDE autocomplete.
|
|
64
|
+
*/
|
|
65
|
+
export declare class FMTable<TFields extends Record<string, FieldBuilder<any, any, any, any>> = any, TName extends string = string, TNavigationPaths extends readonly string[] = readonly string[]> {
|
|
66
|
+
/**
|
|
67
|
+
* Internal Symbols for accessing table metadata.
|
|
68
|
+
* @internal - Not intended for public use. Access table properties via columns instead.
|
|
69
|
+
*/
|
|
70
|
+
static readonly Symbol: {
|
|
71
|
+
Name: symbol;
|
|
72
|
+
EntityId: symbol;
|
|
73
|
+
UseEntityIds: symbol;
|
|
74
|
+
Schema: symbol;
|
|
75
|
+
Fields: symbol;
|
|
76
|
+
NavigationPaths: symbol;
|
|
77
|
+
DefaultSelect: symbol;
|
|
78
|
+
BaseTableConfig: symbol;
|
|
79
|
+
Comment: symbol;
|
|
80
|
+
};
|
|
81
|
+
/** @internal */
|
|
82
|
+
[FMTableName]: TName;
|
|
83
|
+
/** @internal */
|
|
84
|
+
[FMTableEntityId]?: `FMTID:${string}`;
|
|
85
|
+
/** @internal */
|
|
86
|
+
[FMTableUseEntityIds]?: boolean;
|
|
87
|
+
/** @internal */
|
|
88
|
+
[FMTableComment]?: string;
|
|
89
|
+
/** @internal */
|
|
90
|
+
[FMTableSchema]: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
91
|
+
/** @internal */
|
|
92
|
+
[FMTableFields]: TFields;
|
|
93
|
+
/** @internal */
|
|
94
|
+
[FMTableNavigationPaths]: TNavigationPaths;
|
|
95
|
+
/** @internal */
|
|
96
|
+
[FMTableDefaultSelect]: "all" | "schema" | Record<string, Column<any, any, TName>>;
|
|
97
|
+
/** @internal */
|
|
98
|
+
[FMTableBaseTableConfig]: {
|
|
99
|
+
schema: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
100
|
+
inputSchema?: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
101
|
+
idField?: keyof TFields;
|
|
102
|
+
required: readonly (keyof TFields)[];
|
|
103
|
+
readOnly: readonly (keyof TFields)[];
|
|
104
|
+
containerFields: readonly (keyof TFields)[];
|
|
105
|
+
fmfIds?: Record<keyof TFields, `FMFID:${string}`>;
|
|
106
|
+
};
|
|
107
|
+
constructor(config: {
|
|
108
|
+
name: TName;
|
|
109
|
+
entityId?: `FMTID:${string}`;
|
|
110
|
+
useEntityIds?: boolean;
|
|
111
|
+
comment?: string;
|
|
112
|
+
schema: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
113
|
+
fields: TFields;
|
|
114
|
+
navigationPaths: TNavigationPaths;
|
|
115
|
+
defaultSelect: "all" | "schema" | Record<string, Column<any, any, TName>>;
|
|
116
|
+
baseTableConfig: {
|
|
117
|
+
schema: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
118
|
+
inputSchema?: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
119
|
+
idField?: keyof TFields;
|
|
120
|
+
required: readonly (keyof TFields)[];
|
|
121
|
+
readOnly: readonly (keyof TFields)[];
|
|
122
|
+
containerFields: readonly (keyof TFields)[];
|
|
123
|
+
fmfIds?: Record<keyof TFields, `FMFID:${string}`>;
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Type helper to extract the column map from fields.
|
|
129
|
+
* Table name is baked into each column type for validation.
|
|
130
|
+
* Container fields are marked with IsContainer=true.
|
|
131
|
+
* Columns include both output type (for reading) and input type (for writing/filtering).
|
|
132
|
+
*/
|
|
133
|
+
export type ColumnMap<TFields extends Record<string, FieldBuilder<any, any, any, any>>, TName extends string> = {
|
|
134
|
+
[K in keyof TFields]: Column<InferFieldOutput<TFields[K]>, InferFieldInput<TFields[K]>, TName, IsContainerField<TFields[K]>>;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Extract only selectable (non-container) columns from a table.
|
|
138
|
+
* This is used to prevent selecting container fields in queries.
|
|
139
|
+
*/
|
|
140
|
+
export type SelectableColumnMap<TFields extends Record<string, FieldBuilder<any, any, any, any>>, TName extends string> = {
|
|
141
|
+
[K in SelectableFieldKeys<TFields>]: Column<InferFieldOutput<TFields[K]>, InferFieldInput<TFields[K]>, TName, false>;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Validates that a select object doesn't contain container field columns.
|
|
145
|
+
* Returns never if any container fields are found, otherwise returns the original type.
|
|
146
|
+
*/
|
|
147
|
+
export type ValidateNoContainerFields<TSelect extends Record<string, Column<any, any, any, any>>> = {
|
|
148
|
+
[K in keyof TSelect]: TSelect[K] extends Column<any, any, any, true> ? never : TSelect[K];
|
|
149
|
+
} extends TSelect ? TSelect : {
|
|
150
|
+
[K in keyof TSelect]: TSelect[K] extends Column<any, any, any, true> ? "❌ Container fields cannot be selected. Use .getSingleField() instead." : TSelect[K];
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Complete table type with both metadata (via Symbols) and column accessors.
|
|
154
|
+
* This is the return type of fmTableOccurrence - users see columns directly,
|
|
155
|
+
* but internal config is hidden via Symbols.
|
|
156
|
+
*/
|
|
157
|
+
export type FMTableWithColumns<TFields extends Record<string, FieldBuilder<any, any, any, any>>, TName extends string, TNavigationPaths extends readonly string[] = readonly string[]> = FMTable<TFields, TName, TNavigationPaths> & ColumnMap<TFields, TName>;
|
|
158
|
+
/**
|
|
159
|
+
* Options for fmTableOccurrence function.
|
|
160
|
+
* Provides autocomplete-friendly typing while preserving inference for navigationPaths.
|
|
161
|
+
*/
|
|
162
|
+
export interface FMTableOccurrenceOptions<TFields extends Record<string, FieldBuilder<any, any, any, any>>, TName extends string> {
|
|
163
|
+
/** The entity ID (FMTID) for this table occurrence */
|
|
164
|
+
entityId?: `FMTID:${string}`;
|
|
165
|
+
/** The comment for this table */
|
|
166
|
+
comment?: string;
|
|
167
|
+
/**
|
|
168
|
+
* Default select behavior:
|
|
169
|
+
* - "all": Select all fields (including related tables)
|
|
170
|
+
* - "schema": Select only schema-defined fields (default)
|
|
171
|
+
* - function: Custom selection from columns
|
|
172
|
+
*/
|
|
173
|
+
defaultSelect?: "all" | "schema" | ((columns: ColumnMap<TFields, TName>) => Record<string, Column<any, any, TName>>);
|
|
174
|
+
/** Navigation paths available from this table (for expand operations) */
|
|
175
|
+
navigationPaths?: readonly string[];
|
|
176
|
+
/** Whether to use entity IDs (FMTID/FMFID) instead of names in queries */
|
|
177
|
+
useEntityIds?: boolean;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Create a table occurrence with field builders.
|
|
181
|
+
* This is the main API for defining tables in the new ORM style.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* const users = fmTableOccurrence("users", {
|
|
185
|
+
* id: textField().primaryKey().entityId("FMFID:1"),
|
|
186
|
+
* name: textField().notNull().entityId("FMFID:6"),
|
|
187
|
+
* active: numberField()
|
|
188
|
+
* .outputValidator(z.coerce.boolean())
|
|
189
|
+
* .inputValidator(z.boolean().transform(v => v ? 1 : 0))
|
|
190
|
+
* .entityId("FMFID:7"),
|
|
191
|
+
* }, {
|
|
192
|
+
* entityId: "FMTID:100",
|
|
193
|
+
* defaultSelect: "schema",
|
|
194
|
+
* navigationPaths: ["contacts"],
|
|
195
|
+
* });
|
|
196
|
+
*
|
|
197
|
+
* // Access columns
|
|
198
|
+
* users.id // Column<string, "id">
|
|
199
|
+
* users.name // Column<string, "name">
|
|
200
|
+
*
|
|
201
|
+
* // Use in queries
|
|
202
|
+
* db.from(users).select("id", "name").where(eq(users.active, true))
|
|
203
|
+
*/
|
|
204
|
+
export declare function fmTableOccurrence<const TName extends string, const TFields extends Record<string, FieldBuilder<any, any, any, any>>, const TNavPaths extends readonly string[] = readonly []>(name: TName, fields: TFields, options?: FMTableOccurrenceOptions<TFields, TName> & {
|
|
205
|
+
/** Navigation paths available from this table (for expand operations) */
|
|
206
|
+
navigationPaths?: TNavPaths;
|
|
207
|
+
}): FMTableWithColumns<TFields, TName, TNavPaths>;
|
|
208
|
+
/**
|
|
209
|
+
* Helper to extract the schema type from a TableOccurrence or FMTable.
|
|
210
|
+
*/
|
|
211
|
+
export type InferTableSchema<T> = T extends FMTable<infer TFields, any> ? InferSchemaFromFields<TFields> : never;
|
|
212
|
+
/**
|
|
213
|
+
* Extract the schema type from an FMTable instance.
|
|
214
|
+
* This is used to infer the schema from table objects passed to db.from(), expand(), etc.
|
|
215
|
+
*/
|
|
216
|
+
export type InferSchemaOutputFromFMTable<T extends FMTable<any, any>> = T extends FMTable<infer TFields, any> ? InferSchemaFromFields<TFields> : never;
|
|
217
|
+
/**
|
|
218
|
+
* Extract the input schema type from an FMTable instance.
|
|
219
|
+
* This is used for insert and update operations where we need write types.
|
|
220
|
+
*/
|
|
221
|
+
export type InferInputSchemaFromFMTable<T extends FMTable<any, any>> = T extends FMTable<infer TFields, any> ? InferInputSchemaFromFields<TFields> : never;
|
|
222
|
+
/**
|
|
223
|
+
* Helper type to check if a FieldBuilder's input type excludes null and undefined.
|
|
224
|
+
* This checks the TInput type parameter, which preserves nullability from notNull().
|
|
225
|
+
*/
|
|
226
|
+
type FieldInputExcludesNullish<F> = F extends FieldBuilder<any, infer TInput, any> ? null extends TInput ? false : undefined extends TInput ? false : true : false;
|
|
227
|
+
/**
|
|
228
|
+
* Check if a FieldBuilder is readOnly at the type level
|
|
229
|
+
*/
|
|
230
|
+
type IsFieldReadOnly<F> = F extends FieldBuilderType<any, any, any, infer ReadOnly> ? (ReadOnly extends true ? true : false) : false;
|
|
231
|
+
/**
|
|
232
|
+
* Compute insert data type from FMTable, making notNull fields required.
|
|
233
|
+
* Fields are required if their FieldBuilder's TInput type excludes null/undefined.
|
|
234
|
+
* All other fields are optional (can be omitted).
|
|
235
|
+
* readOnly fields are excluded (including primaryKey/idField since they're automatically readOnly).
|
|
236
|
+
*/
|
|
237
|
+
export type InsertDataFromFMTable<T extends FMTable<any, any>> = T extends FMTable<infer TFields, any> ? {
|
|
238
|
+
[K in keyof TFields as IsFieldReadOnly<TFields[K]> extends true ? never : FieldInputExcludesNullish<TFields[K]> extends true ? K : never]: InferFieldInput<TFields[K]>;
|
|
239
|
+
} & {
|
|
240
|
+
[K in keyof TFields as IsFieldReadOnly<TFields[K]> extends true ? never : FieldInputExcludesNullish<TFields[K]> extends true ? never : K]?: InferFieldInput<TFields[K]>;
|
|
241
|
+
} : never;
|
|
242
|
+
/**
|
|
243
|
+
* Compute update data type from FMTable.
|
|
244
|
+
* All fields are optional, but readOnly fields are excluded (including primaryKey/idField).
|
|
245
|
+
*/
|
|
246
|
+
export type UpdateDataFromFMTable<T extends FMTable<any, any>> = T extends FMTable<infer TFields, any> ? {
|
|
247
|
+
[K in keyof TFields as IsFieldReadOnly<TFields[K]> extends true ? never : K]?: InferFieldInput<TFields[K]>;
|
|
248
|
+
} : never;
|
|
249
|
+
/**
|
|
250
|
+
* Extract the table name type from an FMTable.
|
|
251
|
+
* This is a workaround since we can't directly index Symbols in types.
|
|
252
|
+
*/
|
|
253
|
+
export type ExtractTableName<T extends FMTable<any, any>> = T extends FMTable<any, infer Name> ? Name : never;
|
|
254
|
+
/**
|
|
255
|
+
* Validates that a target table's name matches one of the source table's navigationPaths.
|
|
256
|
+
* Used to ensure type-safe expand/navigate operations.
|
|
257
|
+
*/
|
|
258
|
+
export type ValidExpandTarget<SourceTable extends FMTable<any, any, any> | undefined, TargetTable extends FMTable<any, any, any>> = SourceTable extends FMTable<any, any, infer SourceNavPaths> ? ExtractTableName<TargetTable> extends SourceNavPaths[number] ? TargetTable : never : TargetTable;
|
|
259
|
+
/**
|
|
260
|
+
* Get the table name from an FMTable instance.
|
|
261
|
+
* @param table - FMTable instance
|
|
262
|
+
* @returns The table name
|
|
263
|
+
*/
|
|
264
|
+
export declare function getTableName<T extends FMTable<any, any>>(table: T): string;
|
|
265
|
+
/**
|
|
266
|
+
* Get the entity ID (FMTID) from an FMTable instance.
|
|
267
|
+
* @param table - FMTable instance
|
|
268
|
+
* @returns The entity ID or undefined if not using entity IDs
|
|
269
|
+
*/
|
|
270
|
+
export declare function getTableEntityId<T extends FMTable<any, any>>(table: T): string | undefined;
|
|
271
|
+
/**
|
|
272
|
+
* Get the schema validator from an FMTable instance.
|
|
273
|
+
* @param table - FMTable instance
|
|
274
|
+
* @returns The StandardSchemaV1 validator record (partial - only fields with validators)
|
|
275
|
+
*/
|
|
276
|
+
export declare function getTableSchema<T extends FMTable<any, any>>(table: T): Partial<Record<keyof T[typeof FMTableFields], StandardSchemaV1>>;
|
|
277
|
+
/**
|
|
278
|
+
* Get the fields from an FMTable instance.
|
|
279
|
+
* @param table - FMTable instance
|
|
280
|
+
* @returns The fields record
|
|
281
|
+
*/
|
|
282
|
+
export declare function getTableFields<T extends FMTable<any, any>>(table: T): any;
|
|
283
|
+
/**
|
|
284
|
+
* Get the navigation paths from an FMTable instance.
|
|
285
|
+
* @param table - FMTable instance
|
|
286
|
+
* @returns Array of navigation path names
|
|
287
|
+
*/
|
|
288
|
+
export declare function getNavigationPaths<T extends FMTable<any, any>>(table: T): readonly string[];
|
|
289
|
+
/**
|
|
290
|
+
* Get the default select configuration from an FMTable instance.
|
|
291
|
+
* @param table - FMTable instance
|
|
292
|
+
* @returns Default select configuration
|
|
293
|
+
*/
|
|
294
|
+
export declare function getDefaultSelect<T extends FMTable<any, any>>(table: T): "all" | "schema" | Record<string, Column<any, any, any, false>>;
|
|
295
|
+
/**
|
|
296
|
+
* Get the base table configuration from an FMTable instance.
|
|
297
|
+
* This provides access to schema, idField, required fields, readOnly fields, and field IDs.
|
|
298
|
+
* @param table - FMTable instance
|
|
299
|
+
* @returns Base table configuration object
|
|
300
|
+
*/
|
|
301
|
+
export declare function getBaseTableConfig<T extends FMTable<any, any>>(table: T): {
|
|
302
|
+
schema: Partial<Record<string | number | symbol, StandardSchemaV1<unknown, unknown>>>;
|
|
303
|
+
inputSchema?: Partial<Record<string | number | symbol, StandardSchemaV1<unknown, unknown>>> | undefined;
|
|
304
|
+
idField?: string | number | symbol | undefined;
|
|
305
|
+
required: readonly (string | number | symbol)[];
|
|
306
|
+
readOnly: readonly (string | number | symbol)[];
|
|
307
|
+
containerFields: readonly (string | number | symbol)[];
|
|
308
|
+
fmfIds?: Record<string | number | symbol, `FMFID:${string}`> | undefined;
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* Check if an FMTable instance is using entity IDs (both FMTID and FMFIDs).
|
|
312
|
+
* @param table - FMTable instance
|
|
313
|
+
* @returns True if using entity IDs, false otherwise
|
|
314
|
+
*/
|
|
315
|
+
export declare function isUsingEntityIds<T extends FMTable<any, any>>(table: T): boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Get the field ID (FMFID) for a given field name, or the field name itself if not using IDs.
|
|
318
|
+
* @param table - FMTable instance
|
|
319
|
+
* @param fieldName - Field name to get the ID for
|
|
320
|
+
* @returns The FMFID string or the original field name
|
|
321
|
+
*/
|
|
322
|
+
export declare function getFieldId<T extends FMTable<any, any>>(table: T, fieldName: string): string;
|
|
323
|
+
/**
|
|
324
|
+
* Get the field name for a given field ID (FMFID), or the ID itself if not found.
|
|
325
|
+
* @param table - FMTable instance
|
|
326
|
+
* @param fieldId - The FMFID to get the field name for
|
|
327
|
+
* @returns The field name or the original ID
|
|
328
|
+
*/
|
|
329
|
+
export declare function getFieldName<T extends FMTable<any, any>>(table: T, fieldId: string): string;
|
|
330
|
+
/**
|
|
331
|
+
* Get the table ID (FMTID or name) from an FMTable instance.
|
|
332
|
+
* Returns the FMTID if available, otherwise returns the table name.
|
|
333
|
+
* @param table - FMTable instance
|
|
334
|
+
* @returns The FMTID string or the table name
|
|
335
|
+
*/
|
|
336
|
+
export declare function getTableId<T extends FMTable<any, any>>(table: T): string;
|
|
337
|
+
/**
|
|
338
|
+
* Get the comment from an FMTable instance.
|
|
339
|
+
* @param table - FMTable instance
|
|
340
|
+
* @returns The comment string or undefined if not set
|
|
341
|
+
*/
|
|
342
|
+
export declare function getTableComment<T extends FMTable<any, any>>(table: T): string | undefined;
|
|
343
|
+
/**
|
|
344
|
+
* Get all columns from a table as an object.
|
|
345
|
+
* Useful for selecting all fields except some using destructuring.
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* const { password, ...cols } = getTableColumns(users)
|
|
349
|
+
* db.from(users).list().select(cols)
|
|
350
|
+
*
|
|
351
|
+
* @param table - FMTable instance
|
|
352
|
+
* @returns Object with all columns from the table
|
|
353
|
+
*/
|
|
354
|
+
export declare function getTableColumns<T extends FMTable<any, any>>(table: T): ColumnMap<T[typeof FMTableFields], ExtractTableName<T>>;
|
|
355
|
+
export {};
|