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,257 @@
1
+ import {
2
+ isConnectionSqlstate,
3
+ isConnectionFailure
4
+ } from "./ngk8gj61.js";
5
+ import {
6
+ OkmError2,
7
+ stripRowValues,
8
+ matchingParen
9
+ } from "./ycwz42az.js";
10
+
11
+ // src/dialects/pg/errors.ts
12
+ function mapPostgresError(error, options) {
13
+ if (error instanceof OkmError2)
14
+ return error;
15
+ if (!isDriverError(error))
16
+ return OkmError2.from(error);
17
+ const kind = kindOf(error);
18
+ const columns = columnsOf(error);
19
+ const fieldReason = kind === "not_null" ? "not_null" : reasonOf(kind, error.table, error.constraint);
20
+ const values = options?.includeValues === true ? valuesOf(error.detail, columns) : undefined;
21
+ const code = kind === "outcome_unknown" ? "OKM1401" : kind;
22
+ return new OkmError2(code, summaryOf(kind, error, columns, fieldReason), {
23
+ kind,
24
+ fieldReason,
25
+ ...error.table !== undefined ? { table: error.table } : {},
26
+ ...columns.length > 0 ? { columns } : {},
27
+ ...error.constraint !== undefined ? { constraint: error.constraint } : {},
28
+ ...error.sqlstate !== undefined ? { sqlstate: error.sqlstate } : {},
29
+ batchIndex: error.batchIndex,
30
+ cause: error.cause ?? error,
31
+ ...options?.includeValues === true && values !== undefined ? { includeValues: true, values } : {},
32
+ ...options?.http !== undefined ? { http: options.http } : {}
33
+ });
34
+ }
35
+ function isDriverError(error) {
36
+ if (!(error instanceof Error) || error.name !== "DriverError")
37
+ return false;
38
+ return "batchIndex" in error;
39
+ }
40
+ function kindOf(error) {
41
+ if (error.kind === "timeout" || error.kind === "cancelled" || error.kind === "outcome_unknown") {
42
+ return error.kind;
43
+ }
44
+ const sqlstate = error.sqlstate;
45
+ if (sqlstate !== undefined) {
46
+ const mapped = kindFromSqlstate(sqlstate);
47
+ if (mapped !== undefined)
48
+ return mapped;
49
+ }
50
+ if (isConnectionFailure(error))
51
+ return "unavailable";
52
+ return "driver";
53
+ }
54
+ function kindFromSqlstate(sqlstate) {
55
+ switch (sqlstate) {
56
+ case "23505":
57
+ return "unique";
58
+ case "23502":
59
+ return "not_null";
60
+ case "23514":
61
+ return "check";
62
+ case "23503":
63
+ case "23001":
64
+ return "foreign_key";
65
+ case "23P01":
66
+ return "exclusion";
67
+ case "23000":
68
+ return "conflict";
69
+ case "40001":
70
+ return "serialization";
71
+ case "40P01":
72
+ return "deadlock";
73
+ case "55P03":
74
+ return "lock_timeout";
75
+ case "57014":
76
+ return "timeout";
77
+ case "40003":
78
+ return "outcome_unknown";
79
+ case "25006":
80
+ return "read_only";
81
+ default:
82
+ if (isConnectionSqlstate(sqlstate))
83
+ return "unavailable";
84
+ if (sqlstate.startsWith("22"))
85
+ return "invalid";
86
+ if (sqlstate.startsWith("53"))
87
+ return "unavailable";
88
+ return;
89
+ }
90
+ }
91
+ function reasonOf(kind, table, constraint) {
92
+ if (constraint === undefined || constraint.length === 0)
93
+ return kind;
94
+ if (table !== undefined) {
95
+ if (constraint === `${table}_pkey`)
96
+ return "pkey";
97
+ const prefix = `${table}_`;
98
+ if (constraint.startsWith(prefix)) {
99
+ const rest = constraint.slice(prefix.length);
100
+ const nameKey = nameKeyOf(rest);
101
+ if (nameKey !== undefined)
102
+ return nameKey;
103
+ }
104
+ }
105
+ return constraint;
106
+ }
107
+ function nameKeyOf(rest) {
108
+ const tags = ["_fkey", "_check", "_key"];
109
+ for (const tag of tags) {
110
+ if (rest.endsWith(tag) && rest.length > tag.length)
111
+ return rest.slice(0, -tag.length);
112
+ }
113
+ return;
114
+ }
115
+ function columnsOf(error) {
116
+ if (error.column !== undefined && error.column.length > 0)
117
+ return [unquote(error.column)];
118
+ const detail = error.detail;
119
+ if (detail !== undefined) {
120
+ const fromKey = keyColumns(detail);
121
+ if (fromKey.length > 0)
122
+ return fromKey;
123
+ }
124
+ const fromMessage = quotedColumn(error.message);
125
+ return fromMessage === undefined ? [] : [fromMessage];
126
+ }
127
+ function keyColumns(detail) {
128
+ const marker = "Key (";
129
+ const start = detail.indexOf(marker);
130
+ if (start === -1)
131
+ return [];
132
+ const open = start + marker.length - 1;
133
+ const end = matchingParen(detail, open);
134
+ if (end === undefined)
135
+ return [];
136
+ return splitList(detail.slice(open + 1, end));
137
+ }
138
+ function valuesOf(detail, columns) {
139
+ if (detail === undefined || columns.length === 0)
140
+ return;
141
+ const marker = "=(";
142
+ const start = detail.indexOf(marker);
143
+ if (start === -1)
144
+ return;
145
+ const open = start + 1;
146
+ const end = matchingParen(detail, open);
147
+ if (end === undefined)
148
+ return;
149
+ const parts = splitList(detail.slice(open + 1, end));
150
+ if (parts.length !== columns.length)
151
+ return;
152
+ const values = {};
153
+ for (let index = 0;index < columns.length; index += 1) {
154
+ const column = columns[index];
155
+ const value = parts[index];
156
+ if (column === undefined || value === undefined)
157
+ continue;
158
+ values[column] = value;
159
+ }
160
+ return values;
161
+ }
162
+ function quotedColumn(message) {
163
+ const marker = 'column "';
164
+ const start = message.indexOf(marker);
165
+ if (start === -1)
166
+ return;
167
+ const from = start + marker.length;
168
+ const end = message.indexOf('"', from);
169
+ if (end === -1)
170
+ return;
171
+ return message.slice(from, end);
172
+ }
173
+ function splitList(inner) {
174
+ const parts = inner.split(",");
175
+ const names = [];
176
+ for (const part of parts) {
177
+ const name = unquote(part.trim());
178
+ if (name.length > 0)
179
+ names.push(name);
180
+ }
181
+ return names;
182
+ }
183
+ function unquote(name) {
184
+ if (name.startsWith('"') && name.endsWith('"') && name.length >= 2) {
185
+ return name.slice(1, -1);
186
+ }
187
+ return name;
188
+ }
189
+ function summaryOf(kind, error, columns, fieldReason) {
190
+ const label = labelOf(kind);
191
+ if (kind === "driver")
192
+ return stripRowValues(error.message);
193
+ const where = place(error.table, columns);
194
+ if (where === undefined)
195
+ return label;
196
+ if (fieldReason === kind)
197
+ return `${label} on ${where}`;
198
+ return `${label} on ${where} (${fieldReason})`;
199
+ }
200
+ function place(table, columns) {
201
+ if (table === undefined && columns.length === 0)
202
+ return;
203
+ if (table === undefined)
204
+ return columns.join(", ");
205
+ if (columns.length === 0)
206
+ return table;
207
+ if (columns.length === 1)
208
+ return `${table}.${columns[0] ?? ""}`;
209
+ return `${table} (${columns.join(", ")})`;
210
+ }
211
+ function labelOf(kind) {
212
+ switch (kind) {
213
+ case "unique":
214
+ return "Unique violation";
215
+ case "not_null":
216
+ return "Not-null violation";
217
+ case "check":
218
+ return "Check violation";
219
+ case "foreign_key":
220
+ return "Foreign key violation";
221
+ case "exclusion":
222
+ return "Exclusion violation";
223
+ case "conflict":
224
+ return "Conflict";
225
+ case "invalid":
226
+ return "Invalid value";
227
+ case "serialization":
228
+ return "Serialization failure";
229
+ case "deadlock":
230
+ return "Deadlock";
231
+ case "lock_timeout":
232
+ return "Lock timeout";
233
+ case "timeout":
234
+ return "The call timed out";
235
+ case "cancelled":
236
+ return "The call was cancelled";
237
+ case "unavailable":
238
+ return "The database is unavailable";
239
+ case "outcome_unknown":
240
+ return "The commit outcome is unknown";
241
+ case "read_only":
242
+ return "The database is read-only";
243
+ case "schema_drift":
244
+ return "The database schema does not match this build";
245
+ case "not_found":
246
+ return "No row was found";
247
+ case "not_unique":
248
+ return "More than one row was found";
249
+ case "forbidden":
250
+ return "The operation is forbidden";
251
+ case "driver":
252
+ return "Driver error";
253
+ }
254
+ }
255
+ export {
256
+ mapPostgresError
257
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,193 @@
1
+ import"../shared/y9m15dfv.js";
2
+ import {
3
+ formatPlan,
4
+ buildProject,
5
+ generateProject,
6
+ planProject,
7
+ checkProject
8
+ } from "../shared/05w44d8g.js";
9
+ import {
10
+ OkmError2
11
+ } from "../shared/ycwz42az.js";
12
+
13
+ // src/tooling/cli.ts
14
+ import { readFileSync } from "node:fs";
15
+ import { dirname, join } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+
18
+ // src/tooling/migrate/commands.ts
19
+ async function run(argv, io) {
20
+ const cwd = io?.cwd ?? process.cwd();
21
+ const stdout = io?.stdout ?? ((text) => process.stdout.write(text));
22
+ const [command, ...rest] = argv;
23
+ if (command === "build") {
24
+ const directory = await buildProject(cwd);
25
+ stdout(`${directory}
26
+ `);
27
+ return;
28
+ }
29
+ if (command === "check") {
30
+ await checkProject(cwd);
31
+ stdout(`ok
32
+ `);
33
+ return;
34
+ }
35
+ if (command === "generate") {
36
+ const parsed = splitFlags(rest);
37
+ const path = await generateProject(cwd, parsed.name ?? "migration", parsed.flags);
38
+ stdout(path === undefined ? `no changes
39
+ ` : `${path}
40
+ `);
41
+ return;
42
+ }
43
+ if (command === "dev") {
44
+ const { devProject } = await import("../shared/kprcwaha.js");
45
+ stdout(await devProject(cwd));
46
+ return;
47
+ }
48
+ if (command === "push") {
49
+ const { pushProject } = await import("../shared/m3ypagh5.js");
50
+ stdout(await pushProject(cwd, invoke(splitFlags(rest))));
51
+ return;
52
+ }
53
+ if (command === "migrate") {
54
+ const sub = rest[0];
55
+ const parsed = splitFlags(rest.slice(1));
56
+ if (sub === "plan") {
57
+ if (parsed.name === undefined) {
58
+ throw new OkmError2("invalid", "okm migrate plan needs a name.");
59
+ }
60
+ stdout(formatPlan(await planProject(cwd, parsed.name, parsed.flags)));
61
+ return;
62
+ }
63
+ if (sub === "apply") {
64
+ const { applyProject } = await import("../shared/m3ypagh5.js");
65
+ stdout(await applyProject(cwd, invoke(parsed)));
66
+ return;
67
+ }
68
+ if (sub === "status") {
69
+ const { statusProject } = await import("../shared/523ft3e8.js");
70
+ stdout(await statusProject(cwd, invoke(parsed)));
71
+ return;
72
+ }
73
+ }
74
+ throw new OkmError2("invalid", `Unknown command ${command ?? ""}.`);
75
+ }
76
+ function invoke(parsed) {
77
+ return {
78
+ ...parsed.target !== undefined ? { target: parsed.target } : {},
79
+ allowProtected: parsed.allowProtected,
80
+ allowPooler: parsed.allowPooler,
81
+ ...parsed.lockTimeoutMs !== undefined ? { lockTimeoutMs: parsed.lockTimeoutMs } : {},
82
+ ...parsed.statementTimeoutMs !== undefined ? { statementTimeoutMs: parsed.statementTimeoutMs } : {}
83
+ };
84
+ }
85
+ function splitFlags(args) {
86
+ const flags = [];
87
+ const positionals = [];
88
+ let target;
89
+ let allowProtected = false;
90
+ let allowPooler = false;
91
+ let lockTimeoutMs;
92
+ let statementTimeoutMs;
93
+ for (let index = 0;index < args.length; index += 1) {
94
+ const arg = args[index] ?? "";
95
+ if (arg === "--replace") {
96
+ const value = args[index + 1];
97
+ if (value === undefined) {
98
+ throw new OkmError2("OKM1541", "--replace needs table.column.old=new.", {
99
+ fix: { summary: "Pass --replace <table>.<column>.<old>=<new>." }
100
+ });
101
+ }
102
+ flags.push(value);
103
+ index += 1;
104
+ continue;
105
+ }
106
+ if (arg.startsWith("--replace=")) {
107
+ flags.push(arg.slice("--replace=".length));
108
+ continue;
109
+ }
110
+ if (arg === "--allow-protected") {
111
+ allowProtected = true;
112
+ continue;
113
+ }
114
+ if (arg === "--allow-pooler") {
115
+ allowPooler = true;
116
+ continue;
117
+ }
118
+ if (arg === "--target") {
119
+ const value = args[index + 1];
120
+ if (value === undefined || value.startsWith("--")) {
121
+ throw new OkmError2("OKM1853", "--target needs a name.", {
122
+ fix: { summary: "Pass --target <name>." }
123
+ });
124
+ }
125
+ target = value;
126
+ index += 1;
127
+ continue;
128
+ }
129
+ if (arg.startsWith("--target=")) {
130
+ target = arg.slice("--target=".length);
131
+ continue;
132
+ }
133
+ if (arg === "--lock-timeout" || arg === "--statement-timeout") {
134
+ const value = numberFlag(arg, args[index + 1]);
135
+ if (arg === "--lock-timeout")
136
+ lockTimeoutMs = value;
137
+ else
138
+ statementTimeoutMs = value;
139
+ index += 1;
140
+ continue;
141
+ }
142
+ positionals.push(arg);
143
+ }
144
+ return {
145
+ name: positionals[0],
146
+ flags,
147
+ target,
148
+ allowProtected,
149
+ allowPooler,
150
+ lockTimeoutMs,
151
+ statementTimeoutMs
152
+ };
153
+ }
154
+ function numberFlag(flag, value) {
155
+ const parsed = value === undefined ? Number.NaN : Number(value);
156
+ if (!Number.isFinite(parsed) || parsed < 0) {
157
+ throw new OkmError2("invalid", `${flag} needs a number of milliseconds.`, {
158
+ fix: { summary: `Pass ${flag} <milliseconds>.` }
159
+ });
160
+ }
161
+ return parsed;
162
+ }
163
+
164
+ // src/tooling/cli.ts
165
+ var here = dirname(fileURLToPath(import.meta.url));
166
+ var packageJsonPath = join(here, "..", "..", "package.json");
167
+ if (process.argv.includes("--version")) {
168
+ process.stdout.write(`${readPackageVersion(packageJsonPath)}
169
+ `);
170
+ } else if (process.argv.length > 2) {
171
+ try {
172
+ await run(process.argv.slice(2));
173
+ } catch (error) {
174
+ if (error instanceof OkmError2) {
175
+ process.stderr.write(`${error.code}: ${error.message}
176
+ ${error.fix.summary}
177
+ `);
178
+ process.exitCode = 1;
179
+ } else {
180
+ throw error;
181
+ }
182
+ }
183
+ }
184
+ function readPackageVersion(path) {
185
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
186
+ if (!isRecord(parsed) || typeof parsed.version !== "string") {
187
+ throw new Error(`No string version in ${path}`);
188
+ }
189
+ return parsed.version;
190
+ }
191
+ function isRecord(value) {
192
+ return typeof value === "object" && value !== null;
193
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Doctor text for every OKM code in spec §21.
3
+ *
4
+ * This module is not on the runtime entry. A process that never explains a
5
+ * code does not load it. Titles stay short. The summary and the fix are the
6
+ * page `okm doctor <code>` will print.
7
+ */
8
+ /** One code in the error registry. */
9
+ export type ErrorDoc = {
10
+ /** Spec code, for example `OKM1020`. */
11
+ readonly code: string;
12
+ /** Short name. */
13
+ readonly title: string;
14
+ /** What went wrong. */
15
+ readonly summary: string;
16
+ /** What to do. */
17
+ readonly fix: string;
18
+ };
19
+ /**
20
+ * Every OKM code spec §21 names, in numeric order.
21
+ *
22
+ * OKM1111 is a dynamic call the driver's capabilities do not allow.
23
+ */
24
+ export declare const ERROR_DOCS: readonly ErrorDoc[];
25
+ /**
26
+ * Looks up one code.
27
+ *
28
+ * The map is built on the first call, not at import.
29
+ *
30
+ * @param code - Spec code, for example `OKM1401`
31
+ * @returns The doctor entry, or `undefined` when the code is not in spec §21
32
+ */
33
+ export declare function errorDoc(code: string): ErrorDoc | undefined;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Applies migrations on one target.
3
+ *
4
+ * A run holds a session advisory lock. Transactional steps of one migration
5
+ * share a transaction. Steps Postgres cannot run there (`CREATE INDEX
6
+ * CONCURRENTLY`, `ADD VALUE`, `VACUUM`) are their own steps. Each finished
7
+ * step is a history row. A later apply skips those rows.
8
+ */
9
+ import { type PlanStep } from "./plan.js";
10
+ import type { StoredMigration } from "./files.js";
11
+ import { type InvokeFlags } from "./policy.js";
12
+ /** One step with its index in the migration file. */
13
+ export type IndexedStep = {
14
+ readonly index: number;
15
+ readonly step: PlanStep;
16
+ };
17
+ /** Steps that commit together, or one step that cannot. */
18
+ export type ApplyUnit = {
19
+ readonly migrationId: string;
20
+ readonly catalogHash: string;
21
+ /** True when this unit is the last step of its migration. */
22
+ readonly finishes: boolean;
23
+ readonly transactional: boolean;
24
+ readonly steps: readonly IndexedStep[];
25
+ };
26
+ /** What {@link applyTarget} needs. The URL is resolved by the caller. */
27
+ export type ApplyRequest = {
28
+ readonly url: string;
29
+ readonly target: string;
30
+ readonly protected: boolean;
31
+ readonly allowProtected?: boolean;
32
+ readonly allowPooler?: boolean;
33
+ readonly searchPath?: string;
34
+ readonly lockTimeoutMs?: number;
35
+ readonly statementTimeoutMs?: number;
36
+ readonly retries?: number;
37
+ readonly migrations: readonly StoredMigration[];
38
+ /** Runs after the advisory lock is held and before the first step. */
39
+ readonly onLocked?: () => void;
40
+ };
41
+ /** Migrations that ran at least one step in this invocation. */
42
+ export type ApplyReport = {
43
+ readonly target: string;
44
+ readonly applied: readonly string[];
45
+ };
46
+ /**
47
+ * Groups pending steps into the transactions apply will run.
48
+ *
49
+ * A step Postgres cannot run inside a transaction is its own unit even when
50
+ * the plan marked it transactional.
51
+ *
52
+ * @param migration - One file
53
+ * @param done - Keys `${migrationId}:${stepIndex}` already in history
54
+ * @returns Units in apply order
55
+ */
56
+ export declare function applyUnits(migration: StoredMigration, done: ReadonlySet<string>): readonly ApplyUnit[];
57
+ /**
58
+ * Applies pending migrations on one target.
59
+ *
60
+ * The connection is reserved for the whole run so the advisory lock stays
61
+ * session-scoped. Lock timeout retries that step. Any other failure stops
62
+ * at that step.
63
+ *
64
+ * @param request - Target, flags, and the migrations to consider
65
+ * @returns The target and the migration ids that ran
66
+ */
67
+ export declare function applyTarget(request: ApplyRequest): Promise<ApplyReport>;
68
+ /**
69
+ * Applies the migrations in the project to the selected target.
70
+ *
71
+ * @param cwd - Project directory
72
+ * @param flags - `--target`, protection, pooler, and timeouts
73
+ * @returns Text for stdout, including the target name
74
+ */
75
+ export declare function applyProject(cwd: string, flags: InvokeFlags): Promise<string>;
76
+ /**
77
+ * Prototype sync. Blocked on a protected target.
78
+ *
79
+ * A target named production is not special. Protection is the `protected`
80
+ * flag (spec §19.8). The plan's statements run as one migration.
81
+ *
82
+ * @param cwd - Project directory
83
+ * @param flags - Target and protection flags
84
+ * @returns Text for stdout
85
+ */
86
+ export declare function pushProject(cwd: string, flags: InvokeFlags): Promise<string>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `okm` command dispatch.
3
+ *
4
+ * The bin wrapper imports {@link run}. Importing this module does not parse
5
+ * `process.argv`.
6
+ */
7
+ /** Where a command reads the project and writes its text. */
8
+ export type CommandIo = {
9
+ readonly cwd?: string;
10
+ readonly stdout?: (text: string) => void;
11
+ };
12
+ /**
13
+ * Runs one `okm` invocation.
14
+ *
15
+ * `--version` stays in the bin. This function handles `build`, `check`,
16
+ * `generate`, `dev`, `push`, and `migrate plan`, `apply`, and `status`.
17
+ *
18
+ * @param argv - Arguments after the program name
19
+ * @param io - Working directory and stdout. Defaults to the process
20
+ */
21
+ export declare function run(argv: readonly string[], io?: CommandIo): Promise<void>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Project configuration for `okm`.
3
+ *
4
+ * Exported from `okmodel/migrate`. The runtime entry stays free of tooling.
5
+ */
6
+ /** One migration target. A string is the URL. Protection defaults to false. */
7
+ export type TargetInput = string | {
8
+ readonly url?: string;
9
+ /** Refuses contract, push, and other non-expand work unless `--allow-protected`. */
10
+ readonly protected?: boolean;
11
+ };
12
+ /** Paths and targets `okm` reads. */
13
+ export type MigrateConfig = {
14
+ /** Module that exports the built schema. */
15
+ readonly schema: string;
16
+ /** Directory of table files. `okm check` reports one that the schema does not import. */
17
+ readonly tables?: string;
18
+ /** Directory of generated SQL. Defaults to `migrations`. */
19
+ readonly migrations?: string;
20
+ /** Build output. Defaults to `.okm`. */
21
+ readonly out?: string;
22
+ /**
23
+ * The one target named `default`.
24
+ *
25
+ * A direct Postgres URL, not a pooler. Use {@link MigrateConfig.targets} when
26
+ * there is more than one.
27
+ */
28
+ readonly database?: TargetInput;
29
+ /** Named targets. Replaces `database`. */
30
+ readonly targets?: Readonly<Record<string, TargetInput>>;
31
+ /** Apply against a known pooler URL. The default refuses those hosts. */
32
+ readonly allowPooler?: boolean;
33
+ /** Milliseconds for `lock_timeout` and `statement_timeout` during apply. */
34
+ readonly timeouts?: {
35
+ readonly lock?: number;
36
+ readonly statement?: number;
37
+ };
38
+ };
39
+ /**
40
+ * Returns the config unchanged.
41
+ *
42
+ * `database` is one target named `default`. `targets` is the named map.
43
+ * Commands that touch a database require `--target` when several exist.
44
+ *
45
+ * @param config - Schema module, directories, and targets
46
+ * @returns The same config
47
+ */
48
+ export declare function defineConfig(config: MigrateConfig): MigrateConfig;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `okm dev`.
3
+ *
4
+ * When a target named `dev` is configured, the command names it. Otherwise it
5
+ * creates a PGlite database in `.okm/dev-db`.
6
+ */
7
+ /**
8
+ * Starts the dev database.
9
+ *
10
+ * A configured target named `dev` is used as it is. With no such target,
11
+ * PGlite is opened on `.okm/dev-db` so the directory exists for the app.
12
+ *
13
+ * @param cwd - Project directory
14
+ * @returns The target line, or the data directory
15
+ */
16
+ export declare function devProject(cwd: string): Promise<string>;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Structural equality for two catalogs.
3
+ *
4
+ * Introspection stamps the same provenance on every object, so the canonical
5
+ * document is the comparison. Authoring text is not compared to a reprint.
6
+ */
7
+ import type { Catalog } from "../../contracts/catalog/types.js";
8
+ /**
9
+ * Reports whether two catalogs serialise to the same bytes.
10
+ *
11
+ * @param left - First catalog
12
+ * @param right - Second catalog
13
+ * @returns `true` when the canonical documents match
14
+ */
15
+ export declare function catalogsEqual(left: Catalog, right: Catalog): boolean;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Migration files on disk: SQL from {@link formatPlan} plus the catalog hash.
3
+ */
4
+ import { type PlanStep } from "./plan.js";
5
+ /** One migration the applier can run and resume. */
6
+ export type StoredMigration = {
7
+ readonly id: string;
8
+ readonly catalogHash: string;
9
+ readonly steps: readonly PlanStep[];
10
+ };
11
+ /**
12
+ * Loads `*.sql` migrations and the sibling catalog snapshot.
13
+ *
14
+ * Files are applied in name order. A SQL file without its catalog is refused.
15
+ *
16
+ * @param directory - Migrations directory. Missing means there are none
17
+ * @returns Migrations in apply order
18
+ */
19
+ export declare function loadMigrations(directory: string): readonly StoredMigration[];