okmodel 0.0.0 → 0.1.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 (147) hide show
  1. package/README.md +246 -1
  2. package/dist/adapters/capabilities.d.ts +62 -0
  3. package/dist/adapters/error.d.ts +91 -0
  4. package/dist/adapters/failure.d.ts +39 -0
  5. package/dist/adapters/pg/batch.d.ts +36 -0
  6. package/dist/adapters/pg/call.d.ts +59 -0
  7. package/dist/adapters/pg/pglite.d.ts +21 -0
  8. package/dist/adapters/pg/postgres-extra.d.ts +43 -0
  9. package/dist/adapters/pg/postgresjs.d.ts +95 -0
  10. package/dist/adapters/pg/result.d.ts +30 -0
  11. package/dist/contracts/catalog/build.d.ts +18 -0
  12. package/dist/contracts/catalog/document.d.ts +79 -0
  13. package/dist/contracts/catalog/enum.d.ts +35 -0
  14. package/dist/contracts/catalog/identifier.d.ts +71 -0
  15. package/dist/contracts/catalog/identity.d.ts +98 -0
  16. package/dist/contracts/catalog/index.d.ts +11 -0
  17. package/dist/contracts/catalog/json.d.ts +17 -0
  18. package/dist/contracts/catalog/object.d.ts +142 -0
  19. package/dist/contracts/catalog/order.d.ts +43 -0
  20. package/dist/contracts/catalog/rewrite.d.ts +18 -0
  21. package/dist/contracts/catalog/types.d.ts +292 -0
  22. package/dist/contracts/catalog/words.d.ts +13 -0
  23. package/dist/contracts/connection.d.ts +33 -0
  24. package/dist/contracts/driver.d.ts +163 -0
  25. package/dist/contracts/error.d.ts +298 -0
  26. package/dist/contracts/index.d.ts +11 -0
  27. package/dist/contracts/index.js +16 -0
  28. package/dist/contracts/internal.d.ts +15 -0
  29. package/dist/contracts/internal.js +68 -0
  30. package/dist/contracts/nearest.d.ts +15 -0
  31. package/dist/contracts/rows.d.ts +84 -0
  32. package/dist/contracts/sha256.d.ts +14 -0
  33. package/dist/contracts/utf8.d.ts +33 -0
  34. package/dist/dialects/pg/array-literal.d.ts +25 -0
  35. package/dist/dialects/pg/bool.d.ts +46 -0
  36. package/dist/dialects/pg/column.d.ts +386 -0
  37. package/dist/dialects/pg/compile.d.ts +81 -0
  38. package/dist/dialects/pg/custom.d.ts +21 -0
  39. package/dist/dialects/pg/ddl.d.ts +70 -0
  40. package/dist/dialects/pg/decimal.d.ts +62 -0
  41. package/dist/dialects/pg/declarations.d.ts +34 -0
  42. package/dist/dialects/pg/emit.d.ts +18 -0
  43. package/dist/dialects/pg/enum.d.ts +30 -0
  44. package/dist/dialects/pg/errors.d.ts +30 -0
  45. package/dist/dialects/pg/finite.d.ts +15 -0
  46. package/dist/dialects/pg/geometry.d.ts +55 -0
  47. package/dist/dialects/pg/index.d.ts +45 -0
  48. package/dist/dialects/pg/index.js +1821 -0
  49. package/dist/dialects/pg/integer.d.ts +96 -0
  50. package/dist/dialects/pg/introspect.d.ts +43 -0
  51. package/dist/dialects/pg/json.d.ts +43 -0
  52. package/dist/dialects/pg/keys.d.ts +32 -0
  53. package/dist/dialects/pg/misuse.d.ts +31 -0
  54. package/dist/dialects/pg/model.d.ts +71 -0
  55. package/dist/dialects/pg/namespace.d.ts +63 -0
  56. package/dist/dialects/pg/network.d.ts +28 -0
  57. package/dist/dialects/pg/operators.d.ts +71 -0
  58. package/dist/dialects/pg/ops/between.d.ts +10 -0
  59. package/dist/dialects/pg/ops/contains.d.ts +8 -0
  60. package/dist/dialects/pg/ops/endsWith.d.ts +8 -0
  61. package/dist/dialects/pg/ops/eq.d.ts +9 -0
  62. package/dist/dialects/pg/ops/every.d.ts +9 -0
  63. package/dist/dialects/pg/ops/gt.d.ts +9 -0
  64. package/dist/dialects/pg/ops/gte.d.ts +9 -0
  65. package/dist/dialects/pg/ops/has.d.ts +9 -0
  66. package/dist/dialects/pg/ops/ilike.d.ts +8 -0
  67. package/dist/dialects/pg/ops/inList.d.ts +9 -0
  68. package/dist/dialects/pg/ops/inc.d.ts +13 -0
  69. package/dist/dialects/pg/ops/like.d.ts +8 -0
  70. package/dist/dialects/pg/ops/lt.d.ts +9 -0
  71. package/dist/dialects/pg/ops/lte.d.ts +9 -0
  72. package/dist/dialects/pg/ops/none.d.ts +9 -0
  73. package/dist/dialects/pg/ops/not.d.ts +9 -0
  74. package/dist/dialects/pg/ops/notIn.d.ts +9 -0
  75. package/dist/dialects/pg/ops/or.d.ts +9 -0
  76. package/dist/dialects/pg/ops/startsWith.d.ts +8 -0
  77. package/dist/dialects/pg/quote.d.ts +24 -0
  78. package/dist/dialects/pg/range.d.ts +50 -0
  79. package/dist/dialects/pg/relations.d.ts +45 -0
  80. package/dist/dialects/pg/schema.d.ts +77 -0
  81. package/dist/dialects/pg/search.d.ts +23 -0
  82. package/dist/dialects/pg/table.d.ts +201 -0
  83. package/dist/dialects/pg/temporal.d.ts +211 -0
  84. package/dist/dialects/pg/text.d.ts +44 -0
  85. package/dist/dialects/pg/time.d.ts +46 -0
  86. package/dist/okm.js +2 -0
  87. package/dist/okmodel.js +2 -0
  88. package/dist/runtime/client.d.ts +47 -0
  89. package/dist/runtime/conflict.d.ts +38 -0
  90. package/dist/runtime/drift-detail.d.ts +32 -0
  91. package/dist/runtime/drift.d.ts +29 -0
  92. package/dist/runtime/include.d.ts +15 -0
  93. package/dist/runtime/pg/pglite.d.ts +25 -0
  94. package/dist/runtime/pg/pglite.js +48 -0
  95. package/dist/runtime/pg/postgresjs.d.ts +29 -0
  96. package/dist/runtime/pg/postgresjs.js +62 -0
  97. package/dist/runtime/plan.d.ts +167 -0
  98. package/dist/runtime/tx.d.ts +29 -0
  99. package/dist/runtime/types.d.ts +385 -0
  100. package/dist/runtime/write.d.ts +48 -0
  101. package/dist/shared/05w44d8g.js +1524 -0
  102. package/dist/shared/523ft3e8.js +171 -0
  103. package/dist/shared/8b04d28c.js +14 -0
  104. package/dist/shared/cn0n68ft.js +16 -0
  105. package/dist/shared/dkn3y60a.js +374 -0
  106. package/dist/shared/dynq16vb.js +81 -0
  107. package/dist/shared/fgqgsb5z.js +281 -0
  108. package/dist/shared/g5fhqmwe.js +188 -0
  109. package/dist/shared/gk7cs7sp.js +566 -0
  110. package/dist/shared/hadrfb9h.js +398 -0
  111. package/dist/shared/hd293j9g.js +98 -0
  112. package/dist/shared/j5cn2963.js +701 -0
  113. package/dist/shared/jjb7yht9.js +37 -0
  114. package/dist/shared/kprcwaha.js +30 -0
  115. package/dist/shared/m3ypagh5.js +347 -0
  116. package/dist/shared/mkjmqjv4.js +456 -0
  117. package/dist/shared/mtkwv8wx.js +18 -0
  118. package/dist/shared/ngk8gj61.js +40 -0
  119. package/dist/shared/p0cbr3g2.js +79 -0
  120. package/dist/shared/qk3hxfja.js +83 -0
  121. package/dist/shared/rgs0st28.js +1066 -0
  122. package/dist/shared/w8samvk1.js +18 -0
  123. package/dist/shared/x5x59srr.js +566 -0
  124. package/dist/shared/xqbhg6cn.js +119 -0
  125. package/dist/shared/xy79j5hq.js +177 -0
  126. package/dist/shared/y9m15dfv.js +888 -0
  127. package/dist/shared/ycwz42az.js +412 -0
  128. package/dist/shared/yd1kzwn2.js +148 -0
  129. package/dist/shared/zhc5vmgf.js +257 -0
  130. package/dist/tooling/cli.d.ts +1 -0
  131. package/dist/tooling/cli.js +193 -0
  132. package/dist/tooling/errors/registry.d.ts +33 -0
  133. package/dist/tooling/migrate/apply.d.ts +86 -0
  134. package/dist/tooling/migrate/commands.d.ts +21 -0
  135. package/dist/tooling/migrate/config.d.ts +48 -0
  136. package/dist/tooling/migrate/dev.d.ts +16 -0
  137. package/dist/tooling/migrate/equal.d.ts +15 -0
  138. package/dist/tooling/migrate/files.d.ts +19 -0
  139. package/dist/tooling/migrate/index.d.ts +7 -0
  140. package/dist/tooling/migrate/index.js +7 -0
  141. package/dist/tooling/migrate/plan.d.ts +76 -0
  142. package/dist/tooling/migrate/policy.d.ts +78 -0
  143. package/dist/tooling/migrate/project.d.ts +69 -0
  144. package/dist/tooling/migrate/status.d.ts +74 -0
  145. package/dist/tooling/migrate/values.d.ts +29 -0
  146. package/package.json +109 -7
  147. package/dist/index.js +0 -0
@@ -0,0 +1,412 @@
1
+ // src/contracts/nearest.ts
2
+ function nearestName2(input, candidates) {
3
+ if (input.length === 0 || candidates.length === 0)
4
+ return;
5
+ const limit = input.length <= 4 ? 1 : input.length <= 12 ? 2 : 3;
6
+ let width = 0;
7
+ for (const candidate of candidates) {
8
+ if (candidate.length > width)
9
+ width = candidate.length;
10
+ }
11
+ const prev = new Uint16Array(width + 1);
12
+ const next = new Uint16Array(width + 1);
13
+ let best;
14
+ let bestDistance = limit;
15
+ for (const candidate of candidates) {
16
+ if (candidate === input)
17
+ continue;
18
+ const gap = candidate.length > input.length ? candidate.length - input.length : input.length - candidate.length;
19
+ if (gap > bestDistance)
20
+ continue;
21
+ const distance = editDistance(input, candidate, bestDistance, prev, next);
22
+ if (distance === undefined)
23
+ continue;
24
+ if (best === undefined || distance < bestDistance || distance === bestDistance && candidate < best) {
25
+ best = candidate;
26
+ bestDistance = distance;
27
+ }
28
+ }
29
+ return best;
30
+ }
31
+ function editDistance(left, right, cap, prev, next) {
32
+ const leftLength = left.length;
33
+ const rightLength = right.length;
34
+ if (leftLength === 0)
35
+ return rightLength <= cap ? rightLength : undefined;
36
+ if (rightLength === 0)
37
+ return leftLength <= cap ? leftLength : undefined;
38
+ for (let column = 0;column <= rightLength; column += 1)
39
+ prev[column] = column;
40
+ for (let row = 1;row <= leftLength; row += 1) {
41
+ next[0] = row;
42
+ let rowBest = row;
43
+ const leftCode = left.charCodeAt(row - 1);
44
+ for (let column = 1;column <= rightLength; column += 1) {
45
+ const cost = sameLetter(leftCode, right.charCodeAt(column - 1)) ? 0 : 1;
46
+ const deletion = (prev[column] ?? 0) + 1;
47
+ const insertion = (next[column - 1] ?? 0) + 1;
48
+ const substitution = (prev[column - 1] ?? 0) + cost;
49
+ let value = deletion < insertion ? deletion : insertion;
50
+ if (substitution < value)
51
+ value = substitution;
52
+ next[column] = value;
53
+ if (value < rowBest)
54
+ rowBest = value;
55
+ }
56
+ if (rowBest > cap)
57
+ return;
58
+ for (let column = 0;column <= rightLength; column += 1)
59
+ prev[column] = next[column] ?? 0;
60
+ }
61
+ const distance = prev[rightLength] ?? cap + 1;
62
+ return distance <= cap ? distance : undefined;
63
+ }
64
+ function sameLetter(left, right) {
65
+ if (left === right)
66
+ return true;
67
+ const leftFold = left >= 65 && left <= 90 ? left + 32 : left;
68
+ const rightFold = right >= 65 && right <= 90 ? right + 32 : right;
69
+ return leftFold === rightFold;
70
+ }
71
+
72
+ // src/contracts/error.ts
73
+ var CATALOG_CODES2 = [
74
+ "OKM1020",
75
+ "OKM1021",
76
+ "OKM1022",
77
+ "OKM1023",
78
+ "OKM1026",
79
+ "OKM1027",
80
+ "OKM1122"
81
+ ];
82
+ var COLUMN_CODES2 = ["OKM1060", "OKM1061", "OKM1210"];
83
+ var ERROR_KINDS2 = [
84
+ "invalid",
85
+ "not_null",
86
+ "check",
87
+ "foreign_key",
88
+ "unique",
89
+ "exclusion",
90
+ "conflict",
91
+ "not_found",
92
+ "not_unique",
93
+ "forbidden",
94
+ "serialization",
95
+ "deadlock",
96
+ "lock_timeout",
97
+ "timeout",
98
+ "cancelled",
99
+ "unavailable",
100
+ "schema_drift",
101
+ "driver",
102
+ "read_only",
103
+ "outcome_unknown"
104
+ ];
105
+ var ERROR_CATEGORIES2 = [
106
+ "input",
107
+ "conflict",
108
+ "not_found",
109
+ "forbidden",
110
+ "transient",
111
+ "internal"
112
+ ];
113
+ var NO_COLUMNS = [];
114
+ var NO_FIELDS = {};
115
+ var DEFAULT_STATUS = {
116
+ input: 422,
117
+ conflict: 409,
118
+ not_found: 404,
119
+ forbidden: 403,
120
+ transient: 503,
121
+ internal: 500
122
+ };
123
+ var CATEGORY_OF = {
124
+ invalid: "input",
125
+ not_null: "input",
126
+ check: "input",
127
+ foreign_key: "input",
128
+ unique: "conflict",
129
+ exclusion: "conflict",
130
+ conflict: "conflict",
131
+ not_found: "not_found",
132
+ not_unique: "not_found",
133
+ forbidden: "forbidden",
134
+ serialization: "transient",
135
+ deadlock: "transient",
136
+ lock_timeout: "transient",
137
+ timeout: "transient",
138
+ cancelled: "transient",
139
+ unavailable: "transient",
140
+ schema_drift: "internal",
141
+ driver: "internal",
142
+ read_only: "internal",
143
+ outcome_unknown: "internal"
144
+ };
145
+
146
+ class OkmError2 extends Error {
147
+ code;
148
+ kind;
149
+ category;
150
+ retryable;
151
+ fix;
152
+ table;
153
+ columns;
154
+ constraint;
155
+ sqlstate;
156
+ batchIndex;
157
+ fieldReason;
158
+ #fields;
159
+ #values;
160
+ #http;
161
+ get summary() {
162
+ return this.message;
163
+ }
164
+ constructor(code, message, options) {
165
+ const cause = options?.cause;
166
+ super(message, cause === undefined ? undefined : { cause });
167
+ this.name = "OkmError";
168
+ this.code = code;
169
+ const kind = options?.kind ?? kindFromCode(code);
170
+ this.kind = kind;
171
+ this.category = CATEGORY_OF[kind];
172
+ this.retryable = options?.retryable ?? defaultRetryable(kind);
173
+ this.fix = options?.fix ?? { summary: defaultFix(kind) };
174
+ this.table = options?.table;
175
+ const columns = options?.columns;
176
+ this.columns = columns === undefined || columns.length === 0 ? NO_COLUMNS : columns;
177
+ this.constraint = options?.constraint;
178
+ this.sqlstate = options?.sqlstate;
179
+ this.batchIndex = options?.batchIndex === undefined ? null : options.batchIndex;
180
+ this.fieldReason = options?.fieldReason ?? kind;
181
+ this.#values = options?.includeValues === true ? options.values : undefined;
182
+ this.#http = options?.http;
183
+ }
184
+ static from(error) {
185
+ if (error instanceof OkmError2)
186
+ return error;
187
+ if (isDriverError(error))
188
+ return fromDriver(error);
189
+ const message = error instanceof Error ? error.message : "Unknown error";
190
+ return new OkmError2("driver", stripRowValues(message), { kind: "driver", cause: error });
191
+ }
192
+ static is(error, kind, table) {
193
+ if (!(error instanceof OkmError2) || error.kind !== kind)
194
+ return false;
195
+ return table === undefined || error.table === table;
196
+ }
197
+ fields() {
198
+ const cached = this.#fields;
199
+ if (cached !== undefined)
200
+ return cached;
201
+ if (this.columns.length === 0) {
202
+ this.#fields = NO_FIELDS;
203
+ return NO_FIELDS;
204
+ }
205
+ const built = {};
206
+ const reason = this.fieldReason;
207
+ for (const column of this.columns)
208
+ built[column] = reason;
209
+ this.#fields = built;
210
+ return built;
211
+ }
212
+ values() {
213
+ return this.#values;
214
+ }
215
+ toHttp(statuses) {
216
+ const chosen = statuses ?? this.#http;
217
+ const override = chosen?.[this.category];
218
+ return {
219
+ status: override ?? DEFAULT_STATUS[this.category],
220
+ body: {
221
+ code: this.code,
222
+ reason: this.message,
223
+ fields: this.fields()
224
+ }
225
+ };
226
+ }
227
+ log() {
228
+ return {
229
+ name: "OkmError",
230
+ code: this.code,
231
+ kind: this.kind,
232
+ category: this.category,
233
+ summary: this.message,
234
+ retryable: this.retryable,
235
+ batchIndex: this.batchIndex,
236
+ fix: this.fix,
237
+ fields: this.fields(),
238
+ ...this.table !== undefined ? { table: this.table } : {},
239
+ ...this.columns.length > 0 ? { columns: this.columns } : {},
240
+ ...this.constraint !== undefined ? { constraint: this.constraint } : {},
241
+ ...this.sqlstate !== undefined ? { sqlstate: this.sqlstate } : {}
242
+ };
243
+ }
244
+ match(handlers) {
245
+ const handler = handlers[this.category];
246
+ if (handler !== undefined)
247
+ return handler(this);
248
+ return handlers._(this);
249
+ }
250
+ }
251
+ function safe2(pending) {
252
+ return pending.then((value) => ({ ok: true, value }), (error) => ({ ok: false, error: OkmError2.from(error) }));
253
+ }
254
+ function catalogError2(code, message, options) {
255
+ throw new OkmError2(code, message, options);
256
+ }
257
+ function throwNamed2(code, input, candidates, message) {
258
+ const suggestion = nearestName2(input, candidates);
259
+ if (suggestion === undefined)
260
+ throw new OkmError2(code, message);
261
+ throw new OkmError2(code, `${message} Did you mean \`${suggestion}\`?`, {
262
+ fix: { summary: `Use \`${suggestion}\`.`, suggestion }
263
+ });
264
+ }
265
+ function stripRowValues(text) {
266
+ let result = "";
267
+ for (let index = 0;index < text.length; index += 1) {
268
+ if (text.charCodeAt(index) === 61 && text.charCodeAt(index + 1) === 40) {
269
+ const end = matchingParen(text, index + 1);
270
+ if (end !== undefined) {
271
+ index = end;
272
+ continue;
273
+ }
274
+ }
275
+ if (startsAt(text, index, "contains (")) {
276
+ const open = index + "contains ".length;
277
+ const end = matchingParen(text, open);
278
+ if (end !== undefined) {
279
+ result += "contains (…)";
280
+ index = end;
281
+ continue;
282
+ }
283
+ }
284
+ result += text.charAt(index);
285
+ }
286
+ return result;
287
+ }
288
+ function kindFromCode(code) {
289
+ if (isErrorKind(code))
290
+ return code;
291
+ switch (code) {
292
+ case "OKM1401":
293
+ return "outcome_unknown";
294
+ case "OKM1846":
295
+ return "timeout";
296
+ case "OKM1520":
297
+ return "schema_drift";
298
+ default:
299
+ return "invalid";
300
+ }
301
+ }
302
+ function isErrorKind(code) {
303
+ switch (code) {
304
+ case "invalid":
305
+ case "not_null":
306
+ case "check":
307
+ case "foreign_key":
308
+ case "unique":
309
+ case "exclusion":
310
+ case "conflict":
311
+ case "not_found":
312
+ case "not_unique":
313
+ case "forbidden":
314
+ case "serialization":
315
+ case "deadlock":
316
+ case "lock_timeout":
317
+ case "timeout":
318
+ case "cancelled":
319
+ case "unavailable":
320
+ case "schema_drift":
321
+ case "driver":
322
+ case "read_only":
323
+ case "outcome_unknown":
324
+ return true;
325
+ default:
326
+ return false;
327
+ }
328
+ }
329
+ function defaultRetryable(kind) {
330
+ if (kind === "cancelled" || kind === "outcome_unknown")
331
+ return false;
332
+ return CATEGORY_OF[kind] === "transient";
333
+ }
334
+ function defaultFix(kind) {
335
+ switch (kind) {
336
+ case "cancelled":
337
+ return "Do not retry. The caller aborted the call.";
338
+ case "outcome_unknown":
339
+ return "Check whether the write landed, using an idempotency key, before retrying.";
340
+ case "timeout":
341
+ case "serialization":
342
+ case "deadlock":
343
+ case "lock_timeout":
344
+ case "unavailable":
345
+ return "Retry the call.";
346
+ case "unique":
347
+ case "exclusion":
348
+ case "conflict":
349
+ return "Change the conflicting value, or update the existing row.";
350
+ case "not_null":
351
+ return "Provide a value for the column.";
352
+ case "check":
353
+ case "invalid":
354
+ return "Change the value so it passes the check.";
355
+ case "foreign_key":
356
+ return "Use a key that exists, or insert the referenced row first.";
357
+ case "not_found":
358
+ return "Look up a row that exists.";
359
+ case "not_unique":
360
+ return "Narrow the filter so it matches one row.";
361
+ case "forbidden":
362
+ return "Use a role that is allowed to perform this operation.";
363
+ case "read_only":
364
+ return "Run the write on the primary.";
365
+ case "schema_drift":
366
+ return "Apply the migrations that match this build.";
367
+ case "driver":
368
+ return "Read the summary and correct the call.";
369
+ }
370
+ }
371
+ function isDriverError(error) {
372
+ return error instanceof Error && error.name === "DriverError";
373
+ }
374
+ function fromDriver(error) {
375
+ const kind = error.kind ?? "driver";
376
+ const code = kind === "outcome_unknown" ? "OKM1401" : kind;
377
+ const columns = error.column === undefined || error.column.length === 0 ? undefined : [error.column];
378
+ return new OkmError2(code, stripRowValues(error.message), {
379
+ kind,
380
+ ...error.table !== undefined ? { table: error.table } : {},
381
+ ...columns !== undefined ? { columns } : {},
382
+ ...error.constraint !== undefined ? { constraint: error.constraint } : {},
383
+ ...error.sqlstate !== undefined ? { sqlstate: error.sqlstate } : {},
384
+ ...error.batchIndex !== undefined ? { batchIndex: error.batchIndex } : {},
385
+ cause: error.cause ?? error
386
+ });
387
+ }
388
+ function matchingParen(text, open) {
389
+ let depth = 0;
390
+ for (let index = open;index < text.length; index += 1) {
391
+ const code = text.charCodeAt(index);
392
+ if (code === 40)
393
+ depth += 1;
394
+ else if (code === 41) {
395
+ depth -= 1;
396
+ if (depth === 0)
397
+ return index;
398
+ }
399
+ }
400
+ return;
401
+ }
402
+ function startsAt(text, index, needle) {
403
+ if (index + needle.length > text.length)
404
+ return false;
405
+ for (let offset = 0;offset < needle.length; offset += 1) {
406
+ if (text.charCodeAt(index + offset) !== needle.charCodeAt(offset))
407
+ return false;
408
+ }
409
+ return true;
410
+ }
411
+
412
+ export { nearestName2, CATALOG_CODES2, COLUMN_CODES2, ERROR_KINDS2, ERROR_CATEGORIES2, OkmError2, safe2, catalogError2, throwNamed2, stripRowValues, matchingParen };
@@ -0,0 +1,148 @@
1
+ import {
2
+ projectExpr,
3
+ quote,
4
+ list,
5
+ isRecord,
6
+ fail
7
+ } from "./rgs0st28.js";
8
+ import {
9
+ throwNamed2
10
+ } from "./ycwz42az.js";
11
+
12
+ // src/runtime/conflict.ts
13
+ function readConflict(table, value) {
14
+ if (value === undefined || value === "error")
15
+ return;
16
+ if (value === "ignore")
17
+ return { kind: "ignore", columns: [], update: [] };
18
+ if (!isRecord(value)) {
19
+ fail("OKM1120", 'onConflict must be "error", "ignore", { on, update }, or { on, return: true }.');
20
+ }
21
+ const keys = Object.keys(value);
22
+ const update = value.update;
23
+ const ret = value.return;
24
+ if (update !== undefined && ret !== undefined) {
25
+ fail("OKM1120", "onConflict takes update or return, not both.");
26
+ }
27
+ if (ret === true) {
28
+ rejectConflictKeys(keys, ["on", "return"]);
29
+ return { kind: "return", columns: uniqueColumns(table, value.on), update: [] };
30
+ }
31
+ if (update !== undefined) {
32
+ rejectConflictKeys(keys, ["on", "update"]);
33
+ return {
34
+ kind: "update",
35
+ columns: uniqueColumns(table, value.on),
36
+ update: updateColumns(table, update)
37
+ };
38
+ }
39
+ fail("OKM1120", 'onConflict must be "error", "ignore", { on, update }, or { on, return: true }.');
40
+ }
41
+ function finishInsert(head, returning, params, plan, table, returningColumns, keys) {
42
+ if (plan.kind === "ignore") {
43
+ return { text: `${head} on conflict do nothing${returning}`, params: [...params] };
44
+ }
45
+ const target = plan.columns.map((column) => quote(column.sql)).join(", ");
46
+ if (plan.kind === "update") {
47
+ const set = plan.update.map((column) => `${quote(column.sql)} = excluded.${quote(column.sql)}`).join(", ");
48
+ return {
49
+ text: `${head} on conflict (${target}) do update set ${set}${returning}`,
50
+ params: [...params]
51
+ };
52
+ }
53
+ return firstOrCreate(head, returning, params, plan.columns, table, returningColumns, keys);
54
+ }
55
+ function firstOrCreate(head, returning, params, keys, table, returningColumns, keyRows) {
56
+ const next = [...params];
57
+ const tuples = [];
58
+ for (const row of keyRows) {
59
+ const slots = [];
60
+ for (let index = 0;index < keys.length; index += 1) {
61
+ const column = keys[index];
62
+ if (column === undefined)
63
+ continue;
64
+ next.push(row[index] ?? null);
65
+ slots.push(`$${String(next.length)}::${column.dataType}`);
66
+ }
67
+ tuples.push(keys.length === 1 ? slots[0] ?? "null" : `(${slots.join(", ")})`);
68
+ }
69
+ const keyList = keys.map((column) => quote(column.sql)).join(", ");
70
+ const left = keys.length === 1 ? `t.${quote(keys[0]?.sql ?? "")}` : `(${keys.map((column) => `t.${quote(column.sql)}`).join(", ")})`;
71
+ const names = returningColumns.map((column) => quote(column.field)).join(", ");
72
+ const fromTable = returningColumns.map((column) => projectExpr(`t.${quote(column.sql)}`, column.dataType)).join(", ");
73
+ const match = keys.map((column) => `ins.${quote(column.field)} = t.${quote(column.sql)}`).join(" and ");
74
+ const text = `with ins(${names}) as (${head} on conflict (${keyList}) do nothing${returning}) select ${names} from ins union all select ${fromTable} from ${quote(table.model.sql)} t where ${left} in (${tuples.join(", ")}) and not exists (select 1 from ins where ${match})`;
75
+ return { text, params: next };
76
+ }
77
+ function uniqueColumns(table, on) {
78
+ const names = conflictNames(on);
79
+ for (const unique of table.model.uniques) {
80
+ if (!same(unique, names))
81
+ continue;
82
+ const columns = [];
83
+ for (const name of names) {
84
+ const column = table.columns.get(name);
85
+ if (column === undefined) {
86
+ fail("OKM1104", `onConflict column ${name} is not on ${table.model.name}.`);
87
+ }
88
+ columns.push(column);
89
+ }
90
+ return columns;
91
+ }
92
+ const accepted = table.model.uniques.map((fields) => fields.join(", "));
93
+ throwNamed2("OKM1104", names.join(", "), accepted, `onConflict on ${table.model.name} names ${names.join(", ")}, which is not a unique constraint. Accepted: ${list(accepted)}.`);
94
+ }
95
+ function updateColumns(table, value) {
96
+ if (!Array.isArray(value) || value.length === 0) {
97
+ fail("OKM1120", "onConflict update must name at least one column.");
98
+ }
99
+ const columns = [];
100
+ for (const name of value) {
101
+ if (typeof name !== "string")
102
+ fail("OKM1120", "onConflict update must name columns.");
103
+ const column = table.columns.get(name);
104
+ if (column === undefined) {
105
+ throwNamed2("OKM1120", name, table.names, `Field ${name} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
106
+ }
107
+ if (!column.writable)
108
+ refuseWrite(table.model.name, column);
109
+ columns.push(column);
110
+ }
111
+ return columns;
112
+ }
113
+ function conflictNames(on) {
114
+ if (typeof on === "string")
115
+ return [on];
116
+ if (Array.isArray(on) && on.length > 0 && on.every((name) => typeof name === "string")) {
117
+ return on;
118
+ }
119
+ fail("OKM1104", "onConflict on must name a unique constraint's columns.");
120
+ }
121
+ function same(unique, names) {
122
+ if (unique.length !== names.length)
123
+ return false;
124
+ const left = [...unique].sort();
125
+ const right = [...names].sort();
126
+ for (let index = 0;index < left.length; index += 1) {
127
+ if (left[index] !== right[index])
128
+ return false;
129
+ }
130
+ return true;
131
+ }
132
+ function rejectConflictKeys(keys, accepted) {
133
+ for (const key of keys) {
134
+ if (!accepted.includes(key)) {
135
+ throwNamed2("OKM1120", key, accepted, `Option ${key} is not accepted by onConflict. Accepted options: ${list(accepted)}.`);
136
+ }
137
+ }
138
+ }
139
+ function refuseWrite(table, column) {
140
+ if (column.guarded) {
141
+ fail("OKM1190", `Field ${table}.${column.field} is guarded. Input cannot set it.`);
142
+ }
143
+ fail("OKM1120", `Field ${table}.${column.field} cannot be written.`);
144
+ }
145
+ export {
146
+ finishInsert,
147
+ readConflict
148
+ };