@zenstackhq/runtime 2.15.1 → 3.0.0-alpha.0

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 (215) hide show
  1. package/LICENSE +1 -1
  2. package/dist/client.cjs +6094 -0
  3. package/dist/client.cjs.map +1 -0
  4. package/dist/client.d.cts +19 -0
  5. package/dist/client.d.ts +19 -0
  6. package/dist/client.js +6060 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/contract-DguafRNB.d.cts +1272 -0
  9. package/dist/contract-DguafRNB.d.ts +1272 -0
  10. package/dist/index.cjs +6088 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.cts +14 -0
  13. package/dist/index.d.ts +14 -0
  14. package/dist/index.js +6057 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/plugins/policy.cjs +2343 -0
  17. package/dist/plugins/policy.cjs.map +1 -0
  18. package/dist/plugins/policy.d.cts +24 -0
  19. package/dist/plugins/policy.d.ts +24 -0
  20. package/dist/plugins/policy.js +2307 -0
  21. package/dist/plugins/policy.js.map +1 -0
  22. package/dist/schema.cjs +110 -0
  23. package/dist/schema.cjs.map +1 -0
  24. package/dist/schema.d.cts +29 -0
  25. package/dist/schema.d.ts +29 -0
  26. package/dist/schema.js +85 -0
  27. package/dist/schema.js.map +1 -0
  28. package/dist/utils/pg-utils.cjs +39 -0
  29. package/dist/utils/pg-utils.cjs.map +1 -0
  30. package/dist/utils/pg-utils.d.cts +8 -0
  31. package/dist/utils/pg-utils.d.ts +8 -0
  32. package/dist/utils/pg-utils.js +16 -0
  33. package/dist/utils/pg-utils.js.map +1 -0
  34. package/{browser/index.js → dist/utils/sqlite-utils.cjs} +21 -37
  35. package/dist/utils/sqlite-utils.cjs.map +1 -0
  36. package/dist/utils/sqlite-utils.d.cts +8 -0
  37. package/dist/utils/sqlite-utils.d.ts +8 -0
  38. package/dist/utils/sqlite-utils.js +22 -0
  39. package/dist/utils/sqlite-utils.js.map +1 -0
  40. package/package.json +105 -114
  41. package/README.md +0 -5
  42. package/browser/index.d.mts +0 -13
  43. package/browser/index.d.ts +0 -13
  44. package/browser/index.js.map +0 -1
  45. package/browser/index.mjs +0 -33
  46. package/browser/index.mjs.map +0 -1
  47. package/constants.d.ts +0 -62
  48. package/constants.js +0 -76
  49. package/constants.js.map +0 -1
  50. package/cross/index.d.mts +0 -379
  51. package/cross/index.d.ts +0 -379
  52. package/cross/index.js +0 -903
  53. package/cross/index.js.map +0 -1
  54. package/cross/index.mjs +0 -861
  55. package/cross/index.mjs.map +0 -1
  56. package/edge.d.ts +0 -1
  57. package/edge.js +0 -18
  58. package/edge.js.map +0 -1
  59. package/encryption/index.d.ts +0 -25
  60. package/encryption/index.js +0 -74
  61. package/encryption/index.js.map +0 -1
  62. package/encryption/utils.d.ts +0 -9
  63. package/encryption/utils.js +0 -99
  64. package/encryption/utils.js.map +0 -1
  65. package/enhance-edge.d.ts +0 -1
  66. package/enhance-edge.js +0 -10
  67. package/enhance.d.ts +0 -1
  68. package/enhance.js +0 -10
  69. package/enhancements/edge/create-enhancement.d.ts +0 -42
  70. package/enhancements/edge/create-enhancement.js +0 -102
  71. package/enhancements/edge/create-enhancement.js.map +0 -1
  72. package/enhancements/edge/default-auth.d.ts +0 -8
  73. package/enhancements/edge/default-auth.js +0 -180
  74. package/enhancements/edge/default-auth.js.map +0 -1
  75. package/enhancements/edge/delegate.d.ts +0 -77
  76. package/enhancements/edge/delegate.js +0 -1294
  77. package/enhancements/edge/delegate.js.map +0 -1
  78. package/enhancements/edge/encryption.d.ts +0 -7
  79. package/enhancements/edge/encryption.js +0 -150
  80. package/enhancements/edge/encryption.js.map +0 -1
  81. package/enhancements/edge/index.d.ts +0 -4
  82. package/enhancements/edge/index.js +0 -21
  83. package/enhancements/edge/index.js.map +0 -1
  84. package/enhancements/edge/json-processor.d.ts +0 -7
  85. package/enhancements/edge/json-processor.js +0 -89
  86. package/enhancements/edge/json-processor.js.map +0 -1
  87. package/enhancements/edge/logger.d.ts +0 -29
  88. package/enhancements/edge/logger.js +0 -65
  89. package/enhancements/edge/logger.js.map +0 -1
  90. package/enhancements/edge/omit.d.ts +0 -7
  91. package/enhancements/edge/omit.js +0 -96
  92. package/enhancements/edge/omit.js.map +0 -1
  93. package/enhancements/edge/password.d.ts +0 -7
  94. package/enhancements/edge/password.js +0 -64
  95. package/enhancements/edge/password.js.map +0 -1
  96. package/enhancements/edge/policy/check-utils.d.ts +0 -5
  97. package/enhancements/edge/policy/check-utils.js +0 -20
  98. package/enhancements/edge/policy/check-utils.js.map +0 -1
  99. package/enhancements/edge/policy/handler.d.ts +0 -100
  100. package/enhancements/edge/policy/handler.js +0 -1442
  101. package/enhancements/edge/policy/handler.js.map +0 -1
  102. package/enhancements/edge/policy/index.d.ts +0 -19
  103. package/enhancements/edge/policy/index.js +0 -65
  104. package/enhancements/edge/policy/index.js.map +0 -1
  105. package/enhancements/edge/policy/policy-utils.d.ts +0 -181
  106. package/enhancements/edge/policy/policy-utils.js +0 -1357
  107. package/enhancements/edge/policy/policy-utils.js.map +0 -1
  108. package/enhancements/edge/promise.d.ts +0 -15
  109. package/enhancements/edge/promise.js +0 -99
  110. package/enhancements/edge/promise.js.map +0 -1
  111. package/enhancements/edge/proxy.d.ts +0 -120
  112. package/enhancements/edge/proxy.js +0 -287
  113. package/enhancements/edge/proxy.js.map +0 -1
  114. package/enhancements/edge/query-utils.d.ts +0 -53
  115. package/enhancements/edge/query-utils.js +0 -256
  116. package/enhancements/edge/query-utils.js.map +0 -1
  117. package/enhancements/edge/types.d.ts +0 -238
  118. package/enhancements/edge/types.js +0 -3
  119. package/enhancements/edge/types.js.map +0 -1
  120. package/enhancements/edge/utils.d.ts +0 -11
  121. package/enhancements/edge/utils.js +0 -49
  122. package/enhancements/edge/utils.js.map +0 -1
  123. package/enhancements/edge/where-visitor.d.ts +0 -32
  124. package/enhancements/edge/where-visitor.js +0 -86
  125. package/enhancements/edge/where-visitor.js.map +0 -1
  126. package/enhancements/node/create-enhancement.d.ts +0 -42
  127. package/enhancements/node/create-enhancement.js +0 -102
  128. package/enhancements/node/create-enhancement.js.map +0 -1
  129. package/enhancements/node/default-auth.d.ts +0 -8
  130. package/enhancements/node/default-auth.js +0 -180
  131. package/enhancements/node/default-auth.js.map +0 -1
  132. package/enhancements/node/delegate.d.ts +0 -77
  133. package/enhancements/node/delegate.js +0 -1294
  134. package/enhancements/node/delegate.js.map +0 -1
  135. package/enhancements/node/encryption.d.ts +0 -7
  136. package/enhancements/node/encryption.js +0 -150
  137. package/enhancements/node/encryption.js.map +0 -1
  138. package/enhancements/node/index.d.ts +0 -4
  139. package/enhancements/node/index.js +0 -21
  140. package/enhancements/node/index.js.map +0 -1
  141. package/enhancements/node/json-processor.d.ts +0 -7
  142. package/enhancements/node/json-processor.js +0 -89
  143. package/enhancements/node/json-processor.js.map +0 -1
  144. package/enhancements/node/logger.d.ts +0 -29
  145. package/enhancements/node/logger.js +0 -65
  146. package/enhancements/node/logger.js.map +0 -1
  147. package/enhancements/node/omit.d.ts +0 -7
  148. package/enhancements/node/omit.js +0 -96
  149. package/enhancements/node/omit.js.map +0 -1
  150. package/enhancements/node/password.d.ts +0 -7
  151. package/enhancements/node/password.js +0 -64
  152. package/enhancements/node/password.js.map +0 -1
  153. package/enhancements/node/policy/check-utils.d.ts +0 -5
  154. package/enhancements/node/policy/check-utils.js +0 -87
  155. package/enhancements/node/policy/check-utils.js.map +0 -1
  156. package/enhancements/node/policy/constraint-solver.d.ts +0 -27
  157. package/enhancements/node/policy/constraint-solver.js +0 -164
  158. package/enhancements/node/policy/constraint-solver.js.map +0 -1
  159. package/enhancements/node/policy/handler.d.ts +0 -100
  160. package/enhancements/node/policy/handler.js +0 -1442
  161. package/enhancements/node/policy/handler.js.map +0 -1
  162. package/enhancements/node/policy/index.d.ts +0 -19
  163. package/enhancements/node/policy/index.js +0 -65
  164. package/enhancements/node/policy/index.js.map +0 -1
  165. package/enhancements/node/policy/policy-utils.d.ts +0 -181
  166. package/enhancements/node/policy/policy-utils.js +0 -1357
  167. package/enhancements/node/policy/policy-utils.js.map +0 -1
  168. package/enhancements/node/promise.d.ts +0 -15
  169. package/enhancements/node/promise.js +0 -99
  170. package/enhancements/node/promise.js.map +0 -1
  171. package/enhancements/node/proxy.d.ts +0 -120
  172. package/enhancements/node/proxy.js +0 -287
  173. package/enhancements/node/proxy.js.map +0 -1
  174. package/enhancements/node/query-utils.d.ts +0 -53
  175. package/enhancements/node/query-utils.js +0 -256
  176. package/enhancements/node/query-utils.js.map +0 -1
  177. package/enhancements/node/types.d.ts +0 -238
  178. package/enhancements/node/types.js +0 -3
  179. package/enhancements/node/types.js.map +0 -1
  180. package/enhancements/node/utils.d.ts +0 -11
  181. package/enhancements/node/utils.js +0 -49
  182. package/enhancements/node/utils.js.map +0 -1
  183. package/enhancements/node/where-visitor.d.ts +0 -32
  184. package/enhancements/node/where-visitor.js +0 -86
  185. package/enhancements/node/where-visitor.js.map +0 -1
  186. package/error.d.ts +0 -11
  187. package/error.js +0 -22
  188. package/error.js.map +0 -1
  189. package/index.d.ts +0 -7
  190. package/index.js +0 -24
  191. package/index.js.map +0 -1
  192. package/model-meta.d.ts +0 -1
  193. package/model-meta.js +0 -10
  194. package/models.d.ts +0 -1
  195. package/models.js +0 -1
  196. package/types.d.ts +0 -180
  197. package/types.js +0 -4
  198. package/types.js.map +0 -1
  199. package/validation.d.ts +0 -24
  200. package/validation.js +0 -52
  201. package/validation.js.map +0 -1
  202. package/version.d.ts +0 -5
  203. package/version.js +0 -35
  204. package/version.js.map +0 -1
  205. package/zod/index.d.ts +0 -3
  206. package/zod/index.js +0 -5
  207. package/zod/input.d.ts +0 -1
  208. package/zod/input.js +0 -8
  209. package/zod/models.d.ts +0 -1
  210. package/zod/models.js +0 -8
  211. package/zod/objects.d.ts +0 -1
  212. package/zod/objects.js +0 -8
  213. package/zod-utils.d.ts +0 -12
  214. package/zod-utils.js +0 -97
  215. package/zod-utils.js.map +0 -1
@@ -0,0 +1,2307 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/plugins/policy/errors.ts
5
+ var RejectedByPolicyError = class extends Error {
6
+ static {
7
+ __name(this, "RejectedByPolicyError");
8
+ }
9
+ model;
10
+ reason;
11
+ constructor(model, reason) {
12
+ super(reason ?? `Operation rejected by policy${model ? ": " + model : ""}`), this.model = model, this.reason = reason;
13
+ }
14
+ };
15
+
16
+ // src/plugins/policy/policy-handler.ts
17
+ import { AliasNode as AliasNode3, BinaryOperationNode as BinaryOperationNode3, ColumnNode as ColumnNode2, DeleteQueryNode, FromNode as FromNode2, IdentifierNode as IdentifierNode2, InsertQueryNode, OperationNodeTransformer, OperatorNode as OperatorNode3, PrimitiveValueListNode, RawNode, ReturningNode, SelectionNode as SelectionNode2, SelectQueryNode as SelectQueryNode2, TableNode as TableNode3, UpdateQueryNode, ValueNode as ValueNode3, ValuesNode, WhereNode as WhereNode2 } from "kysely";
18
+ import invariant6 from "tiny-invariant";
19
+ import { match as match7 } from "ts-pattern";
20
+
21
+ // src/client/crud/dialects/index.ts
22
+ import { match as match4 } from "ts-pattern";
23
+
24
+ // src/client/crud/dialects/postgresql.ts
25
+ import { sql as sql2 } from "kysely";
26
+ import invariant2 from "tiny-invariant";
27
+ import { match as match2 } from "ts-pattern";
28
+
29
+ // src/client/errors.ts
30
+ var QueryError = class extends Error {
31
+ static {
32
+ __name(this, "QueryError");
33
+ }
34
+ constructor(message) {
35
+ super(message);
36
+ }
37
+ };
38
+ var InternalError = class extends Error {
39
+ static {
40
+ __name(this, "InternalError");
41
+ }
42
+ constructor(message) {
43
+ super(message);
44
+ }
45
+ };
46
+
47
+ // src/client/query-utils.ts
48
+ function getModel(schema, model) {
49
+ return schema.models[model];
50
+ }
51
+ __name(getModel, "getModel");
52
+ function requireModel(schema, model) {
53
+ const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
54
+ if (!matchedName) {
55
+ throw new QueryError(`Model "${model}" not found`);
56
+ }
57
+ return schema.models[matchedName];
58
+ }
59
+ __name(requireModel, "requireModel");
60
+ function getField(schema, model, field) {
61
+ const modelDef = getModel(schema, model);
62
+ return modelDef?.fields[field];
63
+ }
64
+ __name(getField, "getField");
65
+ function requireField(schema, model, field) {
66
+ const modelDef = requireModel(schema, model);
67
+ if (!modelDef.fields[field]) {
68
+ throw new QueryError(`Field "${field}" not found in model "${model}"`);
69
+ }
70
+ return modelDef.fields[field];
71
+ }
72
+ __name(requireField, "requireField");
73
+ function getIdFields(schema, model) {
74
+ const modelDef = requireModel(schema, model);
75
+ return modelDef?.idFields;
76
+ }
77
+ __name(getIdFields, "getIdFields");
78
+ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
79
+ const fieldDef = requireField(schema, model, relationField);
80
+ if (!fieldDef?.relation) {
81
+ throw new InternalError(`Field "${relationField}" is not a relation`);
82
+ }
83
+ if (fieldDef.relation.fields) {
84
+ if (!fieldDef.relation.references) {
85
+ throw new InternalError(`Relation references not defined for field "${relationField}"`);
86
+ }
87
+ return {
88
+ keyPairs: fieldDef.relation.fields.map((f, i) => ({
89
+ fk: f,
90
+ pk: fieldDef.relation.references[i]
91
+ })),
92
+ ownedByModel: true
93
+ };
94
+ } else {
95
+ if (!fieldDef.relation.opposite) {
96
+ throw new InternalError(`Opposite relation not defined for field "${relationField}"`);
97
+ }
98
+ const oppositeField = requireField(schema, fieldDef.type, fieldDef.relation.opposite);
99
+ if (!oppositeField.relation) {
100
+ throw new InternalError(`Field "${fieldDef.relation.opposite}" is not a relation`);
101
+ }
102
+ if (!oppositeField.relation.fields) {
103
+ throw new InternalError(`Relation fields not defined for field "${relationField}"`);
104
+ }
105
+ if (!oppositeField.relation.references) {
106
+ throw new InternalError(`Relation references not defined for field "${relationField}"`);
107
+ }
108
+ return {
109
+ keyPairs: oppositeField.relation.fields.map((f, i) => ({
110
+ fk: f,
111
+ pk: oppositeField.relation.references[i]
112
+ })),
113
+ ownedByModel: false
114
+ };
115
+ }
116
+ }
117
+ __name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
118
+ function getUniqueFields(schema, model) {
119
+ const modelDef = requireModel(schema, model);
120
+ const result = [];
121
+ for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
122
+ if (typeof value !== "object") {
123
+ throw new InternalError(`Invalid unique field definition for "${key}"`);
124
+ }
125
+ if (typeof value.type === "string") {
126
+ result.push({
127
+ name: key,
128
+ def: requireField(schema, model, key)
129
+ });
130
+ } else {
131
+ result.push({
132
+ name: key,
133
+ defs: Object.fromEntries(Object.keys(value).map((k) => [
134
+ k,
135
+ requireField(schema, model, k)
136
+ ]))
137
+ });
138
+ }
139
+ }
140
+ return result;
141
+ }
142
+ __name(getUniqueFields, "getUniqueFields");
143
+ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
144
+ const fieldDef = requireField(schema, model, field);
145
+ if (!fieldDef.computed) {
146
+ return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
147
+ } else {
148
+ let computer;
149
+ if ("computedFields" in options) {
150
+ const computedFields = options.computedFields;
151
+ computer = computedFields?.[model]?.[field];
152
+ }
153
+ if (!computer) {
154
+ throw new QueryError(`Computed field "${field}" implementation not provided`);
155
+ }
156
+ return computer(eb);
157
+ }
158
+ }
159
+ __name(buildFieldRef, "buildFieldRef");
160
+ function isEnum(schema, type) {
161
+ return !!schema.enums?.[type];
162
+ }
163
+ __name(isEnum, "isEnum");
164
+ function buildJoinPairs(schema, model, modelAlias, relationField, relationModelAlias) {
165
+ const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(schema, model, relationField);
166
+ return keyPairs.map(({ fk, pk }) => {
167
+ if (ownedByModel) {
168
+ return [
169
+ `${relationModelAlias}.${pk}`,
170
+ `${modelAlias}.${fk}`
171
+ ];
172
+ } else {
173
+ return [
174
+ `${relationModelAlias}.${fk}`,
175
+ `${modelAlias}.${pk}`
176
+ ];
177
+ }
178
+ });
179
+ }
180
+ __name(buildJoinPairs, "buildJoinPairs");
181
+ function makeDefaultOrderBy(schema, model) {
182
+ const idFields = getIdFields(schema, model);
183
+ return idFields.map((f) => ({
184
+ [f]: "asc"
185
+ }));
186
+ }
187
+ __name(makeDefaultOrderBy, "makeDefaultOrderBy");
188
+ function getManyToManyRelation(schema, model, field) {
189
+ const fieldDef = requireField(schema, model, field);
190
+ if (!fieldDef.array || !fieldDef.relation?.opposite) {
191
+ return void 0;
192
+ }
193
+ const oppositeFieldDef = requireField(schema, fieldDef.type, fieldDef.relation.opposite);
194
+ if (oppositeFieldDef.array) {
195
+ const sortedModelNames = [
196
+ model,
197
+ fieldDef.type
198
+ ].sort();
199
+ return {
200
+ parentFkName: sortedModelNames[0] === model ? "A" : "B",
201
+ otherModel: fieldDef.type,
202
+ otherField: fieldDef.relation.opposite,
203
+ otherFkName: sortedModelNames[0] === fieldDef.type ? "A" : "B",
204
+ joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
205
+ };
206
+ } else {
207
+ return void 0;
208
+ }
209
+ }
210
+ __name(getManyToManyRelation, "getManyToManyRelation");
211
+ function flattenCompoundUniqueFilters(schema, model, filter) {
212
+ if (typeof filter !== "object" || !filter) {
213
+ return filter;
214
+ }
215
+ const uniqueFields = getUniqueFields(schema, model);
216
+ const compoundUniques = uniqueFields.filter((u) => "defs" in u);
217
+ if (compoundUniques.length === 0) {
218
+ return filter;
219
+ }
220
+ const result = {};
221
+ for (const [key, value] of Object.entries(filter)) {
222
+ if (compoundUniques.some(({ name }) => name === key)) {
223
+ Object.assign(result, value);
224
+ } else {
225
+ result[key] = value;
226
+ }
227
+ }
228
+ return result;
229
+ }
230
+ __name(flattenCompoundUniqueFilters, "flattenCompoundUniqueFilters");
231
+
232
+ // src/client/crud/dialects/base.ts
233
+ import { sql } from "kysely";
234
+ import invariant from "tiny-invariant";
235
+ import { match, P } from "ts-pattern";
236
+
237
+ // src/utils/enumerate.ts
238
+ function enumerate(x) {
239
+ if (x === null || x === void 0) {
240
+ return [];
241
+ } else if (Array.isArray(x)) {
242
+ return x;
243
+ } else {
244
+ return [
245
+ x
246
+ ];
247
+ }
248
+ }
249
+ __name(enumerate, "enumerate");
250
+
251
+ // src/client/crud/dialects/base.ts
252
+ import { isPlainObject } from "is-plain-object";
253
+ var BaseCrudDialect = class {
254
+ static {
255
+ __name(this, "BaseCrudDialect");
256
+ }
257
+ schema;
258
+ options;
259
+ constructor(schema, options) {
260
+ this.schema = schema;
261
+ this.options = options;
262
+ }
263
+ transformPrimitive(value, _type) {
264
+ return value;
265
+ }
266
+ buildFilter(eb, model, modelAlias, where) {
267
+ if (where === true || where === void 0) {
268
+ return this.true(eb);
269
+ }
270
+ if (where === false) {
271
+ return this.false(eb);
272
+ }
273
+ let result = this.true(eb);
274
+ const _where = flattenCompoundUniqueFilters(this.schema, model, where);
275
+ for (const [key, payload] of Object.entries(_where)) {
276
+ if (payload === void 0) {
277
+ continue;
278
+ }
279
+ if (key.startsWith("$")) {
280
+ continue;
281
+ }
282
+ if (key === "AND" || key === "OR" || key === "NOT") {
283
+ result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
284
+ continue;
285
+ }
286
+ const fieldDef = requireField(this.schema, model, key);
287
+ if (fieldDef.relation) {
288
+ result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
289
+ } else if (fieldDef.array) {
290
+ result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
291
+ } else {
292
+ result = this.and(eb, result, this.buildPrimitiveFilter(eb, model, modelAlias, key, fieldDef, payload));
293
+ }
294
+ }
295
+ if ("$expr" in _where && typeof _where["$expr"] === "function") {
296
+ result = this.and(eb, result, _where["$expr"](eb));
297
+ }
298
+ return result;
299
+ }
300
+ buildCompositeFilter(eb, model, modelAlias, key, payload) {
301
+ return match(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
302
+ }
303
+ buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
304
+ if (!fieldDef.array) {
305
+ return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
306
+ } else {
307
+ return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
308
+ }
309
+ }
310
+ buildToOneRelationFilter(eb, model, table, field, fieldDef, payload) {
311
+ if (payload === null) {
312
+ const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
313
+ if (ownedByModel) {
314
+ return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${table}.${fk}`), "is", null)));
315
+ } else {
316
+ return this.buildToOneRelationFilter(eb, model, table, field, fieldDef, {
317
+ is: null
318
+ });
319
+ }
320
+ }
321
+ const joinAlias = `${table}$${field}`;
322
+ const joinPairs = buildJoinPairs(this.schema, model, table, field, joinAlias);
323
+ const filterResultField = `${field}$filter`;
324
+ const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
325
+ const conditions = [];
326
+ if ("is" in payload || "isNot" in payload) {
327
+ if ("is" in payload) {
328
+ if (payload.is === null) {
329
+ conditions.push(eb(joinSelect, "=", 0));
330
+ } else {
331
+ conditions.push(eb(joinSelect.where(() => this.buildFilter(eb, fieldDef.type, joinAlias, payload.is)), ">", 0));
332
+ }
333
+ }
334
+ if ("isNot" in payload) {
335
+ if (payload.isNot === null) {
336
+ conditions.push(eb(joinSelect, ">", 0));
337
+ } else {
338
+ conditions.push(this.or(
339
+ eb,
340
+ // is null
341
+ eb(joinSelect, "=", 0),
342
+ // found one that matches the filter
343
+ eb(joinSelect.where(() => this.buildFilter(eb, fieldDef.type, joinAlias, payload.isNot)), "=", 0)
344
+ ));
345
+ }
346
+ }
347
+ } else {
348
+ conditions.push(eb(joinSelect.where(() => this.buildFilter(eb, fieldDef.type, joinAlias, payload)), ">", 0));
349
+ }
350
+ return this.and(eb, ...conditions);
351
+ }
352
+ buildToManyRelationFilter(eb, model, table, field, fieldDef, payload) {
353
+ if (payload === null) {
354
+ return eb(sql.ref(`${table}.${field}`), "is", null);
355
+ }
356
+ const relationModel = fieldDef.type;
357
+ const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
358
+ const m2m = getManyToManyRelation(this.schema, model, field);
359
+ if (m2m) {
360
+ const modelIdField = getIdFields(this.schema, model)[0];
361
+ const relationIdField = getIdFields(this.schema, relationModel)[0];
362
+ return eb2(sql.ref(`${relationModel}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", sql.ref(`${table}.${modelIdField}`)));
363
+ } else {
364
+ const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
365
+ let result2 = this.true(eb2);
366
+ for (const { fk, pk } of relationKeyPairs.keyPairs) {
367
+ if (relationKeyPairs.ownedByModel) {
368
+ result2 = this.and(eb2, result2, eb2(sql.ref(`${table}.${fk}`), "=", sql.ref(`${relationModel}.${pk}`)));
369
+ } else {
370
+ result2 = this.and(eb2, result2, eb2(sql.ref(`${table}.${pk}`), "=", sql.ref(`${relationModel}.${fk}`)));
371
+ }
372
+ }
373
+ return result2;
374
+ }
375
+ }, "buildPkFkWhereRefs");
376
+ let result = this.true(eb);
377
+ for (const [key, subPayload] of Object.entries(payload)) {
378
+ if (!subPayload) {
379
+ continue;
380
+ }
381
+ switch (key) {
382
+ case "some": {
383
+ result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
384
+ break;
385
+ }
386
+ case "every": {
387
+ result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
388
+ break;
389
+ }
390
+ case "none": {
391
+ result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
392
+ break;
393
+ }
394
+ }
395
+ }
396
+ return result;
397
+ }
398
+ buildArrayFilter(eb, model, modelAlias, field, fieldDef, payload) {
399
+ const clauses = [];
400
+ const fieldType = fieldDef.type;
401
+ const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
402
+ for (const [key, _value] of Object.entries(payload)) {
403
+ if (_value === void 0) {
404
+ continue;
405
+ }
406
+ const value = this.transformPrimitive(_value, fieldType);
407
+ switch (key) {
408
+ case "equals": {
409
+ clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
410
+ break;
411
+ }
412
+ case "has": {
413
+ clauses.push(eb(fieldRef, "@>", eb.val([
414
+ value
415
+ ])));
416
+ break;
417
+ }
418
+ case "hasEvery": {
419
+ clauses.push(eb(fieldRef, "@>", eb.val(value)));
420
+ break;
421
+ }
422
+ case "hasSome": {
423
+ clauses.push(eb(fieldRef, "&&", eb.val(value)));
424
+ break;
425
+ }
426
+ case "isEmpty": {
427
+ clauses.push(eb(fieldRef, value === true ? "=" : "!=", eb.val([])));
428
+ break;
429
+ }
430
+ default: {
431
+ throw new InternalError(`Invalid array filter key: ${key}`);
432
+ }
433
+ }
434
+ }
435
+ return this.and(eb, ...clauses);
436
+ }
437
+ buildPrimitiveFilter(eb, model, modelAlias, field, fieldDef, payload) {
438
+ if (payload === null) {
439
+ return eb(sql.ref(`${modelAlias}.${field}`), "is", null);
440
+ }
441
+ if (isEnum(this.schema, fieldDef.type)) {
442
+ return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
443
+ }
444
+ return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).exhaustive();
445
+ }
446
+ buildLiteralFilter(eb, lhs, type, rhs) {
447
+ return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
448
+ }
449
+ buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
450
+ if (payload === null || !isPlainObject(payload)) {
451
+ return {
452
+ conditions: [
453
+ this.buildLiteralFilter(eb, lhs, type, payload)
454
+ ],
455
+ consumedKeys: []
456
+ };
457
+ }
458
+ const conditions = [];
459
+ const consumedKeys = [];
460
+ for (const [op, value] of Object.entries(payload)) {
461
+ if (onlyForKeys && !onlyForKeys.includes(op)) {
462
+ continue;
463
+ }
464
+ const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
465
+ const condition = match(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
466
+ invariant(Array.isArray(rhs), "right hand side must be an array");
467
+ if (rhs.length === 0) {
468
+ return this.false(eb);
469
+ } else {
470
+ return eb(lhs, "in", rhs);
471
+ }
472
+ }).with("notIn", () => {
473
+ invariant(Array.isArray(rhs), "right hand side must be an array");
474
+ if (rhs.length === 0) {
475
+ return this.true(eb);
476
+ } else {
477
+ return eb.not(eb(lhs, "in", rhs));
478
+ }
479
+ }).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).otherwise(() => {
480
+ if (throwIfInvalid) {
481
+ throw new QueryError(`Invalid filter key: ${op}`);
482
+ } else {
483
+ return void 0;
484
+ }
485
+ });
486
+ if (condition) {
487
+ conditions.push(condition);
488
+ consumedKeys.push(op);
489
+ }
490
+ }
491
+ return {
492
+ conditions,
493
+ consumedKeys
494
+ };
495
+ }
496
+ buildStringFilter(eb, table, field, payload) {
497
+ const fieldDef = getField(this.schema, table, field);
498
+ let fieldRef = fieldDef?.computed ? sql.ref(field) : sql.ref(`${table}.${field}`);
499
+ let insensitive = false;
500
+ if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
501
+ insensitive = true;
502
+ fieldRef = eb.fn("lower", [
503
+ fieldRef
504
+ ]);
505
+ }
506
+ const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => this.prepStringCasing(eb, value, insensitive), (value) => this.buildStringFilter(eb, table, field, value));
507
+ if (payload && typeof payload === "object") {
508
+ for (const [key, value] of Object.entries(payload)) {
509
+ if (key === "mode" || consumedKeys.includes(key)) {
510
+ continue;
511
+ }
512
+ const condition = match(key).with("contains", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`%${value}%`)) : eb(fieldRef, "like", sql.lit(`%${value}%`))).with("startsWith", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`${value}%`)) : eb(fieldRef, "like", sql.lit(`${value}%`))).with("endsWith", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`%${value}`)) : eb(fieldRef, "like", sql.lit(`%${value}`))).otherwise(() => {
513
+ throw new Error(`Invalid string filter key: ${key}`);
514
+ });
515
+ if (condition) {
516
+ conditions.push(condition);
517
+ }
518
+ }
519
+ }
520
+ return this.and(eb, ...conditions);
521
+ }
522
+ prepStringCasing(eb, value, toLower = true) {
523
+ if (typeof value === "string") {
524
+ return toLower ? eb.fn("lower", [
525
+ sql.lit(value)
526
+ ]) : sql.lit(value);
527
+ } else if (Array.isArray(value)) {
528
+ return value.map((v) => this.prepStringCasing(eb, v, toLower));
529
+ } else {
530
+ return value === null ? null : sql.lit(value);
531
+ }
532
+ }
533
+ buildNumberFilter(eb, model, table, field, type, payload) {
534
+ const { conditions } = this.buildStandardFilter(eb, type, payload, buildFieldRef(this.schema, model, field, this.options, eb), (value) => this.transformPrimitive(value, type), (value) => this.buildNumberFilter(eb, model, table, field, type, value));
535
+ return this.and(eb, ...conditions);
536
+ }
537
+ buildBooleanFilter(eb, table, field, payload) {
538
+ const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean"), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
539
+ "equals",
540
+ "not"
541
+ ]);
542
+ return this.and(eb, ...conditions);
543
+ }
544
+ buildDateTimeFilter(eb, table, field, payload) {
545
+ const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime"), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
546
+ return this.and(eb, ...conditions);
547
+ }
548
+ buildBytesFilter(eb, table, field, payload) {
549
+ const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes"), (value) => this.buildBytesFilter(eb, table, field, value), true, [
550
+ "equals",
551
+ "in",
552
+ "notIn",
553
+ "not"
554
+ ]);
555
+ return this.and(eb, ...conditions.conditions);
556
+ }
557
+ buildEnumFilter(eb, table, field, fieldDef, payload) {
558
+ const conditions = this.buildStandardFilter(eb, "String", payload, sql.ref(`${table}.${field}`), (value) => value, (value) => this.buildEnumFilter(eb, table, field, fieldDef, value), true, [
559
+ "equals",
560
+ "in",
561
+ "notIn",
562
+ "not"
563
+ ]);
564
+ return this.and(eb, ...conditions.conditions);
565
+ }
566
+ buildOrderBy(query, model, modelAlias, orderBy, useDefaultIfEmpty, negated) {
567
+ if (!orderBy) {
568
+ if (useDefaultIfEmpty) {
569
+ orderBy = makeDefaultOrderBy(this.schema, model);
570
+ } else {
571
+ return query;
572
+ }
573
+ }
574
+ let result = query;
575
+ enumerate(orderBy).forEach((orderBy2) => {
576
+ for (const [field, value] of Object.entries(orderBy2)) {
577
+ if (!value) {
578
+ continue;
579
+ }
580
+ if ([
581
+ "_count",
582
+ "_avg",
583
+ "_sum",
584
+ "_min",
585
+ "_max"
586
+ ].includes(field)) {
587
+ invariant(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
588
+ for (const [k, v] of Object.entries(value)) {
589
+ invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
590
+ result = result.orderBy((eb) => eb.fn(field.slice(1), [
591
+ sql.ref(k)
592
+ ]), sql.raw(this.negateSort(v, negated)));
593
+ }
594
+ continue;
595
+ }
596
+ switch (field) {
597
+ case "_count": {
598
+ invariant(value && typeof value === "object", 'invalid orderBy value for field "_count"');
599
+ for (const [k, v] of Object.entries(value)) {
600
+ invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
601
+ result = result.orderBy((eb) => eb.fn.count(sql.ref(k)), sql.raw(this.negateSort(v, negated)));
602
+ }
603
+ continue;
604
+ }
605
+ default:
606
+ break;
607
+ }
608
+ const fieldDef = requireField(this.schema, model, field);
609
+ if (!fieldDef.relation) {
610
+ if (value === "asc" || value === "desc") {
611
+ result = result.orderBy(sql.ref(`${modelAlias}.${field}`), this.negateSort(value, negated));
612
+ } else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
613
+ result = result.orderBy(sql.ref(`${modelAlias}.${field}`), sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
614
+ }
615
+ } else {
616
+ const relationModel = fieldDef.type;
617
+ if (fieldDef.array) {
618
+ if (typeof value !== "object") {
619
+ throw new QueryError(`invalid orderBy value for field "${field}"`);
620
+ }
621
+ if ("_count" in value) {
622
+ invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
623
+ const sort = this.negateSort(value._count, negated);
624
+ result = result.orderBy((eb) => {
625
+ let subQuery = eb.selectFrom(relationModel);
626
+ const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
627
+ subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
628
+ subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
629
+ return subQuery;
630
+ }, sort);
631
+ }
632
+ } else {
633
+ result = result.leftJoin(relationModel, (join) => {
634
+ const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
635
+ return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
636
+ });
637
+ result = this.buildOrderBy(result, fieldDef.type, relationModel, value, false, negated);
638
+ }
639
+ }
640
+ }
641
+ });
642
+ return result;
643
+ }
644
+ negateSort(sort, negated) {
645
+ return negated ? sort === "asc" ? "desc" : "asc" : sort;
646
+ }
647
+ true(eb) {
648
+ return eb.lit(this.transformPrimitive(true, "Boolean"));
649
+ }
650
+ false(eb) {
651
+ return eb.lit(this.transformPrimitive(false, "Boolean"));
652
+ }
653
+ isTrue(expression) {
654
+ const node = expression.toOperationNode();
655
+ if (node.kind !== "ValueNode") {
656
+ return false;
657
+ }
658
+ return node.value === true || node.value === 1;
659
+ }
660
+ isFalse(expression) {
661
+ const node = expression.toOperationNode();
662
+ if (node.kind !== "ValueNode") {
663
+ return false;
664
+ }
665
+ return node.value === false || node.value === 0;
666
+ }
667
+ and(eb, ...args) {
668
+ const nonTrueArgs = args.filter((arg) => !this.isTrue(arg));
669
+ if (nonTrueArgs.length === 0) {
670
+ return this.true(eb);
671
+ } else if (nonTrueArgs.length === 1) {
672
+ return nonTrueArgs[0];
673
+ } else {
674
+ return eb.and(nonTrueArgs);
675
+ }
676
+ }
677
+ or(eb, ...args) {
678
+ const nonFalseArgs = args.filter((arg) => !this.isFalse(arg));
679
+ if (nonFalseArgs.length === 0) {
680
+ return this.false(eb);
681
+ } else if (nonFalseArgs.length === 1) {
682
+ return nonFalseArgs[0];
683
+ } else {
684
+ return eb.or(nonFalseArgs);
685
+ }
686
+ }
687
+ not(eb, ...args) {
688
+ return eb.not(this.and(eb, ...args));
689
+ }
690
+ };
691
+
692
+ // src/client/crud/dialects/postgresql.ts
693
+ var PostgresCrudDialect = class extends BaseCrudDialect {
694
+ static {
695
+ __name(this, "PostgresCrudDialect");
696
+ }
697
+ get provider() {
698
+ return "postgresql";
699
+ }
700
+ transformPrimitive(value, type) {
701
+ if (value === void 0) {
702
+ return value;
703
+ }
704
+ if (Array.isArray(value)) {
705
+ return value.map((v) => this.transformPrimitive(v, type));
706
+ } else {
707
+ return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
708
+ }
709
+ }
710
+ buildRelationSelection(query, model, relationField, parentAlias, payload) {
711
+ const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload);
712
+ return joinedQuery.select(`${parentAlias}$${relationField}.$j as ${relationField}`);
713
+ }
714
+ buildRelationJSON(model, qb, relationField, parentName, payload) {
715
+ const relationFieldDef = requireField(this.schema, model, relationField);
716
+ const relationModel = relationFieldDef.type;
717
+ return qb.leftJoinLateral((eb) => {
718
+ const joinTableName = `${parentName}$${relationField}`;
719
+ let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
720
+ result = eb.selectFrom(() => {
721
+ let subQuery = eb.selectFrom(`${relationModel}`).selectAll();
722
+ if (payload && typeof payload === "object") {
723
+ if (payload.where) {
724
+ subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
725
+ }
726
+ const skip = payload.skip;
727
+ let take = payload.take;
728
+ let negateOrderBy = false;
729
+ if (take !== void 0 && take < 0) {
730
+ negateOrderBy = true;
731
+ take = -take;
732
+ }
733
+ subQuery = this.buildSkipTake(subQuery, skip, take);
734
+ subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
735
+ }
736
+ const m2m = getManyToManyRelation(this.schema, model, relationField);
737
+ if (m2m) {
738
+ const parentIds = getIdFields(this.schema, model);
739
+ const relationIds = getIdFields(this.schema, relationModel);
740
+ invariant2(parentIds.length === 1, "many-to-many relation must have exactly one id field");
741
+ invariant2(relationIds.length === 1, "many-to-many relation must have exactly one id field");
742
+ subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
743
+ } else {
744
+ const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
745
+ subQuery = subQuery.where((eb2) => this.and(eb2, ...joinPairs.map(([left, right]) => eb2(sql2.ref(left), "=", sql2.ref(right)))));
746
+ }
747
+ return subQuery.as(joinTableName);
748
+ });
749
+ result = this.buildRelationObjectSelect(relationModel, relationField, relationFieldDef, result, payload, parentName);
750
+ result = this.buildRelationJoins(relationModel, relationField, result, payload, parentName);
751
+ return result.as(joinTableName);
752
+ }, (join) => join.onTrue());
753
+ }
754
+ buildRelationObjectSelect(relationModel, relationField, relationFieldDef, qb, payload, parentName) {
755
+ qb = qb.select((eb) => {
756
+ const objArgs = this.buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName);
757
+ if (relationFieldDef.array) {
758
+ return eb.fn.coalesce(sql2`jsonb_agg(jsonb_build_object(${sql2.join(objArgs)}))`, sql2`'[]'::jsonb`).as("$j");
759
+ } else {
760
+ return sql2`jsonb_build_object(${sql2.join(objArgs)})`.as("$j");
761
+ }
762
+ });
763
+ return qb;
764
+ }
765
+ buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName) {
766
+ const relationModelDef = requireModel(this.schema, relationModel);
767
+ const objArgs = [];
768
+ if (payload === true || !payload.select) {
769
+ objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
770
+ sql2.lit(field),
771
+ buildFieldRef(this.schema, relationModel, field, this.options, eb)
772
+ ]).flatMap((v) => v));
773
+ } else if (payload.select) {
774
+ objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => [
775
+ sql2.lit(field),
776
+ buildFieldRef(this.schema, relationModel, field, this.options, eb)
777
+ ]).flatMap((v) => v));
778
+ }
779
+ if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
780
+ objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
781
+ sql2.lit(field),
782
+ eb.ref(`${parentName}$${relationField}$${field}.$j`)
783
+ ]).flatMap((v) => v));
784
+ }
785
+ return objArgs;
786
+ }
787
+ buildRelationJoins(model, relationField, qb, payload, parentName) {
788
+ let result = qb;
789
+ if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
790
+ Object.entries(payload.include).filter(([, value]) => value).forEach(([field, value]) => {
791
+ result = this.buildRelationJSON(model, result, field, `${parentName}$${relationField}`, value);
792
+ });
793
+ }
794
+ return result;
795
+ }
796
+ buildSkipTake(query, skip, take) {
797
+ if (take !== void 0) {
798
+ query = query.limit(take);
799
+ }
800
+ if (skip !== void 0) {
801
+ query = query.offset(skip);
802
+ }
803
+ return query;
804
+ }
805
+ buildJsonObject(eb, value) {
806
+ return eb.fn("jsonb_build_object", Object.entries(value).flatMap(([key, value2]) => [
807
+ sql2.lit(key),
808
+ value2
809
+ ]));
810
+ }
811
+ get supportsUpdateWithLimit() {
812
+ return false;
813
+ }
814
+ get supportsDeleteWithLimit() {
815
+ return false;
816
+ }
817
+ get supportsDistinctOn() {
818
+ return true;
819
+ }
820
+ buildArrayLength(eb, array) {
821
+ return eb.fn("array_length", [
822
+ array
823
+ ]);
824
+ }
825
+ buildArrayLiteralSQL(values) {
826
+ if (values.length === 0) {
827
+ return "{}";
828
+ } else {
829
+ return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
830
+ }
831
+ }
832
+ };
833
+
834
+ // src/client/crud/dialects/sqlite.ts
835
+ import { sql as sql3 } from "kysely";
836
+ import invariant3 from "tiny-invariant";
837
+ import { match as match3 } from "ts-pattern";
838
+ var SqliteCrudDialect = class extends BaseCrudDialect {
839
+ static {
840
+ __name(this, "SqliteCrudDialect");
841
+ }
842
+ get provider() {
843
+ return "sqlite";
844
+ }
845
+ transformPrimitive(value, type) {
846
+ if (value === void 0) {
847
+ return value;
848
+ }
849
+ if (Array.isArray(value)) {
850
+ return value.map((v) => this.transformPrimitive(v, type));
851
+ } else {
852
+ return match3(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).otherwise(() => value);
853
+ }
854
+ }
855
+ buildRelationSelection(query, model, relationField, parentAlias, payload) {
856
+ return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
857
+ }
858
+ buildRelationJSON(model, eb, relationField, parentName, payload) {
859
+ const relationFieldDef = requireField(this.schema, model, relationField);
860
+ const relationModel = relationFieldDef.type;
861
+ const relationModelDef = requireModel(this.schema, relationModel);
862
+ const subQueryName = `${parentName}$${relationField}`;
863
+ let tbl = eb.selectFrom(() => {
864
+ let subQuery = eb.selectFrom(relationModel).selectAll();
865
+ if (payload && typeof payload === "object") {
866
+ if (payload.where) {
867
+ subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
868
+ }
869
+ const skip = payload.skip;
870
+ let take = payload.take;
871
+ let negateOrderBy = false;
872
+ if (take !== void 0 && take < 0) {
873
+ negateOrderBy = true;
874
+ take = -take;
875
+ }
876
+ subQuery = this.buildSkipTake(subQuery, skip, take);
877
+ subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
878
+ }
879
+ const m2m = getManyToManyRelation(this.schema, model, relationField);
880
+ if (m2m) {
881
+ const parentIds = getIdFields(this.schema, model);
882
+ const relationIds = getIdFields(this.schema, relationModel);
883
+ invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
884
+ invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
885
+ subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
886
+ } else {
887
+ const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
888
+ keyPairs.forEach(({ fk, pk }) => {
889
+ if (ownedByModel) {
890
+ subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentName}.${fk}`);
891
+ } else {
892
+ subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentName}.${pk}`);
893
+ }
894
+ });
895
+ }
896
+ return subQuery.as(subQueryName);
897
+ });
898
+ tbl = tbl.select(() => {
899
+ const objArgs = [];
900
+ if (payload === true || !payload.select) {
901
+ objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
902
+ sql3.lit(field),
903
+ buildFieldRef(this.schema, relationModel, field, this.options, eb)
904
+ ]).flatMap((v) => v));
905
+ } else if (payload.select) {
906
+ objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
907
+ const fieldDef = requireField(this.schema, relationModel, field);
908
+ if (fieldDef.relation) {
909
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
910
+ return [
911
+ sql3.lit(field),
912
+ subJson
913
+ ];
914
+ } else {
915
+ return [
916
+ sql3.lit(field),
917
+ buildFieldRef(this.schema, relationModel, field, this.options, eb)
918
+ ];
919
+ }
920
+ }).flatMap((v) => v));
921
+ }
922
+ if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
923
+ objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
924
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
925
+ return [
926
+ sql3.lit(field),
927
+ subJson
928
+ ];
929
+ }).flatMap((v) => v));
930
+ }
931
+ if (relationFieldDef.array) {
932
+ return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$j");
933
+ } else {
934
+ return sql3`json_object(${sql3.join(objArgs)})`.as("data");
935
+ }
936
+ });
937
+ return tbl;
938
+ }
939
+ buildSkipTake(query, skip, take) {
940
+ if (take !== void 0) {
941
+ query = query.limit(take);
942
+ }
943
+ if (skip !== void 0) {
944
+ query = query.offset(skip);
945
+ if (take === void 0) {
946
+ query = query.limit(-1);
947
+ }
948
+ }
949
+ return query;
950
+ }
951
+ buildJsonObject(eb, value) {
952
+ return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
953
+ sql3.lit(key),
954
+ value2
955
+ ]));
956
+ }
957
+ get supportsUpdateWithLimit() {
958
+ return false;
959
+ }
960
+ get supportsDeleteWithLimit() {
961
+ return false;
962
+ }
963
+ get supportsDistinctOn() {
964
+ return false;
965
+ }
966
+ buildArrayLength(eb, array) {
967
+ return eb.fn("json_array_length", [
968
+ array
969
+ ]);
970
+ }
971
+ buildArrayLiteralSQL(_values) {
972
+ throw new Error("SQLite does not support array literals");
973
+ }
974
+ };
975
+
976
+ // src/client/crud/dialects/index.ts
977
+ function getCrudDialect(schema, options) {
978
+ return match4(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
979
+ }
980
+ __name(getCrudDialect, "getCrudDialect");
981
+
982
+ // src/schema/expression.ts
983
+ var ExpressionUtils = {
984
+ literal: /* @__PURE__ */ __name((value) => {
985
+ return {
986
+ kind: "literal",
987
+ value
988
+ };
989
+ }, "literal"),
990
+ array: /* @__PURE__ */ __name((items) => {
991
+ return {
992
+ kind: "array",
993
+ items
994
+ };
995
+ }, "array"),
996
+ call: /* @__PURE__ */ __name((functionName, args) => {
997
+ return {
998
+ kind: "call",
999
+ function: functionName,
1000
+ args
1001
+ };
1002
+ }, "call"),
1003
+ binary: /* @__PURE__ */ __name((left, op, right) => {
1004
+ return {
1005
+ kind: "binary",
1006
+ op,
1007
+ left,
1008
+ right
1009
+ };
1010
+ }, "binary"),
1011
+ unary: /* @__PURE__ */ __name((op, operand) => {
1012
+ return {
1013
+ kind: "unary",
1014
+ op,
1015
+ operand
1016
+ };
1017
+ }, "unary"),
1018
+ field: /* @__PURE__ */ __name((field) => {
1019
+ return {
1020
+ kind: "field",
1021
+ field
1022
+ };
1023
+ }, "field"),
1024
+ member: /* @__PURE__ */ __name((receiver, members) => {
1025
+ return {
1026
+ kind: "member",
1027
+ receiver,
1028
+ members
1029
+ };
1030
+ }, "member"),
1031
+ _this: /* @__PURE__ */ __name(() => {
1032
+ return {
1033
+ kind: "this"
1034
+ };
1035
+ }, "_this"),
1036
+ _null: /* @__PURE__ */ __name(() => {
1037
+ return {
1038
+ kind: "null"
1039
+ };
1040
+ }, "_null"),
1041
+ and: /* @__PURE__ */ __name((expr2, ...expressions) => {
1042
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
1043
+ }, "and"),
1044
+ or: /* @__PURE__ */ __name((expr2, ...expressions) => {
1045
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
1046
+ }, "or"),
1047
+ is: /* @__PURE__ */ __name((value, kind) => {
1048
+ return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
1049
+ }, "is"),
1050
+ isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
1051
+ isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
1052
+ isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
1053
+ isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
1054
+ isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
1055
+ isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
1056
+ isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
1057
+ isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
1058
+ isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
1059
+ };
1060
+
1061
+ // src/utils/default-operation-node-visitor.ts
1062
+ import { OperationNodeVisitor } from "kysely";
1063
+ var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
1064
+ static {
1065
+ __name(this, "DefaultOperationNodeVisitor");
1066
+ }
1067
+ defaultVisit(node) {
1068
+ Object.values(node).forEach((value) => {
1069
+ if (!value) {
1070
+ return;
1071
+ }
1072
+ if (Array.isArray(value)) {
1073
+ value.forEach((el) => this.defaultVisit(el));
1074
+ }
1075
+ if (typeof value === "object" && "kind" in value && typeof value.kind === "string") {
1076
+ this.visitNode(value);
1077
+ }
1078
+ });
1079
+ }
1080
+ visitSelectQuery(node) {
1081
+ this.defaultVisit(node);
1082
+ }
1083
+ visitSelection(node) {
1084
+ this.defaultVisit(node);
1085
+ }
1086
+ visitColumn(node) {
1087
+ this.defaultVisit(node);
1088
+ }
1089
+ visitAlias(node) {
1090
+ this.defaultVisit(node);
1091
+ }
1092
+ visitTable(node) {
1093
+ this.defaultVisit(node);
1094
+ }
1095
+ visitFrom(node) {
1096
+ this.defaultVisit(node);
1097
+ }
1098
+ visitReference(node) {
1099
+ this.defaultVisit(node);
1100
+ }
1101
+ visitAnd(node) {
1102
+ this.defaultVisit(node);
1103
+ }
1104
+ visitOr(node) {
1105
+ this.defaultVisit(node);
1106
+ }
1107
+ visitValueList(node) {
1108
+ this.defaultVisit(node);
1109
+ }
1110
+ visitParens(node) {
1111
+ this.defaultVisit(node);
1112
+ }
1113
+ visitJoin(node) {
1114
+ this.defaultVisit(node);
1115
+ }
1116
+ visitRaw(node) {
1117
+ this.defaultVisit(node);
1118
+ }
1119
+ visitWhere(node) {
1120
+ this.defaultVisit(node);
1121
+ }
1122
+ visitInsertQuery(node) {
1123
+ this.defaultVisit(node);
1124
+ }
1125
+ visitDeleteQuery(node) {
1126
+ this.defaultVisit(node);
1127
+ }
1128
+ visitReturning(node) {
1129
+ this.defaultVisit(node);
1130
+ }
1131
+ visitCreateTable(node) {
1132
+ this.defaultVisit(node);
1133
+ }
1134
+ visitAddColumn(node) {
1135
+ this.defaultVisit(node);
1136
+ }
1137
+ visitColumnDefinition(node) {
1138
+ this.defaultVisit(node);
1139
+ }
1140
+ visitDropTable(node) {
1141
+ this.defaultVisit(node);
1142
+ }
1143
+ visitOrderBy(node) {
1144
+ this.defaultVisit(node);
1145
+ }
1146
+ visitOrderByItem(node) {
1147
+ this.defaultVisit(node);
1148
+ }
1149
+ visitGroupBy(node) {
1150
+ this.defaultVisit(node);
1151
+ }
1152
+ visitGroupByItem(node) {
1153
+ this.defaultVisit(node);
1154
+ }
1155
+ visitUpdateQuery(node) {
1156
+ this.defaultVisit(node);
1157
+ }
1158
+ visitColumnUpdate(node) {
1159
+ this.defaultVisit(node);
1160
+ }
1161
+ visitLimit(node) {
1162
+ this.defaultVisit(node);
1163
+ }
1164
+ visitOffset(node) {
1165
+ this.defaultVisit(node);
1166
+ }
1167
+ visitOnConflict(node) {
1168
+ this.defaultVisit(node);
1169
+ }
1170
+ visitOnDuplicateKey(node) {
1171
+ this.defaultVisit(node);
1172
+ }
1173
+ visitCheckConstraint(node) {
1174
+ this.defaultVisit(node);
1175
+ }
1176
+ visitDataType(node) {
1177
+ this.defaultVisit(node);
1178
+ }
1179
+ visitSelectAll(node) {
1180
+ this.defaultVisit(node);
1181
+ }
1182
+ visitIdentifier(node) {
1183
+ this.defaultVisit(node);
1184
+ }
1185
+ visitSchemableIdentifier(node) {
1186
+ this.defaultVisit(node);
1187
+ }
1188
+ visitValue(node) {
1189
+ this.defaultVisit(node);
1190
+ }
1191
+ visitPrimitiveValueList(node) {
1192
+ this.defaultVisit(node);
1193
+ }
1194
+ visitOperator(node) {
1195
+ this.defaultVisit(node);
1196
+ }
1197
+ visitCreateIndex(node) {
1198
+ this.defaultVisit(node);
1199
+ }
1200
+ visitDropIndex(node) {
1201
+ this.defaultVisit(node);
1202
+ }
1203
+ visitList(node) {
1204
+ this.defaultVisit(node);
1205
+ }
1206
+ visitPrimaryKeyConstraint(node) {
1207
+ this.defaultVisit(node);
1208
+ }
1209
+ visitUniqueConstraint(node) {
1210
+ this.defaultVisit(node);
1211
+ }
1212
+ visitReferences(node) {
1213
+ this.defaultVisit(node);
1214
+ }
1215
+ visitWith(node) {
1216
+ this.defaultVisit(node);
1217
+ }
1218
+ visitCommonTableExpression(node) {
1219
+ this.defaultVisit(node);
1220
+ }
1221
+ visitCommonTableExpressionName(node) {
1222
+ this.defaultVisit(node);
1223
+ }
1224
+ visitHaving(node) {
1225
+ this.defaultVisit(node);
1226
+ }
1227
+ visitCreateSchema(node) {
1228
+ this.defaultVisit(node);
1229
+ }
1230
+ visitDropSchema(node) {
1231
+ this.defaultVisit(node);
1232
+ }
1233
+ visitAlterTable(node) {
1234
+ this.defaultVisit(node);
1235
+ }
1236
+ visitDropColumn(node) {
1237
+ this.defaultVisit(node);
1238
+ }
1239
+ visitRenameColumn(node) {
1240
+ this.defaultVisit(node);
1241
+ }
1242
+ visitAlterColumn(node) {
1243
+ this.defaultVisit(node);
1244
+ }
1245
+ visitModifyColumn(node) {
1246
+ this.defaultVisit(node);
1247
+ }
1248
+ visitAddConstraint(node) {
1249
+ this.defaultVisit(node);
1250
+ }
1251
+ visitDropConstraint(node) {
1252
+ this.defaultVisit(node);
1253
+ }
1254
+ visitForeignKeyConstraint(node) {
1255
+ this.defaultVisit(node);
1256
+ }
1257
+ visitCreateView(node) {
1258
+ this.defaultVisit(node);
1259
+ }
1260
+ visitDropView(node) {
1261
+ this.defaultVisit(node);
1262
+ }
1263
+ visitGenerated(node) {
1264
+ this.defaultVisit(node);
1265
+ }
1266
+ visitDefaultValue(node) {
1267
+ this.defaultVisit(node);
1268
+ }
1269
+ visitOn(node) {
1270
+ this.defaultVisit(node);
1271
+ }
1272
+ visitValues(node) {
1273
+ this.defaultVisit(node);
1274
+ }
1275
+ visitSelectModifier(node) {
1276
+ this.defaultVisit(node);
1277
+ }
1278
+ visitCreateType(node) {
1279
+ this.defaultVisit(node);
1280
+ }
1281
+ visitDropType(node) {
1282
+ this.defaultVisit(node);
1283
+ }
1284
+ visitExplain(node) {
1285
+ this.defaultVisit(node);
1286
+ }
1287
+ visitDefaultInsertValue(node) {
1288
+ this.defaultVisit(node);
1289
+ }
1290
+ visitAggregateFunction(node) {
1291
+ this.defaultVisit(node);
1292
+ }
1293
+ visitOver(node) {
1294
+ this.defaultVisit(node);
1295
+ }
1296
+ visitPartitionBy(node) {
1297
+ this.defaultVisit(node);
1298
+ }
1299
+ visitPartitionByItem(node) {
1300
+ this.defaultVisit(node);
1301
+ }
1302
+ visitSetOperation(node) {
1303
+ this.defaultVisit(node);
1304
+ }
1305
+ visitBinaryOperation(node) {
1306
+ this.defaultVisit(node);
1307
+ }
1308
+ visitUnaryOperation(node) {
1309
+ this.defaultVisit(node);
1310
+ }
1311
+ visitUsing(node) {
1312
+ this.defaultVisit(node);
1313
+ }
1314
+ visitFunction(node) {
1315
+ this.defaultVisit(node);
1316
+ }
1317
+ visitCase(node) {
1318
+ this.defaultVisit(node);
1319
+ }
1320
+ visitWhen(node) {
1321
+ this.defaultVisit(node);
1322
+ }
1323
+ visitJSONReference(node) {
1324
+ this.defaultVisit(node);
1325
+ }
1326
+ visitJSONPath(node) {
1327
+ this.defaultVisit(node);
1328
+ }
1329
+ visitJSONPathLeg(node) {
1330
+ this.defaultVisit(node);
1331
+ }
1332
+ visitJSONOperatorChain(node) {
1333
+ this.defaultVisit(node);
1334
+ }
1335
+ visitTuple(node) {
1336
+ this.defaultVisit(node);
1337
+ }
1338
+ visitMergeQuery(node) {
1339
+ this.defaultVisit(node);
1340
+ }
1341
+ visitMatched(node) {
1342
+ this.defaultVisit(node);
1343
+ }
1344
+ visitAddIndex(node) {
1345
+ this.defaultVisit(node);
1346
+ }
1347
+ visitCast(node) {
1348
+ this.defaultVisit(node);
1349
+ }
1350
+ visitFetch(node) {
1351
+ this.defaultVisit(node);
1352
+ }
1353
+ visitTop(node) {
1354
+ this.defaultVisit(node);
1355
+ }
1356
+ visitOutput(node) {
1357
+ this.defaultVisit(node);
1358
+ }
1359
+ };
1360
+
1361
+ // src/plugins/policy/column-collector.ts
1362
+ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1363
+ static {
1364
+ __name(this, "ColumnCollector");
1365
+ }
1366
+ columns = [];
1367
+ collect(node) {
1368
+ this.columns = [];
1369
+ this.visitNode(node);
1370
+ return this.columns;
1371
+ }
1372
+ visitColumn(node) {
1373
+ if (!this.columns.includes(node.column.name)) {
1374
+ this.columns.push(node.column.name);
1375
+ }
1376
+ }
1377
+ };
1378
+
1379
+ // src/plugins/policy/expression-transformer.ts
1380
+ import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
1381
+ import invariant5 from "tiny-invariant";
1382
+ import { match as match6 } from "ts-pattern";
1383
+
1384
+ // src/plugins/policy/expression-evaluator.ts
1385
+ import invariant4 from "tiny-invariant";
1386
+ import { match as match5 } from "ts-pattern";
1387
+ var ExpressionEvaluator = class {
1388
+ static {
1389
+ __name(this, "ExpressionEvaluator");
1390
+ }
1391
+ evaluate(expression, context) {
1392
+ const result = match5(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
1393
+ return result ?? null;
1394
+ }
1395
+ evaluateCall(expr2, context) {
1396
+ if (expr2.function === "auth") {
1397
+ return context.auth;
1398
+ } else {
1399
+ throw new Error(`Unsupported call expression function: ${expr2.function}`);
1400
+ }
1401
+ }
1402
+ evaluateUnary(expr2, context) {
1403
+ return match5(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1404
+ }
1405
+ evaluateMember(expr2, context) {
1406
+ let val = this.evaluate(expr2.receiver, context);
1407
+ for (const member of expr2.members) {
1408
+ val = val?.[member];
1409
+ }
1410
+ return val;
1411
+ }
1412
+ evaluateLiteral(expr2) {
1413
+ return expr2.value;
1414
+ }
1415
+ evaluateField(expr2, context) {
1416
+ return context.thisValue?.[expr2.field];
1417
+ }
1418
+ evaluateArray(expr2, context) {
1419
+ return expr2.items.map((item) => this.evaluate(item, context));
1420
+ }
1421
+ evaluateBinary(expr2, context) {
1422
+ if (expr2.op === "?" || expr2.op === "!" || expr2.op === "^") {
1423
+ return this.evaluateCollectionPredicate(expr2, context);
1424
+ }
1425
+ const left = this.evaluate(expr2.left, context);
1426
+ const right = this.evaluate(expr2.right, context);
1427
+ return match5(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
1428
+ const _right = right ?? [];
1429
+ invariant4(Array.isArray(_right), 'expected array for "in" operator');
1430
+ return _right.includes(left);
1431
+ }).exhaustive();
1432
+ }
1433
+ evaluateCollectionPredicate(expr2, context) {
1434
+ const op = expr2.op;
1435
+ invariant4(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
1436
+ const left = this.evaluate(expr2.left, context);
1437
+ if (!left) {
1438
+ return false;
1439
+ }
1440
+ invariant4(Array.isArray(left), "expected array");
1441
+ return match5(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1442
+ ...context,
1443
+ thisValue: item
1444
+ }))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
1445
+ ...context,
1446
+ thisValue: item
1447
+ }))).with("^", () => !left.some((item) => this.evaluate(expr2.right, {
1448
+ ...context,
1449
+ thisValue: item
1450
+ }))).exhaustive();
1451
+ }
1452
+ };
1453
+
1454
+ // src/plugins/policy/utils.ts
1455
+ import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
1456
+ function trueNode(dialect) {
1457
+ return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
1458
+ }
1459
+ __name(trueNode, "trueNode");
1460
+ function falseNode(dialect) {
1461
+ return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
1462
+ }
1463
+ __name(falseNode, "falseNode");
1464
+ function isTrueNode(node) {
1465
+ return ValueNode.is(node) && (node.value === true || node.value === 1);
1466
+ }
1467
+ __name(isTrueNode, "isTrueNode");
1468
+ function isFalseNode(node) {
1469
+ return ValueNode.is(node) && (node.value === false || node.value === 0);
1470
+ }
1471
+ __name(isFalseNode, "isFalseNode");
1472
+ function conjunction(dialect, nodes) {
1473
+ if (nodes.some(isFalseNode)) {
1474
+ return falseNode(dialect);
1475
+ }
1476
+ const items = nodes.filter((n) => !isTrueNode(n));
1477
+ if (items.length === 0) {
1478
+ return trueNode(dialect);
1479
+ }
1480
+ return items.reduce((acc, node) => OrNode.is(node) ? AndNode.create(acc, ParensNode.create(node)) : AndNode.create(acc, node));
1481
+ }
1482
+ __name(conjunction, "conjunction");
1483
+ function disjunction(dialect, nodes) {
1484
+ if (nodes.some(isTrueNode)) {
1485
+ return trueNode(dialect);
1486
+ }
1487
+ const items = nodes.filter((n) => !isFalseNode(n));
1488
+ if (items.length === 0) {
1489
+ return falseNode(dialect);
1490
+ }
1491
+ return items.reduce((acc, node) => AndNode.is(node) ? OrNode.create(acc, ParensNode.create(node)) : OrNode.create(acc, node));
1492
+ }
1493
+ __name(disjunction, "disjunction");
1494
+ function logicalNot(node) {
1495
+ return UnaryOperationNode.create(OperatorNode.create("not"), AndNode.is(node) || OrNode.is(node) ? ParensNode.create(node) : node);
1496
+ }
1497
+ __name(logicalNot, "logicalNot");
1498
+ function buildIsFalse(node, dialect) {
1499
+ if (isFalseNode(node)) {
1500
+ return trueNode(dialect);
1501
+ } else if (isTrueNode(node)) {
1502
+ return falseNode(dialect);
1503
+ }
1504
+ return BinaryOperationNode.create(
1505
+ // coalesce so null is treated as false
1506
+ FunctionNode.create("coalesce", [
1507
+ node,
1508
+ falseNode(dialect)
1509
+ ]),
1510
+ OperatorNode.create("="),
1511
+ falseNode(dialect)
1512
+ );
1513
+ }
1514
+ __name(buildIsFalse, "buildIsFalse");
1515
+ function getTableName(node) {
1516
+ if (!node) {
1517
+ return node;
1518
+ }
1519
+ if (TableNode.is(node)) {
1520
+ return node.table.identifier.name;
1521
+ } else if (AliasNode.is(node)) {
1522
+ return getTableName(node.node);
1523
+ } else if (ReferenceNode.is(node) && node.table) {
1524
+ return getTableName(node.table);
1525
+ }
1526
+ return void 0;
1527
+ }
1528
+ __name(getTableName, "getTableName");
1529
+
1530
+ // src/plugins/policy/expression-transformer.ts
1531
+ function _ts_decorate(decorators, target, key, desc) {
1532
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1533
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1534
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1535
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1536
+ }
1537
+ __name(_ts_decorate, "_ts_decorate");
1538
+ function _ts_metadata(k, v) {
1539
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1540
+ }
1541
+ __name(_ts_metadata, "_ts_metadata");
1542
+ var expressionHandlers = /* @__PURE__ */ new Map();
1543
+ function expr(kind) {
1544
+ return function(_target, _propertyKey, descriptor) {
1545
+ if (!expressionHandlers.get(kind)) {
1546
+ expressionHandlers.set(kind, descriptor);
1547
+ }
1548
+ return descriptor;
1549
+ };
1550
+ }
1551
+ __name(expr, "expr");
1552
+ var ExpressionTransformer = class {
1553
+ static {
1554
+ __name(this, "ExpressionTransformer");
1555
+ }
1556
+ schema;
1557
+ clientOptions;
1558
+ auth;
1559
+ dialect;
1560
+ constructor(schema, clientOptions, auth) {
1561
+ this.schema = schema;
1562
+ this.clientOptions = clientOptions;
1563
+ this.auth = auth;
1564
+ this.dialect = getCrudDialect(this.schema, this.clientOptions);
1565
+ }
1566
+ get authType() {
1567
+ if (!this.schema.authType) {
1568
+ throw new InternalError('Schema does not have an "authType" specified');
1569
+ }
1570
+ return this.schema.authType;
1571
+ }
1572
+ transform(expression, context) {
1573
+ const handler = expressionHandlers.get(expression.kind);
1574
+ if (!handler) {
1575
+ throw new Error(`Unsupported expression kind: ${expression.kind}`);
1576
+ }
1577
+ return handler.value.call(this, expression, context);
1578
+ }
1579
+ _literal(expr2) {
1580
+ return this.transformValue(expr2.value, typeof expr2.value === "string" ? "String" : typeof expr2.value === "boolean" ? "Boolean" : "Int");
1581
+ }
1582
+ _array(expr2, context) {
1583
+ return ValueListNode.create(expr2.items.map((item) => this.transform(item, context)));
1584
+ }
1585
+ _field(expr2, context) {
1586
+ const fieldDef = requireField(this.schema, context.model, expr2.field);
1587
+ if (!fieldDef.relation) {
1588
+ if (context.thisEntity) {
1589
+ return context.thisEntity[expr2.field];
1590
+ } else {
1591
+ return this.createColumnRef(expr2.field, context);
1592
+ }
1593
+ } else {
1594
+ const { memberFilter, memberSelect, ...restContext } = context;
1595
+ const relation = this.transformRelationAccess(expr2.field, fieldDef.type, restContext);
1596
+ return {
1597
+ ...relation,
1598
+ where: this.mergeWhere(relation.where, memberFilter),
1599
+ selections: memberSelect ? [
1600
+ memberSelect
1601
+ ] : relation.selections
1602
+ };
1603
+ }
1604
+ }
1605
+ mergeWhere(where, memberFilter) {
1606
+ if (!where) {
1607
+ return WhereNode.create(memberFilter ?? trueNode(this.dialect));
1608
+ }
1609
+ if (!memberFilter) {
1610
+ return where;
1611
+ }
1612
+ return WhereNode.create(conjunction(this.dialect, [
1613
+ where.where,
1614
+ memberFilter
1615
+ ]));
1616
+ }
1617
+ _null() {
1618
+ return ValueNode2.createImmediate(null);
1619
+ }
1620
+ _binary(expr2, context) {
1621
+ if (expr2.op === "&&") {
1622
+ return conjunction(this.dialect, [
1623
+ this.transform(expr2.left, context),
1624
+ this.transform(expr2.right, context)
1625
+ ]);
1626
+ } else if (expr2.op === "||") {
1627
+ return disjunction(this.dialect, [
1628
+ this.transform(expr2.left, context),
1629
+ this.transform(expr2.right, context)
1630
+ ]);
1631
+ }
1632
+ if (this.isAuthCall(expr2.left) || this.isAuthCall(expr2.right)) {
1633
+ return this.transformAuthBinary(expr2);
1634
+ }
1635
+ const op = expr2.op;
1636
+ if (op === "?" || op === "!" || op === "^") {
1637
+ return this.transformCollectionPredicate(expr2, context);
1638
+ }
1639
+ const left = this.transform(expr2.left, context);
1640
+ const right = this.transform(expr2.right, context);
1641
+ if (op === "in") {
1642
+ if (this.isNullNode(left)) {
1643
+ return this.transformValue(false, "Boolean");
1644
+ } else {
1645
+ if (ValueListNode.is(right)) {
1646
+ return BinaryOperationNode2.create(left, OperatorNode2.create("in"), right);
1647
+ } else {
1648
+ return BinaryOperationNode2.create(left, OperatorNode2.create("="), FunctionNode2.create("any", [
1649
+ right
1650
+ ]));
1651
+ }
1652
+ }
1653
+ }
1654
+ if (this.isNullNode(right)) {
1655
+ return expr2.op === "==" ? BinaryOperationNode2.create(left, OperatorNode2.create("is"), right) : BinaryOperationNode2.create(left, OperatorNode2.create("is not"), right);
1656
+ } else if (this.isNullNode(left)) {
1657
+ return expr2.op === "==" ? BinaryOperationNode2.create(right, OperatorNode2.create("is"), ValueNode2.createImmediate(null)) : BinaryOperationNode2.create(right, OperatorNode2.create("is not"), ValueNode2.createImmediate(null));
1658
+ }
1659
+ return BinaryOperationNode2.create(left, this.transformOperator(op), right);
1660
+ }
1661
+ transformCollectionPredicate(expr2, context) {
1662
+ invariant5(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
1663
+ if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
1664
+ const value = new ExpressionEvaluator().evaluate(expr2, {
1665
+ auth: this.auth
1666
+ });
1667
+ return this.transformValue(value, "Boolean");
1668
+ }
1669
+ invariant5(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
1670
+ let newContextModel;
1671
+ if (ExpressionUtils.isField(expr2.left)) {
1672
+ const fieldDef = requireField(this.schema, context.model, expr2.left.field);
1673
+ newContextModel = fieldDef.type;
1674
+ } else {
1675
+ invariant5(ExpressionUtils.isField(expr2.left.receiver));
1676
+ const fieldDef = requireField(this.schema, context.model, expr2.left.receiver.field);
1677
+ newContextModel = fieldDef.type;
1678
+ for (const member of expr2.left.members) {
1679
+ const memberDef = requireField(this.schema, newContextModel, member);
1680
+ newContextModel = memberDef.type;
1681
+ }
1682
+ }
1683
+ let predicateFilter = this.transform(expr2.right, {
1684
+ ...context,
1685
+ model: newContextModel,
1686
+ alias: void 0,
1687
+ thisEntity: void 0
1688
+ });
1689
+ if (expr2.op === "!") {
1690
+ predicateFilter = logicalNot(predicateFilter);
1691
+ }
1692
+ const count = FunctionNode2.create("count", [
1693
+ ValueNode2.createImmediate(1)
1694
+ ]);
1695
+ const predicateResult = match6(expr2.op).with("?", () => BinaryOperationNode2.create(count, OperatorNode2.create(">"), ValueNode2.createImmediate(0))).with("!", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).with("^", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).exhaustive();
1696
+ return this.transform(expr2.left, {
1697
+ ...context,
1698
+ memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
1699
+ memberFilter: predicateFilter
1700
+ });
1701
+ }
1702
+ transformAuthBinary(expr2) {
1703
+ if (expr2.op !== "==" && expr2.op !== "!=") {
1704
+ throw new Error(`Unsupported operator for auth call: ${expr2.op}`);
1705
+ }
1706
+ let other;
1707
+ if (this.isAuthCall(expr2.left)) {
1708
+ other = expr2.right;
1709
+ } else {
1710
+ other = expr2.left;
1711
+ }
1712
+ if (ExpressionUtils.isNull(other)) {
1713
+ return this.transformValue(expr2.op === "==" ? !this.auth : !!this.auth, "Boolean");
1714
+ } else {
1715
+ throw new Error("Unsupported binary expression with `auth()`");
1716
+ }
1717
+ }
1718
+ transformValue(value, type) {
1719
+ return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
1720
+ }
1721
+ _unary(expr2, context) {
1722
+ invariant5(expr2.op === "!", 'only "!" operator is supported');
1723
+ return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
1724
+ }
1725
+ transformOperator(op) {
1726
+ const mappedOp = match6(op).with("==", () => "=").otherwise(() => op);
1727
+ return OperatorNode2.create(mappedOp);
1728
+ }
1729
+ _call(expr2, context) {
1730
+ const result = this.transformCall(expr2, context);
1731
+ return result.toOperationNode();
1732
+ }
1733
+ transformCall(expr2, context) {
1734
+ const func = this.clientOptions.functions?.[expr2.function];
1735
+ if (!func) {
1736
+ throw new QueryError(`Function not implemented: ${expr2.function}`);
1737
+ }
1738
+ const eb = expressionBuilder();
1739
+ return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
1740
+ dialect: this.dialect,
1741
+ model: context.model,
1742
+ operation: context.operation
1743
+ });
1744
+ }
1745
+ transformCallArg(eb, arg, context) {
1746
+ if (ExpressionUtils.isLiteral(arg)) {
1747
+ return eb.val(arg.value);
1748
+ }
1749
+ if (ExpressionUtils.isField(arg)) {
1750
+ return context.thisEntityRaw ? eb.val(context.thisEntityRaw[arg.field]) : eb.ref(arg.field);
1751
+ }
1752
+ if (ExpressionUtils.isCall(arg)) {
1753
+ return this.transformCall(arg, context);
1754
+ }
1755
+ if (this.isAuthMember(arg)) {
1756
+ const valNode = this.valueMemberAccess(context.auth, arg, this.authType);
1757
+ return valNode ? eb.val(valNode.value) : eb.val(null);
1758
+ }
1759
+ throw new InternalError(`Unsupported argument expression: ${arg.kind}`);
1760
+ }
1761
+ _member(expr2, context) {
1762
+ if (this.isAuthCall(expr2.receiver)) {
1763
+ return this.valueMemberAccess(this.auth, expr2, this.authType);
1764
+ }
1765
+ invariant5(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
1766
+ const { memberFilter, memberSelect, ...restContext } = context;
1767
+ const receiver = this.transform(expr2.receiver, restContext);
1768
+ invariant5(SelectQueryNode.is(receiver), "expected receiver to be select query");
1769
+ const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
1770
+ const memberFields = [];
1771
+ let currType = receiverField.type;
1772
+ for (const member of expr2.members) {
1773
+ const fieldDef = requireField(this.schema, currType, member);
1774
+ memberFields.push({
1775
+ fieldDef,
1776
+ fromModel: currType
1777
+ });
1778
+ currType = fieldDef.type;
1779
+ }
1780
+ let currNode = void 0;
1781
+ for (let i = expr2.members.length - 1; i >= 0; i--) {
1782
+ const member = expr2.members[i];
1783
+ const { fieldDef, fromModel } = memberFields[i];
1784
+ if (fieldDef.relation) {
1785
+ const relation = this.transformRelationAccess(member, fieldDef.type, {
1786
+ ...restContext,
1787
+ model: fromModel,
1788
+ alias: void 0,
1789
+ thisEntity: void 0
1790
+ });
1791
+ if (currNode) {
1792
+ invariant5(SelectQueryNode.is(currNode), "expected select query node");
1793
+ currNode = {
1794
+ ...relation,
1795
+ selections: [
1796
+ SelectionNode.create(AliasNode2.create(currNode, IdentifierNode.create(expr2.members[i + 1])))
1797
+ ]
1798
+ };
1799
+ } else {
1800
+ currNode = {
1801
+ ...relation,
1802
+ where: this.mergeWhere(relation.where, memberFilter),
1803
+ selections: memberSelect ? [
1804
+ memberSelect
1805
+ ] : relation.selections
1806
+ };
1807
+ }
1808
+ } else {
1809
+ invariant5(i === expr2.members.length - 1, "plain field access must be the last segment");
1810
+ invariant5(!currNode, "plain field access must be the last segment");
1811
+ currNode = ColumnNode.create(member);
1812
+ }
1813
+ }
1814
+ return {
1815
+ ...receiver,
1816
+ selections: [
1817
+ SelectionNode.create(AliasNode2.create(currNode, IdentifierNode.create("$t")))
1818
+ ]
1819
+ };
1820
+ }
1821
+ valueMemberAccess(receiver, expr2, receiverType) {
1822
+ if (!receiver) {
1823
+ return ValueNode2.createImmediate(null);
1824
+ }
1825
+ if (expr2.members.length !== 1) {
1826
+ throw new Error(`Only single member access is supported`);
1827
+ }
1828
+ const field = expr2.members[0];
1829
+ const fieldDef = requireField(this.schema, receiverType, field);
1830
+ const fieldValue = receiver[field] ?? null;
1831
+ return this.transformValue(fieldValue, fieldDef.type);
1832
+ }
1833
+ transformRelationAccess(field, relationModel, context) {
1834
+ const fromModel = context.model;
1835
+ const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
1836
+ if (context.thisEntity) {
1837
+ let condition;
1838
+ if (ownedByModel) {
1839
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(relationModel)), OperatorNode2.create("="), context.thisEntity[fk])));
1840
+ } else {
1841
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(relationModel)), OperatorNode2.create("="), context.thisEntity[pk])));
1842
+ }
1843
+ return {
1844
+ kind: "SelectQueryNode",
1845
+ from: FromNode.create([
1846
+ TableNode2.create(relationModel)
1847
+ ]),
1848
+ where: WhereNode.create(condition)
1849
+ };
1850
+ } else {
1851
+ let condition;
1852
+ if (ownedByModel) {
1853
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(context.alias ?? fromModel)), OperatorNode2.create("="), ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(relationModel)))));
1854
+ } else {
1855
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(context.alias ?? fromModel)), OperatorNode2.create("="), ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(relationModel)))));
1856
+ }
1857
+ return {
1858
+ kind: "SelectQueryNode",
1859
+ from: FromNode.create([
1860
+ TableNode2.create(relationModel)
1861
+ ]),
1862
+ where: WhereNode.create(condition)
1863
+ };
1864
+ }
1865
+ }
1866
+ createColumnRef(column, context) {
1867
+ return ReferenceNode2.create(ColumnNode.create(column), TableNode2.create(context.alias ?? context.model));
1868
+ }
1869
+ isAuthCall(value) {
1870
+ return ExpressionUtils.isCall(value) && value.function === "auth";
1871
+ }
1872
+ isAuthMember(expr2) {
1873
+ return ExpressionUtils.isMember(expr2) && this.isAuthCall(expr2.receiver);
1874
+ }
1875
+ isNullNode(node) {
1876
+ return ValueNode2.is(node) && node.value === null;
1877
+ }
1878
+ };
1879
+ _ts_decorate([
1880
+ expr("literal"),
1881
+ _ts_metadata("design:type", Function),
1882
+ _ts_metadata("design:paramtypes", [
1883
+ typeof LiteralExpression === "undefined" ? Object : LiteralExpression
1884
+ ]),
1885
+ _ts_metadata("design:returntype", void 0)
1886
+ ], ExpressionTransformer.prototype, "_literal", null);
1887
+ _ts_decorate([
1888
+ expr("array"),
1889
+ _ts_metadata("design:type", Function),
1890
+ _ts_metadata("design:paramtypes", [
1891
+ typeof ArrayExpression === "undefined" ? Object : ArrayExpression,
1892
+ typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
1893
+ ]),
1894
+ _ts_metadata("design:returntype", void 0)
1895
+ ], ExpressionTransformer.prototype, "_array", null);
1896
+ _ts_decorate([
1897
+ expr("field"),
1898
+ _ts_metadata("design:type", Function),
1899
+ _ts_metadata("design:paramtypes", [
1900
+ typeof FieldExpression === "undefined" ? Object : FieldExpression,
1901
+ typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
1902
+ ]),
1903
+ _ts_metadata("design:returntype", void 0)
1904
+ ], ExpressionTransformer.prototype, "_field", null);
1905
+ _ts_decorate([
1906
+ expr("null"),
1907
+ _ts_metadata("design:type", Function),
1908
+ _ts_metadata("design:paramtypes", []),
1909
+ _ts_metadata("design:returntype", void 0)
1910
+ ], ExpressionTransformer.prototype, "_null", null);
1911
+ _ts_decorate([
1912
+ expr("binary"),
1913
+ _ts_metadata("design:type", Function),
1914
+ _ts_metadata("design:paramtypes", [
1915
+ typeof BinaryExpression === "undefined" ? Object : BinaryExpression,
1916
+ typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
1917
+ ]),
1918
+ _ts_metadata("design:returntype", void 0)
1919
+ ], ExpressionTransformer.prototype, "_binary", null);
1920
+ _ts_decorate([
1921
+ expr("unary"),
1922
+ _ts_metadata("design:type", Function),
1923
+ _ts_metadata("design:paramtypes", [
1924
+ typeof UnaryExpression === "undefined" ? Object : UnaryExpression,
1925
+ typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
1926
+ ]),
1927
+ _ts_metadata("design:returntype", void 0)
1928
+ ], ExpressionTransformer.prototype, "_unary", null);
1929
+ _ts_decorate([
1930
+ expr("call"),
1931
+ _ts_metadata("design:type", Function),
1932
+ _ts_metadata("design:paramtypes", [
1933
+ typeof CallExpression === "undefined" ? Object : CallExpression,
1934
+ typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
1935
+ ]),
1936
+ _ts_metadata("design:returntype", void 0)
1937
+ ], ExpressionTransformer.prototype, "_call", null);
1938
+ _ts_decorate([
1939
+ expr("member"),
1940
+ _ts_metadata("design:type", Function),
1941
+ _ts_metadata("design:paramtypes", [
1942
+ typeof MemberExpression === "undefined" ? Object : MemberExpression,
1943
+ typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
1944
+ ]),
1945
+ _ts_metadata("design:returntype", void 0)
1946
+ ], ExpressionTransformer.prototype, "_member", null);
1947
+
1948
+ // src/plugins/policy/policy-handler.ts
1949
+ var PolicyHandler = class extends OperationNodeTransformer {
1950
+ static {
1951
+ __name(this, "PolicyHandler");
1952
+ }
1953
+ client;
1954
+ dialect;
1955
+ constructor(client) {
1956
+ super(), this.client = client;
1957
+ this.dialect = getCrudDialect(this.client.$schema, this.client.$options);
1958
+ }
1959
+ get kysely() {
1960
+ return this.client.$qb;
1961
+ }
1962
+ async handle(node, proceed, transaction) {
1963
+ if (!this.isCrudQueryNode(node)) {
1964
+ throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
1965
+ }
1966
+ if (!this.isMutationQueryNode(node)) {
1967
+ return proceed(this.transformNode(node));
1968
+ }
1969
+ let mutationRequiresTransaction = false;
1970
+ const mutationModel = this.getMutationModel(node);
1971
+ if (InsertQueryNode.is(node)) {
1972
+ const constCondition = this.tryGetConstantPolicy(mutationModel, "create");
1973
+ if (constCondition === false) {
1974
+ throw new RejectedByPolicyError(mutationModel);
1975
+ } else if (constCondition === void 0) {
1976
+ mutationRequiresTransaction = true;
1977
+ }
1978
+ }
1979
+ if (!mutationRequiresTransaction && !node.returning) {
1980
+ return proceed(this.transformNode(node));
1981
+ }
1982
+ let readBackError = false;
1983
+ const result = await transaction(async (txProceed) => {
1984
+ if (InsertQueryNode.is(node)) {
1985
+ await this.enforcePreCreatePolicy(node, txProceed);
1986
+ }
1987
+ const transformedNode = this.transformNode(node);
1988
+ const result2 = await txProceed(transformedNode);
1989
+ if (!this.onlyReturningId(node)) {
1990
+ const readBackResult = await this.processReadBack(node, result2, txProceed);
1991
+ if (readBackResult.rows.length !== result2.rows.length) {
1992
+ readBackError = true;
1993
+ }
1994
+ return readBackResult;
1995
+ } else {
1996
+ return result2;
1997
+ }
1998
+ });
1999
+ if (readBackError) {
2000
+ throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2001
+ }
2002
+ return result;
2003
+ }
2004
+ onlyReturningId(node) {
2005
+ if (!node.returning) {
2006
+ return true;
2007
+ }
2008
+ const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
2009
+ const collector = new ColumnCollector();
2010
+ const selectedColumns = collector.collect(node.returning);
2011
+ return selectedColumns.every((c) => idFields.includes(c));
2012
+ }
2013
+ async enforcePreCreatePolicy(node, proceed) {
2014
+ if (!node.columns || !node.values) {
2015
+ return;
2016
+ }
2017
+ const model = this.getMutationModel(node);
2018
+ const fields = node.columns.map((c) => c.column.name);
2019
+ const valueRows = this.unwrapCreateValueRows(node.values, model, fields);
2020
+ for (const values of valueRows) {
2021
+ await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node), values.map((v) => v.raw), proceed);
2022
+ }
2023
+ }
2024
+ async enforcePreCreatePolicyForOne(model, fields, values, valuesRaw, proceed) {
2025
+ const thisEntity = {};
2026
+ const thisEntityRaw = {};
2027
+ for (let i = 0; i < fields.length; i++) {
2028
+ thisEntity[fields[i]] = values[i];
2029
+ thisEntityRaw[fields[i]] = valuesRaw[i];
2030
+ }
2031
+ const filter = this.buildPolicyFilter(model, void 0, "create", thisEntity, thisEntityRaw);
2032
+ const preCreateCheck = {
2033
+ kind: "SelectQueryNode",
2034
+ selections: [
2035
+ SelectionNode2.create(AliasNode3.create(filter, IdentifierNode2.create("$condition")))
2036
+ ]
2037
+ };
2038
+ const result = await proceed(preCreateCheck);
2039
+ if (!result.rows[0]?.$condition) {
2040
+ throw new RejectedByPolicyError(model);
2041
+ }
2042
+ }
2043
+ unwrapCreateValueRows(node, model, fields) {
2044
+ if (ValuesNode.is(node)) {
2045
+ return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields));
2046
+ } else if (PrimitiveValueListNode.is(node)) {
2047
+ return [
2048
+ this.unwrapCreateValueRow(node.values, model, fields)
2049
+ ];
2050
+ } else {
2051
+ throw new InternalError(`Unexpected node kind: ${node.kind} for unwrapping create values`);
2052
+ }
2053
+ }
2054
+ unwrapCreateValueRow(data, model, fields) {
2055
+ invariant6(data.length === fields.length, "data length must match fields length");
2056
+ const result = [];
2057
+ for (let i = 0; i < data.length; i++) {
2058
+ const item = data[i];
2059
+ const fieldDef = requireField(this.client.$schema, model, fields[i]);
2060
+ if (typeof item === "object" && item && "kind" in item) {
2061
+ invariant6(item.kind === "ValueNode", "expecting a ValueNode");
2062
+ result.push({
2063
+ node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
2064
+ raw: item.value
2065
+ });
2066
+ } else {
2067
+ const value = this.dialect.transformPrimitive(item, fieldDef.type);
2068
+ if (Array.isArray(value)) {
2069
+ result.push({
2070
+ node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
2071
+ raw: value
2072
+ });
2073
+ } else {
2074
+ result.push({
2075
+ node: ValueNode3.create(value),
2076
+ raw: value
2077
+ });
2078
+ }
2079
+ }
2080
+ }
2081
+ return result;
2082
+ }
2083
+ tryGetConstantPolicy(model, operation) {
2084
+ const policies = this.getModelPolicies(model, operation);
2085
+ if (!policies.some((p) => p.kind === "allow")) {
2086
+ return false;
2087
+ } else if (
2088
+ // unconditional deny
2089
+ policies.some((p) => p.kind === "deny" && this.isTrueExpr(p.condition))
2090
+ ) {
2091
+ return false;
2092
+ } else if (
2093
+ // unconditional allow
2094
+ !policies.some((p) => p.kind === "deny") && policies.some((p) => p.kind === "allow" && this.isTrueExpr(p.condition))
2095
+ ) {
2096
+ return true;
2097
+ } else {
2098
+ return void 0;
2099
+ }
2100
+ }
2101
+ isTrueExpr(expr2) {
2102
+ return ExpressionUtils.isLiteral(expr2) && expr2.value === true;
2103
+ }
2104
+ async processReadBack(node, result, proceed) {
2105
+ if (result.rows.length === 0) {
2106
+ return result;
2107
+ }
2108
+ if (!this.isMutationQueryNode(node) || !node.returning) {
2109
+ return result;
2110
+ }
2111
+ const table = this.getMutationModel(node);
2112
+ if (!table) {
2113
+ throw new InternalError(`Unable to get table name for query node: ${node}`);
2114
+ }
2115
+ const idConditions = this.buildIdConditions(table, result.rows);
2116
+ const policyFilter = this.buildPolicyFilter(table, void 0, "read");
2117
+ const select = {
2118
+ kind: "SelectQueryNode",
2119
+ from: FromNode2.create([
2120
+ TableNode3.create(table)
2121
+ ]),
2122
+ where: WhereNode2.create(conjunction(this.dialect, [
2123
+ idConditions,
2124
+ policyFilter
2125
+ ])),
2126
+ selections: node.returning.selections
2127
+ };
2128
+ const selectResult = await proceed(select);
2129
+ return selectResult;
2130
+ }
2131
+ buildIdConditions(table, rows) {
2132
+ const idFields = getIdFields(this.client.$schema, table);
2133
+ return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => BinaryOperationNode3.create(ColumnNode2.create(field), OperatorNode3.create("="), ValueNode3.create(row[field]))))));
2134
+ }
2135
+ getMutationModel(node) {
2136
+ const r = match7(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2137
+ if (node2.from.froms.length !== 1) {
2138
+ throw new InternalError("Only one from table is supported for delete");
2139
+ }
2140
+ return getTableName(node2.from.froms[0]);
2141
+ }).exhaustive();
2142
+ if (!r) {
2143
+ throw new InternalError(`Unable to get table name for query node: ${node}`);
2144
+ }
2145
+ return r;
2146
+ }
2147
+ isCrudQueryNode(node) {
2148
+ return SelectQueryNode2.is(node) || InsertQueryNode.is(node) || UpdateQueryNode.is(node) || DeleteQueryNode.is(node);
2149
+ }
2150
+ isMutationQueryNode(node) {
2151
+ return InsertQueryNode.is(node) || UpdateQueryNode.is(node) || DeleteQueryNode.is(node);
2152
+ }
2153
+ buildPolicyFilter(model, alias, operation, thisEntity, thisEntityRaw) {
2154
+ const policies = this.getModelPolicies(model, operation);
2155
+ if (policies.length === 0) {
2156
+ return falseNode(this.dialect);
2157
+ }
2158
+ const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw));
2159
+ const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw));
2160
+ let combinedPolicy;
2161
+ if (allows.length === 0) {
2162
+ combinedPolicy = falseNode(this.dialect);
2163
+ } else {
2164
+ combinedPolicy = disjunction(this.dialect, allows);
2165
+ if (denies.length !== 0) {
2166
+ const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
2167
+ combinedPolicy = conjunction(this.dialect, [
2168
+ combinedPolicy,
2169
+ combinedDenies
2170
+ ]);
2171
+ }
2172
+ }
2173
+ return combinedPolicy;
2174
+ }
2175
+ transformSelectQuery(node) {
2176
+ let whereNode = node.where;
2177
+ node.from?.froms.forEach((from) => {
2178
+ const extractResult = this.extractTableName(from);
2179
+ if (extractResult) {
2180
+ const { model, alias } = extractResult;
2181
+ const filter = this.buildPolicyFilter(model, alias, "read");
2182
+ whereNode = WhereNode2.create(whereNode?.where ? conjunction(this.dialect, [
2183
+ whereNode.where,
2184
+ filter
2185
+ ]) : filter);
2186
+ }
2187
+ });
2188
+ const baseResult = super.transformSelectQuery({
2189
+ ...node,
2190
+ where: void 0
2191
+ });
2192
+ return {
2193
+ ...baseResult,
2194
+ where: whereNode
2195
+ };
2196
+ }
2197
+ transformInsertQuery(node) {
2198
+ const result = super.transformInsertQuery(node);
2199
+ if (!node.returning) {
2200
+ return result;
2201
+ }
2202
+ if (this.onlyReturningId(node)) {
2203
+ return result;
2204
+ } else {
2205
+ const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
2206
+ return {
2207
+ ...result,
2208
+ returning: ReturningNode.create(idFields.map((field) => SelectionNode2.create(ColumnNode2.create(field))))
2209
+ };
2210
+ }
2211
+ }
2212
+ transformUpdateQuery(node) {
2213
+ const result = super.transformUpdateQuery(node);
2214
+ const mutationModel = this.getMutationModel(node);
2215
+ const filter = this.buildPolicyFilter(mutationModel, void 0, "update");
2216
+ return {
2217
+ ...result,
2218
+ where: WhereNode2.create(result.where ? conjunction(this.dialect, [
2219
+ result.where.where,
2220
+ filter
2221
+ ]) : filter)
2222
+ };
2223
+ }
2224
+ transformDeleteQuery(node) {
2225
+ const result = super.transformDeleteQuery(node);
2226
+ const mutationModel = this.getMutationModel(node);
2227
+ const filter = this.buildPolicyFilter(mutationModel, void 0, "delete");
2228
+ return {
2229
+ ...result,
2230
+ where: WhereNode2.create(result.where ? conjunction(this.dialect, [
2231
+ result.where.where,
2232
+ filter
2233
+ ]) : filter)
2234
+ };
2235
+ }
2236
+ extractTableName(from) {
2237
+ if (TableNode3.is(from)) {
2238
+ return {
2239
+ model: from.table.identifier.name
2240
+ };
2241
+ }
2242
+ if (AliasNode3.is(from)) {
2243
+ const inner = this.extractTableName(from.node);
2244
+ if (!inner) {
2245
+ return void 0;
2246
+ }
2247
+ return {
2248
+ model: inner.model,
2249
+ alias: IdentifierNode2.is(from.alias) ? from.alias.name : void 0
2250
+ };
2251
+ } else {
2252
+ return void 0;
2253
+ }
2254
+ }
2255
+ transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw) {
2256
+ return new ExpressionTransformer(this.client.$schema, this.client.$options, this.client.$auth).transform(policy.condition, {
2257
+ model,
2258
+ alias,
2259
+ operation,
2260
+ thisEntity,
2261
+ thisEntityRaw,
2262
+ auth: this.client.$auth
2263
+ });
2264
+ }
2265
+ getModelPolicies(modelName, operation) {
2266
+ const modelDef = requireModel(this.client.$schema, modelName);
2267
+ const result = [];
2268
+ const extractOperations = /* @__PURE__ */ __name((expr2) => {
2269
+ invariant6(ExpressionUtils.isLiteral(expr2), "expecting a literal");
2270
+ invariant6(typeof expr2.value === "string", "expecting a string literal");
2271
+ return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
2272
+ }, "extractOperations");
2273
+ if (modelDef.attributes) {
2274
+ result.push(...modelDef.attributes.filter((attr) => attr.name === "@@allow" || attr.name === "@@deny").map((attr) => ({
2275
+ kind: attr.name === "@@allow" ? "allow" : "deny",
2276
+ operations: extractOperations(attr.args[0].value),
2277
+ condition: attr.args[1].value
2278
+ })).filter((policy) => policy.operations.includes("all") || policy.operations.includes(operation)));
2279
+ }
2280
+ return result;
2281
+ }
2282
+ };
2283
+
2284
+ // src/plugins/policy/plugin.ts
2285
+ var PolicyPlugin = class {
2286
+ static {
2287
+ __name(this, "PolicyPlugin");
2288
+ }
2289
+ get id() {
2290
+ return "policy";
2291
+ }
2292
+ get name() {
2293
+ return "Access Policy";
2294
+ }
2295
+ get description() {
2296
+ return "Enforces access policies defined in the schema.";
2297
+ }
2298
+ onKyselyQuery({ query, client, proceed, transaction }) {
2299
+ const handler = new PolicyHandler(client);
2300
+ return handler.handle(query, proceed, transaction);
2301
+ }
2302
+ };
2303
+ export {
2304
+ PolicyPlugin,
2305
+ RejectedByPolicyError
2306
+ };
2307
+ //# sourceMappingURL=policy.js.map