okmodel 0.2.1 → 0.3.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.
Files changed (108) hide show
  1. package/README.md +710 -36
  2. package/dist/contracts/catalog/enum.d.ts +31 -4
  3. package/dist/contracts/catalog/extension.d.ts +61 -0
  4. package/dist/contracts/catalog/privilege.d.ts +64 -0
  5. package/dist/contracts/catalog/routine.d.ts +56 -0
  6. package/dist/contracts/catalog/types.d.ts +164 -10
  7. package/dist/contracts/catalog/view.d.ts +73 -0
  8. package/dist/dialects/pg/column.d.ts +3 -1
  9. package/dist/dialects/pg/ddl.d.ts +65 -1
  10. package/dist/dialects/pg/enum.d.ts +10 -8
  11. package/dist/dialects/pg/ext/citext.d.ts +14 -0
  12. package/dist/dialects/pg/ext/citext.js +11 -0
  13. package/dist/dialects/pg/ext/index.d.ts +52 -0
  14. package/dist/dialects/pg/ext/index.js +6 -0
  15. package/dist/dialects/pg/ext/pg-trgm.d.ts +53 -0
  16. package/dist/dialects/pg/ext/pg-trgm.js +42 -0
  17. package/dist/dialects/pg/fn/index.d.ts +107 -0
  18. package/dist/dialects/pg/fn/index.js +175 -0
  19. package/dist/dialects/pg/fn/touch.d.ts +14 -0
  20. package/dist/dialects/pg/index.js +104 -19
  21. package/dist/dialects/pg/introspect.d.ts +10 -1
  22. package/dist/dialects/pg/operators.d.ts +8 -1
  23. package/dist/dialects/pg/role/check.d.ts +45 -0
  24. package/dist/dialects/pg/role/index.d.ts +50 -0
  25. package/dist/dialects/pg/role/sql.d.ts +44 -0
  26. package/dist/dialects/pg/table.d.ts +7 -0
  27. package/dist/dialects/pg/tenancy.d.ts +9 -0
  28. package/dist/dialects/pg/view/client.d.ts +30 -0
  29. package/dist/dialects/pg/view/depend.d.ts +35 -0
  30. package/dist/dialects/pg/view/index.d.ts +114 -0
  31. package/dist/dialects/pg/view/index.js +289 -0
  32. package/dist/dialects/pg/view/scratch.d.ts +21 -0
  33. package/dist/dialects/pg/where.d.ts +2 -2
  34. package/dist/runtime/pg/bun.js +3 -3
  35. package/dist/runtime/pg/pg.js +3 -3
  36. package/dist/runtime/pg/pglite.js +3 -3
  37. package/dist/runtime/pg/postgresjs.js +3 -3
  38. package/dist/runtime/tenancy/index.js +6 -3
  39. package/dist/runtime/traits/index.d.ts +7 -2
  40. package/dist/runtime/traits/index.js +149 -12
  41. package/dist/runtime/validate/index.js +4 -4
  42. package/dist/shared/{ytg3xf9p.js → 01yr20s5.js} +3 -3
  43. package/dist/shared/{cstgkzdx.js → 0jc3ffzf.js} +1 -1
  44. package/dist/shared/{xkz8g6by.js → 1g0drakv.js} +2 -2
  45. package/dist/shared/{eaxwrgby.js → 1tfdfvhh.js} +4 -3
  46. package/dist/shared/2ssqrv66.js +1576 -0
  47. package/dist/shared/{10tjenmd.js → 3ekj9x92.js} +1 -1
  48. package/dist/shared/49ypnfwt.js +1122 -0
  49. package/dist/shared/{sacqha1y.js → 4m9fn52z.js} +2 -2
  50. package/dist/shared/5nmdenb6.js +1229 -0
  51. package/dist/shared/{qa5dsc7z.js → 6bazvqwm.js} +3 -3
  52. package/dist/shared/{x9v1qgeb.js → 6w5j844a.js} +1 -1
  53. package/dist/shared/{0qkxbm1f.js → 75xkjv0t.js} +1 -1
  54. package/dist/shared/7fvtrkwr.js +84 -0
  55. package/dist/shared/94ez8kzh.js +19 -0
  56. package/dist/shared/{1dp5knt7.js → 999ade2q.js} +2 -2
  57. package/dist/shared/{3a5ne750.js → 9m80mkac.js} +2 -2
  58. package/dist/shared/9x25fxhc.js +150 -0
  59. package/dist/shared/{4b9da9d7.js → axhk06q1.js} +19 -1
  60. package/dist/shared/{38crxbgn.js → bqha5cg6.js} +3 -3
  61. package/dist/shared/{zd93g3rq.js → bryqk9k9.js} +1 -1
  62. package/dist/shared/{n47rd821.js → c8aghh05.js} +1 -1
  63. package/dist/shared/{dd4f8mnx.js → c9z5g0fm.js} +4 -2
  64. package/dist/shared/{eqmtn1bj.js → dbjej1tw.js} +71 -14
  65. package/dist/shared/{ps43134h.js → dyj86cmj.js} +4 -4
  66. package/dist/shared/{sfh4pk75.js → fptpmvxp.js} +3 -3
  67. package/dist/shared/{97g2jnrw.js → fs0ex00p.js} +3 -3
  68. package/dist/shared/{rtnaqre0.js → g4f5kcx9.js} +2 -2
  69. package/dist/shared/{yw5c610b.js → gjthds9j.js} +2 -2
  70. package/dist/shared/hcmdtwgh.js +102 -0
  71. package/dist/shared/{qxa0yb9j.js → jkc6ws1p.js} +2 -54
  72. package/dist/shared/{mxmcdsh5.js → k34e0xf2.js} +9 -9
  73. package/dist/shared/{py3nh7jy.js → kgnc8grt.js} +2 -2
  74. package/dist/shared/{g9f0zqce.js → m78s7898.js} +1 -1
  75. package/dist/shared/meck53jv.js +99 -0
  76. package/dist/shared/{v18jva5b.js → mt5wswjz.js} +1 -1
  77. package/dist/shared/{g1b5zzj9.js → n0dgs0pb.js} +1 -1
  78. package/dist/shared/{zt8y0wzb.js → n7mcc1gk.js} +1 -1
  79. package/dist/shared/ne02ng5c.js +68 -0
  80. package/dist/shared/{e7a268fy.js → p24x2334.js} +1 -1
  81. package/dist/shared/qbxzvwwc.js +88 -0
  82. package/dist/shared/{a1gdp7j9.js → qybh48nd.js} +1 -1
  83. package/dist/shared/{d04j53v8.js → scwxrpx2.js} +5 -4
  84. package/dist/shared/{d2whjz4k.js → t616ynfn.js} +530 -24
  85. package/dist/shared/th14ygv2.js +69 -0
  86. package/dist/shared/{xatfg0gn.js → tmbdywx0.js} +4 -19
  87. package/dist/shared/{ge03bfca.js → ty3v3hfk.js} +2 -2
  88. package/dist/shared/wekze34d.js +246 -0
  89. package/dist/shared/{7mht49yd.js → x6wysh83.js} +59 -18
  90. package/dist/shared/{4jzzghr6.js → xva8v7qk.js} +8 -8
  91. package/dist/shared/{ecdzej21.js → xw1d69vd.js} +7 -7
  92. package/dist/shared/y005b761.js +112 -0
  93. package/dist/shared/{mrq77sgw.js → ydaz1sv3.js} +1 -1
  94. package/dist/tooling/cli.js +32 -8
  95. package/dist/tooling/migrate/apply.d.ts +16 -0
  96. package/dist/tooling/migrate/commands.d.ts +2 -1
  97. package/dist/tooling/migrate/config.d.ts +8 -0
  98. package/dist/tooling/migrate/doctor.d.ts +25 -0
  99. package/dist/tooling/migrate/drift.d.ts +19 -0
  100. package/dist/tooling/migrate/ext.d.ts +17 -0
  101. package/dist/tooling/migrate/extensions.d.ts +51 -0
  102. package/dist/tooling/migrate/managed.d.ts +17 -0
  103. package/dist/tooling/migrate/plan.d.ts +14 -1
  104. package/dist/tooling/migrate/project.d.ts +25 -1
  105. package/dist/tooling/migrate/type-name.d.ts +19 -0
  106. package/package.json +22 -2
  107. package/dist/shared/5z4q2zda.js +0 -2073
  108. /package/dist/shared/{9k6vetvf.js → rrstp3kb.js} +0 -0
@@ -0,0 +1,102 @@
1
+ import {
2
+ OkmError2
3
+ } from "./52szzakm.js";
4
+
5
+ // src/dialects/pg/role/check.ts
6
+ async function assertRoleHealth(runner, roles, objects) {
7
+ const managed = new Set((roles.managed ?? []).map((role) => role.name));
8
+ const named = [roles.migration, roles.app];
9
+ for (const name of named) {
10
+ if (managed.has(name))
11
+ continue;
12
+ if (!await roleExists(runner, name)) {
13
+ throw new OkmError2("not_found", `Role ${name} is named in roles and does not exist.`, {
14
+ kind: "not_found",
15
+ fix: { summary: "Create the role, or list it in roles.managed so the plan creates it." }
16
+ });
17
+ }
18
+ }
19
+ if (managed.size > 0)
20
+ await assertCreateRole(runner, await currentUser(runner));
21
+ for (const object of objects) {
22
+ if (object.kind !== "grant" || object.identity.role !== roles.app)
23
+ continue;
24
+ await assertGrant(runner, object);
25
+ }
26
+ }
27
+ async function assertCreateRole(runner, role) {
28
+ const result = await runner.execute("select rolcreaterole from pg_roles where rolname = $1", [
29
+ role
30
+ ]);
31
+ if (!truthy(result.rows[0]?.[0])) {
32
+ throw new OkmError2("forbidden", `Role ${role} lacks CREATEROLE. Nothing was changed.`, {
33
+ kind: "forbidden",
34
+ fix: { summary: "Grant CREATEROLE to the role that applies migrations." }
35
+ });
36
+ }
37
+ }
38
+ async function currentUser(runner) {
39
+ const result = await runner.execute("select current_user");
40
+ const name = result.rows[0]?.[0];
41
+ return typeof name === "string" ? name : "";
42
+ }
43
+ async function roleExists(runner, name) {
44
+ const result = await runner.execute("select 1 from pg_roles where rolname = $1", [name]);
45
+ return result.rows.length > 0;
46
+ }
47
+ async function assertGrant(runner, object) {
48
+ const target = object.identity.object;
49
+ const schema = target.namespace.form === "static" ? target.namespace.name : "public";
50
+ const privilege = object.identity.privilege;
51
+ if (target.kind === "function") {
52
+ const open = target.name.lastIndexOf("(");
53
+ const fn = open < 0 ? target.name : target.name.slice(0, open);
54
+ const args = open < 0 ? "" : target.name.slice(open + 1, -1);
55
+ if (!await functionExists(runner, schema, fn, args))
56
+ return;
57
+ const allowed = await runner.execute("select has_function_privilege($1, format('%I.%I(%s)', $2::text, $3::text, $4::text), $5)", [object.identity.role, schema, fn, args, privilege]);
58
+ if (!truthy(allowed.rows[0]?.[0]))
59
+ missing(object, `${schema}.${fn}`);
60
+ return;
61
+ }
62
+ if (target.kind === "namespace")
63
+ return;
64
+ const relkinds = target.kind === "sequence" ? "'S'" : target.kind === "view" ? "'v'" : target.kind === "materializedView" ? "'m'" : "'r', 'p'";
65
+ if (!await relationExists(runner, schema, target.name, relkinds))
66
+ return;
67
+ const probe = target.kind === "sequence" ? "select has_sequence_privilege($1, format('%I.%I', $2::text, $3::text), $4)" : "select has_table_privilege($1, format('%I.%I', $2::text, $3::text), $4)";
68
+ const allowed = await runner.execute(probe, [
69
+ object.identity.role,
70
+ schema,
71
+ target.name,
72
+ privilege
73
+ ]);
74
+ if (!truthy(allowed.rows[0]?.[0]))
75
+ missing(object, `${schema}.${target.name}`);
76
+ }
77
+ function missing(object, name) {
78
+ throw new OkmError2("OKM1825", `Role ${object.identity.role} lacks ${object.identity.privilege} on ${name}.`, {
79
+ kind: "forbidden",
80
+ fix: {
81
+ summary: "Grant the privilege, or change the role. okm doctor reports the object and the privilege."
82
+ }
83
+ });
84
+ }
85
+ async function relationExists(runner, schema, name, relkinds) {
86
+ const result = await runner.execute(`select 1 from pg_class c
87
+ join pg_namespace n on n.oid = c.relnamespace
88
+ where n.nspname = $1 and c.relname = $2 and c.relkind in (${relkinds})`, [schema, name]);
89
+ return result.rows.length > 0;
90
+ }
91
+ async function functionExists(runner, schema, name, args) {
92
+ const result = await runner.execute(`select 1 from pg_proc p
93
+ join pg_namespace n on n.oid = p.pronamespace
94
+ where n.nspname = $1 and p.proname = $2
95
+ and replace(pg_get_function_identity_arguments(p.oid), ' ', '') = $3`, [schema, name, args]);
96
+ return result.rows.length > 0;
97
+ }
98
+ function truthy(value) {
99
+ return value === true || value === "t" || value === "true";
100
+ }
101
+
102
+ export { assertRoleHealth, assertCreateRole, currentUser, roleExists };
@@ -1,18 +1,11 @@
1
1
  import {
2
- assertNamespace2,
3
2
  identityKey2,
4
3
  identityLabel2,
5
- normaliseEdges,
6
- compareText,
7
- assertProvenance
4
+ compareText
8
5
  } from "./t4tbsy9h.js";
9
6
  import {
10
7
  CATALOG_VERSION2
11
8
  } from "./4e4c6vq2.js";
12
- import {
13
- assertIdentifier2,
14
- assertStoredText
15
- } from "./nfzc5z0w.js";
16
9
  import {
17
10
  catalogError2
18
11
  } from "./52szzakm.js";
@@ -142,49 +135,4 @@ function assertForeignKeys(objects, keys) {
142
135
  }
143
136
  }
144
137
 
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 sameEnumLabels(left, right) {
181
- if (left.length !== right.length)
182
- return false;
183
- for (let index = 0;index < left.length; index += 1) {
184
- if (left[index] !== right[index])
185
- return false;
186
- }
187
- return true;
188
- }
189
-
190
- export { dependencyOrder, catalog, enumType, sameEnumLabels };
138
+ export { dependencyOrder, catalog };
@@ -72,7 +72,7 @@ function openClient(session) {
72
72
  },
73
73
  close,
74
74
  connected: session.connected,
75
- tx: (...args) => import("./g9f0zqce.js").then((mod) => mod.tx(session, args)),
75
+ tx: (...args) => import("./m78s7898.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("./mrq77sgw.js"), table, options, base, view);
110
+ return lazyRead(session, () => import("./ydaz1sv3.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("./e7a268fy.js"), table, options, base, view);
124
+ return lazyRead(session, () => import("./p24x2334.js"), table, options, base, view);
125
125
  },
126
126
  aggregate(options = {}) {
127
- return lazyRead(session, () => import("./10tjenmd.js"), table, options, base, view);
127
+ return lazyRead(session, () => import("./3ekj9x92.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("./v18jva5b.js").then((mod) => mod.batch(session, ops, options, replica)), {
157
+ return queryHandle(() => import("./mt5wswjz.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("./4jzzghr6.js");
163
+ writers ??= import("./xva8v7qk.js");
164
164
  return writers;
165
165
  }
166
166
  function queryHandle(run, extra) {
@@ -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("./zd93g3rq.js");
323
+ const { streamRows } = await import("./bryqk9k9.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("./ge03bfca.js");
360
+ const server = await import("./ty3v3hfk.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("./4b9da9d7.js").then(() => {
389
+ operatorSql ??= import("./axhk06q1.js").then(() => {
390
390
  return;
391
391
  });
392
392
  return operatorSql;
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  open3
3
- } from "./0qkxbm1f.js";
3
+ } from "./75xkjv0t.js";
4
4
  import {
5
5
  PGLITE_CAPABILITIES,
6
6
  readCapability2,
7
7
  hasCapability2
8
- } from "./9k6vetvf.js";
8
+ } from "./rrstp3kb.js";
9
9
  export {
10
10
  PGLITE_CAPABILITIES as capabilities,
11
11
  hasCapability2 as hasCapability,
@@ -5,7 +5,7 @@ import {
5
5
  openClient,
6
6
  withHttp,
7
7
  settleCall
8
- } from "./mxmcdsh5.js";
8
+ } from "./k34e0xf2.js";
9
9
  import {
10
10
  rejectKeys,
11
11
  isRecord,
@@ -0,0 +1,99 @@
1
+ import {
2
+ open2
3
+ } from "./xw1d69vd.js";
4
+ import"./t616ynfn.js";
5
+ import"./n442h54c.js";
6
+ import {
7
+ assertTargetPolicy,
8
+ selectTarget,
9
+ openProject
10
+ } from "./5nmdenb6.js";
11
+ import"./2ssqrv66.js";
12
+ import {
13
+ isExactVersion,
14
+ compareExtensionVersions
15
+ } from "./th14ygv2.js";
16
+ import {
17
+ OkmError2
18
+ } from "./52szzakm.js";
19
+
20
+ // src/tooling/migrate/ext.ts
21
+ async function extProject(cwd, command, flags) {
22
+ const opened = await openProject(cwd);
23
+ const target = selectTarget(opened.config, flags.target);
24
+ assertTargetPolicy(target, "check", flags.allowProtected);
25
+ const pool = open2({ url: target.url, max: 1 });
26
+ try {
27
+ if (command === "list")
28
+ return formatList(await readExtensions(pool));
29
+ return formatCheck(opened.built.catalog.objects, await readExtensions(pool));
30
+ } finally {
31
+ await pool.close();
32
+ }
33
+ }
34
+ var LIST_SQL = `
35
+ select a.name, a.default_version, e.extversion, n.nspname
36
+ from pg_available_extensions a
37
+ left join pg_extension e on e.extname = a.name
38
+ left join pg_namespace n on n.oid = e.extnamespace
39
+ order by a.name
40
+ `;
41
+ async function readExtensions(pool) {
42
+ const result = await pool.execute(LIST_SQL);
43
+ return result.rows.map((row) => ({
44
+ name: cell(row[0]),
45
+ defaultVersion: cell(row[1]),
46
+ installedVersion: cell(row[2]),
47
+ schema: cell(row[3])
48
+ }));
49
+ }
50
+ function cell(value) {
51
+ return typeof value === "string" ? value : "";
52
+ }
53
+ function formatList(rows) {
54
+ const lines = ["name\tdefault\tinstalled\tschema"];
55
+ for (const row of rows) {
56
+ lines.push([row.name, row.defaultVersion, row.installedVersion, row.schema].join("\t"));
57
+ }
58
+ return `${lines.join(`
59
+ `)}
60
+ `;
61
+ }
62
+ function formatCheck(objects, server) {
63
+ const declared = objects.filter((object) => object.kind === "extension");
64
+ if (declared.length === 0)
65
+ return `no extensions
66
+ `;
67
+ const installed = new Map(server.map((row) => [row.name, row.installedVersion]));
68
+ const lines = ["name\tdeclared\tinstalled"];
69
+ for (const object of [...declared].sort((left, right) => left.identity.name < right.identity.name ? -1 : 1)) {
70
+ const name = object.identity.name;
71
+ const have = installed.get(name) ?? "";
72
+ if (have.length === 0) {
73
+ throw new OkmError2("OKM1811", `Extension ${name} is not installed on the server.`, {
74
+ fix: { summary: "Install the extension, or remove the declaration." }
75
+ });
76
+ }
77
+ const want = object.definition.version;
78
+ if (!versionAccepted(want, have)) {
79
+ throw new OkmError2("OKM1812", `Extension ${name} is ${have} on the server. The schema requires ${want ?? ""}.`, { fix: { summary: "Install a version the declaration accepts, or change the pin." } });
80
+ }
81
+ lines.push([name, want ?? "-", have].join("\t"));
82
+ }
83
+ return `${lines.join(`
84
+ `)}
85
+ `;
86
+ }
87
+ function versionAccepted(declared, installed) {
88
+ if (declared === undefined)
89
+ return true;
90
+ const floor = /^>=(\d+(?:\.\d+)*)$/.exec(declared);
91
+ const minimum = floor?.[1];
92
+ if (minimum !== undefined) {
93
+ return isExactVersion(installed) && compareExtensionVersions(installed, minimum) >= 0;
94
+ }
95
+ return declared === installed;
96
+ }
97
+ export {
98
+ extProject
99
+ };
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  withHttp,
6
6
  settleCall
7
- } from "./mxmcdsh5.js";
7
+ } from "./k34e0xf2.js";
8
8
  import {
9
9
  rejectKeys,
10
10
  isRecord,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  definition,
3
3
  unavailable
4
- } from "./xatfg0gn.js";
4
+ } from "./tmbdywx0.js";
5
5
 
6
6
  // src/dialects/pg/trait.ts
7
7
  var TRAIT_KEYS = new Set(["fields", "name", "presets", "sealed", "touch"]);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeArray
3
- } from "./xatfg0gn.js";
3
+ } from "./tmbdywx0.js";
4
4
  import {
5
5
  OkmError2
6
6
  } from "./52szzakm.js";
@@ -0,0 +1,68 @@
1
+ import {
2
+ open2
3
+ } from "./xw1d69vd.js";
4
+ import"./n442h54c.js";
5
+ import"./t616ynfn.js";
6
+ import {
7
+ assertRoleHealth
8
+ } from "./hcmdtwgh.js";
9
+ import {
10
+ errorDoc,
11
+ selectTarget,
12
+ openProject
13
+ } from "./5nmdenb6.js";
14
+ import {
15
+ omitManagedObjects
16
+ } from "./2ssqrv66.js";
17
+ import {
18
+ OkmError2
19
+ } from "./52szzakm.js";
20
+
21
+ // src/tooling/migrate/doctor.ts
22
+ async function doctorProject(cwd, code, flags) {
23
+ if (code !== undefined) {
24
+ const doc = errorDoc(code);
25
+ if (doc === undefined) {
26
+ throw new OkmError2("invalid", `Unknown code ${code}.`, {
27
+ fix: { summary: "Pass a code from the registry, or run okm doctor with no argument." }
28
+ });
29
+ }
30
+ return `${doc.code}: ${doc.title}
31
+ ${doc.summary}
32
+ ${doc.fix}
33
+ `;
34
+ }
35
+ const opened = await openProject(cwd);
36
+ const objects = omitManagedObjects(opened.built.catalog).objects;
37
+ if (opened.config.roles !== undefined) {
38
+ const target = selectTarget(opened.config, flags?.target);
39
+ const pool = open2({ url: target.url, max: 1 });
40
+ try {
41
+ await assertRoleHealth(pool, opened.config.roles, objects);
42
+ } finally {
43
+ await pool.close();
44
+ }
45
+ }
46
+ return formatTriggers(objects);
47
+ }
48
+ function formatTriggers(objects) {
49
+ const tables = new Map;
50
+ for (const object of objects) {
51
+ if (object.kind !== "trigger")
52
+ continue;
53
+ const table = object.identity.parent.name;
54
+ const names = tables.get(table) ?? [];
55
+ names.push(object.identity.name);
56
+ tables.set(table, names);
57
+ }
58
+ if (tables.size === 0)
59
+ return `no triggers
60
+ `;
61
+ const lines = [...tables.entries()].sort((left, right) => left[0] < right[0] ? -1 : left[0] > right[0] ? 1 : 0).map(([table, names]) => `${table}: ${[...names].sort().join(", ")}`);
62
+ return `${lines.join(`
63
+ `)}
64
+ `;
65
+ }
66
+ export {
67
+ doctorProject
68
+ };
@@ -3,7 +3,7 @@ import {
3
3
  readHandle,
4
4
  readCall,
5
5
  attachHttp
6
- } from "./mxmcdsh5.js";
6
+ } from "./k34e0xf2.js";
7
7
  import {
8
8
  selectedColumns,
9
9
  parseOrder,
@@ -0,0 +1,88 @@
1
+ import {
2
+ assertNamespace2,
3
+ normaliseEdges,
4
+ assertProvenance
5
+ } from "./t4tbsy9h.js";
6
+ import {
7
+ assertIdentifier2,
8
+ assertStoredText
9
+ } from "./nfzc5z0w.js";
10
+ import {
11
+ catalogError2
12
+ } from "./52szzakm.js";
13
+
14
+ // src/contracts/catalog/enum.ts
15
+ function enumType(input) {
16
+ assertNamespace2(input.namespace);
17
+ assertIdentifier2(input.name, "type");
18
+ assertProvenance(input.provenance);
19
+ if (input.labels.length === 0) {
20
+ catalogError2("OKM1020", `Enum ${input.name} must list at least one label.`);
21
+ }
22
+ const labels = [];
23
+ const seen = new Set;
24
+ for (const label of input.labels) {
25
+ assertStoredText(label, "enum label");
26
+ if (label.length === 0) {
27
+ catalogError2("OKM1020", `Enum ${input.name} has an empty label.`);
28
+ }
29
+ if (seen.has(label)) {
30
+ catalogError2("OKM1020", `Enum ${input.name} repeats label ${label}.`);
31
+ }
32
+ seen.add(label);
33
+ labels.push(label);
34
+ }
35
+ const identity = {
36
+ kind: "type",
37
+ namespace: input.namespace,
38
+ name: input.name
39
+ };
40
+ return {
41
+ kind: "type",
42
+ identity,
43
+ owner: input.owner ?? "managed",
44
+ definition: { labels },
45
+ dependencies: normaliseEdges(input.dependencies ?? []),
46
+ provenance: input.provenance
47
+ };
48
+ }
49
+ function domainType(input) {
50
+ assertNamespace2(input.namespace);
51
+ assertIdentifier2(input.name, "type");
52
+ assertProvenance(input.provenance);
53
+ if (input.base.length === 0) {
54
+ catalogError2("OKM1020", `Domain ${input.name} needs a base type.`);
55
+ }
56
+ assertStoredText(input.check, "domain check");
57
+ if (input.check.length === 0) {
58
+ catalogError2("OKM1020", `Domain ${input.name} needs a check.`);
59
+ }
60
+ const identity = {
61
+ kind: "type",
62
+ namespace: input.namespace,
63
+ name: input.name
64
+ };
65
+ const definition = { base: input.base, check: input.check };
66
+ return {
67
+ kind: "type",
68
+ identity,
69
+ owner: input.owner ?? "managed",
70
+ definition,
71
+ dependencies: normaliseEdges(input.dependencies ?? []),
72
+ provenance: input.provenance
73
+ };
74
+ }
75
+ function isDomain(definition) {
76
+ return "base" in definition;
77
+ }
78
+ function sameEnumLabels(left, right) {
79
+ if (left.length !== right.length)
80
+ return false;
81
+ for (let index = 0;index < left.length; index += 1) {
82
+ if (left[index] !== right[index])
83
+ return false;
84
+ }
85
+ return true;
86
+ }
87
+
88
+ export { enumType, domainType, isDomain, sameEnumLabels };
@@ -6,7 +6,7 @@ import {
6
6
  catalogHash2,
7
7
  loadTrustedCatalog2,
8
8
  parseCatalog2
9
- } from "./d2whjz4k.js";
9
+ } from "./t616ynfn.js";
10
10
  export {
11
11
  catalogHash2 as catalogHash,
12
12
  creationOrder2 as creationOrder,
@@ -1,16 +1,17 @@
1
1
  import {
2
2
  open2
3
- } from "./ecdzej21.js";
4
- import"./d2whjz4k.js";
3
+ } from "./xw1d69vd.js";
4
+ import"./t616ynfn.js";
5
5
  import"./n442h54c.js";
6
6
  import {
7
7
  loadMigrations
8
- } from "./rtnaqre0.js";
8
+ } from "./g4f5kcx9.js";
9
9
  import {
10
10
  assertTargetPolicy,
11
11
  listTargets,
12
12
  loadConfig
13
- } from "./5z4q2zda.js";
13
+ } from "./5nmdenb6.js";
14
+ import"./2ssqrv66.js";
14
15
  import {
15
16
  OkmError2
16
17
  } from "./52szzakm.js";