okmodel 0.2.1 → 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.
Files changed (148) hide show
  1. package/README.md +882 -48
  2. package/dist/contracts/catalog/document.d.ts +6 -2
  3. package/dist/contracts/catalog/enum.d.ts +31 -4
  4. package/dist/contracts/catalog/extension.d.ts +61 -0
  5. package/dist/contracts/catalog/privilege.d.ts +64 -0
  6. package/dist/contracts/catalog/routine.d.ts +56 -0
  7. package/dist/contracts/catalog/types.d.ts +164 -10
  8. package/dist/contracts/catalog/view.d.ts +73 -0
  9. package/dist/dialects/pg/column.d.ts +3 -1
  10. package/dist/dialects/pg/ddl.d.ts +65 -1
  11. package/dist/dialects/pg/enum.d.ts +10 -8
  12. package/dist/dialects/pg/ext/citext.d.ts +14 -0
  13. package/dist/dialects/pg/ext/citext.js +11 -0
  14. package/dist/dialects/pg/ext/index.d.ts +52 -0
  15. package/dist/dialects/pg/ext/index.js +6 -0
  16. package/dist/dialects/pg/ext/pg-trgm.d.ts +53 -0
  17. package/dist/dialects/pg/ext/pg-trgm.js +42 -0
  18. package/dist/dialects/pg/fn/index.d.ts +107 -0
  19. package/dist/dialects/pg/fn/index.js +175 -0
  20. package/dist/dialects/pg/fn/touch.d.ts +14 -0
  21. package/dist/dialects/pg/index.js +104 -19
  22. package/dist/dialects/pg/introspect.d.ts +10 -1
  23. package/dist/dialects/pg/operators.d.ts +8 -1
  24. package/dist/dialects/pg/role/check.d.ts +45 -0
  25. package/dist/dialects/pg/role/index.d.ts +50 -0
  26. package/dist/dialects/pg/role/sql.d.ts +51 -0
  27. package/dist/dialects/pg/table.d.ts +24 -1
  28. package/dist/dialects/pg/tenancy.d.ts +9 -0
  29. package/dist/dialects/pg/view/client.d.ts +30 -0
  30. package/dist/dialects/pg/view/depend.d.ts +35 -0
  31. package/dist/dialects/pg/view/index.d.ts +114 -0
  32. package/dist/dialects/pg/view/index.js +289 -0
  33. package/dist/dialects/pg/view/scratch.d.ts +22 -0
  34. package/dist/dialects/pg/where.d.ts +2 -2
  35. package/dist/runtime/catalog-cache.d.ts +17 -0
  36. package/dist/runtime/compat-words.d.ts +23 -0
  37. package/dist/runtime/drift-detail.d.ts +20 -4
  38. package/dist/runtime/drift.d.ts +4 -2
  39. package/dist/runtime/pg/bun.js +3 -3
  40. package/dist/runtime/pg/pg.js +3 -3
  41. package/dist/runtime/pg/pglite.js +3 -3
  42. package/dist/runtime/pg/postgresjs.js +3 -3
  43. package/dist/runtime/tenancy/index.js +6 -3
  44. package/dist/runtime/traits/index.d.ts +7 -2
  45. package/dist/runtime/traits/index.js +151 -13
  46. package/dist/runtime/types.d.ts +2 -0
  47. package/dist/runtime/validate/index.js +4 -4
  48. package/dist/shared/{xkz8g6by.js → 1g0drakv.js} +2 -2
  49. package/dist/shared/2321avmn.js +418 -0
  50. package/dist/shared/{7mht49yd.js → 3p4b1fg0.js} +57 -18
  51. package/dist/shared/41kv2xdm.js +318 -0
  52. package/dist/shared/{97g2jnrw.js → 4ef7mmqf.js} +3 -3
  53. package/dist/shared/{sacqha1y.js → 4m9fn52z.js} +2 -2
  54. package/dist/shared/5mtf6cj3.js +94 -0
  55. package/dist/shared/{1dp5knt7.js → 5vdm4sgp.js} +2 -2
  56. package/dist/shared/{a1gdp7j9.js → 6693j9rs.js} +1 -1
  57. package/dist/shared/{38crxbgn.js → 6p5k20sm.js} +3 -3
  58. package/dist/shared/7nk68fj8.js +751 -0
  59. package/dist/shared/84ptn35q.js +71 -0
  60. package/dist/shared/{d2whjz4k.js → 8jb4ymh2.js} +581 -28
  61. package/dist/shared/8ktwd3rh.js +97 -0
  62. package/dist/shared/94ez8kzh.js +19 -0
  63. package/dist/shared/{3a5ne750.js → 9m80mkac.js} +2 -2
  64. package/dist/shared/9x25fxhc.js +150 -0
  65. package/dist/shared/9yn6a2vd.js +11 -0
  66. package/dist/shared/ady1ms74.js +72 -0
  67. package/dist/shared/{4jzzghr6.js → awrsqrn7.js} +6 -6
  68. package/dist/shared/{4b9da9d7.js → axhk06q1.js} +19 -1
  69. package/dist/shared/{d04j53v8.js → c5g81ngb.js} +82 -14
  70. package/dist/shared/{n47rd821.js → c8aghh05.js} +1 -1
  71. package/dist/shared/{dd4f8mnx.js → c9z5g0fm.js} +4 -2
  72. package/dist/shared/{ps43134h.js → dyj86cmj.js} +4 -4
  73. package/dist/shared/{0qkxbm1f.js → fa9vt245.js} +1 -1
  74. package/dist/shared/{qa5dsc7z.js → fb00y8fp.js} +3 -3
  75. package/dist/shared/{qxa0yb9j.js → g7ez901n.js} +30 -1
  76. package/dist/shared/{py3nh7jy.js → gdh9mrtp.js} +2 -2
  77. package/dist/shared/{yw5c610b.js → gjthds9j.js} +2 -2
  78. package/dist/shared/hcmdtwgh.js +102 -0
  79. package/dist/shared/hqjsxnz7.js +13 -0
  80. package/dist/shared/htnaj77v.js +17 -0
  81. package/dist/shared/{v18jva5b.js → jgxzjzcz.js} +1 -1
  82. package/dist/shared/{x9v1qgeb.js → jsd07prz.js} +3 -3
  83. package/dist/shared/{g9f0zqce.js → kafaa5zv.js} +1 -1
  84. package/dist/shared/kj680nxv.js +19 -0
  85. package/dist/shared/{mxmcdsh5.js → kkzwp3d2.js} +9 -9
  86. package/dist/shared/{g1b5zzj9.js → n0dgs0pb.js} +1 -1
  87. package/dist/shared/n5y9zyj1.js +2431 -0
  88. package/dist/shared/{zt8y0wzb.js → n7mcc1gk.js} +1 -1
  89. package/dist/shared/{ge03bfca.js → nxb42q7h.js} +2 -2
  90. package/dist/shared/q6zsyh31.js +2192 -0
  91. package/dist/shared/{sfh4pk75.js → q795afwa.js} +26 -21
  92. package/dist/shared/{10tjenmd.js → qn0srwwq.js} +1 -1
  93. package/dist/shared/s4mb6a4b.js +545 -0
  94. package/dist/shared/{ytg3xf9p.js → sf8m6tfy.js} +3 -3
  95. package/dist/shared/{zd93g3rq.js → sr5ms7b3.js} +1 -1
  96. package/dist/shared/{xatfg0gn.js → tmbdywx0.js} +4 -19
  97. package/dist/shared/tny2t3sm.js +100 -0
  98. package/dist/shared/{e7a268fy.js → v7tpnhnz.js} +1 -1
  99. package/dist/shared/{ecdzej21.js → wqem4jed.js} +7 -7
  100. package/dist/shared/xghkt7a9.js +1144 -0
  101. package/dist/shared/y005b761.js +112 -0
  102. package/dist/shared/ycatkxmq.js +84 -0
  103. package/dist/shared/ygem90rn.js +900 -0
  104. package/dist/shared/{eaxwrgby.js → yjw02enp.js} +6 -3
  105. package/dist/shared/{mrq77sgw.js → zg24x0hm.js} +1 -1
  106. package/dist/shared/{cstgkzdx.js → zvbjc949.js} +1 -1
  107. package/dist/tooling/cli.js +66 -13
  108. package/dist/tooling/migrate/apply.d.ts +75 -5
  109. package/dist/tooling/migrate/backfill.d.ts +136 -0
  110. package/dist/tooling/migrate/check.d.ts +65 -0
  111. package/dist/tooling/migrate/classify.d.ts +108 -0
  112. package/dist/tooling/migrate/commands.d.ts +2 -1
  113. package/dist/tooling/migrate/config.d.ts +30 -0
  114. package/dist/tooling/migrate/doctor.d.ts +28 -0
  115. package/dist/tooling/migrate/drift.d.ts +35 -0
  116. package/dist/tooling/migrate/estimate.d.ts +50 -0
  117. package/dist/tooling/migrate/ext.d.ts +17 -0
  118. package/dist/tooling/migrate/extensions.d.ts +53 -0
  119. package/dist/tooling/migrate/files.d.ts +12 -0
  120. package/dist/tooling/migrate/index.d.ts +3 -2
  121. package/dist/tooling/migrate/index.js +67 -1
  122. package/dist/tooling/migrate/lint-rules.d.ts +51 -0
  123. package/dist/tooling/migrate/lint.d.ts +71 -0
  124. package/dist/tooling/migrate/managed.d.ts +17 -0
  125. package/dist/tooling/migrate/plan.d.ts +78 -10
  126. package/dist/tooling/migrate/project.d.ts +64 -5
  127. package/dist/tooling/migrate/provision.d.ts +18 -0
  128. package/dist/tooling/migrate/reference.d.ts +40 -0
  129. package/dist/tooling/migrate/runner.d.ts +108 -0
  130. package/dist/tooling/migrate/safe.d.ts +77 -0
  131. package/dist/tooling/migrate/seed.d.ts +20 -0
  132. package/dist/tooling/migrate/snapshot.d.ts +78 -0
  133. package/dist/tooling/migrate/status.d.ts +25 -6
  134. package/dist/tooling/migrate/type-name.d.ts +19 -0
  135. package/dist/tooling/testing/factories.d.ts +117 -0
  136. package/dist/tooling/testing/facts.d.ts +72 -0
  137. package/dist/tooling/testing/index.d.ts +89 -0
  138. package/dist/tooling/testing/index.js +8 -0
  139. package/dist/tooling/testing/isolation.d.ts +30 -0
  140. package/dist/tooling/testing/random.d.ts +40 -0
  141. package/dist/tooling/testing/record.d.ts +38 -0
  142. package/package.json +26 -2
  143. package/dist/shared/5z4q2zda.js +0 -2073
  144. package/dist/shared/eqmtn1bj.js +0 -399
  145. package/dist/shared/rtnaqre0.js +0 -37
  146. package/dist/shared/zwmqxb0g.js +0 -79
  147. package/dist/shared/{m9tv7xn7.js → radd3z4g.js} +3 -3
  148. /package/dist/shared/{9k6vetvf.js → rrstp3kb.js} +0 -0
@@ -0,0 +1,89 @@
1
+ /**
2
+ * `okmodel/testing`: a real database, factories, query counts, and the
3
+ * isolation check (spec §20, D199).
4
+ *
5
+ * The database is never mocked. Pass a driver pool from `open()`.
6
+ */
7
+ import type { DriverPool } from "../../contracts/driver.js";
8
+ import type { Connected } from "../../runtime/types.js";
9
+ import { type TableFactory } from "./factories.js";
10
+ import { type TestingSchema } from "./facts.js";
11
+ import { type IsolationReport } from "./isolation.js";
12
+ /** Options for {@link testing}. */
13
+ export type TestingOptions = {
14
+ /**
15
+ * A driver pool, or a promise of one.
16
+ *
17
+ * `open()` from `okmodel/pg/pglite` and `open({ url })` from
18
+ * `okmodel/pg/postgresjs` both satisfy this.
19
+ */
20
+ readonly driver: DriverPool | Promise<DriverPool>;
21
+ /**
22
+ * Seed for factory generators.
23
+ *
24
+ * The default is `1`. The same seed replays the same values.
25
+ */
26
+ readonly seed?: number;
27
+ /**
28
+ * Apply the schema's catalog before connecting.
29
+ *
30
+ * The default is true, for an empty test database. `okm seed` passes false:
31
+ * the target already has its schema.
32
+ */
33
+ readonly migrate?: boolean;
34
+ };
35
+ /**
36
+ * What a factory definition may call.
37
+ *
38
+ * Re-exported so a seed file can name the argument.
39
+ */
40
+ export type { FactoryContext, TableFactory } from "./factories.js";
41
+ export type { IsolationReport } from "./isolation.js";
42
+ /** Definitions passed to {@link Testing.factories}. */
43
+ export type FactoryDefinitions = {
44
+ readonly [table: string]: (context: import("./factories.js").FactoryContext) => Readonly<Record<string, unknown>>;
45
+ };
46
+ /**
47
+ * A connected test database.
48
+ *
49
+ * @typeParam S - Schema passed to {@link testing}
50
+ */
51
+ export type Testing<S extends TestingSchema = TestingSchema> = {
52
+ /** The client. `close` on the harness closes this pool. */
53
+ readonly db: Connected<S>;
54
+ /**
55
+ * Builds factories for the named tables.
56
+ *
57
+ * @param definitions - One function per table
58
+ * @returns `create`, `createMany`, and `with` for each table
59
+ */
60
+ factories<const D extends FactoryDefinitions>(definitions: D): {
61
+ readonly [K in keyof D]: TableFactory;
62
+ };
63
+ /**
64
+ * Fails when `run` sends a different number of statements than `count`.
65
+ *
66
+ * Transaction control is not counted. The error lists the statements that were.
67
+ *
68
+ * @param count - Expected statements
69
+ * @param run - The work to count
70
+ */
71
+ expectQueries(count: number, run: () => Promise<unknown>): Promise<void>;
72
+ /**
73
+ * Runs the cross-tenant check.
74
+ *
75
+ * @returns Checked tenant tables and skipped global tables
76
+ */
77
+ isolation(): Promise<IsolationReport>;
78
+ /** Closes the client and the pool. */
79
+ close(): Promise<void>;
80
+ };
81
+ /**
82
+ * Opens `schema` on `driver` and returns the test harness.
83
+ *
84
+ * @typeParam S - Schema
85
+ * @param schema - A `schema()` value
86
+ * @param options - Driver, seed, and whether to apply the catalog
87
+ * @returns The harness
88
+ */
89
+ export declare function testing<const S extends TestingSchema>(schema: S, options: TestingOptions): Promise<Testing<S>>;
@@ -0,0 +1,8 @@
1
+ import {
2
+ testing2
3
+ } from "../../shared/ygem90rn.js";
4
+ import"../../shared/41kv2xdm.js";
5
+ import"../../shared/8jb4ymh2.js";
6
+ export {
7
+ testing2 as testing
8
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Cross-tenant isolation check.
3
+ *
4
+ * For every tenant table, insert one row as tenant B and run the basic reads
5
+ * and writes as tenant A. A returned row, a count above zero, or an update or
6
+ * delete that touches a row is a leak. Global tables are skipped and listed.
7
+ * Column tenancy is the strategy this version has. A table is tenant when its
8
+ * predicate says so (D199).
9
+ */
10
+ import { type FactoryHost } from "./factories.js";
11
+ /** What {@link isolation} checked, and the global tables it skipped. */
12
+ export type IsolationReport = {
13
+ /** Tenant tables whose queries stayed inside tenant A. */
14
+ readonly checked: readonly string[];
15
+ /** Global tables, with the reason from `global("reason")`. */
16
+ readonly skipped: readonly {
17
+ readonly table: string;
18
+ readonly reason: string;
19
+ }[];
20
+ };
21
+ /**
22
+ * Runs the check on `host`.
23
+ *
24
+ * The cache used for `x.ref` is set aside for the run, so a row the test
25
+ * already inserted is not reused as tenant B's row.
26
+ *
27
+ * @param host - The open harness
28
+ * @returns The tables that were checked and the global tables that were not
29
+ */
30
+ export declare function isolation(host: FactoryHost): Promise<IsolationReport>;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Seeded generators for factories.
3
+ *
4
+ * Mulberry32, a fixed word list, and a counter. No runtime dependency.
5
+ * The same seed replays the same sequence (D199).
6
+ */
7
+ /** A seeded sequence and the values factories ask for. */
8
+ export type Rng = {
9
+ /** Next unit interval, `[0, 1)`. */
10
+ next(): number;
11
+ /** Integer in `[0, bound)`. */
12
+ int(bound: number): number;
13
+ /** A version-4 UUID. The bits come from this sequence. */
14
+ uuid(): string;
15
+ /** `local@example.com`, unique for this sequence. */
16
+ email(): string;
17
+ /** A first and last name from the fixed lists. */
18
+ name(): string;
19
+ /** `count` words from the fixed list. */
20
+ words(count: number): string;
21
+ /** A boolean. */
22
+ boolean(): boolean;
23
+ /** A number in `[0, 1)`. */
24
+ float(): number;
25
+ /** An ISO date `YYYY-MM-DD` in 2020. */
26
+ date(): string;
27
+ /** One value from `list`. */
28
+ pick<T>(list: readonly T[]): T;
29
+ /** The next counter value, starting at 1. Text defaults append it. */
30
+ counter(): number;
31
+ };
32
+ /**
33
+ * Builds the sequence for `seed`.
34
+ *
35
+ * Seed `1` is the default. `0` is shifted so the first step is not a fixed point.
36
+ *
37
+ * @param seed - Integer seed
38
+ * @returns The sequence
39
+ */
40
+ export declare function rng(seed: number): Rng;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A pool that records every statement sent to the driver.
3
+ *
4
+ * `expectQueries` counts this log. Transaction control is left out (D199).
5
+ * The runtime logger records errors only, and `hookm` records notices and
6
+ * transaction phases, not statement text, so the count wraps the pool.
7
+ */
8
+ import type { DriverPool, WireValue } from "../../contracts/driver.js";
9
+ /** One statement that reached the driver. */
10
+ export type Recorded = {
11
+ readonly text: string;
12
+ readonly params: readonly WireValue[];
13
+ };
14
+ /** A recording pool and its log. */
15
+ export type Recording = {
16
+ readonly pool: DriverPool;
17
+ /** Every statement since the pool was wrapped, in the order sent. */
18
+ readonly log: Recorded[];
19
+ };
20
+ /**
21
+ * Reports whether `text` only frames a transaction.
22
+ *
23
+ * Not counted: `BEGIN`, `START TRANSACTION`, `COMMIT`, `END`, `ROLLBACK`,
24
+ * `ROLLBACK TO`, `SAVEPOINT`, `RELEASE SAVEPOINT`, `SET TRANSACTION`,
25
+ * `SET LOCAL`, and `SET SESSION CHARACTERISTICS`. A data statement is counted,
26
+ * including one that runs inside a transaction.
27
+ *
28
+ * @param text - Statement text
29
+ * @returns Whether the statement is transaction control
30
+ */
31
+ export declare function isTransactionControl(text: string): boolean;
32
+ /**
33
+ * Wraps a pool so each statement is logged.
34
+ *
35
+ * @param pool - The real pool
36
+ * @returns The wrapped pool and its log
37
+ */
38
+ export declare function record(pool: DriverPool): Recording;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okmodel",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "okmodel is a catalog-first TypeScript ORM, PostgreSQL first.",
5
5
  "keywords": [
6
6
  "migrations",
@@ -82,13 +82,37 @@
82
82
  "types": "./dist/runtime/tenancy/index.d.ts",
83
83
  "import": "./dist/runtime/tenancy/index.js"
84
84
  },
85
+ "./testing": {
86
+ "types": "./dist/tooling/testing/index.d.ts",
87
+ "import": "./dist/tooling/testing/index.js"
88
+ },
85
89
  "./validate": {
86
90
  "types": "./dist/runtime/validate/index.d.ts",
87
91
  "import": "./dist/runtime/validate/index.js"
92
+ },
93
+ "./ext": {
94
+ "types": "./dist/dialects/pg/ext/index.d.ts",
95
+ "import": "./dist/dialects/pg/ext/index.js"
96
+ },
97
+ "./fn": {
98
+ "types": "./dist/dialects/pg/fn/index.d.ts",
99
+ "import": "./dist/dialects/pg/fn/index.js"
100
+ },
101
+ "./view": {
102
+ "types": "./dist/dialects/pg/view/index.d.ts",
103
+ "import": "./dist/dialects/pg/view/index.js"
104
+ },
105
+ "./pg/citext": {
106
+ "types": "./dist/dialects/pg/ext/citext.d.ts",
107
+ "import": "./dist/dialects/pg/ext/citext.js"
108
+ },
109
+ "./pg/pg_trgm": {
110
+ "types": "./dist/dialects/pg/ext/pg-trgm.d.ts",
111
+ "import": "./dist/dialects/pg/ext/pg-trgm.js"
88
112
  }
89
113
  },
90
114
  "scripts": {
91
- "build": "rm -rf dist && bun build ./src/contracts/index.ts ./src/contracts/internal.ts ./src/dialects/pg/index.ts ./src/runtime/pg/postgresjs.ts ./src/runtime/pg/pglite.ts ./src/runtime/pg/pg.ts ./src/runtime/pg/bun.ts ./src/runtime/ids/index.ts ./src/runtime/safety/index.ts ./src/runtime/traits/index.ts ./src/runtime/tenancy/index.ts ./src/runtime/validate/index.ts ./src/tooling/migrate/index.ts ./src/tooling/cli.ts --outdir ./dist --root ./src --format esm --target node --splitting --chunk-naming=shared/[hash].js --external postgres --external @electric-sql/pglite --external pg --external bun && bunx tsc -p tsconfig.build.json && bun ./scripts/write-bin-wrappers.ts",
115
+ "build": "rm -rf dist && bun build ./src/contracts/index.ts ./src/contracts/internal.ts ./src/dialects/pg/index.ts ./src/runtime/pg/postgresjs.ts ./src/runtime/pg/pglite.ts ./src/runtime/pg/pg.ts ./src/runtime/pg/bun.ts ./src/runtime/ids/index.ts ./src/runtime/safety/index.ts ./src/runtime/traits/index.ts ./src/runtime/tenancy/index.ts ./src/runtime/validate/index.ts ./src/dialects/pg/ext/index.ts ./src/dialects/pg/fn/index.ts ./src/dialects/pg/view/index.ts ./src/dialects/pg/ext/citext.ts ./src/dialects/pg/ext/pg-trgm.ts ./src/tooling/migrate/index.ts ./src/tooling/testing/index.ts ./src/tooling/cli.ts --outdir ./dist --root ./src --format esm --target node --splitting --chunk-naming=shared/[hash].js --external postgres --external @electric-sql/pglite --external pg --external bun && bunx tsc -p tsconfig.build.json && bun ./scripts/write-bin-wrappers.ts",
92
116
  "driver-bench": "bun ./scripts/driver-bench.ts",
93
117
  "typecheck": "bunx tsc --noEmit -p tsconfig.json",
94
118
  "editor-check": "bun ./scripts/editor-check.ts",