okmodel 0.1.0 → 0.2.1

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 (181) hide show
  1. package/README.md +237 -19
  2. package/dist/adapters/capabilities.d.ts +34 -0
  3. package/dist/adapters/pg/bunsql-extra.d.ts +17 -0
  4. package/dist/adapters/pg/bunsql.d.ts +60 -0
  5. package/dist/adapters/pg/call.d.ts +2 -12
  6. package/dist/adapters/pg/nodepostgres-extra.d.ts +18 -0
  7. package/dist/adapters/pg/nodepostgres.d.ts +57 -0
  8. package/dist/adapters/pg/postgres-extra.d.ts +50 -1
  9. package/dist/adapters/pg/postgresjs.d.ts +0 -4
  10. package/dist/adapters/pg/session.d.ts +94 -0
  11. package/dist/adapters/pg/watch.d.ts +18 -0
  12. package/dist/contracts/catalog/object.d.ts +1 -0
  13. package/dist/contracts/catalog/types.d.ts +15 -8
  14. package/dist/contracts/connection.d.ts +13 -0
  15. package/dist/contracts/driver.d.ts +18 -5
  16. package/dist/contracts/error.d.ts +17 -1
  17. package/dist/contracts/generator.d.ts +63 -0
  18. package/dist/contracts/index.d.ts +2 -2
  19. package/dist/contracts/index.js +1 -1
  20. package/dist/contracts/internal.js +11 -9
  21. package/dist/contracts/location.d.ts +24 -0
  22. package/dist/contracts/rows.d.ts +15 -0
  23. package/dist/dialects/pg/archive-bind.d.ts +22 -0
  24. package/dist/dialects/pg/column.d.ts +126 -9
  25. package/dist/dialects/pg/compile.d.ts +1 -0
  26. package/dist/dialects/pg/custom.d.ts +6 -0
  27. package/dist/dialects/pg/filter-parse.d.ts +19 -0
  28. package/dist/dialects/pg/filters.d.ts +19 -0
  29. package/dist/dialects/pg/index.d.ts +11 -2
  30. package/dist/dialects/pg/index.js +159 -1063
  31. package/dist/dialects/pg/keys.d.ts +19 -3
  32. package/dist/dialects/pg/model.d.ts +223 -2
  33. package/dist/dialects/pg/operator-fit.d.ts +86 -0
  34. package/dist/dialects/pg/operators.d.ts +39 -1
  35. package/dist/dialects/pg/ops/arr-append.d.ts +9 -0
  36. package/dist/dialects/pg/ops/arr-ns.d.ts +7 -0
  37. package/dist/dialects/pg/ops/arr-remove.d.ts +9 -0
  38. package/dist/dialects/pg/ops/containedBy.d.ts +9 -0
  39. package/dist/dialects/pg/ops/contains.d.ts +8 -4
  40. package/dist/dialects/pg/ops/hasAnyKey.d.ts +8 -0
  41. package/dist/dialects/pg/ops/hasKey.d.ts +8 -0
  42. package/dist/dialects/pg/ops/json-ns.d.ts +6 -0
  43. package/dist/dialects/pg/ops/json-set.d.ts +12 -0
  44. package/dist/dialects/pg/ops/matches.d.ts +16 -0
  45. package/dist/dialects/pg/ops/overlaps.d.ts +9 -0
  46. package/dist/dialects/pg/ops/path.d.ts +13 -0
  47. package/dist/dialects/pg/preset.d.ts +76 -0
  48. package/dist/dialects/pg/relations.d.ts +59 -2
  49. package/dist/dialects/pg/schema.d.ts +109 -5
  50. package/dist/dialects/pg/table.d.ts +130 -11
  51. package/dist/dialects/pg/temporal.d.ts +9 -7
  52. package/dist/dialects/pg/tenancy.d.ts +94 -0
  53. package/dist/dialects/pg/through.d.ts +21 -0
  54. package/dist/dialects/pg/trait.d.ts +141 -0
  55. package/dist/dialects/pg/where.d.ts +37 -0
  56. package/dist/runtime/aggregate.d.ts +25 -0
  57. package/dist/runtime/archive-handle.d.ts +18 -0
  58. package/dist/runtime/archive-rules.d.ts +12 -0
  59. package/dist/runtime/archive.d.ts +73 -0
  60. package/dist/runtime/batch.d.ts +20 -0
  61. package/dist/runtime/client.d.ts +114 -5
  62. package/dist/runtime/conflict.d.ts +2 -1
  63. package/dist/runtime/exposure.d.ts +27 -0
  64. package/dist/runtime/hookm.d.ts +39 -0
  65. package/dist/runtime/ids/index.d.ts +11 -0
  66. package/dist/runtime/ids/index.js +193 -0
  67. package/dist/runtime/ids/okid-extended.d.ts +19 -0
  68. package/dist/runtime/ids/okid-generator.d.ts +21 -0
  69. package/dist/runtime/ids/okid-shared.d.ts +89 -0
  70. package/dist/runtime/ids/okid.d.ts +24 -0
  71. package/dist/runtime/ids/uuid.d.ts +21 -0
  72. package/dist/runtime/lock.d.ts +22 -0
  73. package/dist/runtime/operator-sql.d.ts +8 -0
  74. package/dist/runtime/page.d.ts +25 -0
  75. package/dist/runtime/pg/bun.d.ts +30 -0
  76. package/dist/runtime/pg/bun.js +52 -0
  77. package/dist/runtime/pg/pg.d.ts +29 -0
  78. package/dist/runtime/pg/pg.js +52 -0
  79. package/dist/runtime/pg/pglite.js +16 -17
  80. package/dist/runtime/pg/postgresjs.js +14 -24
  81. package/dist/runtime/plan.d.ts +146 -7
  82. package/dist/runtime/preset-stack.d.ts +17 -0
  83. package/dist/runtime/presets.d.ts +48 -0
  84. package/dist/runtime/read-stream.d.ts +26 -0
  85. package/dist/runtime/safety/index.d.ts +159 -0
  86. package/dist/runtime/safety/index.js +294 -0
  87. package/dist/runtime/safety-hook.d.ts +42 -0
  88. package/dist/runtime/server-check.d.ts +34 -0
  89. package/dist/runtime/tenancy/index.d.ts +37 -0
  90. package/dist/runtime/tenancy/index.js +365 -0
  91. package/dist/runtime/trait-read.d.ts +30 -0
  92. package/dist/runtime/traits/index.d.ts +128 -0
  93. package/dist/runtime/traits/index.js +509 -0
  94. package/dist/runtime/transaction.d.ts +19 -0
  95. package/dist/runtime/tx.d.ts +22 -7
  96. package/dist/runtime/types.d.ts +390 -25
  97. package/dist/runtime/validate/bind.d.ts +11 -0
  98. package/dist/runtime/validate/closed.d.ts +16 -0
  99. package/dist/runtime/validate/engine.d.ts +41 -0
  100. package/dist/runtime/validate/hook.d.ts +17 -0
  101. package/dist/runtime/validate/index.d.ts +21 -0
  102. package/dist/runtime/validate/index.js +175 -0
  103. package/dist/runtime/validate/load.d.ts +13 -0
  104. package/dist/runtime/validate/places.d.ts +41 -0
  105. package/dist/runtime/validate/rules.d.ts +108 -0
  106. package/dist/runtime/validate/surface.d.ts +102 -0
  107. package/dist/runtime/write.d.ts +30 -5
  108. package/dist/shared/{fgqgsb5z.js → 0qkxbm1f.js} +2 -2
  109. package/dist/shared/0v1g424p.js +26 -0
  110. package/dist/shared/10tjenmd.js +210 -0
  111. package/dist/shared/{tb4ze1tr.js → 1dp5knt7.js} +95 -10
  112. package/dist/shared/38crxbgn.js +229 -0
  113. package/dist/shared/3a5ne750.js +158 -0
  114. package/dist/shared/4b9da9d7.js +138 -0
  115. package/dist/shared/4e4c6vq2.js +62 -0
  116. package/dist/shared/{ckb1p0a4.js → 4jzzghr6.js} +416 -83
  117. package/dist/shared/{ycwz42az.js → 52szzakm.js} +6 -26
  118. package/dist/shared/{kynx7vbm.js → 5z4q2zda.js} +604 -21
  119. package/dist/shared/672t5vym.js +12 -0
  120. package/dist/shared/7m88x3e9.js +45 -0
  121. package/dist/shared/7mht49yd.js +1091 -0
  122. package/dist/shared/{mtkwv8wx.js → 7p2wbz7f.js} +1 -1
  123. package/dist/shared/83eaefwr.js +10 -0
  124. package/dist/shared/96ps4g1z.js +32 -0
  125. package/dist/shared/97g2jnrw.js +76 -0
  126. package/dist/shared/{xy79j5hq.js → 9k6vetvf.js} +25 -36
  127. package/dist/shared/{w8samvk1.js → a1gdp7j9.js} +1 -1
  128. package/dist/shared/a5sxz52y.js +13 -0
  129. package/dist/shared/{dynq16vb.js → b066g80h.js} +8 -6
  130. package/dist/shared/cstgkzdx.js +154 -0
  131. package/dist/shared/{ax16zpvm.js → d04j53v8.js} +6 -5
  132. package/dist/shared/{y9m15dfv.js → d2whjz4k.js} +15 -9
  133. package/dist/shared/dd4f8mnx.js +307 -0
  134. package/dist/shared/e6wg00wd.js +164 -0
  135. package/dist/shared/e7a268fy.js +195 -0
  136. package/dist/shared/{vkm3q4x1.js → eaxwrgby.js} +4 -3
  137. package/dist/shared/{7ck0dtry.js → ecdzej21.js} +160 -81
  138. package/dist/shared/{px90pf9p.js → edwqqryd.js} +21 -16
  139. package/dist/shared/{g2v6gnc8.js → eqmtn1bj.js} +57 -5
  140. package/dist/shared/g1b5zzj9.js +75 -0
  141. package/dist/shared/g9f0zqce.js +376 -0
  142. package/dist/shared/ge03bfca.js +64 -0
  143. package/dist/shared/{79ggp945.js → jns2wx4t.js} +55 -12
  144. package/dist/shared/k3ted12y.js +33 -0
  145. package/dist/shared/k7dwkhvq.js +31 -0
  146. package/dist/shared/{hd293j9g.js → kyxb62mc.js} +14 -2
  147. package/dist/shared/m9tv7xn7.js +404 -0
  148. package/dist/shared/mrq77sgw.js +55 -0
  149. package/dist/shared/mxmcdsh5.js +450 -0
  150. package/dist/shared/n442h54c.js +14 -0
  151. package/dist/shared/n47rd821.js +442 -0
  152. package/dist/shared/n4jqhpqz.js +27 -0
  153. package/dist/shared/{mkjmqjv4.js → nfzc5z0w.js} +2 -104
  154. package/dist/shared/nsva2a6b.js +42 -0
  155. package/dist/shared/ps43134h.js +69 -0
  156. package/dist/shared/{8b04d28c.js → py3nh7jy.js} +2 -2
  157. package/dist/shared/qa5dsc7z.js +86 -0
  158. package/dist/shared/{g5fhqmwe.js → qxa0yb9j.js} +6 -4
  159. package/dist/shared/r6nwkxnt.js +86 -0
  160. package/dist/shared/{4j72449d.js → rtnaqre0.js} +3 -3
  161. package/dist/shared/rwmrejjz.js +26 -0
  162. package/dist/shared/{zhc5vmgf.js → s6gqfn5j.js} +2 -2
  163. package/dist/shared/sacqha1y.js +70 -0
  164. package/dist/shared/{qk3hxfja.js → sfh4pk75.js} +5 -5
  165. package/dist/shared/{j5cn2963.js → t4tbsy9h.js} +13 -64
  166. package/dist/shared/{ngk8gj61.js → tbszx8mz.js} +15 -1
  167. package/dist/shared/v18jva5b.js +90 -0
  168. package/dist/shared/x9v1qgeb.js +201 -0
  169. package/dist/shared/xatfg0gn.js +193 -0
  170. package/dist/shared/xkz8g6by.js +225 -0
  171. package/dist/shared/{f5thc1s0.js → xrfnq5k8.js} +237 -418
  172. package/dist/shared/ytg3xf9p.js +149 -0
  173. package/dist/shared/yw5c610b.js +48 -0
  174. package/dist/shared/zd93g3rq.js +31 -0
  175. package/dist/shared/zt8y0wzb.js +132 -0
  176. package/dist/shared/{p0cbr3g2.js → zwmqxb0g.js} +1 -1
  177. package/dist/tooling/cli.js +14 -10
  178. package/dist/tooling/migrate/commands.d.ts +10 -0
  179. package/dist/tooling/migrate/engine.d.ts +36 -0
  180. package/package.json +56 -4
  181. package/dist/shared/gk7cs7sp.js +0 -566
@@ -0,0 +1,307 @@
1
+ import {
2
+ definition,
3
+ rejected,
4
+ quoteLiteral,
5
+ writeArray,
6
+ readArray
7
+ } from "./xatfg0gn.js";
8
+ import {
9
+ REFERENTIAL_ACTIONS,
10
+ referentialAction
11
+ } from "./4e4c6vq2.js";
12
+ import {
13
+ readClientGenerator
14
+ } from "./rwmrejjz.js";
15
+
16
+ // src/dialects/pg/column.ts
17
+ class ColumnBuilder2 {
18
+ state;
19
+ constructor(state) {
20
+ this.state = state;
21
+ }
22
+ encode(value) {
23
+ return this.state.encode(value);
24
+ }
25
+ decode(wire) {
26
+ return this.state.decode(wire);
27
+ }
28
+ nullable() {
29
+ return rebuild(this.state, { nullable: true });
30
+ }
31
+ default(value) {
32
+ const clientDefault = readClientGenerator(value);
33
+ if (clientDefault !== undefined) {
34
+ return rebuild(this.state, {
35
+ hasDefault: true,
36
+ defaultSql: undefined,
37
+ defaultValue: undefined,
38
+ clientDefault,
39
+ generated: undefined
40
+ });
41
+ }
42
+ if (value === null && this.state.nullable === false) {
43
+ definition("A null default is only accepted on a nullable column. Call .nullable() first.");
44
+ }
45
+ if (this.state.picklist !== undefined && value !== null) {
46
+ const text = String(value);
47
+ if (!this.state.picklist.values.includes(text)) {
48
+ definition(`Default ${text} is not in the picklist ${this.state.picklist.values.join(", ")}.`);
49
+ }
50
+ }
51
+ return rebuild(this.state, {
52
+ hasDefault: true,
53
+ defaultSql: value === null ? "NULL" : sqlOf(this.state, value),
54
+ defaultValue: value,
55
+ clientDefault: undefined,
56
+ generated: undefined
57
+ });
58
+ }
59
+ defaultSql(expression) {
60
+ if (expression.length === 0) {
61
+ definition("defaultSql must be a non-empty SQL expression.");
62
+ }
63
+ return rebuild(this.state, {
64
+ hasDefault: true,
65
+ defaultSql: expression,
66
+ defaultValue: undefined,
67
+ clientDefault: undefined,
68
+ generated: undefined
69
+ });
70
+ }
71
+ primaryKey() {
72
+ return rebuild(this.state, {
73
+ primaryKey: true,
74
+ omitUpdate: true
75
+ });
76
+ }
77
+ unique(options) {
78
+ const marker = options?.global;
79
+ if (typeof marker === "string" && marker.trim().length === 0) {
80
+ definition("unique() global needs a reason.");
81
+ }
82
+ const named = typeof marker === "string" ? marker.trim() : undefined;
83
+ const globalFlag = typeof marker === "string" ? true : marker;
84
+ return rebuild(this.state, {
85
+ unique: {
86
+ reason: named ?? options?.reason,
87
+ global: globalFlag
88
+ }
89
+ });
90
+ }
91
+ picklist(values, options) {
92
+ if (values.length === 0) {
93
+ definition("A picklist must contain at least one value.");
94
+ }
95
+ const allowed = new Set;
96
+ for (const value of values) {
97
+ if (value.length === 0) {
98
+ definition("Picklist values must be non-empty strings.");
99
+ }
100
+ if (allowed.has(value)) {
101
+ definition(`Picklist value ${value} is repeated. Each value is accepted once.`);
102
+ }
103
+ allowed.add(value);
104
+ }
105
+ if (typeof this.state.defaultValue === "string" && !allowed.has(this.state.defaultValue)) {
106
+ definition(`Default ${this.state.defaultValue} is not in the picklist ${values.join(", ")}.`);
107
+ }
108
+ const previous = this.state.elementEncode;
109
+ const elementEncode = (value) => {
110
+ if (typeof value !== "string" || !allowed.has(value)) {
111
+ rejected(`Picklist rejected ${String(value)}. Accepted values: ${[...allowed].join(", ")}.`);
112
+ }
113
+ return previous(value);
114
+ };
115
+ return rebuild(this.state, {
116
+ picklist: { values: values.slice(), check: options?.check !== false },
117
+ elementEncode,
118
+ encode: elementEncode
119
+ });
120
+ }
121
+ generated(expression, options) {
122
+ if (expression.length === 0) {
123
+ definition("generated() must be a non-empty SQL expression.");
124
+ }
125
+ return rebuild(this.state, {
126
+ generated: { stored: options?.stored !== false, expression },
127
+ hasDefault: true,
128
+ defaultSql: undefined,
129
+ defaultValue: undefined,
130
+ clientDefault: undefined
131
+ });
132
+ }
133
+ guarded() {
134
+ return rebuild(this.state, { guarded: true });
135
+ }
136
+ hidden() {
137
+ return rebuild(this.state, { hidden: true });
138
+ }
139
+ sensitive() {
140
+ return rebuild(this.state, { sensitive: true });
141
+ }
142
+ validate(rules) {
143
+ const list = Array.isArray(rules) ? rules : [rules];
144
+ return rebuild(this.state, { validate: { rules: list } });
145
+ }
146
+ references(table, options) {
147
+ if (table.length === 0) {
148
+ definition("references() needs a table name.");
149
+ }
150
+ const onDelete = readAction(options?.onDelete, "onDelete");
151
+ const onUpdate = readAction(options?.onUpdate, "onUpdate");
152
+ const columns = readReferenceColumns(options?.columns);
153
+ return rebuild(this.state, {
154
+ references: {
155
+ table,
156
+ ...onDelete !== undefined ? { onDelete } : {},
157
+ ...onUpdate !== undefined ? { onUpdate } : {},
158
+ ...columns !== undefined ? { columns } : {}
159
+ }
160
+ });
161
+ }
162
+ renamedFrom(name) {
163
+ if (name.length === 0) {
164
+ definition("renamedFrom must be a non-empty previous column name.");
165
+ }
166
+ return rebuild(this.state, { renamedFrom: name });
167
+ }
168
+ sqlName(name) {
169
+ if (name.length === 0) {
170
+ definition("sqlName must be a non-empty SQL identifier.");
171
+ }
172
+ return rebuild(this.state, { sqlName: name });
173
+ }
174
+ comment(text) {
175
+ return rebuild(this.state, { comment: text });
176
+ }
177
+ array(options) {
178
+ if (this.state.dims !== 0) {
179
+ definition("array() accepts a scalar column. This column is already an array.");
180
+ }
181
+ const dims = options?.dims ?? 1;
182
+ if (!Number.isInteger(dims) || dims < 1 || dims > 6) {
183
+ definition(`Array dims ${String(dims)} must be an integer from 1 to 6.`);
184
+ }
185
+ const elementEncode = this.state.elementEncode;
186
+ const elementDecode = this.state.elementDecode;
187
+ const raw = this.state.sqlForm === "raw";
188
+ return rebuild(this.state, {
189
+ dims,
190
+ accepts: ["Array"],
191
+ encode: (value) => writeArray(value, dims, elementEncode, raw),
192
+ decode: (wire) => readArray(wire, dims, elementDecode)
193
+ });
194
+ }
195
+ }
196
+ function required(body) {
197
+ return openColumn({
198
+ nullable: false,
199
+ hasDefault: false,
200
+ generated: false,
201
+ guarded: false,
202
+ hidden: false,
203
+ omitWrite: false,
204
+ ...body
205
+ });
206
+ }
207
+ function openColumn(input) {
208
+ const elementEncode = input.encode;
209
+ const elementDecode = input.decode;
210
+ return new ColumnBuilder2({
211
+ baseType: input.baseType,
212
+ dims: 0,
213
+ nullable: input.nullable,
214
+ hasDefault: input.hasDefault,
215
+ defaultSql: input.defaultSql,
216
+ defaultValue: undefined,
217
+ clientDefault: input.clientDefault,
218
+ collation: input.collation,
219
+ idSource: input.idSource,
220
+ identity: input.identity,
221
+ generated: undefined,
222
+ unique: undefined,
223
+ picklist: undefined,
224
+ guarded: input.guarded,
225
+ hidden: input.hidden,
226
+ sensitive: false,
227
+ omitWrite: input.omitWrite,
228
+ omitUpdate: input.omitUpdate === true,
229
+ renamedFrom: undefined,
230
+ sqlName: undefined,
231
+ comment: undefined,
232
+ extension: input.extension,
233
+ typeDependency: input.typeDependency,
234
+ enumLabels: input.enumLabels,
235
+ domain: input.domain,
236
+ primaryKey: input.primaryKey === true,
237
+ typeLabel: input.typeLabel,
238
+ references: undefined,
239
+ validate: undefined,
240
+ sqlForm: input.sqlForm,
241
+ encode: input.encode,
242
+ decode: input.decode,
243
+ elementEncode,
244
+ elementDecode,
245
+ accepts: input.accepts
246
+ });
247
+ }
248
+ function formatType(baseType, dims) {
249
+ if (dims === 0) {
250
+ return baseType;
251
+ }
252
+ return baseType + "[]".repeat(dims);
253
+ }
254
+ function sqlOf(state, value) {
255
+ const encoded = state.encode(value);
256
+ const typed = formatType(state.baseType, state.dims);
257
+ if (state.sqlForm === "cast") {
258
+ return `${quoteLiteral(encoded)}::${typed}`;
259
+ }
260
+ if (state.sqlForm === "json") {
261
+ return `${quoteLiteral(encoded)}::json`;
262
+ }
263
+ if (state.sqlForm === "jsonb") {
264
+ return `${quoteLiteral(encoded)}::jsonb`;
265
+ }
266
+ if (state.dims > 0 || state.sqlForm === "quote") {
267
+ return quoteLiteral(encoded);
268
+ }
269
+ return encoded;
270
+ }
271
+ function readAction(action, role) {
272
+ if (action === undefined) {
273
+ return;
274
+ }
275
+ if (referentialAction(action) === undefined) {
276
+ definition(`references() ${role} ${action} is not a referential action. Accepted actions: ${REFERENTIAL_ACTIONS.join(", ")}.`);
277
+ }
278
+ return action;
279
+ }
280
+ function readReferenceColumns(columns) {
281
+ if (columns === undefined) {
282
+ return;
283
+ }
284
+ if (columns.length === 0) {
285
+ definition("references() columns must name at least one target column.");
286
+ }
287
+ const copy = [];
288
+ for (const name of columns) {
289
+ if (name.length === 0) {
290
+ definition("references() columns must be non-empty names.");
291
+ }
292
+ copy.push(name);
293
+ }
294
+ return copy;
295
+ }
296
+ function retarget(column, patch) {
297
+ return rebuild(column.state, {
298
+ ...patch.dropUnique === true ? { unique: undefined } : {},
299
+ ...patch.dropPrimary === true ? { primaryKey: false } : {},
300
+ ...patch.references !== undefined ? { references: patch.references } : {}
301
+ });
302
+ }
303
+ function rebuild(state, patch) {
304
+ return new ColumnBuilder2({ ...state, ...patch });
305
+ }
306
+
307
+ export { ColumnBuilder2, required, openColumn, formatType, retarget };
@@ -0,0 +1,164 @@
1
+ import {
2
+ safetyInstalled,
3
+ runSafety
4
+ } from "./a5sxz52y.js";
5
+ import {
6
+ isOperator,
7
+ operatorValue
8
+ } from "./cn0n68ft.js";
9
+ import {
10
+ OkmError2
11
+ } from "./52szzakm.js";
12
+
13
+ // src/runtime/exposure.ts
14
+ var REDACTED = "[redacted]";
15
+ var namesOf = new WeakMap;
16
+ function redactView(schema, view, call) {
17
+ const names = concealedNames(schema);
18
+ const secrets = new Set;
19
+ harvest(schema, call.where, names, undefined, secrets);
20
+ harvest(schema, call.include, names, undefined, secrets);
21
+ const model = schema.model[call.table];
22
+ const rules = model === undefined ? view.rules : [...view.rules, ...exposureRules(model, call)];
23
+ if (safetyInstalled())
24
+ runSafety(rules, undefined);
25
+ return {
26
+ ...view,
27
+ intent: {
28
+ ...view.intent,
29
+ where: walk(view.intent.where, names),
30
+ include: walk(view.intent.include, names)
31
+ },
32
+ rules,
33
+ sql: {
34
+ ...view.sql,
35
+ params: view.sql.params.map((value) => value !== null && secrets.has(value) ? REDACTED : value)
36
+ }
37
+ };
38
+ }
39
+ function scrubCall(error, schema, call) {
40
+ const names = concealedNames(schema);
41
+ const secrets = new Set;
42
+ harvest(schema, call.where, names, undefined, secrets);
43
+ harvest(schema, call.include, names, undefined, secrets);
44
+ let message = error.message;
45
+ for (const secret of secrets) {
46
+ if (secret.length < 4 || !message.includes(secret))
47
+ continue;
48
+ message = message.replaceAll(secret, REDACTED);
49
+ }
50
+ if (message === error.message)
51
+ return error;
52
+ return new OkmError2(error.code, message, {
53
+ kind: error.kind,
54
+ ...error.table !== undefined ? { table: error.table } : {},
55
+ ...error.columns.length > 0 ? { columns: error.columns } : {},
56
+ fix: error.fix
57
+ });
58
+ }
59
+ function concealedNames(schema) {
60
+ const cached = namesOf.get(schema);
61
+ if (cached !== undefined)
62
+ return cached;
63
+ const names = new Set;
64
+ for (const model of Object.values(schema.model)) {
65
+ if (model.conceal !== true)
66
+ continue;
67
+ for (const column of model.columns) {
68
+ if (column.hidden || column.sensitive)
69
+ names.add(column.field);
70
+ }
71
+ }
72
+ namesOf.set(schema, names);
73
+ return names;
74
+ }
75
+ function exposureRules(model, call) {
76
+ const named = namedSelect(call.select);
77
+ const source = model.source;
78
+ const rules = [];
79
+ for (const column of model.columns) {
80
+ if (column.hidden && (named === undefined || !named.has(column.field))) {
81
+ rules.push({
82
+ rule: "hidden",
83
+ contribution: `hidden ${model.name}.${column.field} excluded`,
84
+ provenance: "catalog",
85
+ ...source !== undefined ? { source } : {}
86
+ });
87
+ }
88
+ if (column.sensitive) {
89
+ rules.push({
90
+ rule: "sensitive",
91
+ contribution: `sensitive ${model.name}.${column.field} redacted`,
92
+ provenance: "catalog",
93
+ ...source !== undefined ? { source } : {}
94
+ });
95
+ }
96
+ }
97
+ return rules;
98
+ }
99
+ function namedSelect(select) {
100
+ if (!Array.isArray(select))
101
+ return;
102
+ const names = new Set;
103
+ for (const name of select) {
104
+ if (typeof name === "string")
105
+ names.add(name);
106
+ }
107
+ return names;
108
+ }
109
+ function harvest(schema, value, names, key, into) {
110
+ if (Array.isArray(value)) {
111
+ for (const item of value)
112
+ harvest(schema, item, names, key, into);
113
+ return;
114
+ }
115
+ if (isOperator(value)) {
116
+ harvest(schema, operatorValue(value), names, key, into);
117
+ return;
118
+ }
119
+ if (typeof value === "object" && value !== null) {
120
+ const record = value;
121
+ for (const child of Object.keys(record))
122
+ harvest(schema, record[child], names, child, into);
123
+ return;
124
+ }
125
+ if (key === undefined || !names.has(key))
126
+ return;
127
+ const encode = encodeOf(schema, key);
128
+ if (encode === undefined)
129
+ return;
130
+ try {
131
+ into.add(encode(value));
132
+ } catch {}
133
+ }
134
+ function encodeOf(schema, field) {
135
+ for (const model of Object.values(schema.model)) {
136
+ for (const column of model.columns) {
137
+ if (column.field === field && (column.hidden || column.sensitive)) {
138
+ return column.encode;
139
+ }
140
+ }
141
+ }
142
+ return;
143
+ }
144
+ function walk(value, names, key) {
145
+ if (Array.isArray(value))
146
+ return value.map((item) => walk(item, names, key));
147
+ if (typeof value === "object" && value !== null) {
148
+ const record = value;
149
+ if (typeof record.op === "string" && "value" in record) {
150
+ return { op: record.op, value: walk(record.value, names, key) };
151
+ }
152
+ const out = {};
153
+ for (const child of Object.keys(record))
154
+ out[child] = walk(record[child], names, child);
155
+ return out;
156
+ }
157
+ if (key !== undefined && names.has(key))
158
+ return REDACTED;
159
+ return value;
160
+ }
161
+ export {
162
+ redactView,
163
+ scrubCall
164
+ };
@@ -0,0 +1,195 @@
1
+ import {
2
+ decodeRows,
3
+ readHandle,
4
+ readCall,
5
+ attachHttp
6
+ } from "./mxmcdsh5.js";
7
+ import {
8
+ selectedColumns,
9
+ parseOrder,
10
+ rejectKeys,
11
+ readLimit,
12
+ indexes,
13
+ quote,
14
+ list,
15
+ isRecord,
16
+ registerFailFix,
17
+ fail
18
+ } from "./xrfnq5k8.js";
19
+ import {
20
+ OkmError2,
21
+ throwNamed2
22
+ } from "./52szzakm.js";
23
+
24
+ // src/runtime/page.ts
25
+ registerFailFix("OKM1130", "Request the next page with the same orderBy and the exact next value the previous page returned. The cursor encodes that order.");
26
+ var OPTIONS = [
27
+ "where",
28
+ "select",
29
+ "orderBy",
30
+ "limit",
31
+ "include",
32
+ "after",
33
+ "signal",
34
+ "timeout"
35
+ ];
36
+ function build(session, table, options, mods, view) {
37
+ try {
38
+ return plan(session, table, options, mods, view);
39
+ } catch (error) {
40
+ throw error instanceof OkmError2 ? attachHttp(session.http, error) : error;
41
+ }
42
+ }
43
+ function plan(session, table, options, mods, view) {
44
+ const record = isRecord(options) ? options : {};
45
+ rejectKeys(record, OPTIONS, "page");
46
+ const indexed = indexes(session.schema).get(table);
47
+ if (indexed === undefined)
48
+ fail("OKM1120", `Table ${table} is not in the schema.`);
49
+ if (record.limit === undefined)
50
+ fail("OKM1101", "page() needs a limit.");
51
+ const size = readLimit(record.limit);
52
+ if (size < 1) {
53
+ throw new OkmError2("invalid", "page() limit must be at least 1.", { kind: "invalid" });
54
+ }
55
+ const keys = orderKeys(indexed, record.orderBy);
56
+ const signature = `${table}:${keys.map((key) => `${key.column.field}.${key.dir}.${key.nulls}`).join(",")}`;
57
+ const after = record.after === undefined || record.after === null ? undefined : keyset(keys, signature, record.after);
58
+ const wanted = selectedColumns(indexed, record.select);
59
+ const extra = keys.filter((key) => !wanted.includes(key.column)).map((key) => key.column.field);
60
+ const select = extra.length === 0 ? record.select : [...wanted.map((column) => column.field), ...extra];
61
+ const orderBy = {};
62
+ for (const key of keys)
63
+ orderBy[key.column.field] = { dir: key.dir, nulls: key.nulls };
64
+ const call = {
65
+ ...readCall("find", table, {
66
+ where: record.where,
67
+ select,
68
+ orderBy,
69
+ limit: size + 1,
70
+ include: record.include,
71
+ signal: record.signal,
72
+ timeout: record.timeout
73
+ }, undefined, session.scope, session.schema.model[table], session.schema, view),
74
+ ...after !== undefined ? { after } : {}
75
+ };
76
+ return readHandle(session, table, call, mods, async (compiled, rows) => {
77
+ const items = await decodeRows(compiled, rows, table);
78
+ const more = items.length > size;
79
+ const kept = more ? items.slice(0, size) : items;
80
+ const last = rows[size - 1];
81
+ const next = more && last !== undefined ? makeCursor(compiled, last, keys, signature) : null;
82
+ if (extra.length > 0) {
83
+ for (const item of kept) {
84
+ for (const field of extra)
85
+ delete item[field];
86
+ }
87
+ }
88
+ return { items: kept, next };
89
+ });
90
+ }
91
+ function orderKeys(table, orderBy) {
92
+ if (orderBy !== undefined && !isRecord(orderBy)) {
93
+ fail("OKM1120", "orderBy must be an object of fields.");
94
+ }
95
+ const keys = [];
96
+ for (const field of Object.keys(orderBy ?? {})) {
97
+ const column = table.columns.get(field);
98
+ if (column === undefined) {
99
+ throwNamed2("OKM1120", field, table.names, `Field ${field} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
100
+ }
101
+ keys.push({ column, ...parseOrder(field, orderBy?.[field]) });
102
+ }
103
+ if (table.model.primary.length === 0) {
104
+ fail("OKM1120", `page() needs a primary key on ${table.model.name} to break ties.`);
105
+ }
106
+ for (const field of table.model.primary) {
107
+ const column = table.columns.get(field);
108
+ if (column === undefined || keys.some((key) => key.column === column))
109
+ continue;
110
+ keys.push({ column, dir: "asc", nulls: "last" });
111
+ }
112
+ return keys;
113
+ }
114
+ function keyset(keys, signature, token) {
115
+ const values = readCursor(token, signature, keys.length);
116
+ return (sink, alias) => {
117
+ sink.mark(`k:${signature}:${values.map((value) => value === null ? "n" : "v").join("")}`);
118
+ let wrote = false;
119
+ for (let index = 0;index < keys.length; index += 1) {
120
+ const key = keys[index];
121
+ const value = values[index];
122
+ if (key === undefined || value === undefined)
123
+ continue;
124
+ if (value === null && key.nulls === "last")
125
+ continue;
126
+ sink.text(wrote ? " or (" : "(");
127
+ wrote = true;
128
+ for (let before = 0;before < index; before += 1) {
129
+ const prior = keys[before];
130
+ const held = values[before];
131
+ if (prior === undefined || held === undefined)
132
+ continue;
133
+ const ref = `${alias}.${quote(prior.column.sql)}`;
134
+ if (held === null) {
135
+ sink.text(`${ref} is null and `);
136
+ } else {
137
+ sink.text(`${ref} = `);
138
+ sink.param(held);
139
+ sink.text(" and ");
140
+ }
141
+ }
142
+ const ref = `${alias}.${quote(key.column.sql)}`;
143
+ if (value === null) {
144
+ sink.text(`${ref} is not null`);
145
+ } else {
146
+ sink.text(key.nulls === "last" ? `(${ref} ${compare(key)} ` : `${ref} ${compare(key)} `);
147
+ sink.param(value);
148
+ sink.text(key.nulls === "last" ? ` or ${ref} is null)` : "");
149
+ }
150
+ sink.text(")");
151
+ }
152
+ if (!wrote)
153
+ sink.text("false");
154
+ };
155
+ }
156
+ function compare(key) {
157
+ return key.dir === "asc" ? ">" : "<";
158
+ }
159
+ function makeCursor(plan, row, keys, signature) {
160
+ const values = keys.map((key) => {
161
+ const at = plan.outputs.fields.find((field) => field.key === key.column.field)?.at;
162
+ return at === undefined ? null : row[at] ?? null;
163
+ });
164
+ const bytes = new TextEncoder().encode(JSON.stringify([signature, ...values]));
165
+ let binary = "";
166
+ for (const byte of bytes)
167
+ binary += String.fromCharCode(byte);
168
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
169
+ }
170
+ function readCursor(token, signature, count) {
171
+ let parsed;
172
+ if (typeof token === "string") {
173
+ try {
174
+ const binary = atob(token.replaceAll("-", "+").replaceAll("_", "/"));
175
+ const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
176
+ parsed = JSON.parse(new TextDecoder().decode(bytes));
177
+ } catch {
178
+ parsed = undefined;
179
+ }
180
+ }
181
+ if (!Array.isArray(parsed) || typeof parsed[0] !== "string") {
182
+ fail("OKM1130", "after is not a cursor that page() returned.");
183
+ }
184
+ if (parsed[0] !== signature) {
185
+ fail("OKM1130", `The cursor was made for another order: ${parsed[0]}. This page orders by ${signature}.`);
186
+ }
187
+ const values = parsed.slice(1);
188
+ if (values.length !== count || !values.every((value) => value === null || typeof value === "string")) {
189
+ fail("OKM1130", "after is not a cursor that page() returned.");
190
+ }
191
+ return values;
192
+ }
193
+ export {
194
+ build
195
+ };
@@ -1,8 +1,9 @@
1
- import"./y9m15dfv.js";
1
+ import"./d2whjz4k.js";
2
+ import"./n442h54c.js";
2
3
  import {
3
4
  listTargets,
4
5
  loadConfig
5
- } from "./kynx7vbm.js";
6
+ } from "./5z4q2zda.js";
6
7
 
7
8
  // src/tooling/migrate/dev.ts
8
9
  import { mkdirSync } from "node:fs";
@@ -15,7 +16,7 @@ async function devProject(cwd) {
15
16
  `;
16
17
  const directory = join(cwd, config.out ?? ".okm", "dev-db");
17
18
  mkdirSync(directory, { recursive: true });
18
- const { open } = await import("./8b04d28c.js");
19
+ const { open } = await import("./py3nh7jy.js");
19
20
  const pool = await open({ dataDir: directory });
20
21
  try {
21
22
  await pool.execute("select 1");