@proofkit/fmodata 0.1.0-alpha.13 → 0.1.0-alpha.15

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.
Files changed (143) hide show
  1. package/README.md +489 -334
  2. package/dist/esm/client/batch-builder.d.ts +7 -5
  3. package/dist/esm/client/batch-builder.js +84 -25
  4. package/dist/esm/client/batch-builder.js.map +1 -1
  5. package/dist/esm/client/builders/default-select.d.ts +7 -0
  6. package/dist/esm/client/builders/default-select.js +42 -0
  7. package/dist/esm/client/builders/default-select.js.map +1 -0
  8. package/dist/esm/client/builders/expand-builder.d.ts +43 -0
  9. package/dist/esm/client/builders/expand-builder.js +173 -0
  10. package/dist/esm/client/builders/expand-builder.js.map +1 -0
  11. package/dist/esm/client/builders/index.d.ts +8 -0
  12. package/dist/esm/client/builders/query-string-builder.d.ts +15 -0
  13. package/dist/esm/client/builders/query-string-builder.js +25 -0
  14. package/dist/esm/client/builders/query-string-builder.js.map +1 -0
  15. package/dist/esm/client/builders/response-processor.d.ts +39 -0
  16. package/dist/esm/client/builders/response-processor.js +170 -0
  17. package/dist/esm/client/builders/response-processor.js.map +1 -0
  18. package/dist/esm/client/builders/select-mixin.d.ts +31 -0
  19. package/dist/esm/client/builders/select-mixin.js +30 -0
  20. package/dist/esm/client/builders/select-mixin.js.map +1 -0
  21. package/dist/esm/client/builders/select-utils.d.ts +8 -0
  22. package/dist/esm/client/builders/select-utils.js +15 -0
  23. package/dist/esm/client/builders/select-utils.js.map +1 -0
  24. package/dist/esm/client/builders/shared-types.d.ts +39 -0
  25. package/dist/esm/client/builders/table-utils.d.ts +35 -0
  26. package/dist/esm/client/builders/table-utils.js +45 -0
  27. package/dist/esm/client/builders/table-utils.js.map +1 -0
  28. package/dist/esm/client/database.d.ts +3 -22
  29. package/dist/esm/client/database.js +14 -76
  30. package/dist/esm/client/database.js.map +1 -1
  31. package/dist/esm/client/delete-builder.d.ts +12 -19
  32. package/dist/esm/client/delete-builder.js +26 -26
  33. package/dist/esm/client/delete-builder.js.map +1 -1
  34. package/dist/esm/client/entity-set.d.ts +32 -32
  35. package/dist/esm/client/entity-set.js +92 -69
  36. package/dist/esm/client/entity-set.js.map +1 -1
  37. package/dist/esm/client/error-parser.d.ts +12 -0
  38. package/dist/esm/client/error-parser.js +30 -0
  39. package/dist/esm/client/error-parser.js.map +1 -0
  40. package/dist/esm/client/filemaker-odata.d.ts +2 -4
  41. package/dist/esm/client/filemaker-odata.js +1 -5
  42. package/dist/esm/client/filemaker-odata.js.map +1 -1
  43. package/dist/esm/client/insert-builder.d.ts +9 -12
  44. package/dist/esm/client/insert-builder.js +70 -24
  45. package/dist/esm/client/insert-builder.js.map +1 -1
  46. package/dist/esm/client/query/expand-builder.d.ts +35 -0
  47. package/dist/esm/client/query/index.d.ts +3 -0
  48. package/dist/esm/client/query/query-builder.d.ts +133 -0
  49. package/dist/esm/client/query/query-builder.js +505 -0
  50. package/dist/esm/client/query/query-builder.js.map +1 -0
  51. package/dist/esm/client/query/response-processor.d.ts +22 -0
  52. package/dist/esm/client/query/types.d.ts +52 -0
  53. package/dist/esm/client/query/url-builder.d.ts +71 -0
  54. package/dist/esm/client/query/url-builder.js +107 -0
  55. package/dist/esm/client/query/url-builder.js.map +1 -0
  56. package/dist/esm/client/query-builder.d.ts +1 -111
  57. package/dist/esm/client/record-builder.d.ts +56 -64
  58. package/dist/esm/client/record-builder.js +158 -297
  59. package/dist/esm/client/record-builder.js.map +1 -1
  60. package/dist/esm/client/response-processor.d.ts +3 -3
  61. package/dist/esm/client/update-builder.d.ts +17 -25
  62. package/dist/esm/client/update-builder.js +56 -30
  63. package/dist/esm/client/update-builder.js.map +1 -1
  64. package/dist/esm/errors.d.ts +8 -1
  65. package/dist/esm/errors.js +17 -0
  66. package/dist/esm/errors.js.map +1 -1
  67. package/dist/esm/index.d.ts +3 -7
  68. package/dist/esm/index.js +37 -8
  69. package/dist/esm/index.js.map +1 -1
  70. package/dist/esm/orm/column.d.ts +45 -0
  71. package/dist/esm/orm/column.js +59 -0
  72. package/dist/esm/orm/column.js.map +1 -0
  73. package/dist/esm/orm/field-builders.d.ts +154 -0
  74. package/dist/esm/orm/field-builders.js +152 -0
  75. package/dist/esm/orm/field-builders.js.map +1 -0
  76. package/dist/esm/orm/index.d.ts +4 -0
  77. package/dist/esm/orm/operators.d.ts +175 -0
  78. package/dist/esm/orm/operators.js +221 -0
  79. package/dist/esm/orm/operators.js.map +1 -0
  80. package/dist/esm/orm/table.d.ts +341 -0
  81. package/dist/esm/orm/table.js +211 -0
  82. package/dist/esm/orm/table.js.map +1 -0
  83. package/dist/esm/transform.d.ts +20 -21
  84. package/dist/esm/transform.js +34 -34
  85. package/dist/esm/transform.js.map +1 -1
  86. package/dist/esm/types.d.ts +73 -12
  87. package/dist/esm/types.js.map +1 -1
  88. package/dist/esm/validation.d.ts +14 -4
  89. package/dist/esm/validation.js +45 -1
  90. package/dist/esm/validation.js.map +1 -1
  91. package/package.json +22 -17
  92. package/src/client/batch-builder.ts +102 -33
  93. package/src/client/builders/default-select.ts +69 -0
  94. package/src/client/builders/expand-builder.ts +236 -0
  95. package/src/client/builders/index.ts +11 -0
  96. package/src/client/builders/query-string-builder.ts +41 -0
  97. package/src/client/builders/response-processor.ts +273 -0
  98. package/src/client/builders/select-mixin.ts +74 -0
  99. package/src/client/builders/select-utils.ts +34 -0
  100. package/src/client/builders/shared-types.ts +41 -0
  101. package/src/client/builders/table-utils.ts +87 -0
  102. package/src/client/database.ts +19 -160
  103. package/src/client/delete-builder.ts +48 -52
  104. package/src/client/entity-set.ts +227 -302
  105. package/src/client/error-parser.ts +59 -0
  106. package/src/client/filemaker-odata.ts +3 -14
  107. package/src/client/insert-builder.ts +126 -44
  108. package/src/client/query/expand-builder.ts +164 -0
  109. package/src/client/query/index.ts +13 -0
  110. package/src/client/query/query-builder.ts +826 -0
  111. package/src/client/query/response-processor.ts +244 -0
  112. package/src/client/query/types.ts +102 -0
  113. package/src/client/query/url-builder.ts +179 -0
  114. package/src/client/query-builder.ts +8 -1454
  115. package/src/client/record-builder.ts +336 -586
  116. package/src/client/response-processor.ts +4 -5
  117. package/src/client/update-builder.ts +113 -75
  118. package/src/errors.ts +22 -1
  119. package/src/index.ts +58 -5
  120. package/src/orm/column.ts +78 -0
  121. package/src/orm/field-builders.ts +296 -0
  122. package/src/orm/index.ts +60 -0
  123. package/src/orm/operators.ts +428 -0
  124. package/src/orm/table.ts +759 -0
  125. package/src/transform.ts +62 -48
  126. package/src/types.ts +88 -63
  127. package/src/validation.ts +76 -4
  128. package/LICENSE.md +0 -21
  129. package/dist/esm/client/base-table.d.ts +0 -128
  130. package/dist/esm/client/base-table.js +0 -57
  131. package/dist/esm/client/base-table.js.map +0 -1
  132. package/dist/esm/client/build-occurrences.d.ts +0 -74
  133. package/dist/esm/client/build-occurrences.js +0 -31
  134. package/dist/esm/client/build-occurrences.js.map +0 -1
  135. package/dist/esm/client/query-builder.js +0 -900
  136. package/dist/esm/client/query-builder.js.map +0 -1
  137. package/dist/esm/client/table-occurrence.d.ts +0 -86
  138. package/dist/esm/client/table-occurrence.js +0 -58
  139. package/dist/esm/client/table-occurrence.js.map +0 -1
  140. package/src/client/base-table.ts +0 -178
  141. package/src/client/build-occurrences.ts +0 -155
  142. package/src/client/query-builder.ts.bak +0 -1457
  143. package/src/client/table-occurrence.ts +0 -156
@@ -0,0 +1,175 @@
1
+ import { Column } from './column.js';
2
+ /**
3
+ * FilterExpression represents a filter condition that can be used in where() clauses.
4
+ * Internal representation of operator expressions that get converted to OData filter syntax.
5
+ */
6
+ export declare class FilterExpression {
7
+ readonly operator: string;
8
+ readonly operands: (Column | any | FilterExpression)[];
9
+ constructor(operator: string, operands: (Column | any | FilterExpression)[]);
10
+ /**
11
+ * Convert this expression to OData filter syntax.
12
+ * @internal Used by QueryBuilder
13
+ */
14
+ toODataFilter(useEntityIds?: boolean): string;
15
+ private _binaryOp;
16
+ private _functionOp;
17
+ private _inOp;
18
+ private _notInOp;
19
+ private _isNullOp;
20
+ private _isNotNullOp;
21
+ private _logicalOp;
22
+ private _notOp;
23
+ private _operandToString;
24
+ }
25
+ /**
26
+ * Equal operator - checks if column equals a value or another column.
27
+ *
28
+ * @example
29
+ * eq(users.name, "John") // name equals "John"
30
+ * eq(users.id, contacts.id_user) // cross-table comparison
31
+ */
32
+ export declare function eq<T>(column: Column<T>, value: T): FilterExpression;
33
+ export declare function eq<T>(column1: Column<T>, column2: Column<T>): FilterExpression;
34
+ /**
35
+ * Not equal operator - checks if column does not equal a value or another column.
36
+ *
37
+ * @example
38
+ * ne(users.status, "inactive") // status not equal to "inactive"
39
+ * ne(users.id, contacts.id_user) // cross-table comparison
40
+ */
41
+ export declare function ne<T>(column: Column<T>, value: T): FilterExpression;
42
+ export declare function ne<T>(column1: Column<T>, column2: Column<T>): FilterExpression;
43
+ /**
44
+ * Greater than operator - checks if column is greater than a value.
45
+ *
46
+ * @example
47
+ * gt(users.age, 18) // age greater than 18
48
+ */
49
+ export declare function gt<T extends number | string | Date | null>(column: Column<T>, value: T): FilterExpression;
50
+ /**
51
+ * Greater than or equal operator - checks if column is >= a value.
52
+ *
53
+ * @example
54
+ * gte(users.age, 18) // age >= 18
55
+ */
56
+ export declare function gte<T extends number | string | Date | null>(column: Column<T>, value: T): FilterExpression;
57
+ /**
58
+ * Less than operator - checks if column is less than a value.
59
+ *
60
+ * @example
61
+ * lt(users.age, 65) // age less than 65
62
+ */
63
+ export declare function lt<T extends number | string | Date | null>(column: Column<T>, value: T): FilterExpression;
64
+ /**
65
+ * Less than or equal operator - checks if column is <= a value.
66
+ *
67
+ * @example
68
+ * lte(users.age, 65) // age <= 65
69
+ */
70
+ export declare function lte<T extends number | string | Date | null>(column: Column<T>, value: T): FilterExpression;
71
+ /**
72
+ * Contains operator - checks if a string column contains a substring.
73
+ *
74
+ * @example
75
+ * contains(users.name, "John") // name contains "John"
76
+ */
77
+ export declare function contains(column: Column<string | null>, value: string): FilterExpression;
78
+ /**
79
+ * Starts with operator - checks if a string column starts with a prefix.
80
+ *
81
+ * @example
82
+ * startsWith(users.email, "admin") // email starts with "admin"
83
+ */
84
+ export declare function startsWith(column: Column<string | null>, value: string): FilterExpression;
85
+ /**
86
+ * Ends with operator - checks if a string column ends with a suffix.
87
+ *
88
+ * @example
89
+ * endsWith(users.email, "@example.com") // email ends with "@example.com"
90
+ */
91
+ export declare function endsWith(column: Column<string | null>, value: string): FilterExpression;
92
+ /**
93
+ * In array operator - checks if column value is in an array of values.
94
+ *
95
+ * @example
96
+ * inArray(users.status, ["active", "pending"]) // status is "active" or "pending"
97
+ */
98
+ export declare function inArray<T>(column: Column<T | null>, values: T[]): FilterExpression;
99
+ /**
100
+ * Not in array operator - checks if column value is not in an array of values.
101
+ *
102
+ * @example
103
+ * notInArray(users.status, ["deleted", "banned"]) // status is neither "deleted" nor "banned"
104
+ */
105
+ export declare function notInArray<T>(column: Column<T>, values: T[]): FilterExpression;
106
+ /**
107
+ * Is null operator - checks if column value is null.
108
+ *
109
+ * @example
110
+ * isNull(users.deletedAt) // deletedAt is null
111
+ */
112
+ export declare function isNull<T>(column: Column<T>): FilterExpression;
113
+ /**
114
+ * Is not null operator - checks if column value is not null.
115
+ *
116
+ * @example
117
+ * isNotNull(users.email) // email is not null
118
+ */
119
+ export declare function isNotNull<T>(column: Column<T>): FilterExpression;
120
+ /**
121
+ * AND operator - combines multiple filter expressions with logical AND.
122
+ * All expressions must be true for the record to match.
123
+ *
124
+ * @example
125
+ * and(
126
+ * eq(users.active, true),
127
+ * gt(users.age, 18)
128
+ * ) // active is true AND age > 18
129
+ */
130
+ export declare function and(...expressions: FilterExpression[]): FilterExpression;
131
+ /**
132
+ * OR operator - combines multiple filter expressions with logical OR.
133
+ * At least one expression must be true for the record to match.
134
+ *
135
+ * @example
136
+ * or(
137
+ * eq(users.role, "admin"),
138
+ * eq(users.role, "moderator")
139
+ * ) // role is "admin" OR "moderator"
140
+ */
141
+ export declare function or(...expressions: FilterExpression[]): FilterExpression;
142
+ /**
143
+ * NOT operator - negates a filter expression.
144
+ *
145
+ * @example
146
+ * not(eq(users.status, "deleted")) // status is NOT "deleted"
147
+ */
148
+ export declare function not(expression: FilterExpression): FilterExpression;
149
+ /**
150
+ * OrderByExpression represents a sort order specification for a column.
151
+ * Used in orderBy() clauses to provide type-safe sorting with direction.
152
+ */
153
+ export declare class OrderByExpression<TableName extends string = string> {
154
+ readonly column: Column<any, TableName>;
155
+ readonly direction: "asc" | "desc";
156
+ constructor(column: Column<any, TableName>, direction: "asc" | "desc");
157
+ }
158
+ /**
159
+ * Type guard to check if a value is an OrderByExpression instance.
160
+ */
161
+ export declare function isOrderByExpression(value: any): value is OrderByExpression;
162
+ /**
163
+ * Ascending order operator - sorts a column in ascending order.
164
+ *
165
+ * @example
166
+ * asc(users.name) // Sort by name ascending
167
+ */
168
+ export declare function asc<TableName extends string>(column: Column<any, TableName>): OrderByExpression<TableName>;
169
+ /**
170
+ * Descending order operator - sorts a column in descending order.
171
+ *
172
+ * @example
173
+ * desc(users.age) // Sort by age descending
174
+ */
175
+ export declare function desc<TableName extends string>(column: Column<any, TableName>): OrderByExpression<TableName>;
@@ -0,0 +1,221 @@
1
+ import { isColumn } from "./column.js";
2
+ class FilterExpression {
3
+ constructor(operator, operands) {
4
+ this.operator = operator;
5
+ this.operands = operands;
6
+ }
7
+ /**
8
+ * Convert this expression to OData filter syntax.
9
+ * @internal Used by QueryBuilder
10
+ */
11
+ toODataFilter(useEntityIds) {
12
+ switch (this.operator) {
13
+ // Comparison operators
14
+ case "eq":
15
+ return this._binaryOp("eq", useEntityIds);
16
+ case "ne":
17
+ return this._binaryOp("ne", useEntityIds);
18
+ case "gt":
19
+ return this._binaryOp("gt", useEntityIds);
20
+ case "gte":
21
+ return this._binaryOp("ge", useEntityIds);
22
+ case "lt":
23
+ return this._binaryOp("lt", useEntityIds);
24
+ case "lte":
25
+ return this._binaryOp("le", useEntityIds);
26
+ case "in":
27
+ return this._inOp(useEntityIds);
28
+ case "notIn":
29
+ return this._notInOp(useEntityIds);
30
+ // String operators
31
+ case "contains":
32
+ return this._functionOp("contains", useEntityIds);
33
+ case "startsWith":
34
+ return this._functionOp("startswith", useEntityIds);
35
+ case "endsWith":
36
+ return this._functionOp("endswith", useEntityIds);
37
+ // Null checks
38
+ case "isNull":
39
+ return this._isNullOp(useEntityIds);
40
+ case "isNotNull":
41
+ return this._isNotNullOp(useEntityIds);
42
+ // Logical operators
43
+ case "and":
44
+ return this._logicalOp("and", useEntityIds);
45
+ case "or":
46
+ return this._logicalOp("or", useEntityIds);
47
+ case "not":
48
+ return this._notOp(useEntityIds);
49
+ default:
50
+ throw new Error(`Unknown operator: ${this.operator}`);
51
+ }
52
+ }
53
+ _binaryOp(op, useEntityIds) {
54
+ const [left, right] = this.operands;
55
+ const leftStr = this._operandToString(left, useEntityIds);
56
+ const rightStr = this._operandToString(right, useEntityIds);
57
+ return `${leftStr} ${op} ${rightStr}`;
58
+ }
59
+ _functionOp(fnName, useEntityIds) {
60
+ const [column, value] = this.operands;
61
+ const columnStr = this._operandToString(column, useEntityIds);
62
+ const valueStr = this._operandToString(value, useEntityIds);
63
+ return `${fnName}(${columnStr}, ${valueStr})`;
64
+ }
65
+ _inOp(useEntityIds) {
66
+ const [column, values] = this.operands;
67
+ const columnStr = this._operandToString(column, useEntityIds);
68
+ const valuesStr = values.map((v) => this._operandToString(v, useEntityIds)).join(", ");
69
+ return `${columnStr} in (${valuesStr})`;
70
+ }
71
+ _notInOp(useEntityIds) {
72
+ const [column, values] = this.operands;
73
+ const columnStr = this._operandToString(column, useEntityIds);
74
+ const valuesStr = values.map((v) => this._operandToString(v, useEntityIds)).join(", ");
75
+ return `not (${columnStr} in (${valuesStr}))`;
76
+ }
77
+ _isNullOp(useEntityIds) {
78
+ const [column] = this.operands;
79
+ const columnStr = this._operandToString(column, useEntityIds);
80
+ return `${columnStr} eq null`;
81
+ }
82
+ _isNotNullOp(useEntityIds) {
83
+ const [column] = this.operands;
84
+ const columnStr = this._operandToString(column, useEntityIds);
85
+ return `${columnStr} ne null`;
86
+ }
87
+ _logicalOp(op, useEntityIds) {
88
+ const expressions = this.operands.map((expr) => {
89
+ if (expr instanceof FilterExpression) {
90
+ const innerExpr = expr.toODataFilter(useEntityIds);
91
+ if (expr.operator === "and" || expr.operator === "or") {
92
+ return `(${innerExpr})`;
93
+ }
94
+ return innerExpr;
95
+ }
96
+ throw new Error("Logical operators require FilterExpression operands");
97
+ });
98
+ return expressions.join(` ${op} `);
99
+ }
100
+ _notOp(useEntityIds) {
101
+ const [expr] = this.operands;
102
+ if (expr instanceof FilterExpression) {
103
+ return `not (${expr.toODataFilter(useEntityIds)})`;
104
+ }
105
+ throw new Error("NOT operator requires a FilterExpression operand");
106
+ }
107
+ _operandToString(operand, useEntityIds) {
108
+ if (isColumn(operand)) {
109
+ return operand.getFieldIdentifier(useEntityIds);
110
+ }
111
+ if (typeof operand === "string") {
112
+ return `'${operand.replace(/'/g, "''")}'`;
113
+ }
114
+ if (operand === null || operand === void 0) {
115
+ return "null";
116
+ }
117
+ if (operand instanceof Date) {
118
+ return operand.toISOString();
119
+ }
120
+ return String(operand);
121
+ }
122
+ }
123
+ function eq(column, value) {
124
+ return new FilterExpression("eq", [column, value]);
125
+ }
126
+ function ne(column, value) {
127
+ return new FilterExpression("ne", [column, value]);
128
+ }
129
+ function gt(column, value) {
130
+ return new FilterExpression("gt", [column, value]);
131
+ }
132
+ function gte(column, value) {
133
+ return new FilterExpression("gte", [column, value]);
134
+ }
135
+ function lt(column, value) {
136
+ return new FilterExpression("lt", [column, value]);
137
+ }
138
+ function lte(column, value) {
139
+ return new FilterExpression("lte", [column, value]);
140
+ }
141
+ function contains(column, value) {
142
+ return new FilterExpression("contains", [column, value]);
143
+ }
144
+ function startsWith(column, value) {
145
+ return new FilterExpression("startsWith", [column, value]);
146
+ }
147
+ function endsWith(column, value) {
148
+ return new FilterExpression("endsWith", [column, value]);
149
+ }
150
+ function inArray(column, values) {
151
+ return new FilterExpression("in", [column, values]);
152
+ }
153
+ function notInArray(column, values) {
154
+ return new FilterExpression("notIn", [column, values]);
155
+ }
156
+ function isNull(column) {
157
+ return new FilterExpression("isNull", [column]);
158
+ }
159
+ function isNotNull(column) {
160
+ return new FilterExpression("isNotNull", [column]);
161
+ }
162
+ function and(...expressions) {
163
+ if (expressions.length === 0) {
164
+ throw new Error("AND operator requires at least one expression");
165
+ }
166
+ if (expressions.length === 1 && expressions[0] !== void 0) {
167
+ return expressions[0];
168
+ }
169
+ return new FilterExpression("and", expressions);
170
+ }
171
+ function or(...expressions) {
172
+ if (expressions.length === 0) {
173
+ throw new Error("OR operator requires at least one expression");
174
+ }
175
+ if (expressions.length === 1 && expressions[0] !== void 0) {
176
+ return expressions[0];
177
+ }
178
+ return new FilterExpression("or", expressions);
179
+ }
180
+ function not(expression) {
181
+ return new FilterExpression("not", [expression]);
182
+ }
183
+ class OrderByExpression {
184
+ constructor(column, direction) {
185
+ this.column = column;
186
+ this.direction = direction;
187
+ }
188
+ }
189
+ function isOrderByExpression(value) {
190
+ return value instanceof OrderByExpression;
191
+ }
192
+ function asc(column) {
193
+ return new OrderByExpression(column, "asc");
194
+ }
195
+ function desc(column) {
196
+ return new OrderByExpression(column, "desc");
197
+ }
198
+ export {
199
+ FilterExpression,
200
+ OrderByExpression,
201
+ and,
202
+ asc,
203
+ contains,
204
+ desc,
205
+ endsWith,
206
+ eq,
207
+ gt,
208
+ gte,
209
+ inArray,
210
+ isNotNull,
211
+ isNull,
212
+ isOrderByExpression,
213
+ lt,
214
+ lte,
215
+ ne,
216
+ not,
217
+ notInArray,
218
+ or,
219
+ startsWith
220
+ };
221
+ //# sourceMappingURL=operators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operators.js","sources":["../../../src/orm/operators.ts"],"sourcesContent":["import 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 constructor(\n public readonly operator: string,\n public readonly operands: (Column | any | FilterExpression)[],\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 const leftStr = this._operandToString(left, useEntityIds);\n const rightStr = this._operandToString(right, useEntityIds);\n return `${leftStr} ${op} ${rightStr}`;\n }\n\n private _functionOp(fnName: string, useEntityIds?: boolean): string {\n const [column, value] = this.operands;\n const columnStr = this._operandToString(column, useEntityIds);\n const valueStr = this._operandToString(value, useEntityIds);\n return `${fnName}(${columnStr}, ${valueStr})`;\n }\n\n private _inOp(useEntityIds?: boolean): string {\n const [column, values] = this.operands;\n const columnStr = this._operandToString(column, useEntityIds);\n const valuesStr = (values as any[])\n .map((v) => this._operandToString(v, useEntityIds))\n .join(\", \");\n return `${columnStr} in (${valuesStr})`;\n }\n\n private _notInOp(useEntityIds?: boolean): string {\n const [column, values] = this.operands;\n const columnStr = this._operandToString(column, useEntityIds);\n const valuesStr = (values as any[])\n .map((v) => this._operandToString(v, useEntityIds))\n .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(operand: any, useEntityIds?: boolean): string {\n if (isColumn(operand)) {\n return operand.getFieldIdentifier(useEntityIds);\n }\n if (typeof operand === \"string\") {\n return `'${operand.replace(/'/g, \"''\")}'`; // Escape single quotes\n }\n if (operand === null || operand === undefined) {\n return \"null\";\n }\n if (operand instanceof Date) {\n return operand.toISOString();\n }\n return String(operand);\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<T>(column: Column<T>, value: T): FilterExpression;\nexport function eq<T>(column1: Column<T>, column2: Column<T>): FilterExpression;\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<T>(column: Column<T>, value: T): FilterExpression;\nexport function ne<T>(column1: Column<T>, column2: Column<T>): FilterExpression;\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<T extends number | string | Date | null>(\n column: Column<T>,\n value: T,\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<T extends number | string | Date | null>(\n column: Column<T>,\n value: T,\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<T extends number | string | Date | null>(\n column: Column<T>,\n value: T,\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<T extends number | string | Date | null>(\n column: Column<T>,\n value: T,\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(\n column: Column<string | null>,\n value: string,\n): 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(\n column: Column<string | null>,\n value: string,\n): 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(\n column: Column<string | null>,\n value: string,\n): 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<T>(\n column: Column<T | null>,\n values: T[],\n): 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<T>(\n column: Column<T>,\n values: T[],\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<T>(column: Column<T>): 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<T>(column: Column<T>): 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 constructor(\n public readonly column: Column<any, TableName>,\n public readonly direction: \"asc\" | \"desc\",\n ) {}\n}\n\n/**\n * Type guard to check if a value is an OrderByExpression instance.\n */\nexport function isOrderByExpression(\n value: any,\n): 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 */\nexport function asc<TableName extends string>(\n column: Column<any, TableName>,\n): 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 */\nexport function desc<TableName extends string>(\n column: Column<any, TableName>,\n): OrderByExpression<TableName> {\n return new OrderByExpression(column, \"desc\");\n}\n"],"names":[],"mappings":"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"}