okmodel 0.8.0 → 0.9.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 (202) hide show
  1. package/README.md +14 -0
  2. package/dist/dialects/pg/ext/btree-gin.d.ts +26 -0
  3. package/dist/dialects/pg/ext/btree-gin.js +20 -0
  4. package/dist/dialects/pg/ext/btree-gist.d.ts +26 -0
  5. package/dist/dialects/pg/ext/btree-gist.js +20 -0
  6. package/dist/dialects/pg/ext/call.d.ts +53 -0
  7. package/dist/dialects/pg/ext/citext.js +1 -1
  8. package/dist/dialects/pg/ext/feature.d.ts +26 -0
  9. package/dist/dialects/pg/ext/fuzzystrmatch.d.ts +34 -0
  10. package/dist/dialects/pg/ext/fuzzystrmatch.js +33 -0
  11. package/dist/dialects/pg/ext/hstore.d.ts +41 -0
  12. package/dist/dialects/pg/ext/hstore.js +29 -0
  13. package/dist/dialects/pg/ext/index.d.ts +56 -0
  14. package/dist/dialects/pg/ext/index.js +1 -1
  15. package/dist/dialects/pg/ext/ltree.d.ts +41 -0
  16. package/dist/dialects/pg/ext/ltree.js +29 -0
  17. package/dist/dialects/pg/ext/pg-trgm.js +4 -13
  18. package/dist/dialects/pg/ext/pgcrypto.d.ts +33 -0
  19. package/dist/dialects/pg/ext/pgcrypto.js +33 -0
  20. package/dist/dialects/pg/ext/unaccent.d.ts +26 -0
  21. package/dist/dialects/pg/ext/unaccent.js +21 -0
  22. package/dist/dialects/pg/ext/using.d.ts +23 -0
  23. package/dist/dialects/pg/ext/versions.d.ts +36 -0
  24. package/dist/dialects/pg/external.d.ts +19 -0
  25. package/dist/dialects/pg/fn/index.js +4 -4
  26. package/dist/dialects/pg/index.d.ts +1 -0
  27. package/dist/dialects/pg/index.js +16 -11
  28. package/dist/dialects/pg/view/index.js +5 -5
  29. package/dist/dialects/pg/view/scratch.d.ts +4 -1
  30. package/dist/runtime/artifact-file.d.ts +22 -0
  31. package/dist/runtime/client.d.ts +10 -0
  32. package/dist/runtime/drift-detail.d.ts +2 -1
  33. package/dist/runtime/drift.d.ts +3 -10
  34. package/dist/runtime/pg/bun.js +4 -4
  35. package/dist/runtime/pg/neon.js +4 -4
  36. package/dist/runtime/pg/pg.js +4 -4
  37. package/dist/runtime/pg/pglite.js +4 -4
  38. package/dist/runtime/pg/postgresjs.js +4 -4
  39. package/dist/runtime/server-check.d.ts +36 -6
  40. package/dist/runtime/traits/index.js +5 -5
  41. package/dist/runtime/validate/index.js +1 -1
  42. package/dist/shared/{4m6hskg8.js → 0j6qe91y.js} +4 -4
  43. package/dist/shared/{14x60fbf.js → 1mxm04fy.js} +5 -5
  44. package/dist/shared/{b6d6p0zc.js → 2szgv6yj.js} +5 -5
  45. package/dist/shared/{f4jy1j7x.js → 2zdxkt7b.js} +909 -100
  46. package/dist/shared/{mnvjvqyp.js → 3456242y.js} +17 -17
  47. package/dist/shared/3t6kw83m.js +1 -1
  48. package/dist/shared/{6m78c8ss.js → 5kyb3tqx.js} +1 -1
  49. package/dist/shared/61bmrmhr.js +35 -0
  50. package/dist/shared/{zbqbmmrp.js → 62b603gr.js} +8 -8
  51. package/dist/shared/{jgqj11w4.js → 6f0z3hzh.js} +4 -0
  52. package/dist/shared/{dpc2r7rb.js → 6nae0spm.js} +150 -89
  53. package/dist/shared/{0wrea3jq.js → 71n0jmhc.js} +1 -1
  54. package/dist/shared/7ba5h6pb.js +17 -0
  55. package/dist/shared/{k86n8vq3.js → 8jesqsrk.js} +1 -1
  56. package/dist/shared/{qd9hhd8f.js → 8n688yjg.js} +1 -1
  57. package/dist/shared/{zgex00fd.js → 8qzkd9f3.js} +5 -5
  58. package/dist/shared/{mkrn359n.js → 90sg0w5a.js} +159 -31
  59. package/dist/shared/{7ghwamrf.js → 99qp9vtg.js} +1 -1
  60. package/dist/shared/{bxas03mq.js → 9dtgn1z2.js} +1 -1
  61. package/dist/shared/{p5nh3r8q.js → aksb89mn.js} +2 -2
  62. package/dist/shared/{wcrheftc.js → bphrgwz9.js} +2 -2
  63. package/dist/shared/{wz2a78mp.js → c3mvnq7a.js} +1 -1
  64. package/dist/shared/{pan0370z.js → ccsmhv9r.js} +24 -6
  65. package/dist/shared/{n0jmpgj1.js → cexb7z6b.js} +1 -1
  66. package/dist/shared/{wvdjznah.js → cf8zdz5p.js} +5 -5
  67. package/dist/shared/{3449rcae.js → ckz05z15.js} +4 -4
  68. package/dist/shared/{35q0n9tz.js → dd5pmnky.js} +7 -7
  69. package/dist/shared/{e8zyaqvj.js → ds229x4r.js} +1 -1
  70. package/dist/{tooling/shared/yw30vnq2.js → shared/e275q7sd.js} +1 -1
  71. package/dist/shared/{mfedzr74.js → ebhz8vh6.js} +4 -4
  72. package/dist/shared/{z581d7ny.js → fdsz3w80.js} +2 -2
  73. package/dist/shared/{sjk86yrx.js → fk9vef30.js} +84 -73
  74. package/dist/shared/{needfe47.js → g89fmz5s.js} +1 -1
  75. package/dist/shared/{m4xff2a6.js → ghqzdp94.js} +2 -2
  76. package/dist/shared/h9811jjm.js +17 -0
  77. package/dist/shared/{kj9d8maq.js → jpybhf98.js} +1 -1
  78. package/dist/shared/kzgrnckd.js +29 -0
  79. package/dist/shared/{agsfb86s.js → mazpbcdj.js} +4 -4
  80. package/dist/shared/{195pzzzz.js → mgaq2sd3.js} +10 -7
  81. package/dist/shared/{5mtf6cj3.js → mvmm3xpb.js} +5 -2
  82. package/dist/shared/{p3xbdcvt.js → myk8fswx.js} +55 -6
  83. package/dist/shared/{njga14v4.js → n306gqkd.js} +8 -8
  84. package/dist/shared/n5whk3mt.js +665 -0
  85. package/dist/shared/{bah9nbg3.js → npdftanb.js} +12 -20
  86. package/dist/shared/{16kvjebh.js → pg4ezgyf.js} +7 -26
  87. package/dist/{tooling/shared/08kemxjd.js → shared/pgsak1yw.js} +1 -1
  88. package/dist/shared/{jp36k7dp.js → qvwwp1mp.js} +61 -40
  89. package/dist/shared/rbxt795q.js +1766 -0
  90. package/dist/shared/{g5yc06ka.js → s7he5e5d.js} +1 -1
  91. package/dist/shared/{hfqmpasr.js → ss2kv2rs.js} +5 -5
  92. package/dist/shared/stfa9xcw.js +450 -0
  93. package/dist/{tooling/shared/rs1jb051.js → shared/tr64w5p0.js} +1 -1
  94. package/dist/shared/{jebgrkeq.js → tw1nvvfj.js} +2 -2
  95. package/dist/shared/{v1wad97q.js → wvtjg5m3.js} +1 -1
  96. package/dist/shared/xqacq37x.js +61 -0
  97. package/dist/shared/{n05z9nwz.js → xtsydxjg.js} +1 -1
  98. package/dist/shared/{jx2m62cs.js → xv8qj97g.js} +5 -5
  99. package/dist/shared/{63f4ksbz.js → xwhdcrm4.js} +1 -1
  100. package/dist/shared/{hm5f8jby.js → yvabyg9k.js} +6 -6
  101. package/dist/shared/yybhre6n.js +136 -0
  102. package/dist/shared/zdqf8k5d.js +8 -0
  103. package/dist/tooling/cli.js +94 -22
  104. package/dist/tooling/driver-run.js +15 -332
  105. package/dist/tooling/github/comment.d.ts +50 -0
  106. package/dist/tooling/github/post-comment.d.ts +17 -0
  107. package/dist/tooling/migrate/commands.d.ts +2 -1
  108. package/dist/tooling/migrate/config.d.ts +13 -0
  109. package/dist/tooling/migrate/export.d.ts +165 -0
  110. package/dist/tooling/migrate/ext-surface.d.ts +80 -0
  111. package/dist/tooling/migrate/ext.d.ts +31 -4
  112. package/dist/tooling/migrate/import-drizzle.d.ts +40 -0
  113. package/dist/tooling/migrate/index.d.ts +3 -0
  114. package/dist/tooling/migrate/index.js +55 -10
  115. package/dist/tooling/migrate/lint-rules.d.ts +18 -1
  116. package/dist/tooling/migrate/lint.d.ts +14 -1
  117. package/dist/tooling/migrate/place.d.ts +18 -0
  118. package/dist/tooling/migrate/plan-json.d.ts +65 -0
  119. package/dist/tooling/migrate/project.d.ts +10 -1
  120. package/dist/tooling/migrate/pull-emit.d.ts +98 -0
  121. package/dist/tooling/migrate/pull-routines.d.ts +126 -0
  122. package/dist/tooling/migrate/pull-verify.d.ts +26 -0
  123. package/dist/tooling/migrate/pull.d.ts +62 -0
  124. package/dist/tooling/migrate/reprint.d.ts +32 -0
  125. package/dist/tooling/migrate/sandbox.d.ts +8 -2
  126. package/dist/tooling/migrate/schema-api.d.ts +43 -0
  127. package/dist/tooling/migrate/sql-lex.d.ts +18 -0
  128. package/dist/tooling/shared/{3m1hkg7z.js → 04svnxxj.js} +4 -4
  129. package/dist/tooling/shared/{ppnnnvj8.js → 0j0jtse1.js} +1 -1
  130. package/dist/tooling/shared/{z8d7ptht.js → 0r05zhyq.js} +5 -5
  131. package/dist/tooling/shared/{a6pp9d12.js → 1800eymw.js} +3 -3
  132. package/dist/tooling/shared/{cmptmb4f.js → 35zemrmf.js} +1 -1
  133. package/dist/tooling/shared/{w7qe8sj1.js → 3rmaz3pq.js} +1 -1
  134. package/dist/{shared/q0cqt2sp.js → tooling/shared/3yn79q5m.js} +1 -1
  135. package/dist/tooling/shared/{2revefqt.js → 57btdkgm.js} +2 -2
  136. package/dist/tooling/shared/{ma2340rx.js → 5bmksndh.js} +2 -2
  137. package/dist/tooling/shared/{9xzm7hjg.js → 5p8km5jb.js} +3 -3
  138. package/dist/tooling/shared/{xhrnjch9.js → 5x3pf400.js} +3 -3
  139. package/dist/tooling/shared/{wwnekq5n.js → 5zrzffnk.js} +1 -1
  140. package/dist/tooling/shared/{p7f08ktn.js → 62fxpc1p.js} +7 -7
  141. package/dist/tooling/shared/{7ae7rjmn.js → 68tf18v4.js} +2 -2
  142. package/dist/tooling/shared/{rf83gr2d.js → 6vk28rjp.js} +7 -3
  143. package/dist/tooling/shared/76pv6qff.js +9 -0
  144. package/dist/tooling/shared/{bz2dqhab.js → 7aews1zg.js} +3 -3
  145. package/dist/tooling/shared/{9kazs5p6.js → 7b3xp9gc.js} +3 -3
  146. package/dist/tooling/shared/{4d2w25vw.js → 7pxncnzs.js} +2 -2
  147. package/dist/tooling/shared/{zvnhh1n0.js → 829fjxyw.js} +2 -2
  148. package/dist/tooling/shared/{dzx85q70.js → 8m5znpdt.js} +1 -1
  149. package/dist/tooling/shared/{g9ad4n80.js → 8yr7ges1.js} +7 -7
  150. package/dist/tooling/shared/{tn8gay14.js → 9qr9rkbh.js} +6 -6
  151. package/dist/tooling/shared/{8sqrsw3s.js → 9sfbtwsk.js} +3 -3
  152. package/dist/{shared/bnby0esn.js → tooling/shared/9wsnsvbf.js} +1 -1
  153. package/dist/tooling/shared/{aftb2mwr.js → a2xe04bm.js} +1 -1
  154. package/dist/tooling/shared/{nf7jmhfa.js → a4pzghha.js} +2 -2
  155. package/dist/tooling/shared/{y5656f0e.js → am04v8na.js} +5 -5
  156. package/dist/tooling/shared/{417zdsk7.js → asgr07mp.js} +5 -5
  157. package/dist/tooling/shared/{pqy21k24.js → c0xevn1h.js} +4 -4
  158. package/dist/tooling/shared/dhatassp.js +134 -0
  159. package/dist/tooling/shared/{spk1jg3r.js → ezqn88nj.js} +8 -8
  160. package/dist/tooling/shared/{6nyfyw70.js → f77nnfqy.js} +2 -2
  161. package/dist/tooling/shared/{wt7j7nf6.js → fh07z1dt.js} +1 -1
  162. package/dist/tooling/shared/{3rrw5w8f.js → gqwevek4.js} +1 -1
  163. package/dist/tooling/shared/{f9mphxej.js → hfq3n3bd.js} +346 -19
  164. package/dist/tooling/shared/{vs0t6qt8.js → j664qjrt.js} +2 -2
  165. package/dist/tooling/shared/{733a1tq3.js → jpgmjsx3.js} +3 -3
  166. package/dist/tooling/shared/{mtrqn2hn.js → jr2nmr81.js} +22 -30
  167. package/dist/{shared/mtw6jz76.js → tooling/shared/jsjjz875.js} +1 -1
  168. package/dist/tooling/shared/{2wtvc7rw.js → kbqnrs1x.js} +2 -2
  169. package/dist/tooling/shared/{gfvtj6d0.js → kz715295.js} +7 -7
  170. package/dist/tooling/shared/{a7q7t4n3.js → m3xt8b1h.js} +2 -2
  171. package/dist/tooling/shared/{dw08f3m8.js → m4hhb8aa.js} +2 -2
  172. package/dist/tooling/shared/{y031jct9.js → mw5npye0.js} +2 -2
  173. package/dist/tooling/shared/{vraj6d74.js → nxq95eb6.js} +3 -3
  174. package/dist/tooling/shared/{fb9k2qwd.js → qartgazh.js} +11 -30
  175. package/dist/tooling/shared/{xjs6zqtc.js → rcywj2w8.js} +9 -9
  176. package/dist/tooling/shared/{dy672fz6.js → s6qha57m.js} +2 -2
  177. package/dist/tooling/shared/{vx86qjv8.js → shjs0379.js} +3 -3
  178. package/dist/tooling/shared/{345tbc2k.js → sjwkt1pg.js} +1 -1
  179. package/dist/tooling/shared/{rq5kk8j6.js → stebqyyd.js} +3 -3
  180. package/dist/tooling/shared/{yk9mp7vb.js → t4xveemq.js} +4 -4
  181. package/dist/tooling/shared/{djydjpqt.js → t6zjeake.js} +5 -5
  182. package/dist/tooling/shared/{zhwnfyb2.js → tcwpjvxe.js} +1 -1
  183. package/dist/tooling/shared/{72fyg4zv.js → tpssp7ac.js} +1 -1
  184. package/dist/tooling/shared/{jne7b93p.js → v6j1ep6w.js} +3 -3
  185. package/dist/tooling/shared/{ec71zqgt.js → vwr2y833.js} +2 -2
  186. package/dist/tooling/shared/{j9t5s12a.js → w17sj05d.js} +2 -2
  187. package/dist/tooling/shared/{3tq8pnb8.js → w5d89rb4.js} +1 -1
  188. package/dist/tooling/shared/{smn6kz1p.js → wbwq1jsa.js} +2 -2
  189. package/dist/tooling/shared/{pwsytxm5.js → wezxf3h8.js} +1 -1
  190. package/dist/tooling/shared/{5bvw2nev.js → yb4kd19s.js} +1 -1
  191. package/dist/tooling/shared/{gmcf9cxf.js → ybdew6j7.js} +2 -2
  192. package/dist/tooling/shared/{ep8zh3bk.js → yfedr1zb.js} +1 -1
  193. package/dist/tooling/shared/{ddjtfgnx.js → yhp829bx.js} +3 -3
  194. package/dist/tooling/shared/{yfr8hzhm.js → ytk1tjs0.js} +1 -1
  195. package/dist/tooling/shared/{03k6res6.js → zs9aymcp.js} +1 -1
  196. package/dist/tooling/shared/zx3v9phv.js +8 -0
  197. package/dist/tooling/testing/index.js +2 -2
  198. package/package.json +38 -9
  199. package/dist/shared/fjpnhqan.js +0 -71
  200. package/dist/shared/n41w4fbz.js +0 -113
  201. package/dist/tooling/shared/pw8fgahx.js +0 -69
  202. /package/dist/shared/{ae4j5f42.js → mfvx6kjx.js} +0 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Catalog reads shared by `okm ext scaffold` and `okm ext test`.
3
+ *
4
+ * Both are read-only. The queries are `pg_depend`, `pg_type`, `pg_proc`,
5
+ * `pg_operator`, and `pg_settings`. Nothing is created.
6
+ */
7
+ import type { DriverPool } from "../../contracts/driver.js";
8
+ import type { Extension, ExtensionFunction, ExtensionIndexMethod, ExtensionOperator, ExtensionProvides, ExtensionType } from "../../dialects/pg/ext/index.js";
9
+ /** One extension as the connected server describes it. */
10
+ export type ServerSurface = {
11
+ readonly name: string;
12
+ readonly version: string;
13
+ readonly schema: string;
14
+ readonly relocatable: boolean;
15
+ readonly serverMajor: number;
16
+ readonly types: readonly ExtensionType[];
17
+ readonly operators: readonly ExtensionOperator[];
18
+ readonly functions: readonly ExtensionFunction[];
19
+ readonly indexMethods: readonly ExtensionIndexMethod[];
20
+ readonly settings: readonly string[];
21
+ };
22
+ /**
23
+ * Reads one installed extension.
24
+ *
25
+ * A name that is not installed is OKM1811. The connection is not asked to
26
+ * create it.
27
+ *
28
+ * @param pool - Connected server
29
+ * @param name - Extension name
30
+ * @returns The catalog surface
31
+ */
32
+ export declare function readSurface(pool: DriverPool, name: string): Promise<ServerSurface>;
33
+ /**
34
+ * Prints a starting `extension()` definition.
35
+ *
36
+ * The developer owns the file. `requires` and `provides` are the fields
37
+ * `okm ext test` reads. Settings are a comment, because they are not part
38
+ * of the definition.
39
+ *
40
+ * @param surface - Catalog read
41
+ * @returns TypeScript source, including the trailing newline
42
+ */
43
+ export declare function renderScaffold(surface: ServerSurface): string;
44
+ /**
45
+ * Lists mismatches between a definition and the server.
46
+ *
47
+ * An empty list means the definition matches. Version failures and signature
48
+ * failures are both lines in that list.
49
+ *
50
+ * @param declared - The loaded `extension()` value
51
+ * @param server - The catalog read for `declared.name`
52
+ * @returns Mismatch lines, stable order
53
+ */
54
+ export declare function surfaceMismatches(declared: Extension, server: ServerSurface): readonly string[];
55
+ /**
56
+ * Throws when {@link surfaceMismatches} found any line.
57
+ *
58
+ * Version lines are OKM1812. A signature line is `invalid`. Both are listed
59
+ * in the message.
60
+ *
61
+ * @param name - Extension name
62
+ * @param mismatches - Lines from {@link surfaceMismatches}
63
+ */
64
+ export declare function refuseMismatches(name: string, mismatches: readonly string[]): void;
65
+ /**
66
+ * Reports whether a value is an `extension()` result.
67
+ *
68
+ * @param value - A module export
69
+ * @returns `true` when it has a name and `contribute`
70
+ */
71
+ export declare function isExtension(value: unknown): value is Extension;
72
+ /**
73
+ * Reads `extension()` values exported by a loaded module.
74
+ *
75
+ * @param imported - Module namespace
76
+ * @returns The definitions, in export order
77
+ */
78
+ export declare function extensionsFromModule(imported: unknown): readonly Extension[];
79
+ /** Provides kept on the type so a scaffold round-trip can name them. */
80
+ export type { ExtensionProvides };
@@ -1,9 +1,10 @@
1
1
  /**
2
- * `okm ext list` and `okm ext check`.
2
+ * `okm ext list`, `check`, `scaffold`, and `test`.
3
3
  *
4
- * Both talk to the selected target. List prints every extension the server
5
- * can install, and the installed version when one is present. Check compares
6
- * the schema's declarations with what is installed.
4
+ * All four talk to the selected target and are read-only, including on a
5
+ * protected target. List prints every extension the server can install.
6
+ * Check compares the schema's declarations with what is installed. Scaffold
7
+ * prints a starting definition. Test checks that definition against the server.
7
8
  */
8
9
  import { type InvokeFlags } from "./policy.js";
9
10
  /**
@@ -15,3 +16,29 @@ import { type InvokeFlags } from "./policy.js";
15
16
  * @returns Text for stdout, including the trailing newline
16
17
  */
17
18
  export declare function extProject(cwd: string, command: "list" | "check", flags: InvokeFlags): Promise<string>;
19
+ /**
20
+ * Prints a starting definition for one installed extension.
21
+ *
22
+ * `--out` writes the file when that path does not exist. An existing file
23
+ * is refused and nothing is written. Without `--out`, the text is returned
24
+ * for stdout.
25
+ *
26
+ * @param cwd - Project directory
27
+ * @param name - Extension name
28
+ * @param flags - Target and protection flags
29
+ * @param out - File to write, when the caller passed `--out`
30
+ * @returns The definition, or a one-line wrote message
31
+ */
32
+ export declare function extScaffold(cwd: string, name: string, flags: InvokeFlags, out?: string): Promise<string>;
33
+ /**
34
+ * Checks one definition file against the connected server.
35
+ *
36
+ * Every declared type, operator, function, and index method must exist with
37
+ * the declared signature. `requires` must be met (OKM1812).
38
+ *
39
+ * @param cwd - Project directory
40
+ * @param file - Definition file, relative to `cwd` or absolute
41
+ * @param flags - Target and protection flags
42
+ * @returns `ok <name>` for each definition
43
+ */
44
+ export declare function extTest(cwd: string, file: string, flags: InvokeFlags): Promise<string>;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `okm import drizzle` reads a Drizzle schema and writes table files.
3
+ *
4
+ * The schema is imported with the project's own `drizzle-orm`. That import
5
+ * runs the file. okmodel does not depend on drizzle-orm. The catalog is
6
+ * written by the same emitter as `okm pull`.
7
+ */
8
+ import { type PullSkip } from "./pull-emit.js";
9
+ /** What `okm import drizzle` prints, and the objects the files leave out. */
10
+ export type ImportDrizzleResult = {
11
+ /** Report text, including the trailing newline. */
12
+ readonly text: string;
13
+ /** Objects that were not written. */
14
+ readonly skipped: readonly PullSkip[];
15
+ /** Postgres schema the tables share. `schema()` still compiles `public`. */
16
+ readonly namespace: string;
17
+ };
18
+ /**
19
+ * Imports a Drizzle schema and writes one table file per table, plus the schema file.
20
+ *
21
+ * The path is a module in the project. `--out` is the directory that receives
22
+ * `schema.ts` and `tables/`. Without it, an `okmodel.config.ts` in `cwd`
23
+ * supplies the layout. A project that has no config yet writes `schema.ts`
24
+ * and `tables/` in `cwd`.
25
+ *
26
+ * @param cwd - Project directory the files are written into
27
+ * @param argv - Arguments after `import drizzle`
28
+ * @returns The report and the Postgres schema name
29
+ */
30
+ export declare function importDrizzle(cwd: string, argv: readonly string[]): Promise<ImportDrizzleResult>;
31
+ /**
32
+ * Reads the schema path and `--out`.
33
+ *
34
+ * @param argv - Arguments after `import drizzle`
35
+ * @returns The path and the optional output directory
36
+ */
37
+ export declare function parseImportArgs(argv: readonly string[]): {
38
+ readonly path: string;
39
+ readonly out: string | undefined;
40
+ };
@@ -2,7 +2,10 @@
2
2
  * Public entry for `okmodel/migrate`.
3
3
  *
4
4
  * `defineConfig`, its types, and `provision` for one configured target.
5
+ * `describe` and `buildCatalog` are the programmatic schema API.
5
6
  * The CLI imports planning and apply helpers from their modules.
6
7
  */
7
8
  export { defineConfig, type MigrateConfig, type TargetInput } from "./config.js";
9
+ export { type LogicalIdentity } from "./export.js";
10
+ export { buildCatalog, describe, type SchemaDescription } from "./schema-api.js";
8
11
  export { provision } from "./provision.js";
@@ -1,35 +1,78 @@
1
- import"../../shared/35q0n9tz.js";
2
- import"../../shared/12z7aznj.js";
1
+ import {
2
+ serializeCatalog2,
3
+ parseCatalog2
4
+ } from "../../shared/12z7aznj.js";
5
+ import"../../shared/fk9vef30.js";
6
+ import"../../shared/dd5pmnky.js";
3
7
  import"../../shared/n442h54c.js";
4
8
  import {
5
9
  applyTarget2,
6
10
  backfillTiming2
7
- } from "../../shared/pan0370z.js";
11
+ } from "../../shared/ccsmhv9r.js";
8
12
  import {
9
13
  readReference
10
- } from "../../shared/mnvjvqyp.js";
11
- import"../../shared/kj9d8maq.js";
12
- import"../../shared/p3xbdcvt.js";
14
+ } from "../../shared/3456242y.js";
15
+ import"../../shared/jpybhf98.js";
16
+ import"../../shared/myk8fswx.js";
13
17
  import {
14
18
  projectPath,
19
+ LOGICAL_FORMAT,
15
20
  loadMigrations,
16
21
  loadHeadSnapshot,
17
22
  loadBuiltSchema,
18
23
  loadConfig
19
- } from "../../shared/f4jy1j7x.js";
24
+ } from "../../shared/2zdxkt7b.js";
20
25
  import {
21
26
  assertTargetPolicy,
22
27
  selectTarget
23
- } from "../../shared/dpc2r7rb.js";
24
- import"../../shared/sjk86yrx.js";
28
+ } from "../../shared/6nae0spm.js";
29
+ import {
30
+ canonicalJson
31
+ } from "../../shared/358zsv4r.js";
25
32
  import {
26
- OkmError2
33
+ OkmError2,
34
+ catalogError2
27
35
  } from "../../shared/52szzakm.js";
28
36
 
29
37
  // src/tooling/migrate/config.ts
30
38
  function defineConfig(config) {
31
39
  return config;
32
40
  }
41
+ // src/tooling/migrate/schema-api.ts
42
+ var LOGICAL_NAMESPACE = "public";
43
+ function describe(schema) {
44
+ const source = schemaCatalog(schema);
45
+ const document = JSON.parse(serializeCatalog2(source));
46
+ const text = canonicalJson({
47
+ catalog: document,
48
+ logical: {
49
+ format: LOGICAL_FORMAT,
50
+ name: LOGICAL_NAMESPACE,
51
+ namespace: LOGICAL_NAMESPACE
52
+ }
53
+ });
54
+ return JSON.parse(text);
55
+ }
56
+ function buildCatalog(description) {
57
+ if (description === null || typeof description !== "object" || !("catalog" in description)) {
58
+ catalogError2("OKM1027", "Catalog document is not an object.");
59
+ }
60
+ const body = description.catalog;
61
+ if (body === null || typeof body !== "object") {
62
+ catalogError2("OKM1027", "Catalog document is not an object.");
63
+ }
64
+ return parseCatalog2(JSON.stringify(body));
65
+ }
66
+ function schemaCatalog(schema) {
67
+ if (schema === null || typeof schema !== "object") {
68
+ catalogError2("OKM1020", "describe() needs the schema() result.");
69
+ }
70
+ const catalog = schema.catalog;
71
+ if (typeof catalog !== "object" || catalog === null || !("objects" in catalog)) {
72
+ catalogError2("OKM1020", "describe() needs the schema() result.");
73
+ }
74
+ return catalog;
75
+ }
33
76
  // src/tooling/migrate/provision.ts
34
77
  async function provision(target, cwd = process.cwd()) {
35
78
  const config = await loadConfig(cwd);
@@ -71,6 +114,8 @@ ${report.applied.map((id) => `applied ${id}`).join(`
71
114
  `;
72
115
  }
73
116
  export {
117
+ buildCatalog,
74
118
  defineConfig,
119
+ describe,
75
120
  provision
76
121
  };
@@ -42,10 +42,27 @@ export type ColumnRule = {
42
42
  * Step rules, lowest free code in each category.
43
43
  *
44
44
  * OKM1534 to OKM1537 are errors when the statement is not the safe form.
45
- * OKM1538 stays a warning: a rewriting type change has no safe form here.
45
+ * OKM1538 stays a warning, and only when the type change rewrites the table.
46
46
  */
47
47
  export declare const STEP_RULES: readonly StepRule[];
48
48
  /**
49
49
  * Type preferences. Warnings, read from the schema catalog by `okm check`.
50
50
  */
51
51
  export declare const COLUMN_RULES: readonly ColumnRule[];
52
+ /**
53
+ * Collapses whitespace and lowercases SQL outside quoted identifiers.
54
+ *
55
+ * @param sql - One statement
56
+ * @returns The comparison form
57
+ */
58
+ export declare function normalizedSql(sql: string): string;
59
+ /**
60
+ * A create or alter of a domain, or a `LANGUAGE sql` function.
61
+ *
62
+ * Offline lint cannot see the reprint. The allow is still for that statement.
63
+ * `okm migrate check` decides whether the text actually differs.
64
+ *
65
+ * @param sql - One statement
66
+ * @returns `true` when OKM1552 can fire for this statement
67
+ */
68
+ export declare function statementMayReprint(sql: string): boolean;
@@ -8,7 +8,7 @@
8
8
  import type { Catalog } from "../../contracts/catalog/types.js";
9
9
  import { OkmError } from "../../contracts/error.js";
10
10
  import { type LintSeverity } from "./lint-rules.js";
11
- import type { MigrationPlan } from "./plan.js";
11
+ import type { MigrationPlan, PlanStep } from "./plan.js";
12
12
  /** One finding. `place` is `step N`, `step N statement M`, or `table.column`. */
13
13
  export type Finding = {
14
14
  readonly severity: LintSeverity;
@@ -26,6 +26,19 @@ export type Finding = {
26
26
  * @returns Findings in step order, then code order
27
27
  */
28
28
  export declare function lintPlan(plan: MigrationPlan, before: Catalog, after: Catalog): readonly Finding[];
29
+ /**
30
+ * Warns when a replayed domain check or `LANGUAGE sql` body reprints.
31
+ *
32
+ * Called from `okm migrate check` after introspection. A warning does not
33
+ * fail the command. An allow with an empty reason, or a code the replay did
34
+ * not trigger, is OKM1510.
35
+ *
36
+ * @param declared - Catalog stored with the migration
37
+ * @param stored - Catalog read back from the scratch schema
38
+ * @param steps - Statements of that migration, including `-- okm-allow`
39
+ * @returns Findings in catalog order
40
+ */
41
+ export declare function lintReprints(declared: Catalog, stored: Catalog, steps: readonly PlanStep[]): readonly Finding[];
29
42
  /**
30
43
  * Lints type preferences on the author catalog.
31
44
  *
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Places a `schema()` catalog into the namespace from `defineConfig`.
3
+ *
4
+ * `schema()` compiles `public`. Planning reads this copy, so two catalogs
5
+ * on one database do not share table identities. An `external` table keeps
6
+ * the namespace from its snapshot. A catalog that is already `public` and
7
+ * has no external namespace is returned as itself, so its hash does not change.
8
+ */
9
+ import type { Catalog } from "../../contracts/catalog/types.js";
10
+ /**
11
+ * Rewrites managed objects into `namespace` and external tables into `externalNamespaces`.
12
+ *
13
+ * @param source - Catalog from `schema()`, after ownership is stamped
14
+ * @param namespace - Postgres schema this catalog owns. `public` is the default
15
+ * @param externalNamespaces - SQL table name to the owning catalog's namespace
16
+ * @returns `source` when nothing moves, otherwise a new catalog
17
+ */
18
+ export declare function placeCatalog(source: Catalog, namespace: string, externalNamespaces: ReadonlyMap<string, string>): Catalog;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Machine-readable `okm migrate plan --json` (D279).
3
+ *
4
+ * The document is the plan the comment renderer reads. It is not parsed
5
+ * back out of the human SQL text.
6
+ */
7
+ import type { MigrationClass } from "./classify.js";
8
+ import type { Finding } from "./lint.js";
9
+ import type { MigrationPlan, PlanStep } from "./plan.js";
10
+ /** One step in a plan document. `lock` matches the human `-- lock:` line. */
11
+ export type PlanStepJson = {
12
+ readonly class: MigrationClass;
13
+ readonly lock: string;
14
+ readonly sql: string;
15
+ };
16
+ /** One lint finding in a plan document. */
17
+ export type PlanFindingJson = {
18
+ readonly severity: "error" | "warning";
19
+ readonly code: string;
20
+ readonly place: string;
21
+ readonly reason: string;
22
+ readonly fix: string;
23
+ };
24
+ /**
25
+ * What `okm migrate plan --json` prints.
26
+ *
27
+ * `class` is the strictest class, the same value as the human header.
28
+ */
29
+ export type PlanDocument = {
30
+ readonly name: string;
31
+ readonly class: MigrationClass;
32
+ readonly steps: readonly PlanStepJson[];
33
+ readonly findings: readonly PlanFindingJson[];
34
+ };
35
+ /**
36
+ * Builds the document `okm migrate plan --json` prints.
37
+ *
38
+ * `lockText` is the same callback {@link formatPlan} uses, so a lock line
39
+ * that includes a row estimate is the same string in both outputs.
40
+ *
41
+ * @param plan - Plan the command already computed
42
+ * @param findings - Lint findings for that plan
43
+ * @param lockText - Annotated lock, when a target answered
44
+ * @returns The document
45
+ */
46
+ export declare function planDocument(plan: MigrationPlan, findings: readonly Finding[], lockText?: (step: PlanStep) => string): PlanDocument;
47
+ /**
48
+ * Serialises a plan document.
49
+ *
50
+ * @param plan - Plan the command already computed
51
+ * @param findings - Lint findings for that plan
52
+ * @param lockText - Annotated lock, when a target answered
53
+ * @returns JSON text ending in a newline
54
+ */
55
+ export declare function formatPlanJson(plan: MigrationPlan, findings: readonly Finding[], lockText?: (step: PlanStep) => string): string;
56
+ /**
57
+ * Reads a plan document.
58
+ *
59
+ * Extra fields are ignored. A missing field, or a class that is not
60
+ * `expand`, `contract`, or `unclassified`, is refused.
61
+ *
62
+ * @param text - JSON from `okm migrate plan --json`
63
+ * @returns The document
64
+ */
65
+ export declare function parsePlanJson(text: string): PlanDocument;
@@ -46,12 +46,13 @@ export declare function generateProject(cwd: string, name: string, flags: readon
46
46
  * @param name - Plan name
47
47
  * @param flags - `--replace` values
48
48
  * @param invoke - Target and protection flags, when the command passed them
49
- * @returns The plan, its lint findings, and the text to print
49
+ * @returns The plan, its lint findings, the human text, and the `--json` document. Both forms use the same lock lines
50
50
  */
51
51
  export declare function planProject(cwd: string, name: string, flags: readonly string[], invoke?: InvokeFlags): Promise<{
52
52
  readonly plan: MigrationPlan;
53
53
  readonly findings: readonly Finding[];
54
54
  readonly text: string;
55
+ readonly json: string;
55
56
  }>;
56
57
  /**
57
58
  * Validates the schema, then reports stale renames and unlisted table files.
@@ -113,6 +114,14 @@ export declare function openProject(cwd: string): Promise<{
113
114
  * @returns The built schema, with roles attached when the config declares them
114
115
  */
115
116
  export declare function loadBuiltSchema(cwd: string, config: MigrateConfig): Promise<Built>;
117
+ /**
118
+ * Prints or writes the catalog snapshot.
119
+ *
120
+ * @param cwd - Project directory
121
+ * @param args - Arguments after `export`
122
+ * @returns Stdout
123
+ */
124
+ export declare function exportProject(cwd: string, args: readonly string[]): Promise<string>;
116
125
  /**
117
126
  * Loads `okmodel.config.ts`.
118
127
  *
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Turns an introspected catalog into table files and a schema file.
3
+ *
4
+ * `schema()` is the only writer. Functions, triggers, and views are written
5
+ * beside the tables. A kind it cannot store is returned, with the SQL the
6
+ * catalog already holds, and is not guessed.
7
+ */
8
+ import type { Catalog } from "../../contracts/catalog/types.js";
9
+ import { type RoutinePlan, type RoutineVerdict } from "./pull-routines.js";
10
+ /** One file `okm pull` writes. */
11
+ export type PullFile = {
12
+ /** Absolute path. */
13
+ readonly path: string;
14
+ /** Source text, before the project formatter runs. */
15
+ readonly text: string;
16
+ };
17
+ /** One object the schema file does not declare. */
18
+ export type PullSkip = {
19
+ /** {@link identityKey} of the catalog object. */
20
+ readonly key: string;
21
+ /** Catalog kind, or `column` for a type `table()` cannot build. */
22
+ readonly kind: string;
23
+ /** `table.column`, or the object name. */
24
+ readonly label: string;
25
+ /** Why this step left it out. */
26
+ readonly reason: string;
27
+ /** SQL from the catalog. Empty when the kind has no statement of its own. */
28
+ readonly sql: string;
29
+ };
30
+ /** Where the schema file and the table files go. */
31
+ export type PullLayout = {
32
+ /** Absolute path of the schema module. */
33
+ readonly schemaFile: string;
34
+ /** Absolute directory of one file per table. */
35
+ readonly tablesDir: string;
36
+ };
37
+ /** Files to write, and the objects those files leave out. */
38
+ export type PullEmission = {
39
+ readonly files: readonly PullFile[];
40
+ readonly skipped: readonly PullSkip[];
41
+ /** Scratch results for the routines the files declare. */
42
+ readonly verdicts: readonly RoutineVerdict[];
43
+ readonly counts: {
44
+ readonly tables: number;
45
+ readonly functions: number;
46
+ readonly triggers: number;
47
+ readonly views: number;
48
+ readonly materializedViews: number;
49
+ };
50
+ };
51
+ /** A kind the catalog cannot store, counted for the report. */
52
+ export type PullCount = {
53
+ readonly kind: string;
54
+ readonly count: number;
55
+ readonly reason: string;
56
+ };
57
+ /** Scratch verdicts and the kinds the catalog has no object for. */
58
+ export type PullReview = {
59
+ readonly plan: RoutinePlan;
60
+ readonly verdicts: readonly RoutineVerdict[];
61
+ readonly unexpressed: readonly PullCount[];
62
+ };
63
+ /**
64
+ * Writes one table module per table and the schema module that imports them.
65
+ *
66
+ * Column order, import order, and option keys are sorted, so the same catalog
67
+ * produces the same text.
68
+ *
69
+ * @param source - Catalog from introspection, logical namespace `public`
70
+ * @param layout - Schema file and tables directory
71
+ * @param review - Scratch verdicts. Omitted marks every function candidate-only
72
+ * @returns The files and the objects they do not declare
73
+ */
74
+ export declare function emitPull(source: Catalog, layout: PullLayout, review?: PullReview): PullEmission;
75
+ /**
76
+ * Text `okm pull` prints.
77
+ *
78
+ * Deferred kinds and kinds the catalog cannot store are always listed,
79
+ * including a count of zero, so a kind is not dropped without a line.
80
+ * Each pulled function is `verified`, `candidate-only`, or `unverified`.
81
+ *
82
+ * @param counts - Objects the files declare
83
+ * @param skipped - Objects the files leave out
84
+ * @param verdicts - Scratch results. Empty when no routine was pulled
85
+ * @param unexpressed - Aggregates, procedures, event triggers, and rules
86
+ * @param verb - `imported` for `okm import drizzle`. `pulled` is `okm pull`
87
+ * @returns The report, with a trailing newline
88
+ */
89
+ export declare function formatPullReport(counts: PullEmission["counts"], skipped: readonly PullSkip[], verdicts?: readonly RoutineVerdict[], unexpressed?: readonly PullCount[], verb?: "pulled" | "imported"): string;
90
+ /**
91
+ * SQL table name to the binding `table()` writes.
92
+ *
93
+ * A partitioned table is omitted. The binding matches the table file.
94
+ *
95
+ * @param source - Introspected catalog
96
+ * @returns Bindings for tables this step writes
97
+ */
98
+ export declare function tableExportNames(source: Catalog): ReadonlyMap<string, string>;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Plans `fn()`, `trigger()`, `view()`, and `materializedView()` for `okm pull`.
3
+ *
4
+ * Views and `BEGIN ATOMIC` bodies take edges the catalog already read from
5
+ * `pg_depend`. A plpgsql or SQL-string body gets table candidates from
6
+ * {@link sqlIdentifiers}. A view or a function named in that body is an
7
+ * ordering edge only: `dependsOn` accepts tables and columns. A view query
8
+ * is matched the same way, so a view over a view waits for the view it names
9
+ * when `pg_depend` recorded no column edge.
10
+ */
11
+ import type { Catalog, FunctionObject, IndexObject, MaterializedViewObject, ObjectIdentity, TriggerObject, ViewObject } from "../../contracts/catalog/types.js";
12
+ /** Why a pulled routine is marked the way it is. */
13
+ export type RoutineStatus = "verified" | "candidate-only" | "unverified";
14
+ /** One function, trigger, or view after the scratch replay. */
15
+ export type RoutineVerdict = {
16
+ /** {@link identityKey} of the catalog object. */
17
+ readonly key: string;
18
+ /** Catalog kind. */
19
+ readonly kind: "function" | "trigger" | "view" | "materializedView";
20
+ /** Report label. */
21
+ readonly label: string;
22
+ /** What the scratch run proved. */
23
+ readonly status: RoutineStatus;
24
+ /** Postgres error, or why the scratch schema did not run. Empty when proved or candidate-only. */
25
+ readonly detail: string;
26
+ };
27
+ /** One object the schema file does not declare. Shape matches the pull skip. */
28
+ export type RoutineSkip = {
29
+ readonly key: string;
30
+ readonly kind: string;
31
+ readonly label: string;
32
+ readonly reason: string;
33
+ readonly sql: string;
34
+ };
35
+ /** A function the schema file will declare. */
36
+ export type PlannedFunction = {
37
+ readonly object: FunctionObject;
38
+ /** Binding in the schema file. */
39
+ readonly binding: string;
40
+ /** Source fragments inside `dependsOn: [...]`. */
41
+ readonly dependsOn: readonly string[];
42
+ };
43
+ /** A trigger the schema file will declare. */
44
+ export type PlannedTrigger = {
45
+ readonly object: TriggerObject;
46
+ readonly binding: string;
47
+ /** Table binding passed to `on`. */
48
+ readonly on: string;
49
+ /** Function binding passed to `calls`. */
50
+ readonly calls: string;
51
+ };
52
+ /** A view or materialized view the schema file will declare. */
53
+ export type PlannedView = {
54
+ readonly object: ViewObject | MaterializedViewObject;
55
+ readonly binding: string;
56
+ /** Indexes `materializedView()` can store. Expression indexes are skipped. */
57
+ readonly indexes: readonly IndexObject[];
58
+ };
59
+ /**
60
+ * Routines to write, and the extra edges the scratch replay orders by.
61
+ *
62
+ * `orderEdges` are not written. `dependsOn` cannot name a view or a function.
63
+ */
64
+ export type RoutinePlan = {
65
+ readonly functions: readonly PlannedFunction[];
66
+ readonly triggers: readonly PlannedTrigger[];
67
+ readonly views: readonly PlannedView[];
68
+ readonly skipped: readonly RoutineSkip[];
69
+ /** Identity key to edges added for the scratch order only. */
70
+ readonly orderEdges: ReadonlyMap<string, readonly ObjectIdentity[]>;
71
+ };
72
+ /** Bindings and declarations inserted into the schema file. */
73
+ export type RenderedRoutines = {
74
+ readonly imports: readonly string[];
75
+ readonly body: string;
76
+ readonly functions: readonly string[];
77
+ readonly triggers: readonly string[];
78
+ readonly views: readonly string[];
79
+ };
80
+ /**
81
+ * Chooses which routines to write and which names `dependsOn` can cite.
82
+ *
83
+ * @param source - Introspected catalog
84
+ * @param tableExports - SQL table name to the binding `table()` writes
85
+ * @returns The plan. Comments are applied later, from the scratch verdicts
86
+ */
87
+ export declare function planRoutines(source: Catalog, tableExports: ReadonlyMap<string, string>): RoutinePlan;
88
+ /**
89
+ * Renders the schema-file text for a plan.
90
+ *
91
+ * A missing verdict is candidate-only for a function and unverified for a
92
+ * view or a trigger. That is what a scratch run that did not happen can say.
93
+ *
94
+ * @param plan - Routines to write
95
+ * @param verdicts - Scratch results, keyed by {@link identityKey}
96
+ * @returns Imports, bindings, and the `schema()` lists
97
+ */
98
+ export declare function renderRoutines(plan: RoutinePlan, verdicts: ReadonlyMap<string, RoutineVerdict>): RenderedRoutines;
99
+ /**
100
+ * Verdicts for a plan when the scratch schema was not created.
101
+ *
102
+ * Nothing is verified. A plpgsql function stays candidate-only. A SQL
103
+ * function, a view, and a trigger are unverified.
104
+ *
105
+ * @param plan - Routines that would have been replayed
106
+ * @param detail - Why the scratch schema was not created
107
+ * @returns One verdict per planned routine
108
+ */
109
+ export declare function verdictsWithoutScratch(plan: RoutinePlan, detail: string): readonly RoutineVerdict[];
110
+ /**
111
+ * Tables, views, and functions named in `body`.
112
+ *
113
+ * Unquoted names fold to lower case. A quoted name matches the stored spelling.
114
+ * The function's own name is included; the caller drops a self-edge.
115
+ *
116
+ * @param body - Function body or view query
117
+ * @param tables - Pulled tables
118
+ * @param views - Pulled views and materialized views
119
+ * @param functions - Functions grouped by name
120
+ * @returns Matches, tables by SQL name and the other two as identities
121
+ */
122
+ export declare function matchNames(body: string, tables: ReadonlyMap<string, ObjectIdentity>, views: ReadonlyMap<string, ViewObject | MaterializedViewObject>, functions: ReadonlyMap<string, readonly FunctionObject[]>): {
123
+ readonly tables: readonly string[];
124
+ readonly views: readonly ObjectIdentity[];
125
+ readonly functions: readonly ObjectIdentity[];
126
+ };