okmodel 0.3.0 → 0.5.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.
- package/README.md +263 -23
- package/dist/contracts/catalog/document.d.ts +26 -2
- package/dist/contracts/driver.d.ts +7 -0
- package/dist/dialects/pg/ext/citext.js +1 -1
- package/dist/dialects/pg/ext/index.js +1 -1
- package/dist/dialects/pg/ext/pg-trgm.js +1 -1
- package/dist/dialects/pg/index.js +3 -3
- package/dist/dialects/pg/introspect.d.ts +6 -0
- package/dist/dialects/pg/role/sql.d.ts +21 -4
- package/dist/dialects/pg/schema.d.ts +15 -6
- package/dist/dialects/pg/table.d.ts +17 -1
- package/dist/dialects/pg/view/index.d.ts +20 -6
- package/dist/dialects/pg/view/index.js +1 -1
- package/dist/dialects/pg/view/scratch.d.ts +2 -1
- package/dist/runtime/catalog-cache.d.ts +17 -0
- package/dist/runtime/compat-words.d.ts +23 -0
- package/dist/runtime/drift-detail.d.ts +20 -4
- package/dist/runtime/drift.d.ts +4 -2
- package/dist/runtime/pg/bun.d.ts +12 -7
- package/dist/runtime/pg/bun.js +5 -2
- package/dist/runtime/pg/pg.d.ts +12 -6
- package/dist/runtime/pg/pg.js +5 -2
- package/dist/runtime/pg/pglite.d.ts +11 -3
- package/dist/runtime/pg/pglite.js +5 -2
- package/dist/runtime/pg/postgresjs.d.ts +12 -6
- package/dist/runtime/pg/postgresjs.js +5 -2
- package/dist/runtime/plan.d.ts +3 -1
- package/dist/runtime/tenancy/index.js +1 -1
- package/dist/runtime/topology.d.ts +191 -0
- package/dist/runtime/traits/index.js +7 -6
- package/dist/runtime/types.d.ts +59 -2
- package/dist/runtime/validate/index.js +2 -2
- package/dist/shared/{x6wysh83.js → 3p4b1fg0.js} +3 -5
- package/dist/shared/{ty3v3hfk.js → 47xzb9fc.js} +2 -2
- package/dist/shared/{fs0ex00p.js → 4ef7mmqf.js} +2 -2
- package/dist/shared/{qybh48nd.js → 5fqx9yh4.js} +6 -2
- package/dist/shared/5mtf6cj3.js +94 -0
- package/dist/shared/{999ade2q.js → 5vdm4sgp.js} +1 -1
- package/dist/shared/{bqha5cg6.js → 6p5k20sm.js} +2 -2
- package/dist/shared/{t616ynfn.js → 8bwbwy8h.js} +71 -13
- package/dist/shared/{th14ygv2.js → 8ktwd3rh.js} +29 -1
- package/dist/shared/{wekze34d.js → 8xsbagad.js} +74 -2
- package/dist/shared/{bryqk9k9.js → 922qbgnw.js} +3 -3
- package/dist/shared/{meck53jv.js → 990a291j.js} +6 -5
- package/dist/shared/{jns2wx4t.js → 9tgmr1gh.js} +1 -1
- package/dist/shared/9yn6a2vd.js +11 -0
- package/dist/shared/{2ssqrv66.js → ayz64vzj.js} +1037 -181
- package/dist/shared/{k34e0xf2.js → bt9sfq0z.js} +16 -14
- package/dist/shared/{scwxrpx2.js → bzsjtd7c.js} +84 -15
- package/dist/shared/{m9tv7xn7.js → ckjbyrt9.js} +4 -4
- package/dist/shared/{ydaz1sv3.js → dxjp14rk.js} +10 -2
- package/dist/shared/{49ypnfwt.js → fancm5pt.js} +24 -229
- package/dist/shared/{6bazvqwm.js → fb00y8fp.js} +2 -2
- package/dist/shared/{1tfdfvhh.js → fyqkk1m0.js} +6 -4
- package/dist/shared/g516zdsb.js +905 -0
- package/dist/shared/{jkc6ws1p.js → g7ez901n.js} +83 -2
- package/dist/shared/{kgnc8grt.js → gdh9mrtp.js} +1 -1
- package/dist/shared/{p24x2334.js → h4nqvjkp.js} +5 -3
- package/dist/shared/{edwqqryd.js → h8ne16fq.js} +1 -1
- package/dist/shared/htnaj77v.js +17 -0
- package/dist/shared/jdgqqx31.js +72 -0
- package/dist/shared/{6w5j844a.js → jsd07prz.js} +2 -2
- package/dist/shared/{m78s7898.js → k7cc9nzk.js} +24 -7
- package/dist/shared/kdkxh3kb.js +758 -0
- package/dist/shared/nkc9sfqb.js +1161 -0
- package/dist/shared/{xva8v7qk.js → p7pfx624.js} +5 -5
- package/dist/shared/{xrfnq5k8.js → qgvt8nx1.js} +11 -2
- package/dist/shared/{ne02ng5c.js → qy9rdq0g.js} +9 -5
- package/dist/shared/{3ekj9x92.js → r6pj4fq2.js} +5 -3
- package/dist/shared/r73pt594.js +426 -0
- package/dist/shared/rasvvzgz.js +21 -0
- package/dist/shared/{01yr20s5.js → sf8m6tfy.js} +2 -2
- package/dist/shared/{hcmdtwgh.js → szm0cksa.js} +4 -1
- package/dist/shared/{axhk06q1.js → tq9afp8d.js} +1 -1
- package/dist/shared/{xw1d69vd.js → wqem4jed.js} +6 -6
- package/dist/shared/wxn4b7pp.js +252 -0
- package/dist/shared/xdpj5kkm.js +2203 -0
- package/dist/shared/xhh1srw3.js +589 -0
- package/dist/shared/{mt5wswjz.js → xsq7v6wp.js} +2 -2
- package/dist/shared/{7fvtrkwr.js → ycatkxmq.js} +1 -1
- package/dist/shared/ykv7wh5b.js +14 -0
- package/dist/shared/{fptpmvxp.js → z2rnngj4.js} +26 -21
- package/dist/tooling/cli.js +46 -17
- package/dist/tooling/migrate/apply.d.ts +61 -5
- package/dist/tooling/migrate/backfill.d.ts +136 -0
- package/dist/tooling/migrate/check.d.ts +65 -0
- package/dist/tooling/migrate/classify.d.ts +108 -0
- package/dist/tooling/migrate/commands.d.ts +2 -2
- package/dist/tooling/migrate/config.d.ts +22 -0
- package/dist/tooling/migrate/doctor.d.ts +3 -0
- package/dist/tooling/migrate/drift.d.ts +18 -2
- package/dist/tooling/migrate/estimate.d.ts +50 -0
- package/dist/tooling/migrate/extensions.d.ts +2 -0
- package/dist/tooling/migrate/files.d.ts +19 -0
- package/dist/tooling/migrate/index.d.ts +3 -2
- package/dist/tooling/migrate/index.js +69 -1
- package/dist/tooling/migrate/lint-rules.d.ts +51 -0
- package/dist/tooling/migrate/lint.d.ts +71 -0
- package/dist/tooling/migrate/managed.d.ts +1 -1
- package/dist/tooling/migrate/plan.d.ts +64 -9
- package/dist/tooling/migrate/project.d.ts +42 -7
- package/dist/tooling/migrate/provision.d.ts +18 -0
- package/dist/tooling/migrate/reference.d.ts +40 -0
- package/dist/tooling/migrate/runner.d.ts +108 -0
- package/dist/tooling/migrate/safe.d.ts +77 -0
- package/dist/tooling/migrate/seed.d.ts +20 -0
- package/dist/tooling/migrate/snapshot.d.ts +78 -0
- package/dist/tooling/migrate/status.d.ts +25 -6
- package/dist/tooling/testing/factories.d.ts +117 -0
- package/dist/tooling/testing/facts.d.ts +75 -0
- package/dist/tooling/testing/index.d.ts +89 -0
- package/dist/tooling/testing/index.js +8 -0
- package/dist/tooling/testing/isolation.d.ts +30 -0
- package/dist/tooling/testing/random.d.ts +40 -0
- package/dist/tooling/testing/record.d.ts +38 -0
- package/package.json +6 -2
- package/dist/shared/5nmdenb6.js +0 -1229
- package/dist/shared/dbjej1tw.js +0 -456
- package/dist/shared/g4f5kcx9.js +0 -37
- package/dist/shared/qbxzvwwc.js +0 -88
- package/dist/shared/zwmqxb0g.js +0 -79
- /package/dist/shared/{75xkjv0t.js → fa9vt245.js} +0 -0
- /package/dist/shared/{0jc3ffzf.js → zvbjc949.js} +0 -0
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
decodeResult,
|
|
8
8
|
logicalIntent,
|
|
9
9
|
appliedRules
|
|
10
|
-
} from "./
|
|
10
|
+
} from "./qgvt8nx1.js";
|
|
11
11
|
import {
|
|
12
12
|
OkmError2,
|
|
13
13
|
safe2,
|
|
@@ -72,7 +72,7 @@ function openClient(session) {
|
|
|
72
72
|
},
|
|
73
73
|
close,
|
|
74
74
|
connected: session.connected,
|
|
75
|
-
tx: (...args) => import("./
|
|
75
|
+
tx: (...args) => import("./k7cc9nzk.js").then((mod) => mod.tx(session, args)),
|
|
76
76
|
batch: (ops, options) => batchHandle(session, ops, options),
|
|
77
77
|
...session.tx?.extras
|
|
78
78
|
};
|
|
@@ -107,7 +107,7 @@ function tableApi(session, table, view, uses) {
|
|
|
107
107
|
const api = {
|
|
108
108
|
find(options = {}) {
|
|
109
109
|
if ("lock" in options) {
|
|
110
|
-
return lazyRead(session, () => import("./
|
|
110
|
+
return lazyRead(session, () => import("./dxjp14rk.js"), table, options, base, view);
|
|
111
111
|
}
|
|
112
112
|
return start(session, "find", table, options, base, view);
|
|
113
113
|
},
|
|
@@ -121,10 +121,10 @@ function tableApi(session, table, view, uses) {
|
|
|
121
121
|
return start(session, "exists", table, options, base, view);
|
|
122
122
|
},
|
|
123
123
|
page(options) {
|
|
124
|
-
return lazyRead(session, () => import("./
|
|
124
|
+
return lazyRead(session, () => import("./h4nqvjkp.js"), table, options, base, view);
|
|
125
125
|
},
|
|
126
126
|
aggregate(options = {}) {
|
|
127
|
-
return lazyRead(session, () => import("./
|
|
127
|
+
return lazyRead(session, () => import("./r6pj4fq2.js"), table, options, base, view);
|
|
128
128
|
},
|
|
129
129
|
insert(data, options = {}) {
|
|
130
130
|
return writeHandle(session, "insert", table, data, options, mods);
|
|
@@ -154,13 +154,13 @@ function tableApi(session, table, view, uses) {
|
|
|
154
154
|
return api;
|
|
155
155
|
}
|
|
156
156
|
function batchHandle(session, ops, options, replica) {
|
|
157
|
-
return queryHandle(() => import("./
|
|
157
|
+
return queryHandle(() => import("./xsq7v6wp.js").then((mod) => mod.batch(session, ops, options, replica)), {
|
|
158
158
|
replica: () => batchHandle(session, ops, options, true)
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
var writers;
|
|
162
162
|
function loadWrite() {
|
|
163
|
-
writers ??= import("./
|
|
163
|
+
writers ??= import("./p7pfx624.js");
|
|
164
164
|
return writers;
|
|
165
165
|
}
|
|
166
166
|
function queryHandle(run, extra) {
|
|
@@ -245,7 +245,7 @@ function lazyRead(session, load, table, options, mods, view) {
|
|
|
245
245
|
});
|
|
246
246
|
}
|
|
247
247
|
async function decodeRows(plan, rows, table) {
|
|
248
|
-
return plan.outputs.includes.length === 0 ? decodeResult(plan, rows, table) : (await import("./
|
|
248
|
+
return plan.outputs.includes.length === 0 ? decodeResult(plan, rows, table) : (await import("./h8ne16fq.js")).decodeIncluded(plan, rows, table);
|
|
249
249
|
}
|
|
250
250
|
function readHandle(session, table, call, mods, decode, extra) {
|
|
251
251
|
let prepared;
|
|
@@ -320,7 +320,7 @@ function readHandle(session, table, call, mods, decode, extra) {
|
|
|
320
320
|
}
|
|
321
321
|
function streamLazy(session, call, prepare) {
|
|
322
322
|
return async function* () {
|
|
323
|
-
const { streamRows } = await import("./
|
|
323
|
+
const { streamRows } = await import("./922qbgnw.js");
|
|
324
324
|
yield* streamRows(session, call, prepare, (error) => logged(session, error));
|
|
325
325
|
}();
|
|
326
326
|
}
|
|
@@ -357,7 +357,7 @@ function readCall(op, table, options, all, scope, model, schema, view) {
|
|
|
357
357
|
};
|
|
358
358
|
}
|
|
359
359
|
async function checkServer(pool, schema, http, requireMeta, options, source) {
|
|
360
|
-
const server = await import("./
|
|
360
|
+
const server = await import("./47xzb9fc.js");
|
|
361
361
|
let rows;
|
|
362
362
|
try {
|
|
363
363
|
const result = await pool.execute(server.versionQuery, undefined, options);
|
|
@@ -386,7 +386,7 @@ function errorFields(error) {
|
|
|
386
386
|
var includeHooks;
|
|
387
387
|
var operatorSql;
|
|
388
388
|
function loadOperatorSql() {
|
|
389
|
-
operatorSql ??= import("./
|
|
389
|
+
operatorSql ??= import("./tq9afp8d.js").then(() => {
|
|
390
390
|
return;
|
|
391
391
|
});
|
|
392
392
|
return operatorSql;
|
|
@@ -394,7 +394,7 @@ function loadOperatorSql() {
|
|
|
394
394
|
function hooksFor(call) {
|
|
395
395
|
if (call.include === undefined)
|
|
396
396
|
return Promise.resolve(undefined);
|
|
397
|
-
includeHooks ??= import("./
|
|
397
|
+
includeHooks ??= import("./h8ne16fq.js").then((mod) => mod.includeHooks);
|
|
398
398
|
return includeHooks;
|
|
399
399
|
}
|
|
400
400
|
function bindNow(schema, call) {
|
|
@@ -426,11 +426,13 @@ function attachHttp(http, error) {
|
|
|
426
426
|
}
|
|
427
427
|
function callOptions(input, statement) {
|
|
428
428
|
const timeout = input.timeout ?? statement;
|
|
429
|
-
|
|
429
|
+
const route = input.route;
|
|
430
|
+
if (input.signal === undefined && timeout === undefined && route === undefined)
|
|
430
431
|
return;
|
|
431
432
|
return {
|
|
432
433
|
...input.signal !== undefined ? { signal: input.signal } : {},
|
|
433
|
-
...timeout !== undefined ? { timeout } : {}
|
|
434
|
+
...timeout !== undefined ? { timeout } : {},
|
|
435
|
+
...route !== undefined ? { route } : {}
|
|
434
436
|
};
|
|
435
437
|
}
|
|
436
438
|
function mapOptions(http, includeValues) {
|
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open2
|
|
3
|
-
} from "./
|
|
4
|
-
import"./
|
|
3
|
+
} from "./wqem4jed.js";
|
|
4
|
+
import"./8bwbwy8h.js";
|
|
5
5
|
import"./n442h54c.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
CURRENT,
|
|
8
|
+
BEHIND_EXPAND,
|
|
9
|
+
BEHIND_CONTRACT,
|
|
10
|
+
AHEAD_EXPAND,
|
|
11
|
+
AHEAD_CONTRACT,
|
|
12
|
+
failedAt
|
|
13
|
+
} from "./9yn6a2vd.js";
|
|
14
|
+
import {
|
|
15
|
+
loadMigrations,
|
|
16
|
+
expandProvisioned,
|
|
17
|
+
provisionHistoryIsKnown
|
|
18
|
+
} from "./kdkxh3kb.js";
|
|
19
|
+
import"./szm0cksa.js";
|
|
20
|
+
import"./fancm5pt.js";
|
|
9
21
|
import {
|
|
10
22
|
assertTargetPolicy,
|
|
11
23
|
listTargets,
|
|
12
24
|
loadConfig
|
|
13
|
-
} from "./
|
|
14
|
-
import"./
|
|
25
|
+
} from "./xdpj5kkm.js";
|
|
26
|
+
import"./ayz64vzj.js";
|
|
27
|
+
import"./8xsbagad.js";
|
|
15
28
|
import {
|
|
16
29
|
OkmError2
|
|
17
30
|
} from "./52szzakm.js";
|
|
@@ -19,8 +32,8 @@ import {
|
|
|
19
32
|
// src/tooling/migrate/status.ts
|
|
20
33
|
import { join } from "node:path";
|
|
21
34
|
function describeStatus(migrations, history, recorded) {
|
|
22
|
-
const done = new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`));
|
|
23
35
|
const known = new Set(migrations.map((migration) => migration.id));
|
|
36
|
+
const done = expandProvisioned(migrations, new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`)), history.map((row) => row.migrationId));
|
|
24
37
|
for (const migration of migrations) {
|
|
25
38
|
let have = 0;
|
|
26
39
|
let missing = -1;
|
|
@@ -34,33 +47,33 @@ function describeStatus(migrations, history, recorded) {
|
|
|
34
47
|
return {
|
|
35
48
|
version: migration.id,
|
|
36
49
|
catalogHash: recorded?.hash ?? "-",
|
|
37
|
-
state:
|
|
50
|
+
state: failedAt(missing)
|
|
38
51
|
};
|
|
39
52
|
}
|
|
40
53
|
}
|
|
41
|
-
const extra = history.some((row) => !known.has(row.migrationId));
|
|
42
54
|
const pending = migrations.filter((migration) => migration.steps.some((_, index) => !done.has(`${migration.id}:${String(index)}`)));
|
|
43
55
|
const finished = lastComplete(migrations, done);
|
|
44
56
|
const version = recorded?.version ?? finished ?? "-";
|
|
45
57
|
const catalogHash = recorded?.hash ?? "-";
|
|
58
|
+
const extra = history.some((row) => !provisionHistoryIsKnown(row.migrationId, known));
|
|
46
59
|
if (extra)
|
|
47
|
-
return { version, catalogHash, state:
|
|
60
|
+
return { version, catalogHash, state: aheadState(history, known) };
|
|
48
61
|
if (pending.length > 0) {
|
|
49
62
|
const contract = pending.some((migration) => migration.steps.some((step) => step.class !== "expand"));
|
|
50
63
|
return {
|
|
51
64
|
version,
|
|
52
65
|
catalogHash,
|
|
53
|
-
state: contract ?
|
|
66
|
+
state: contract ? BEHIND_CONTRACT : BEHIND_EXPAND
|
|
54
67
|
};
|
|
55
68
|
}
|
|
56
69
|
const last = migrations.at(-1);
|
|
57
70
|
if (last !== undefined && recorded !== undefined && recorded.hash !== last.catalogHash) {
|
|
58
|
-
return { version, catalogHash, state:
|
|
71
|
+
return { version, catalogHash, state: aheadState(history, known) };
|
|
59
72
|
}
|
|
60
73
|
return {
|
|
61
74
|
version: recorded?.version ?? last?.id ?? "-",
|
|
62
75
|
catalogHash: recorded?.hash ?? last?.catalogHash ?? "-",
|
|
63
|
-
state:
|
|
76
|
+
state: CURRENT
|
|
64
77
|
};
|
|
65
78
|
}
|
|
66
79
|
async function readTargetStatus(input) {
|
|
@@ -82,7 +95,8 @@ async function readTargetStatus(input) {
|
|
|
82
95
|
version: described.version,
|
|
83
96
|
catalogHash: described.catalogHash,
|
|
84
97
|
state: described.state,
|
|
85
|
-
protected: input.protected
|
|
98
|
+
protected: input.protected,
|
|
99
|
+
backfills: await readBackfills(pool)
|
|
86
100
|
};
|
|
87
101
|
} finally {
|
|
88
102
|
await pool.close();
|
|
@@ -105,8 +119,17 @@ async function statusProject(cwd, flags) {
|
|
|
105
119
|
}
|
|
106
120
|
function formatStatus(rows) {
|
|
107
121
|
const lines = ["target\tversion\tcatalog\tstate\tprotected"];
|
|
122
|
+
const backfills = [];
|
|
108
123
|
for (const row of rows) {
|
|
109
124
|
lines.push([row.target, row.version, row.catalogHash, row.state, row.protected ? "true" : "false"].join("\t"));
|
|
125
|
+
backfills.push(...row.backfills);
|
|
126
|
+
}
|
|
127
|
+
if (backfills.length > 0) {
|
|
128
|
+
lines.push("backfill");
|
|
129
|
+
lines.push("migration\tstep\trows\tkey\tstate");
|
|
130
|
+
for (const item of backfills) {
|
|
131
|
+
lines.push([item.migrationId, String(item.stepIndex), item.rows, item.lastKey, item.state].join("\t"));
|
|
132
|
+
}
|
|
110
133
|
}
|
|
111
134
|
return `${lines.join(`
|
|
112
135
|
`)}
|
|
@@ -160,7 +183,33 @@ async function readHistory(pool) {
|
|
|
160
183
|
rows.push({
|
|
161
184
|
migrationId,
|
|
162
185
|
stepIndex: Number(step),
|
|
163
|
-
class: stepClass
|
|
186
|
+
class: storedClass(stepClass)
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return rows;
|
|
190
|
+
}
|
|
191
|
+
async function readBackfills(pool) {
|
|
192
|
+
const present = await pool.execute("select to_regclass('okm_backfill') is not null");
|
|
193
|
+
if (!wireTrue(present.rows[0]?.[0] ?? null))
|
|
194
|
+
return [];
|
|
195
|
+
const result = await pool.execute(`select migration_id, step_index::text, rows_touched::text, last_key, state
|
|
196
|
+
from okm_backfill
|
|
197
|
+
where state <> 'done'
|
|
198
|
+
order by migration_id, step_index`);
|
|
199
|
+
const rows = [];
|
|
200
|
+
for (const row of result.rows) {
|
|
201
|
+
const migrationId = row[0];
|
|
202
|
+
const step = row[1];
|
|
203
|
+
const touched = row[2];
|
|
204
|
+
const state = row[4];
|
|
205
|
+
if (migrationId == null || step == null || touched == null || state == null)
|
|
206
|
+
continue;
|
|
207
|
+
rows.push({
|
|
208
|
+
migrationId,
|
|
209
|
+
stepIndex: Number(step),
|
|
210
|
+
rows: touched,
|
|
211
|
+
lastKey: row[3] ?? "-",
|
|
212
|
+
state
|
|
164
213
|
});
|
|
165
214
|
}
|
|
166
215
|
return rows;
|
|
@@ -168,6 +217,26 @@ async function readHistory(pool) {
|
|
|
168
217
|
function wireTrue(value) {
|
|
169
218
|
return value === "t" || value === "true";
|
|
170
219
|
}
|
|
220
|
+
function aheadState(history, known) {
|
|
221
|
+
let sawExtra = false;
|
|
222
|
+
let expandOnly = true;
|
|
223
|
+
for (const row of history) {
|
|
224
|
+
if (known.has(row.migrationId))
|
|
225
|
+
continue;
|
|
226
|
+
sawExtra = true;
|
|
227
|
+
if (row.class !== "expand")
|
|
228
|
+
expandOnly = false;
|
|
229
|
+
}
|
|
230
|
+
if (!sawExtra) {
|
|
231
|
+
expandOnly = history.length > 0 && history.every((row) => row.class === "expand");
|
|
232
|
+
}
|
|
233
|
+
return expandOnly ? AHEAD_EXPAND : AHEAD_CONTRACT;
|
|
234
|
+
}
|
|
235
|
+
function storedClass(value) {
|
|
236
|
+
if (value === "expand" || value === "contract" || value === "unclassified")
|
|
237
|
+
return value;
|
|
238
|
+
return "unclassified";
|
|
239
|
+
}
|
|
171
240
|
export {
|
|
172
241
|
statusProject
|
|
173
242
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
runWrite
|
|
3
|
-
} from "./n4jqhpqz.js";
|
|
4
1
|
import {
|
|
5
2
|
stack
|
|
6
3
|
} from "./672t5vym.js";
|
|
4
|
+
import {
|
|
5
|
+
runWrite
|
|
6
|
+
} from "./n4jqhpqz.js";
|
|
7
7
|
import {
|
|
8
8
|
withRowFilters,
|
|
9
9
|
archiveRules,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
isRecord,
|
|
15
15
|
registerFailFix,
|
|
16
16
|
fail
|
|
17
|
-
} from "./
|
|
17
|
+
} from "./qgvt8nx1.js";
|
|
18
18
|
import {
|
|
19
19
|
safetyInstalled,
|
|
20
20
|
runSafety
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
readHandle,
|
|
4
4
|
readCall,
|
|
5
5
|
attachHttp
|
|
6
|
-
} from "./
|
|
6
|
+
} from "./bt9sfq0z.js";
|
|
7
7
|
import {
|
|
8
8
|
fail
|
|
9
|
-
} from "./
|
|
9
|
+
} from "./qgvt8nx1.js";
|
|
10
10
|
import {
|
|
11
11
|
OkmError2,
|
|
12
12
|
throwNamed2
|
|
@@ -27,6 +27,14 @@ function build(session, table, options, mods, view) {
|
|
|
27
27
|
}
|
|
28
28
|
function plan(session, table, options, mods, view) {
|
|
29
29
|
const { lock, wait, ...rest } = options;
|
|
30
|
+
const forced = session.pool.forcedRoute;
|
|
31
|
+
if (rest.route === "replica" || forced === "replica") {
|
|
32
|
+
throw new OkmError2("OKM1840", "A locking read needs the primary.", {
|
|
33
|
+
fix: {
|
|
34
|
+
summary: "Run the operation on the primary. Writes, batch, locks, and tx() never go to a replica."
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
30
38
|
if (session.tx === undefined) {
|
|
31
39
|
throw new OkmError2("OKM1830", "A row lock needs a transaction. find was called outside tx().", {
|
|
32
40
|
fix: { summary: "Move the find into tx(): the lock lasts until the transaction ends." }
|
|
@@ -2,13 +2,10 @@ import {
|
|
|
2
2
|
roleObject,
|
|
3
3
|
grantObject,
|
|
4
4
|
defaultPrivilegeObject
|
|
5
|
-
} from "./
|
|
6
|
-
import {
|
|
7
|
-
planMigration
|
|
8
|
-
} from "./2ssqrv66.js";
|
|
5
|
+
} from "./8bwbwy8h.js";
|
|
9
6
|
import {
|
|
10
7
|
quoteIdent
|
|
11
|
-
} from "./
|
|
8
|
+
} from "./8xsbagad.js";
|
|
12
9
|
import {
|
|
13
10
|
functionObject,
|
|
14
11
|
triggerObject
|
|
@@ -21,14 +18,12 @@ import {
|
|
|
21
18
|
} from "./y005b761.js";
|
|
22
19
|
import {
|
|
23
20
|
extensionObject
|
|
24
|
-
} from "./
|
|
25
|
-
import {
|
|
26
|
-
catalog
|
|
27
|
-
} from "./jkc6ws1p.js";
|
|
21
|
+
} from "./8ktwd3rh.js";
|
|
28
22
|
import {
|
|
23
|
+
catalog,
|
|
29
24
|
enumType,
|
|
30
25
|
domainType
|
|
31
|
-
} from "./
|
|
26
|
+
} from "./g7ez901n.js";
|
|
32
27
|
import {
|
|
33
28
|
staticNamespace2,
|
|
34
29
|
identityKey2,
|
|
@@ -41,12 +36,6 @@ import {
|
|
|
41
36
|
import {
|
|
42
37
|
referentialAction
|
|
43
38
|
} from "./4e4c6vq2.js";
|
|
44
|
-
import {
|
|
45
|
-
OkmError2
|
|
46
|
-
} from "./52szzakm.js";
|
|
47
|
-
|
|
48
|
-
// src/tooling/migrate/drift.ts
|
|
49
|
-
import postgres from "postgres";
|
|
50
39
|
|
|
51
40
|
// src/dialects/pg/view/depend.ts
|
|
52
41
|
function cellText(value) {
|
|
@@ -252,6 +241,7 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
|
|
|
252
241
|
const parent = parents.get(parentName) ?? { namespace, name: parentName };
|
|
253
242
|
const kind = constraintKind(text(row, "contype"));
|
|
254
243
|
const columns = list(text(row, "columns"));
|
|
244
|
+
const name = text(row, "name");
|
|
255
245
|
const expression = kind === "check" ? checkExpression(text(row, "definition")) : "";
|
|
256
246
|
const refTable = text(row, "ref_table");
|
|
257
247
|
const refColumns = list(text(row, "ref_columns"));
|
|
@@ -261,8 +251,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
|
|
|
261
251
|
objects.push(constraint2({
|
|
262
252
|
parent,
|
|
263
253
|
constraintKind: kind,
|
|
264
|
-
name
|
|
265
|
-
nameKey: kind
|
|
254
|
+
name,
|
|
255
|
+
nameKey: constraintNameKey(kind, parentName, name, columns),
|
|
266
256
|
columns,
|
|
267
257
|
provenance,
|
|
268
258
|
deferrable: flag(row, "deferrable"),
|
|
@@ -446,8 +436,9 @@ var RELATION_GRANTS = `select c.relname as name,
|
|
|
446
436
|
select 1 from pg_depend d
|
|
447
437
|
where d.classid = 'pg_class'::regclass and d.objid = c.oid and d.deptype = 'e'
|
|
448
438
|
)`;
|
|
439
|
+
var FUNCTION_ARG_TYPES = "replace(oidvectortypes(p.proargtypes), ' ', '')";
|
|
449
440
|
var FUNCTION_GRANTS = `select p.proname as name,
|
|
450
|
-
|
|
441
|
+
${FUNCTION_ARG_TYPES} as args,
|
|
451
442
|
r.rolname as role, a.privilege_type as privilege
|
|
452
443
|
from pg_proc p
|
|
453
444
|
join pg_namespace n on n.oid = p.pronamespace
|
|
@@ -861,6 +852,19 @@ function partitionMethod(value) {
|
|
|
861
852
|
return "hash";
|
|
862
853
|
return;
|
|
863
854
|
}
|
|
855
|
+
function constraintNameKey(kind, parent, name, columns) {
|
|
856
|
+
if (kind === "primaryKey")
|
|
857
|
+
return "pkey";
|
|
858
|
+
const tag = kind === "unique" ? "key" : kind === "foreignKey" ? "fkey" : "check";
|
|
859
|
+
const prefix = `${parent}_`;
|
|
860
|
+
const suffix = `_${tag}`;
|
|
861
|
+
if (name.startsWith(prefix) && name.endsWith(suffix) && name.length > prefix.length + suffix.length) {
|
|
862
|
+
return name.slice(prefix.length, -suffix.length);
|
|
863
|
+
}
|
|
864
|
+
if (columns.length > 0)
|
|
865
|
+
return columns.join("_");
|
|
866
|
+
return tag;
|
|
867
|
+
}
|
|
864
868
|
function constraintKind(value) {
|
|
865
869
|
if (value === "p")
|
|
866
870
|
return "primaryKey";
|
|
@@ -910,213 +914,4 @@ function flag(row, key) {
|
|
|
910
914
|
return value === true || value === "true" || value === "t";
|
|
911
915
|
}
|
|
912
916
|
|
|
913
|
-
|
|
914
|
-
var SCRATCH = "okm_view_seal";
|
|
915
|
-
var VIEW_SHAPE = `
|
|
916
|
-
select c.relname as name, c.relkind as kind, pg_get_viewdef(c.oid, true) as query,
|
|
917
|
-
(
|
|
918
|
-
select coalesce(string_agg(
|
|
919
|
-
a.attname || '|' || format_type(a.atttypid, a.atttypmod),
|
|
920
|
-
E'\\n' order by a.attnum
|
|
921
|
-
), '')
|
|
922
|
-
from pg_attribute a
|
|
923
|
-
where a.attrelid = c.oid and a.attnum > 0 and not a.attisdropped
|
|
924
|
-
) as columns
|
|
925
|
-
from pg_class c
|
|
926
|
-
join pg_namespace n on n.oid = c.relnamespace
|
|
927
|
-
where n.nspname = $1 and c.relkind in ('v', 'm')
|
|
928
|
-
`;
|
|
929
|
-
async function sealViews(runner, source) {
|
|
930
|
-
const views = source.objects.filter((object) => object.kind === "view" || object.kind === "materializedView");
|
|
931
|
-
if (views.length === 0)
|
|
932
|
-
return source;
|
|
933
|
-
await dropScratch(runner);
|
|
934
|
-
await runner.query(`create schema ${quoteIdent(SCRATCH)}`);
|
|
935
|
-
try {
|
|
936
|
-
await runner.query(`set search_path to ${quoteIdent(SCRATCH)}`);
|
|
937
|
-
for (const object of source.objects) {
|
|
938
|
-
if (object.kind !== "table")
|
|
939
|
-
continue;
|
|
940
|
-
await runner.query(stubTable(object, source));
|
|
941
|
-
}
|
|
942
|
-
await createViews(runner, views);
|
|
943
|
-
const shapes = await runner.query(VIEW_SHAPE, [SCRATCH]);
|
|
944
|
-
const deps = await runner.query(VIEW_DEPENDENCIES, [SCRATCH]);
|
|
945
|
-
const edges = viewDependencyEdges(deps, PUBLIC, source.objects);
|
|
946
|
-
const byName = new Map(shapes.map((row) => [cellText(row.name), row]));
|
|
947
|
-
const next = source.objects.map((object) => {
|
|
948
|
-
if (object.kind !== "view" && object.kind !== "materializedView")
|
|
949
|
-
return object;
|
|
950
|
-
const row = byName.get(object.identity.name);
|
|
951
|
-
if (row === undefined) {
|
|
952
|
-
throw new OkmError2("OKM1020", `View ${object.identity.name} was not created in the scratch schema.`, {
|
|
953
|
-
fix: { summary: "The query has to run against the tables in this schema." }
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
const columns = readColumns(object, cellText(row.columns));
|
|
957
|
-
const query = normaliseViewQuery(cellText(row.query));
|
|
958
|
-
const dependencies = edges.get(object.identity.name) ?? [];
|
|
959
|
-
if (object.kind === "view") {
|
|
960
|
-
return viewObject({
|
|
961
|
-
namespace: object.identity.namespace,
|
|
962
|
-
name: object.identity.name,
|
|
963
|
-
columns,
|
|
964
|
-
query,
|
|
965
|
-
owner: object.owner,
|
|
966
|
-
provenance: object.provenance,
|
|
967
|
-
dependencies
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
return materializedViewObject({
|
|
971
|
-
namespace: object.identity.namespace,
|
|
972
|
-
name: object.identity.name,
|
|
973
|
-
columns,
|
|
974
|
-
query,
|
|
975
|
-
owner: object.owner,
|
|
976
|
-
provenance: object.provenance,
|
|
977
|
-
dependencies,
|
|
978
|
-
...object.definition.refresh !== undefined ? { refresh: object.definition.refresh } : {}
|
|
979
|
-
});
|
|
980
|
-
});
|
|
981
|
-
return catalog(next);
|
|
982
|
-
} finally {
|
|
983
|
-
await runner.query("set search_path to public");
|
|
984
|
-
await dropScratch(runner);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
async function createViews(runner, views) {
|
|
988
|
-
const pending = [...views];
|
|
989
|
-
let last = "";
|
|
990
|
-
for (let pass = 0;pass < views.length && pending.length > 0; pass += 1) {
|
|
991
|
-
const failed = [];
|
|
992
|
-
let created = 0;
|
|
993
|
-
for (const object of pending) {
|
|
994
|
-
const sql = object.kind === "materializedView" ? `create materialized view ${quoteIdent(object.identity.name)} as ${object.definition.query} with no data` : `create view ${quoteIdent(object.identity.name)} as ${object.definition.query}`;
|
|
995
|
-
try {
|
|
996
|
-
await runner.query(sql);
|
|
997
|
-
created += 1;
|
|
998
|
-
} catch (error) {
|
|
999
|
-
last = error instanceof Error ? error.message : String(error);
|
|
1000
|
-
failed.push(object);
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
if (created === 0) {
|
|
1004
|
-
throw new OkmError2("OKM1020", `View ${failed[0]?.identity.name ?? ""} could not be created. ${last}`, {
|
|
1005
|
-
fix: { summary: "The query has to run against the tables in this schema." }
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
pending.length = 0;
|
|
1009
|
-
pending.push(...failed);
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
function stubTable(object, source) {
|
|
1013
|
-
const columns = source.objects.filter((item) => item.kind === "column" && item.identity.parent.name === object.identity.name);
|
|
1014
|
-
const lines = columns.map((column) => `${quoteIdent(column.identity.name)} ${column.definition.dataType}`);
|
|
1015
|
-
return `create table ${quoteIdent(object.identity.name)} (${lines.join(", ")})`;
|
|
1016
|
-
}
|
|
1017
|
-
function readColumns(object, printed) {
|
|
1018
|
-
const live = printed.length === 0 ? [] : printed.split(`
|
|
1019
|
-
`);
|
|
1020
|
-
const declared = object.definition.columns;
|
|
1021
|
-
if (live.length !== declared.length) {
|
|
1022
|
-
throw mismatch(object.identity.name, declared.map((column) => column.name).join(", "), printed);
|
|
1023
|
-
}
|
|
1024
|
-
return declared.map((column, index) => {
|
|
1025
|
-
const line = live[index] ?? "";
|
|
1026
|
-
const splitAt = line.indexOf("|");
|
|
1027
|
-
const name = splitAt < 0 ? line : line.slice(0, splitAt);
|
|
1028
|
-
const type = splitAt < 0 ? "" : line.slice(splitAt + 1);
|
|
1029
|
-
if (name !== column.name || type !== column.dataType) {
|
|
1030
|
-
throw mismatch(object.identity.name, `${column.name}:${column.dataType}`, live[index] ?? "");
|
|
1031
|
-
}
|
|
1032
|
-
return column;
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
function mismatch(view, declared, live) {
|
|
1036
|
-
return new OkmError2("OKM1020", `View ${view} declares ${declared} and the database has ${live}.`, { fix: { summary: "Declare the columns the query returns, in that order, with those types." } });
|
|
1037
|
-
}
|
|
1038
|
-
async function dropScratch(runner) {
|
|
1039
|
-
const present = await runner.query(`select 1 as ok from pg_namespace where nspname = $1`, [
|
|
1040
|
-
SCRATCH
|
|
1041
|
-
]);
|
|
1042
|
-
if (present.length === 0)
|
|
1043
|
-
return;
|
|
1044
|
-
const rows = await runner.query(`
|
|
1045
|
-
select c.relname as name, c.relkind as kind
|
|
1046
|
-
from pg_class c
|
|
1047
|
-
join pg_namespace n on n.oid = c.relnamespace
|
|
1048
|
-
where n.nspname = $1 and c.relkind in ('v', 'm', 'r')
|
|
1049
|
-
`, [SCRATCH]);
|
|
1050
|
-
const views = rows.filter((row) => cellText(row.kind) === "v" || cellText(row.kind) === "m");
|
|
1051
|
-
for (let pass = 0;pass < Math.max(views.length, 1); pass += 1) {
|
|
1052
|
-
for (const row of views) {
|
|
1053
|
-
const kind = cellText(row.kind) === "m" ? "materialized view" : "view";
|
|
1054
|
-
try {
|
|
1055
|
-
await runner.query(`drop ${kind} if exists ${quoteIdent(SCRATCH)}.${quoteIdent(cellText(row.name))}`);
|
|
1056
|
-
} catch {}
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
for (const row of rows) {
|
|
1060
|
-
if (cellText(row.kind) !== "r")
|
|
1061
|
-
continue;
|
|
1062
|
-
await runner.query(`drop table if exists ${quoteIdent(SCRATCH)}.${quoteIdent(cellText(row.name))}`);
|
|
1063
|
-
}
|
|
1064
|
-
await runner.query(`drop schema if exists ${quoteIdent(SCRATCH)}`);
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
// src/tooling/migrate/drift.ts
|
|
1068
|
-
async function assertAuthorDrift(url, author, roles) {
|
|
1069
|
-
const sql = postgres(url, {
|
|
1070
|
-
max: 1,
|
|
1071
|
-
connect_timeout: 5,
|
|
1072
|
-
idle_timeout: 1,
|
|
1073
|
-
onnotice: () => {}
|
|
1074
|
-
});
|
|
1075
|
-
try {
|
|
1076
|
-
const present = await sql`
|
|
1077
|
-
select to_regclass('public.okm_meta')::text as reg
|
|
1078
|
-
`;
|
|
1079
|
-
if (present[0]?.reg == null)
|
|
1080
|
-
return;
|
|
1081
|
-
const runner = queryOf(sql);
|
|
1082
|
-
const managed = managedRoleNames(roles);
|
|
1083
|
-
const authorOnServer = await sealViews(runner, author);
|
|
1084
|
-
const live = await introspectSchema(runner, "public", "public", managed === undefined ? undefined : { managedRoles: managed });
|
|
1085
|
-
const plan = planMigration({ before: live, after: authorOnServer, name: "check" });
|
|
1086
|
-
if (plan.steps.length === 0)
|
|
1087
|
-
return;
|
|
1088
|
-
throw new OkmError2("OKM1520", `The database differs from the schema.
|
|
1089
|
-
${plan.steps.map((step) => step.sql).join(`
|
|
1090
|
-
`)}`, {
|
|
1091
|
-
fix: {
|
|
1092
|
-
summary: "Change the schema or the database so okm check reports no difference."
|
|
1093
|
-
}
|
|
1094
|
-
});
|
|
1095
|
-
} finally {
|
|
1096
|
-
await sql.end({ timeout: 5 });
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
function managedRoleNames(roles) {
|
|
1100
|
-
if (roles === undefined)
|
|
1101
|
-
return;
|
|
1102
|
-
const names = new Set([roles.migration, roles.app]);
|
|
1103
|
-
for (const role of roles.managed ?? [])
|
|
1104
|
-
names.add(role.name);
|
|
1105
|
-
return [...names];
|
|
1106
|
-
}
|
|
1107
|
-
function queryOf(sql) {
|
|
1108
|
-
return {
|
|
1109
|
-
async query(text, params) {
|
|
1110
|
-
const rows = await sql.unsafe(text, params === undefined ? undefined : [...params]);
|
|
1111
|
-
return rows.map((row) => {
|
|
1112
|
-
const copy = {};
|
|
1113
|
-
for (const [key, value] of Object.entries(row))
|
|
1114
|
-
copy[key] = value;
|
|
1115
|
-
return copy;
|
|
1116
|
-
});
|
|
1117
|
-
}
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
export {
|
|
1121
|
-
assertAuthorDrift
|
|
1122
|
-
};
|
|
917
|
+
export { cellText, VIEW_DEPENDENCIES, viewDependencyEdges, PUBLIC, introspectSchema, FUNCTION_ARG_TYPES };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
send,
|
|
3
3
|
connectClient
|
|
4
|
-
} from "./
|
|
4
|
+
} from "./6p5k20sm.js";
|
|
5
5
|
import {
|
|
6
6
|
isConnectionLost
|
|
7
7
|
} from "./tbszx8mz.js";
|
|
8
8
|
import {
|
|
9
9
|
WireSession
|
|
10
|
-
} from "./
|
|
10
|
+
} from "./zvbjc949.js";
|
|
11
11
|
import {
|
|
12
12
|
rejectClosed,
|
|
13
13
|
runCall
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import"./
|
|
1
|
+
import"./8bwbwy8h.js";
|
|
2
2
|
import"./n442h54c.js";
|
|
3
|
+
import"./wqem4jed.js";
|
|
3
4
|
import {
|
|
4
5
|
listTargets,
|
|
5
6
|
loadConfig
|
|
6
|
-
} from "./
|
|
7
|
-
import"./
|
|
7
|
+
} from "./xdpj5kkm.js";
|
|
8
|
+
import"./ayz64vzj.js";
|
|
9
|
+
import"./8xsbagad.js";
|
|
8
10
|
|
|
9
11
|
// src/tooling/migrate/dev.ts
|
|
10
12
|
import { mkdirSync } from "node:fs";
|
|
@@ -17,7 +19,7 @@ async function devProject(cwd) {
|
|
|
17
19
|
`;
|
|
18
20
|
const directory = join(cwd, config.out ?? ".okm", "dev-db");
|
|
19
21
|
mkdirSync(directory, { recursive: true });
|
|
20
|
-
const { open } = await import("./
|
|
22
|
+
const { open } = await import("./gdh9mrtp.js");
|
|
21
23
|
const pool = await open({ dataDir: directory });
|
|
22
24
|
try {
|
|
23
25
|
await pool.execute("select 1");
|