okmodel 0.3.0 → 0.4.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 +182 -22
- package/dist/contracts/catalog/document.d.ts +6 -2
- 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/role/sql.d.ts +11 -4
- package/dist/dialects/pg/table.d.ts +17 -1
- package/dist/dialects/pg/view/index.js +1 -1
- package/dist/dialects/pg/view/scratch.d.ts +3 -2
- 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.js +2 -2
- package/dist/runtime/pg/pg.js +2 -2
- package/dist/runtime/pg/pglite.js +2 -2
- package/dist/runtime/pg/postgresjs.js +2 -2
- package/dist/runtime/traits/index.js +5 -4
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/validate/index.js +2 -2
- package/dist/shared/2321avmn.js +418 -0
- package/dist/shared/{x6wysh83.js → 3p4b1fg0.js} +3 -5
- package/dist/shared/{wekze34d.js → 41kv2xdm.js} +74 -2
- package/dist/shared/{fs0ex00p.js → 4ef7mmqf.js} +2 -2
- package/dist/shared/5mtf6cj3.js +94 -0
- package/dist/shared/{999ade2q.js → 5vdm4sgp.js} +1 -1
- package/dist/shared/{qybh48nd.js → 6693j9rs.js} +1 -1
- package/dist/shared/{bqha5cg6.js → 6p5k20sm.js} +2 -2
- package/dist/shared/7nk68fj8.js +751 -0
- package/dist/shared/{ne02ng5c.js → 84ptn35q.js} +7 -4
- package/dist/shared/{t616ynfn.js → 8jb4ymh2.js} +59 -12
- package/dist/shared/{th14ygv2.js → 8ktwd3rh.js} +29 -1
- package/dist/shared/9yn6a2vd.js +11 -0
- package/dist/shared/ady1ms74.js +72 -0
- package/dist/shared/{scwxrpx2.js → c5g81ngb.js} +82 -15
- package/dist/shared/{6bazvqwm.js → fb00y8fp.js} +2 -2
- package/dist/shared/{jkc6ws1p.js → g7ez901n.js} +83 -2
- package/dist/shared/{kgnc8grt.js → gdh9mrtp.js} +1 -1
- package/dist/shared/hqjsxnz7.js +13 -0
- package/dist/shared/htnaj77v.js +17 -0
- package/dist/shared/{mt5wswjz.js → jgxzjzcz.js} +1 -1
- package/dist/shared/{6w5j844a.js → jsd07prz.js} +2 -2
- package/dist/shared/{m78s7898.js → kafaa5zv.js} +1 -1
- package/dist/shared/kj680nxv.js +19 -0
- package/dist/shared/{k34e0xf2.js → kkzwp3d2.js} +8 -8
- package/dist/shared/{2ssqrv66.js → n5y9zyj1.js} +1029 -174
- package/dist/shared/{ty3v3hfk.js → nxb42q7h.js} +2 -2
- package/dist/shared/{5nmdenb6.js → q6zsyh31.js} +1003 -40
- package/dist/shared/{fptpmvxp.js → q795afwa.js} +26 -21
- package/dist/shared/{3ekj9x92.js → qn0srwwq.js} +1 -1
- package/dist/shared/s4mb6a4b.js +545 -0
- package/dist/shared/{01yr20s5.js → sf8m6tfy.js} +2 -2
- package/dist/shared/{bryqk9k9.js → sr5ms7b3.js} +1 -1
- package/dist/shared/{meck53jv.js → tny2t3sm.js} +6 -5
- package/dist/shared/{p24x2334.js → v7tpnhnz.js} +1 -1
- package/dist/shared/{xw1d69vd.js → wqem4jed.js} +6 -6
- package/dist/shared/{49ypnfwt.js → xghkt7a9.js} +50 -28
- package/dist/shared/{7fvtrkwr.js → ycatkxmq.js} +1 -1
- package/dist/shared/ygem90rn.js +900 -0
- package/dist/shared/{1tfdfvhh.js → yjw02enp.js} +6 -4
- package/dist/shared/{ydaz1sv3.js → zg24x0hm.js} +1 -1
- package/dist/tooling/cli.js +46 -17
- package/dist/tooling/migrate/apply.d.ts +59 -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 +12 -0
- package/dist/tooling/migrate/index.d.ts +3 -2
- package/dist/tooling/migrate/index.js +67 -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 +72 -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/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/{xva8v7qk.js → awrsqrn7.js} +3 -3
- package/dist/shared/{75xkjv0t.js → fa9vt245.js} +0 -0
- package/dist/shared/{m9tv7xn7.js → radd3z4g.js} +3 -3
- /package/dist/shared/{0jc3ffzf.js → zvbjc949.js} +0 -0
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open2
|
|
3
|
-
} from "./
|
|
3
|
+
} from "./wqem4jed.js";
|
|
4
4
|
import"./n442h54c.js";
|
|
5
|
-
import"./
|
|
5
|
+
import"./8jb4ymh2.js";
|
|
6
6
|
import {
|
|
7
7
|
assertRoleHealth
|
|
8
8
|
} from "./hcmdtwgh.js";
|
|
9
9
|
import {
|
|
10
10
|
errorDoc,
|
|
11
|
+
assertTargetPolicy,
|
|
11
12
|
selectTarget,
|
|
12
13
|
openProject
|
|
13
|
-
} from "./
|
|
14
|
+
} from "./q6zsyh31.js";
|
|
14
15
|
import {
|
|
15
16
|
omitManagedObjects
|
|
16
|
-
} from "./
|
|
17
|
+
} from "./n5y9zyj1.js";
|
|
18
|
+
import"./41kv2xdm.js";
|
|
17
19
|
import {
|
|
18
20
|
OkmError2
|
|
19
21
|
} from "./52szzakm.js";
|
|
@@ -36,6 +38,7 @@ ${doc.fix}
|
|
|
36
38
|
const objects = omitManagedObjects(opened.built.catalog).objects;
|
|
37
39
|
if (opened.config.roles !== undefined) {
|
|
38
40
|
const target = selectTarget(opened.config, flags?.target);
|
|
41
|
+
assertTargetPolicy(target, "check", flags?.allowProtected ?? false);
|
|
39
42
|
const pool = open2({ url: target.url, max: 1 });
|
|
40
43
|
try {
|
|
41
44
|
await assertRoleHealth(pool, opened.config.roles, objects);
|
|
@@ -9,16 +9,14 @@ import {
|
|
|
9
9
|
} from "./y005b761.js";
|
|
10
10
|
import {
|
|
11
11
|
extensionObject
|
|
12
|
-
} from "./
|
|
12
|
+
} from "./8ktwd3rh.js";
|
|
13
13
|
import {
|
|
14
14
|
dependencyOrder,
|
|
15
|
-
catalog
|
|
16
|
-
} from "./jkc6ws1p.js";
|
|
17
|
-
import {
|
|
15
|
+
catalog,
|
|
18
16
|
enumType,
|
|
19
17
|
domainType,
|
|
20
18
|
isDomain
|
|
21
|
-
} from "./
|
|
19
|
+
} from "./g7ez901n.js";
|
|
22
20
|
import {
|
|
23
21
|
canonicalJson,
|
|
24
22
|
staticNamespace2,
|
|
@@ -46,7 +44,8 @@ import {
|
|
|
46
44
|
} from "./4e4c6vq2.js";
|
|
47
45
|
import {
|
|
48
46
|
sha2562,
|
|
49
|
-
assertIdentifier2
|
|
47
|
+
assertIdentifier2,
|
|
48
|
+
fitIdentifier2
|
|
50
49
|
} from "./nfzc5z0w.js";
|
|
51
50
|
import {
|
|
52
51
|
catalogError2
|
|
@@ -201,7 +200,7 @@ function renameTable2(source, change) {
|
|
|
201
200
|
if (!found) {
|
|
202
201
|
catalogError2("OKM1020", `Table ${change.from} is not in the catalog.`);
|
|
203
202
|
}
|
|
204
|
-
const next = source.objects.map((object) => rewriteTableName(object, change, fromKey, toIdentity));
|
|
203
|
+
const next = source.objects.map((object) => rewriteTableName(object, change, fromKey, toIdentity, source));
|
|
205
204
|
return catalog(next);
|
|
206
205
|
}
|
|
207
206
|
var serializedText = new WeakMap;
|
|
@@ -473,8 +472,8 @@ function rewriteExpr(text, change, active) {
|
|
|
473
472
|
return text;
|
|
474
473
|
return replaceIdentifier(text, change.from, change.to);
|
|
475
474
|
}
|
|
476
|
-
function rewriteTableName(object, change, fromKey, toIdentity) {
|
|
477
|
-
const dependencies = retarget(object.dependencies, fromKey, toIdentity);
|
|
475
|
+
function rewriteTableName(object, change, fromKey, toIdentity, source) {
|
|
476
|
+
const dependencies = retarget(object.dependencies, fromKey, toIdentity, change);
|
|
478
477
|
const named = object.kind === "table" && object.identity.name === change.from && sameNamespace2(object.identity.namespace, change.namespace);
|
|
479
478
|
if (object.kind === "table") {
|
|
480
479
|
return table3({
|
|
@@ -579,9 +578,19 @@ function rewriteTableName(object, change, fromKey, toIdentity) {
|
|
|
579
578
|
});
|
|
580
579
|
return rewriteView(object, dependencies, rewriteExpr(object.definition.query, { from: change.from, to: change.to }, local));
|
|
581
580
|
}
|
|
582
|
-
if (object.kind === "role" || object.kind === "
|
|
581
|
+
if (object.kind === "role" || object.kind === "defaultPrivilege") {
|
|
583
582
|
return retargeted(object, dependencies);
|
|
584
583
|
}
|
|
584
|
+
if (object.kind === "grant") {
|
|
585
|
+
return grantObject({
|
|
586
|
+
role: object.identity.role,
|
|
587
|
+
object: movedGrantRef(object.identity.object, change, source),
|
|
588
|
+
privilege: object.identity.privilege,
|
|
589
|
+
owner: object.owner,
|
|
590
|
+
provenance: object.provenance,
|
|
591
|
+
dependencies
|
|
592
|
+
});
|
|
593
|
+
}
|
|
585
594
|
if (object.kind === "trigger") {
|
|
586
595
|
const parent = movedParent(object.identity.parent, change);
|
|
587
596
|
const local = parent.name !== object.identity.parent.name;
|
|
@@ -644,8 +653,46 @@ function rewriteSequence(object, dependencies) {
|
|
|
644
653
|
function renameList(names, from, to) {
|
|
645
654
|
return names.map((name) => name === from ? to : name);
|
|
646
655
|
}
|
|
647
|
-
function retarget(edges, fromKey, to) {
|
|
648
|
-
return edges.map((edge) =>
|
|
656
|
+
function retarget(edges, fromKey, to, change) {
|
|
657
|
+
return edges.map((edge) => {
|
|
658
|
+
if (identityKey2(edge.target) === fromKey)
|
|
659
|
+
return to;
|
|
660
|
+
if (change === undefined)
|
|
661
|
+
return edge.target;
|
|
662
|
+
return movedChild(edge.target, change);
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
function movedChild(target, change) {
|
|
666
|
+
if (!("parent" in target))
|
|
667
|
+
return target;
|
|
668
|
+
if (target.parent.name !== change.from || !sameNamespace2(target.parent.namespace, change.namespace)) {
|
|
669
|
+
return target;
|
|
670
|
+
}
|
|
671
|
+
return { ...target, parent: { namespace: target.parent.namespace, name: change.to } };
|
|
672
|
+
}
|
|
673
|
+
function movedGrantRef(object, change, source) {
|
|
674
|
+
if (object.kind === "table" && object.name === change.from && sameNamespace2(object.namespace, change.namespace)) {
|
|
675
|
+
return { ...object, name: change.to };
|
|
676
|
+
}
|
|
677
|
+
if (object.kind !== "sequence")
|
|
678
|
+
return object;
|
|
679
|
+
const next = renamedIdentitySequence(source, change, object.name);
|
|
680
|
+
if (next === undefined)
|
|
681
|
+
return object;
|
|
682
|
+
return { ...object, name: next };
|
|
683
|
+
}
|
|
684
|
+
function renamedIdentitySequence(source, change, sequenceName) {
|
|
685
|
+
for (const object of source.objects) {
|
|
686
|
+
if (object.kind !== "column" || object.definition.identity === undefined)
|
|
687
|
+
continue;
|
|
688
|
+
if (object.identity.parent.name !== change.from || !sameNamespace2(object.identity.parent.namespace, change.namespace)) {
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
if (fitIdentifier2(`${change.from}_${object.identity.name}_seq`) !== sequenceName)
|
|
692
|
+
continue;
|
|
693
|
+
return fitIdentifier2(`${change.to}_${object.identity.name}_seq`);
|
|
694
|
+
}
|
|
695
|
+
return;
|
|
649
696
|
}
|
|
650
697
|
function dependencyJson(edges) {
|
|
651
698
|
const indexed = edges.map((edge) => ({
|
|
@@ -50,11 +50,39 @@ function sameExtensionDefinition(before, after) {
|
|
|
50
50
|
return false;
|
|
51
51
|
return sameVersion(before.definition.version, after.definition.version);
|
|
52
52
|
}
|
|
53
|
+
function alignExtensionVersions(source, other) {
|
|
54
|
+
const loose = looseNames(source, other);
|
|
55
|
+
if (loose.size === 0)
|
|
56
|
+
return source;
|
|
57
|
+
let changed = false;
|
|
58
|
+
const objects = source.objects.map((object) => {
|
|
59
|
+
if (object.kind !== "extension" || object.definition.version === undefined)
|
|
60
|
+
return object;
|
|
61
|
+
if (!loose.has(object.identity.name))
|
|
62
|
+
return object;
|
|
63
|
+
changed = true;
|
|
64
|
+
const { version: _version, ...definition } = object.definition;
|
|
65
|
+
return { ...object, definition };
|
|
66
|
+
});
|
|
67
|
+
return changed ? { version: source.version, objects } : source;
|
|
68
|
+
}
|
|
53
69
|
function sameVersion(before, after) {
|
|
54
70
|
if (!isExactVersion(after) || !isExactVersion(before))
|
|
55
71
|
return true;
|
|
56
72
|
return before === after;
|
|
57
73
|
}
|
|
74
|
+
function looseNames(source, other) {
|
|
75
|
+
const names = new Set;
|
|
76
|
+
for (const catalog of [source, other]) {
|
|
77
|
+
for (const object of catalog.objects) {
|
|
78
|
+
if (object.kind !== "extension")
|
|
79
|
+
continue;
|
|
80
|
+
if (!isExactVersion(object.definition.version))
|
|
81
|
+
names.add(object.identity.name);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return names;
|
|
85
|
+
}
|
|
58
86
|
function assertVersion(version) {
|
|
59
87
|
if (version === undefined)
|
|
60
88
|
return;
|
|
@@ -66,4 +94,4 @@ function parts(version) {
|
|
|
66
94
|
return version.split(".").map((part) => Number(part));
|
|
67
95
|
}
|
|
68
96
|
|
|
69
|
-
export { extensionObject, isExactVersion, compareExtensionVersions, sameExtensionDefinition };
|
|
97
|
+
export { extensionObject, isExactVersion, compareExtensionVersions, sameExtensionDefinition, alignExtensionVersions };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/runtime/compat-words.ts
|
|
2
|
+
var CURRENT = "current";
|
|
3
|
+
var BEHIND_EXPAND = "behind by expand";
|
|
4
|
+
var BEHIND_CONTRACT = "behind by contract";
|
|
5
|
+
var AHEAD_EXPAND = "ahead by expand";
|
|
6
|
+
var AHEAD_CONTRACT = "ahead by contract";
|
|
7
|
+
function failedAt(step) {
|
|
8
|
+
return `failed at step ${String(step)} (resume with okm migrate apply)`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { CURRENT, BEHIND_EXPAND, BEHIND_CONTRACT, AHEAD_EXPAND, AHEAD_CONTRACT, failedAt };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
open2
|
|
3
|
+
} from "./wqem4jed.js";
|
|
4
|
+
import"./8jb4ymh2.js";
|
|
5
|
+
import {
|
|
6
|
+
createdOf,
|
|
7
|
+
testing2
|
|
8
|
+
} from "./ygem90rn.js";
|
|
9
|
+
import"./n442h54c.js";
|
|
10
|
+
import {
|
|
11
|
+
assertTargetPolicy,
|
|
12
|
+
assertDirectConnection,
|
|
13
|
+
selectTarget,
|
|
14
|
+
loadConfig,
|
|
15
|
+
loadSchema
|
|
16
|
+
} from "./q6zsyh31.js";
|
|
17
|
+
import"./n5y9zyj1.js";
|
|
18
|
+
import"./41kv2xdm.js";
|
|
19
|
+
import {
|
|
20
|
+
OkmError2
|
|
21
|
+
} from "./52szzakm.js";
|
|
22
|
+
|
|
23
|
+
// src/tooling/migrate/seed.ts
|
|
24
|
+
import { existsSync } from "node:fs";
|
|
25
|
+
import { join } from "node:path";
|
|
26
|
+
import { pathToFileURL } from "node:url";
|
|
27
|
+
async function seedProject(cwd, file, flags) {
|
|
28
|
+
const config = await loadConfig(cwd);
|
|
29
|
+
const target = selectTarget(config, flags.target);
|
|
30
|
+
assertTargetPolicy(target, "seed", flags.allowProtected);
|
|
31
|
+
const path = join(cwd, file);
|
|
32
|
+
if (!existsSync(path)) {
|
|
33
|
+
throw new OkmError2("invalid", `Seed file ${file} was not found.`, {
|
|
34
|
+
fix: { summary: "Pass okm seed <file> a module in this project." }
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
assertDirectConnection(target.url, flags.allowPooler || config.allowPooler === true);
|
|
38
|
+
const schema = await loadSchema(cwd, config.schema);
|
|
39
|
+
const pool = open2({ url: target.url, max: 1 });
|
|
40
|
+
const harness = await testing2(schema, { driver: pool, migrate: false });
|
|
41
|
+
try {
|
|
42
|
+
const imported = await import(`${pathToFileURL(path).href}?okm=${Date.now()}`);
|
|
43
|
+
const seed = isRecord(imported) ? imported.default : undefined;
|
|
44
|
+
if (typeof seed !== "function") {
|
|
45
|
+
throw new OkmError2("invalid", `${file} must default-export a function.`, {
|
|
46
|
+
fix: { summary: "export default async function seed(t) { ... }." }
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
await seed(harness);
|
|
50
|
+
return formatCreated(target.name, createdOf(harness));
|
|
51
|
+
} finally {
|
|
52
|
+
await harness.close();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function formatCreated(target, counts) {
|
|
56
|
+
const lines = [`target ${target}`];
|
|
57
|
+
if (counts.length === 0)
|
|
58
|
+
lines.push("created nothing");
|
|
59
|
+
else {
|
|
60
|
+
for (const item of counts)
|
|
61
|
+
lines.push(`${item.table} ${String(item.count)}`);
|
|
62
|
+
}
|
|
63
|
+
return `${lines.join(`
|
|
64
|
+
`)}
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
function isRecord(value) {
|
|
68
|
+
return typeof value === "object" && value !== null;
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
seedProject
|
|
72
|
+
};
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open2
|
|
3
|
-
} from "./
|
|
4
|
-
import"./
|
|
3
|
+
} from "./wqem4jed.js";
|
|
4
|
+
import"./8jb4ymh2.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 "./7nk68fj8.js";
|
|
9
19
|
import {
|
|
10
20
|
assertTargetPolicy,
|
|
11
21
|
listTargets,
|
|
12
22
|
loadConfig
|
|
13
|
-
} from "./
|
|
14
|
-
import"./
|
|
23
|
+
} from "./q6zsyh31.js";
|
|
24
|
+
import"./n5y9zyj1.js";
|
|
25
|
+
import"./41kv2xdm.js";
|
|
15
26
|
import {
|
|
16
27
|
OkmError2
|
|
17
28
|
} from "./52szzakm.js";
|
|
@@ -19,8 +30,8 @@ import {
|
|
|
19
30
|
// src/tooling/migrate/status.ts
|
|
20
31
|
import { join } from "node:path";
|
|
21
32
|
function describeStatus(migrations, history, recorded) {
|
|
22
|
-
const done = new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`));
|
|
23
33
|
const known = new Set(migrations.map((migration) => migration.id));
|
|
34
|
+
const done = expandProvisioned(migrations, new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`)), history.map((row) => row.migrationId));
|
|
24
35
|
for (const migration of migrations) {
|
|
25
36
|
let have = 0;
|
|
26
37
|
let missing = -1;
|
|
@@ -34,33 +45,33 @@ function describeStatus(migrations, history, recorded) {
|
|
|
34
45
|
return {
|
|
35
46
|
version: migration.id,
|
|
36
47
|
catalogHash: recorded?.hash ?? "-",
|
|
37
|
-
state:
|
|
48
|
+
state: failedAt(missing)
|
|
38
49
|
};
|
|
39
50
|
}
|
|
40
51
|
}
|
|
41
|
-
const extra = history.some((row) => !known.has(row.migrationId));
|
|
42
52
|
const pending = migrations.filter((migration) => migration.steps.some((_, index) => !done.has(`${migration.id}:${String(index)}`)));
|
|
43
53
|
const finished = lastComplete(migrations, done);
|
|
44
54
|
const version = recorded?.version ?? finished ?? "-";
|
|
45
55
|
const catalogHash = recorded?.hash ?? "-";
|
|
56
|
+
const extra = history.some((row) => !provisionHistoryIsKnown(row.migrationId, known));
|
|
46
57
|
if (extra)
|
|
47
|
-
return { version, catalogHash, state:
|
|
58
|
+
return { version, catalogHash, state: aheadState(history, known) };
|
|
48
59
|
if (pending.length > 0) {
|
|
49
60
|
const contract = pending.some((migration) => migration.steps.some((step) => step.class !== "expand"));
|
|
50
61
|
return {
|
|
51
62
|
version,
|
|
52
63
|
catalogHash,
|
|
53
|
-
state: contract ?
|
|
64
|
+
state: contract ? BEHIND_CONTRACT : BEHIND_EXPAND
|
|
54
65
|
};
|
|
55
66
|
}
|
|
56
67
|
const last = migrations.at(-1);
|
|
57
68
|
if (last !== undefined && recorded !== undefined && recorded.hash !== last.catalogHash) {
|
|
58
|
-
return { version, catalogHash, state:
|
|
69
|
+
return { version, catalogHash, state: aheadState(history, known) };
|
|
59
70
|
}
|
|
60
71
|
return {
|
|
61
72
|
version: recorded?.version ?? last?.id ?? "-",
|
|
62
73
|
catalogHash: recorded?.hash ?? last?.catalogHash ?? "-",
|
|
63
|
-
state:
|
|
74
|
+
state: CURRENT
|
|
64
75
|
};
|
|
65
76
|
}
|
|
66
77
|
async function readTargetStatus(input) {
|
|
@@ -82,7 +93,8 @@ async function readTargetStatus(input) {
|
|
|
82
93
|
version: described.version,
|
|
83
94
|
catalogHash: described.catalogHash,
|
|
84
95
|
state: described.state,
|
|
85
|
-
protected: input.protected
|
|
96
|
+
protected: input.protected,
|
|
97
|
+
backfills: await readBackfills(pool)
|
|
86
98
|
};
|
|
87
99
|
} finally {
|
|
88
100
|
await pool.close();
|
|
@@ -105,8 +117,17 @@ async function statusProject(cwd, flags) {
|
|
|
105
117
|
}
|
|
106
118
|
function formatStatus(rows) {
|
|
107
119
|
const lines = ["target\tversion\tcatalog\tstate\tprotected"];
|
|
120
|
+
const backfills = [];
|
|
108
121
|
for (const row of rows) {
|
|
109
122
|
lines.push([row.target, row.version, row.catalogHash, row.state, row.protected ? "true" : "false"].join("\t"));
|
|
123
|
+
backfills.push(...row.backfills);
|
|
124
|
+
}
|
|
125
|
+
if (backfills.length > 0) {
|
|
126
|
+
lines.push("backfill");
|
|
127
|
+
lines.push("migration\tstep\trows\tkey\tstate");
|
|
128
|
+
for (const item of backfills) {
|
|
129
|
+
lines.push([item.migrationId, String(item.stepIndex), item.rows, item.lastKey, item.state].join("\t"));
|
|
130
|
+
}
|
|
110
131
|
}
|
|
111
132
|
return `${lines.join(`
|
|
112
133
|
`)}
|
|
@@ -160,7 +181,33 @@ async function readHistory(pool) {
|
|
|
160
181
|
rows.push({
|
|
161
182
|
migrationId,
|
|
162
183
|
stepIndex: Number(step),
|
|
163
|
-
class: stepClass
|
|
184
|
+
class: storedClass(stepClass)
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return rows;
|
|
188
|
+
}
|
|
189
|
+
async function readBackfills(pool) {
|
|
190
|
+
const present = await pool.execute("select to_regclass('okm_backfill') is not null");
|
|
191
|
+
if (!wireTrue(present.rows[0]?.[0] ?? null))
|
|
192
|
+
return [];
|
|
193
|
+
const result = await pool.execute(`select migration_id, step_index::text, rows_touched::text, last_key, state
|
|
194
|
+
from okm_backfill
|
|
195
|
+
where state <> 'done'
|
|
196
|
+
order by migration_id, step_index`);
|
|
197
|
+
const rows = [];
|
|
198
|
+
for (const row of result.rows) {
|
|
199
|
+
const migrationId = row[0];
|
|
200
|
+
const step = row[1];
|
|
201
|
+
const touched = row[2];
|
|
202
|
+
const state = row[4];
|
|
203
|
+
if (migrationId == null || step == null || touched == null || state == null)
|
|
204
|
+
continue;
|
|
205
|
+
rows.push({
|
|
206
|
+
migrationId,
|
|
207
|
+
stepIndex: Number(step),
|
|
208
|
+
rows: touched,
|
|
209
|
+
lastKey: row[3] ?? "-",
|
|
210
|
+
state
|
|
164
211
|
});
|
|
165
212
|
}
|
|
166
213
|
return rows;
|
|
@@ -168,6 +215,26 @@ async function readHistory(pool) {
|
|
|
168
215
|
function wireTrue(value) {
|
|
169
216
|
return value === "t" || value === "true";
|
|
170
217
|
}
|
|
218
|
+
function aheadState(history, known) {
|
|
219
|
+
let sawExtra = false;
|
|
220
|
+
let expandOnly = true;
|
|
221
|
+
for (const row of history) {
|
|
222
|
+
if (known.has(row.migrationId))
|
|
223
|
+
continue;
|
|
224
|
+
sawExtra = true;
|
|
225
|
+
if (row.class !== "expand")
|
|
226
|
+
expandOnly = false;
|
|
227
|
+
}
|
|
228
|
+
if (!sawExtra) {
|
|
229
|
+
expandOnly = history.length > 0 && history.every((row) => row.class === "expand");
|
|
230
|
+
}
|
|
231
|
+
return expandOnly ? AHEAD_EXPAND : AHEAD_CONTRACT;
|
|
232
|
+
}
|
|
233
|
+
function storedClass(value) {
|
|
234
|
+
if (value === "expand" || value === "contract" || value === "unclassified")
|
|
235
|
+
return value;
|
|
236
|
+
return "unclassified";
|
|
237
|
+
}
|
|
171
238
|
export {
|
|
172
239
|
statusProject
|
|
173
240
|
};
|
|
@@ -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,11 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
+
assertNamespace2,
|
|
2
3
|
identityKey2,
|
|
3
4
|
identityLabel2,
|
|
4
|
-
|
|
5
|
+
normaliseEdges,
|
|
6
|
+
compareText,
|
|
7
|
+
assertProvenance
|
|
5
8
|
} from "./t4tbsy9h.js";
|
|
6
9
|
import {
|
|
7
10
|
CATALOG_VERSION2
|
|
8
11
|
} from "./4e4c6vq2.js";
|
|
12
|
+
import {
|
|
13
|
+
assertIdentifier2,
|
|
14
|
+
assertStoredText
|
|
15
|
+
} from "./nfzc5z0w.js";
|
|
9
16
|
import {
|
|
10
17
|
catalogError2
|
|
11
18
|
} from "./52szzakm.js";
|
|
@@ -135,4 +142,78 @@ function assertForeignKeys(objects, keys) {
|
|
|
135
142
|
}
|
|
136
143
|
}
|
|
137
144
|
|
|
138
|
-
|
|
145
|
+
// src/contracts/catalog/enum.ts
|
|
146
|
+
function enumType(input) {
|
|
147
|
+
assertNamespace2(input.namespace);
|
|
148
|
+
assertIdentifier2(input.name, "type");
|
|
149
|
+
assertProvenance(input.provenance);
|
|
150
|
+
if (input.labels.length === 0) {
|
|
151
|
+
catalogError2("OKM1020", `Enum ${input.name} must list at least one label.`);
|
|
152
|
+
}
|
|
153
|
+
const labels = [];
|
|
154
|
+
const seen = new Set;
|
|
155
|
+
for (const label of input.labels) {
|
|
156
|
+
assertStoredText(label, "enum label");
|
|
157
|
+
if (label.length === 0) {
|
|
158
|
+
catalogError2("OKM1020", `Enum ${input.name} has an empty label.`);
|
|
159
|
+
}
|
|
160
|
+
if (seen.has(label)) {
|
|
161
|
+
catalogError2("OKM1020", `Enum ${input.name} repeats label ${label}.`);
|
|
162
|
+
}
|
|
163
|
+
seen.add(label);
|
|
164
|
+
labels.push(label);
|
|
165
|
+
}
|
|
166
|
+
const identity = {
|
|
167
|
+
kind: "type",
|
|
168
|
+
namespace: input.namespace,
|
|
169
|
+
name: input.name
|
|
170
|
+
};
|
|
171
|
+
return {
|
|
172
|
+
kind: "type",
|
|
173
|
+
identity,
|
|
174
|
+
owner: input.owner ?? "managed",
|
|
175
|
+
definition: { labels },
|
|
176
|
+
dependencies: normaliseEdges(input.dependencies ?? []),
|
|
177
|
+
provenance: input.provenance
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function domainType(input) {
|
|
181
|
+
assertNamespace2(input.namespace);
|
|
182
|
+
assertIdentifier2(input.name, "type");
|
|
183
|
+
assertProvenance(input.provenance);
|
|
184
|
+
if (input.base.length === 0) {
|
|
185
|
+
catalogError2("OKM1020", `Domain ${input.name} needs a base type.`);
|
|
186
|
+
}
|
|
187
|
+
assertStoredText(input.check, "domain check");
|
|
188
|
+
if (input.check.length === 0) {
|
|
189
|
+
catalogError2("OKM1020", `Domain ${input.name} needs a check.`);
|
|
190
|
+
}
|
|
191
|
+
const identity = {
|
|
192
|
+
kind: "type",
|
|
193
|
+
namespace: input.namespace,
|
|
194
|
+
name: input.name
|
|
195
|
+
};
|
|
196
|
+
const definition = { base: input.base, check: input.check };
|
|
197
|
+
return {
|
|
198
|
+
kind: "type",
|
|
199
|
+
identity,
|
|
200
|
+
owner: input.owner ?? "managed",
|
|
201
|
+
definition,
|
|
202
|
+
dependencies: normaliseEdges(input.dependencies ?? []),
|
|
203
|
+
provenance: input.provenance
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function isDomain(definition) {
|
|
207
|
+
return "base" in definition;
|
|
208
|
+
}
|
|
209
|
+
function sameEnumLabels(left, right) {
|
|
210
|
+
if (left.length !== right.length)
|
|
211
|
+
return false;
|
|
212
|
+
for (let index = 0;index < left.length; index += 1) {
|
|
213
|
+
if (left[index] !== right[index])
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export { dependencyOrder, catalog, enumType, domainType, isDomain, sameEnumLabels };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertAuthorDrift2,
|
|
3
|
+
catalogQuery2,
|
|
4
|
+
managedRoleOptions2
|
|
5
|
+
} from "./xghkt7a9.js";
|
|
6
|
+
import"./n5y9zyj1.js";
|
|
7
|
+
import"./41kv2xdm.js";
|
|
8
|
+
import"./8jb4ymh2.js";
|
|
9
|
+
export {
|
|
10
|
+
assertAuthorDrift2 as assertAuthorDrift,
|
|
11
|
+
catalogQuery2 as catalogQuery,
|
|
12
|
+
managedRoleOptions2 as managedRoleOptions
|
|
13
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/runtime/catalog-cache.ts
|
|
2
|
+
var inflight = new Map;
|
|
3
|
+
function loadOnce(key, load) {
|
|
4
|
+
const found = inflight.get(key);
|
|
5
|
+
if (found !== undefined)
|
|
6
|
+
return found;
|
|
7
|
+
const pending = Promise.resolve().then(load);
|
|
8
|
+
inflight.set(key, pending);
|
|
9
|
+
pending.catch(() => {
|
|
10
|
+
if (inflight.get(key) === pending)
|
|
11
|
+
inflight.delete(key);
|
|
12
|
+
});
|
|
13
|
+
return pending;
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
loadOnce
|
|
17
|
+
};
|
|
@@ -60,6 +60,7 @@ var TABLE_KNOWN = new Set([
|
|
|
60
60
|
"omitDefaults",
|
|
61
61
|
"presets",
|
|
62
62
|
"primaryKey",
|
|
63
|
+
"reference",
|
|
63
64
|
"relations",
|
|
64
65
|
"renamedFrom",
|
|
65
66
|
"sqlName",
|
|
@@ -71,8 +72,7 @@ var TABLE_KNOWN = new Set([
|
|
|
71
72
|
]);
|
|
72
73
|
var TABLE_LATER = {
|
|
73
74
|
computed: "later",
|
|
74
|
-
policies: "later"
|
|
75
|
-
reference: "0.4"
|
|
75
|
+
policies: "later"
|
|
76
76
|
};
|
|
77
77
|
function table2(name, columns, options) {
|
|
78
78
|
const source = callerLocation(1);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyTarget2,
|
|
3
|
+
applyProject2,
|
|
4
|
+
pushProject2,
|
|
5
|
+
backfillTiming2
|
|
6
|
+
} from "./s4mb6a4b.js";
|
|
7
|
+
import"./7nk68fj8.js";
|
|
8
|
+
import"./q6zsyh31.js";
|
|
9
|
+
import"./n5y9zyj1.js";
|
|
10
|
+
import"./n442h54c.js";
|
|
11
|
+
import"./41kv2xdm.js";
|
|
12
|
+
import"./8jb4ymh2.js";
|
|
13
|
+
import"./wqem4jed.js";
|
|
14
|
+
export {
|
|
15
|
+
applyProject2 as applyProject,
|
|
16
|
+
applyTarget2 as applyTarget,
|
|
17
|
+
backfillTiming2 as backfillTiming,
|
|
18
|
+
pushProject2 as pushProject
|
|
19
|
+
};
|