okmodel 0.4.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.
Files changed (64) hide show
  1. package/README.md +86 -6
  2. package/dist/contracts/catalog/document.d.ts +20 -0
  3. package/dist/contracts/driver.d.ts +7 -0
  4. package/dist/dialects/pg/introspect.d.ts +6 -0
  5. package/dist/dialects/pg/role/sql.d.ts +10 -0
  6. package/dist/dialects/pg/schema.d.ts +15 -6
  7. package/dist/dialects/pg/view/index.d.ts +20 -6
  8. package/dist/dialects/pg/view/scratch.d.ts +2 -2
  9. package/dist/runtime/pg/bun.d.ts +12 -7
  10. package/dist/runtime/pg/bun.js +4 -1
  11. package/dist/runtime/pg/pg.d.ts +12 -6
  12. package/dist/runtime/pg/pg.js +4 -1
  13. package/dist/runtime/pg/pglite.d.ts +11 -3
  14. package/dist/runtime/pg/pglite.js +4 -1
  15. package/dist/runtime/pg/postgresjs.d.ts +12 -6
  16. package/dist/runtime/pg/postgresjs.js +4 -1
  17. package/dist/runtime/plan.d.ts +3 -1
  18. package/dist/runtime/tenancy/index.js +1 -1
  19. package/dist/runtime/topology.d.ts +191 -0
  20. package/dist/runtime/traits/index.js +6 -6
  21. package/dist/runtime/types.d.ts +57 -2
  22. package/dist/runtime/validate/index.js +1 -1
  23. package/dist/shared/{nxb42q7h.js → 47xzb9fc.js} +2 -2
  24. package/dist/shared/{6693j9rs.js → 5fqx9yh4.js} +6 -2
  25. package/dist/shared/{8jb4ymh2.js → 8bwbwy8h.js} +12 -1
  26. package/dist/shared/{41kv2xdm.js → 8xsbagad.js} +1 -1
  27. package/dist/shared/{sr5ms7b3.js → 922qbgnw.js} +3 -3
  28. package/dist/shared/{tny2t3sm.js → 990a291j.js} +4 -4
  29. package/dist/shared/{jns2wx4t.js → 9tgmr1gh.js} +1 -1
  30. package/dist/shared/{n5y9zyj1.js → ayz64vzj.js} +13 -12
  31. package/dist/shared/{kkzwp3d2.js → bt9sfq0z.js} +16 -14
  32. package/dist/shared/{c5g81ngb.js → bzsjtd7c.js} +7 -5
  33. package/dist/shared/{radd3z4g.js → ckjbyrt9.js} +1 -1
  34. package/dist/shared/{zg24x0hm.js → dxjp14rk.js} +10 -2
  35. package/dist/shared/{xghkt7a9.js → fancm5pt.js} +6 -233
  36. package/dist/shared/{yjw02enp.js → fyqkk1m0.js} +4 -4
  37. package/dist/shared/{ygem90rn.js → g516zdsb.js} +8 -3
  38. package/dist/shared/{v7tpnhnz.js → h4nqvjkp.js} +5 -3
  39. package/dist/shared/{edwqqryd.js → h8ne16fq.js} +1 -1
  40. package/dist/shared/{ady1ms74.js → jdgqqx31.js} +5 -5
  41. package/dist/shared/{kafaa5zv.js → k7cc9nzk.js} +24 -7
  42. package/dist/shared/{7nk68fj8.js → kdkxh3kb.js} +17 -10
  43. package/dist/shared/nkc9sfqb.js +1161 -0
  44. package/dist/shared/{awrsqrn7.js → p7pfx624.js} +2 -2
  45. package/dist/shared/{xrfnq5k8.js → qgvt8nx1.js} +11 -2
  46. package/dist/shared/{84ptn35q.js → qy9rdq0g.js} +6 -5
  47. package/dist/shared/{qn0srwwq.js → r6pj4fq2.js} +5 -3
  48. package/dist/shared/{2321avmn.js → r73pt594.js} +21 -13
  49. package/dist/shared/{kj680nxv.js → rasvvzgz.js} +8 -6
  50. package/dist/shared/{hcmdtwgh.js → szm0cksa.js} +4 -1
  51. package/dist/shared/{axhk06q1.js → tq9afp8d.js} +1 -1
  52. package/dist/shared/wxn4b7pp.js +252 -0
  53. package/dist/shared/{q6zsyh31.js → xdpj5kkm.js} +19 -8
  54. package/dist/shared/{s4mb6a4b.js → xhh1srw3.js} +54 -10
  55. package/dist/shared/{jgxzjzcz.js → xsq7v6wp.js} +2 -2
  56. package/dist/shared/{hqjsxnz7.js → ykv7wh5b.js} +5 -4
  57. package/dist/shared/{q795afwa.js → z2rnngj4.js} +3 -3
  58. package/dist/tooling/cli.js +12 -12
  59. package/dist/tooling/migrate/apply.d.ts +2 -0
  60. package/dist/tooling/migrate/files.d.ts +7 -0
  61. package/dist/tooling/migrate/index.js +8 -6
  62. package/dist/tooling/testing/facts.d.ts +3 -0
  63. package/dist/tooling/testing/index.js +3 -3
  64. package/package.json +1 -1
@@ -2,8 +2,8 @@ import {
2
2
  open2
3
3
  } from "./wqem4jed.js";
4
4
  import {
5
- catalogHash2
6
- } from "./8jb4ymh2.js";
5
+ startupHash2
6
+ } from "./8bwbwy8h.js";
7
7
  import {
8
8
  runTarget,
9
9
  assumeRole,
@@ -15,12 +15,12 @@ import {
15
15
  provisionMark,
16
16
  expandProvisioned,
17
17
  installSnapshot
18
- } from "./7nk68fj8.js";
18
+ } from "./kdkxh3kb.js";
19
19
  import {
20
20
  assertCreateRole,
21
21
  currentUser,
22
22
  roleExists
23
- } from "./hcmdtwgh.js";
23
+ } from "./szm0cksa.js";
24
24
  import {
25
25
  lintMigrationDirectory,
26
26
  hasError,
@@ -31,13 +31,13 @@ import {
31
31
  projectHead,
32
32
  loadBuiltSchema,
33
33
  loadConfig
34
- } from "./q6zsyh31.js";
34
+ } from "./xdpj5kkm.js";
35
35
  import {
36
36
  changesRole,
37
37
  batchSizeField,
38
38
  assertExtensionsAvailable,
39
39
  planMigration
40
- } from "./n5y9zyj1.js";
40
+ } from "./ayz64vzj.js";
41
41
  import {
42
42
  OkmError2
43
43
  } from "./52szzakm.js";
@@ -202,6 +202,7 @@ async function applyTarget2(request) {
202
202
  await connection.execute(META);
203
203
  await connection.execute(HISTORY);
204
204
  await connection.execute(BACKFILL);
205
+ const restamped = await restampLegacy(connection, request);
205
206
  const history = await readHistory(connection);
206
207
  const done = expandProvisioned(request.migrations, history.done, history.ids);
207
208
  const units = request.migrations.flatMap((migration) => applyUnits(migration, done));
@@ -221,7 +222,7 @@ async function applyTarget2(request) {
221
222
  if (request.snapshot !== undefined) {
222
223
  await insertReference(connection, request);
223
224
  }
224
- return report;
225
+ return restamped.length === 0 ? report : { ...report, restamped };
225
226
  } finally {
226
227
  if (locked)
227
228
  await connection.execute("select pg_advisory_unlock(hashtext($1))", [
@@ -306,7 +307,7 @@ no changes
306
307
  migrations: [
307
308
  {
308
309
  id: "push",
309
- catalogHash: catalogHash2(head.catalog),
310
+ catalogHash: startupHash2(head.catalog),
310
311
  steps: plan.steps
311
312
  }
312
313
  ],
@@ -323,15 +324,58 @@ function backfillTiming2(backfill) {
323
324
  function formatReport(report) {
324
325
  const role = report.setRole !== undefined ? `set role ${report.setRole}
325
326
  ` : "";
327
+ const restamped = (report.restamped ?? []).map((id) => `restamped ${id}
328
+ `).join("");
326
329
  if (report.applied.length === 0)
327
330
  return `target ${report.target}
328
- ${role}nothing to apply
331
+ ${role}${restamped}nothing to apply
329
332
  `;
330
333
  return `target ${report.target}
331
- ${role}${report.applied.map((id) => `applied ${id}`).join(`
334
+ ${role}${restamped}${report.applied.map((id) => `applied ${id}`).join(`
332
335
  `)}
333
336
  `;
334
337
  }
338
+ async function restampLegacy(connection, request) {
339
+ const pairs = [];
340
+ for (const migration of request.migrations) {
341
+ if (migration.legacyHash === undefined)
342
+ continue;
343
+ pairs.push({
344
+ id: migration.id,
345
+ mark: provisionMark(migration.id),
346
+ legacy: migration.legacyHash,
347
+ startup: migration.catalogHash
348
+ });
349
+ }
350
+ if (pairs.length === 0)
351
+ return [];
352
+ await connection.execute("begin");
353
+ try {
354
+ const result = await connection.execute(RESTAMP, [JSON.stringify(pairs)]);
355
+ const restamped = result.rows.flatMap((row) => typeof row[0] === "string" ? [row[0]] : []);
356
+ if (restamped.length > 0) {
357
+ assertTargetPolicy({ name: request.target, protected: request.protected }, "history-repair", request.allowProtected === true);
358
+ }
359
+ await connection.execute("commit");
360
+ return restamped;
361
+ } catch (error) {
362
+ await connection.execute("rollback");
363
+ throw error;
364
+ }
365
+ }
366
+ var RESTAMP = `with pairs as (
367
+ select * from json_to_recordset($1::json) as p(id text, mark text, legacy text, startup text)
368
+ ), history as (
369
+ update okm_history h set catalog_hash = p.startup from pairs p
370
+ where h.migration_id in (p.id, p.mark) and h.catalog_hash = p.legacy
371
+ returning p.id, h.migration_id
372
+ ), meta as (
373
+ update okm_meta m set catalog_hash = p.startup from pairs p
374
+ where m.id = 'head' and m.migration_id in (p.id, p.mark) and m.catalog_hash = p.legacy
375
+ and m.migration_id in (select migration_id from history)
376
+ returning m.id
377
+ )
378
+ select distinct id from history order by id`;
335
379
  function joinMigrations(cwd, migrations) {
336
380
  return join(cwd, migrations ?? "migrations");
337
381
  }
@@ -4,12 +4,12 @@ import {
4
4
  import {
5
5
  withHttp,
6
6
  settleCall
7
- } from "./kkzwp3d2.js";
7
+ } from "./bt9sfq0z.js";
8
8
  import {
9
9
  rejectKeys,
10
10
  isRecord,
11
11
  fail
12
- } from "./xrfnq5k8.js";
12
+ } from "./qgvt8nx1.js";
13
13
  import {
14
14
  OkmError2
15
15
  } from "./52szzakm.js";
@@ -2,10 +2,11 @@ import {
2
2
  assertAuthorDrift2,
3
3
  catalogQuery2,
4
4
  managedRoleOptions2
5
- } from "./xghkt7a9.js";
6
- import"./n5y9zyj1.js";
7
- import"./41kv2xdm.js";
8
- import"./8jb4ymh2.js";
5
+ } from "./wxn4b7pp.js";
6
+ import"./fancm5pt.js";
7
+ import"./ayz64vzj.js";
8
+ import"./8xsbagad.js";
9
+ import"./8bwbwy8h.js";
9
10
  export {
10
11
  assertAuthorDrift2 as assertAuthorDrift,
11
12
  catalogQuery2 as catalogQuery,
@@ -11,7 +11,7 @@ async function assertCompatible(pool, schema, recordedHash, source, options) {
11
11
  if (code.artifact !== undefined) {
12
12
  const artifact = code.artifact;
13
13
  await loadOnce(`text\x00${artifact.hash}`, async () => {
14
- const { loadTrustedCatalog } = await import("./6693j9rs.js");
14
+ const { loadTrustedCatalog } = await import("./5fqx9yh4.js");
15
15
  loadTrustedCatalog(artifact.text, artifact.hash);
16
16
  });
17
17
  } else if (code.fromFile) {
@@ -25,7 +25,7 @@ async function assertCompatible(pool, schema, recordedHash, source, options) {
25
25
  }
26
26
  });
27
27
  }
28
- const { loadTrustedCatalog } = await import("./6693j9rs.js");
28
+ const { loadTrustedCatalog } = await import("./5fqx9yh4.js");
29
29
  loadTrustedCatalog(text, code.hash);
30
30
  });
31
31
  }
@@ -39,7 +39,7 @@ async function codeHash(schema, source) {
39
39
  const listed = await readHashFile(source.catalogDir);
40
40
  if (listed !== undefined)
41
41
  return { hash: listed, fromFile: true };
42
- const { catalogHash } = await import("./6693j9rs.js");
42
+ const { catalogHash } = await import("./5fqx9yh4.js");
43
43
  return { hash: catalogHash(schemaCatalog(schema)), fromFile: false };
44
44
  }
45
45
  function schemaCatalog(schema) {
@@ -1,4 +1,4 @@
1
- import"../shared/8jb4ymh2.js";
1
+ import"../shared/8bwbwy8h.js";
2
2
  import"../shared/n442h54c.js";
3
3
  import"../shared/wqem4jed.js";
4
4
  import {
@@ -9,9 +9,9 @@ import {
9
9
  generateProject,
10
10
  planProject,
11
11
  checkProject
12
- } from "../shared/q6zsyh31.js";
13
- import"../shared/n5y9zyj1.js";
14
- import"../shared/41kv2xdm.js";
12
+ } from "../shared/xdpj5kkm.js";
13
+ import"../shared/ayz64vzj.js";
14
+ import"../shared/8xsbagad.js";
15
15
  import {
16
16
  OkmError2
17
17
  } from "../shared/52szzakm.js";
@@ -57,12 +57,12 @@ async function run(argv, io) {
57
57
  return;
58
58
  }
59
59
  if (command === "dev") {
60
- const { devProject } = await import("../shared/yjw02enp.js");
60
+ const { devProject } = await import("../shared/fyqkk1m0.js");
61
61
  stdout(await devProject(cwd));
62
62
  return;
63
63
  }
64
64
  if (command === "push") {
65
- const { pushProject } = await import("../shared/kj680nxv.js");
65
+ const { pushProject } = await import("../shared/rasvvzgz.js");
66
66
  stdout(await pushProject(cwd, invoke(splitFlags(rest))));
67
67
  return;
68
68
  }
@@ -81,17 +81,17 @@ async function run(argv, io) {
81
81
  return;
82
82
  }
83
83
  if (sub === "apply") {
84
- const { applyProject } = await import("../shared/kj680nxv.js");
84
+ const { applyProject } = await import("../shared/rasvvzgz.js");
85
85
  stdout(await applyProject(cwd, invoke(parsed), stdout));
86
86
  return;
87
87
  }
88
88
  if (sub === "status") {
89
- const { statusProject } = await import("../shared/c5g81ngb.js");
89
+ const { statusProject } = await import("../shared/bzsjtd7c.js");
90
90
  stdout(await statusProject(cwd, invoke(parsed)));
91
91
  return;
92
92
  }
93
93
  if (sub === "check") {
94
- const { checkMigrations } = await import("../shared/2321avmn.js");
94
+ const { checkMigrations } = await import("../shared/r73pt594.js");
95
95
  const provision = parsed.flags.includes("--provision") || rest.slice(1).includes("--provision");
96
96
  stdout(await checkMigrations(cwd, invoke(parsed), { provision }));
97
97
  return;
@@ -104,13 +104,13 @@ async function run(argv, io) {
104
104
  fix: { summary: "Pass okm seed <file>." }
105
105
  });
106
106
  }
107
- const { seedProject } = await import("../shared/ady1ms74.js");
107
+ const { seedProject } = await import("../shared/jdgqqx31.js");
108
108
  stdout(await seedProject(cwd, parsed.name, invoke(parsed)));
109
109
  return;
110
110
  }
111
111
  if (command === "doctor") {
112
112
  const parsed = splitFlags(rest);
113
- const { doctorProject } = await import("../shared/84ptn35q.js");
113
+ const { doctorProject } = await import("../shared/qy9rdq0g.js");
114
114
  stdout(await doctorProject(cwd, parsed.name, invoke(parsed)));
115
115
  return;
116
116
  }
@@ -122,7 +122,7 @@ async function run(argv, io) {
122
122
  });
123
123
  }
124
124
  if (sub === "list" || sub === "check") {
125
- const { extProject } = await import("../shared/tny2t3sm.js");
125
+ const { extProject } = await import("../shared/990a291j.js");
126
126
  stdout(await extProject(cwd, sub, invoke(splitFlags(rest.slice(1)))));
127
127
  return;
128
128
  }
@@ -90,6 +90,8 @@ export type ApplyRequest = {
90
90
  export type ApplyReport = {
91
91
  readonly target: string;
92
92
  readonly applied: readonly string[];
93
+ /** Migrations whose stored hash moved from the pre-D208 hash to the startup hash. */
94
+ readonly restamped?: readonly string[];
93
95
  /** Set when the runner issued `SET ROLE` at session start. */
94
96
  readonly setRole?: string;
95
97
  };
@@ -7,6 +7,13 @@ import { type PlanStep } from "./plan.js";
7
7
  export type StoredMigration = {
8
8
  readonly id: string;
9
9
  readonly catalogHash: string;
10
+ /**
11
+ * The hash written before D208, which counted roles and grants.
12
+ *
13
+ * Set only when the catalog has them. Apply moves a stored copy of it to
14
+ * {@link StoredMigration.catalogHash}.
15
+ */
16
+ readonly legacyHash?: string;
10
17
  readonly steps: readonly PlanStep[];
11
18
  };
12
19
  /**
@@ -1,23 +1,25 @@
1
1
  import"../../shared/wqem4jed.js";
2
- import"../../shared/8jb4ymh2.js";
2
+ import"../../shared/8bwbwy8h.js";
3
3
  import"../../shared/n442h54c.js";
4
4
  import {
5
5
  applyTarget2,
6
6
  backfillTiming2
7
- } from "../../shared/s4mb6a4b.js";
7
+ } from "../../shared/xhh1srw3.js";
8
8
  import {
9
9
  loadMigrations,
10
10
  loadHeadSnapshot,
11
11
  readReference
12
- } from "../../shared/7nk68fj8.js";
12
+ } from "../../shared/kdkxh3kb.js";
13
+ import"../../shared/szm0cksa.js";
14
+ import"../../shared/fancm5pt.js";
13
15
  import {
14
16
  assertTargetPolicy,
15
17
  selectTarget,
16
18
  loadBuiltSchema,
17
19
  loadConfig
18
- } from "../../shared/q6zsyh31.js";
19
- import"../../shared/n5y9zyj1.js";
20
- import"../../shared/41kv2xdm.js";
20
+ } from "../../shared/xdpj5kkm.js";
21
+ import"../../shared/ayz64vzj.js";
22
+ import"../../shared/8xsbagad.js";
21
23
  import {
22
24
  OkmError2
23
25
  } from "../../shared/52szzakm.js";
@@ -56,6 +56,9 @@ export declare const tenantProbe = "00000000-0000-4000-8000-000000000001";
56
56
  /**
57
57
  * Reads every table in declaration order.
58
58
  *
59
+ * Views and materialized views are in the query model too. They have no rows
60
+ * of their own to insert, so they are left out.
61
+ *
59
62
  * @param schema - Compiled schema
60
63
  * @returns One facts object per table
61
64
  */
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  testing2
3
- } from "../../shared/ygem90rn.js";
4
- import"../../shared/41kv2xdm.js";
5
- import"../../shared/8jb4ymh2.js";
3
+ } from "../../shared/g516zdsb.js";
4
+ import"../../shared/8xsbagad.js";
5
+ import"../../shared/8bwbwy8h.js";
6
6
  export {
7
7
  testing2 as testing
8
8
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okmodel",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "okmodel is a catalog-first TypeScript ORM, PostgreSQL first.",
5
5
  "keywords": [
6
6
  "migrations",