@fuzdev/fuz_app 0.69.0 → 0.71.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 (42) hide show
  1. package/dist/db/CLAUDE.md +3 -3
  2. package/dist/db/cell_history_ddl.d.ts +1 -1
  3. package/dist/db/cell_history_ddl.js +1 -1
  4. package/dist/db/fact_ddl.d.ts +11 -11
  5. package/dist/db/fact_ddl.d.ts.map +1 -1
  6. package/dist/db/fact_ddl.js +13 -13
  7. package/dist/db/fact_queries.d.ts +9 -9
  8. package/dist/db/fact_queries.d.ts.map +1 -1
  9. package/dist/db/fact_queries.js +18 -18
  10. package/dist/db/fact_store.d.ts +3 -3
  11. package/dist/db/fact_store.js +2 -2
  12. package/dist/testing/CLAUDE.md +16 -11
  13. package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts +57 -0
  14. package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts.map +1 -0
  15. package/dist/testing/cross_backend/create_cross_backend_global_setup.js +31 -0
  16. package/dist/testing/cross_backend/create_schema_parity_global_setup.d.ts +59 -0
  17. package/dist/testing/cross_backend/create_schema_parity_global_setup.d.ts.map +1 -0
  18. package/dist/testing/cross_backend/create_schema_parity_global_setup.js +27 -0
  19. package/dist/testing/cross_backend/default_backend_configs.d.ts +13 -0
  20. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  21. package/dist/testing/cross_backend/default_backend_configs.js +4 -4
  22. package/dist/testing/cross_backend/make_cross_backend_project.d.ts +72 -0
  23. package/dist/testing/cross_backend/make_cross_backend_project.d.ts.map +1 -0
  24. package/dist/testing/cross_backend/make_cross_backend_project.js +51 -0
  25. package/dist/testing/cross_backend/setup.d.ts +16 -0
  26. package/dist/testing/cross_backend/setup.d.ts.map +1 -1
  27. package/dist/testing/cross_backend/setup.js +16 -0
  28. package/dist/testing/cross_backend/standard.d.ts +8 -0
  29. package/dist/testing/cross_backend/standard.d.ts.map +1 -1
  30. package/dist/testing/cross_backend/standard.js +1 -0
  31. package/dist/testing/cross_backend/testing_reset_actions.d.ts +71 -11
  32. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  33. package/dist/testing/cross_backend/testing_reset_actions.js +38 -5
  34. package/dist/testing/integration.d.ts.map +1 -1
  35. package/dist/testing/integration.js +20 -3
  36. package/dist/testing/schema_introspect.d.ts +74 -58
  37. package/dist/testing/schema_introspect.d.ts.map +1 -1
  38. package/dist/testing/schema_introspect.js +77 -15
  39. package/dist/testing/schema_parity.d.ts +7 -17
  40. package/dist/testing/schema_parity.d.ts.map +1 -1
  41. package/dist/testing/schema_parity.js +3 -37
  42. package/package.json +1 -1
@@ -5,8 +5,6 @@ import './assert_dev_env.js';
5
5
  *
6
6
  * The snapshot covers:
7
7
  *
8
- * - `schema_version` rows (`namespace`, `name`, `sequence`) — captures
9
- * migration set state across impls
10
8
  * - Tables with columns (data type, nullability, default, identity)
11
9
  * - Indexes with canonical Postgres-rendered definitions
12
10
  * - Constraints (CHECK, FOREIGN KEY, PRIMARY KEY, UNIQUE, EXCLUSION)
@@ -21,60 +19,80 @@ import './assert_dev_env.js';
21
19
  *
22
20
  * @module
23
21
  */
22
+ import { z } from 'zod';
24
23
  import type { Db } from '../db/db.js';
25
- /** Per-column structural metadata. */
26
- export interface ColumnSnapshot {
27
- /** SQL standard type name from `information_schema.columns.data_type`. */
28
- readonly data_type: string;
29
- /** Postgres-native type name from `information_schema.columns.udt_name`. */
30
- readonly udt_name: string;
31
- /** `true` when the column accepts NULL. */
32
- readonly is_nullable: boolean;
33
- /** Default-value expression as Postgres reports it, or `null` if none. */
34
- readonly column_default: string | null;
35
- /** `true` when the column was declared GENERATED ... AS IDENTITY. */
36
- readonly is_identity: boolean;
37
- }
24
+ /**
25
+ * Per-column structural metadata. The Zod schema is the canonical source
26
+ * for the column shape `SchemaSnapshot` reuses it as the cross-impl
27
+ * `_testing_schema_snapshot` RPC action's wire validator, so the
28
+ * introspection type and the wire contract can't drift apart.
29
+ */
30
+ export declare const ColumnSnapshot: z.ZodObject<{
31
+ data_type: z.ZodString;
32
+ udt_name: z.ZodString;
33
+ is_nullable: z.ZodBoolean;
34
+ column_default: z.ZodNullable<z.ZodString>;
35
+ is_identity: z.ZodBoolean;
36
+ }, z.core.$strip>;
37
+ export type ColumnSnapshot = z.infer<typeof ColumnSnapshot>;
38
38
  /** Per-table structural metadata. */
39
- export interface TableSnapshot {
40
- /** Column metadata keyed by column name (sorted on serialization). */
41
- readonly columns: Record<string, ColumnSnapshot>;
42
- /** Index definitions as Postgres renders them via `pg_indexes.indexdef`. */
43
- readonly indexes: ReadonlyArray<{
44
- readonly name: string;
45
- readonly definition: string;
46
- }>;
47
- /** Constraint definitions as Postgres renders them via `pg_get_constraintdef`. */
48
- readonly constraints: ReadonlyArray<{
49
- readonly name: string;
50
- readonly type: string;
51
- readonly definition: string;
52
- }>;
53
- }
39
+ export declare const TableSnapshot: z.ZodObject<{
40
+ columns: z.ZodRecord<z.ZodString, z.ZodObject<{
41
+ data_type: z.ZodString;
42
+ udt_name: z.ZodString;
43
+ is_nullable: z.ZodBoolean;
44
+ column_default: z.ZodNullable<z.ZodString>;
45
+ is_identity: z.ZodBoolean;
46
+ }, z.core.$strip>>;
47
+ indexes: z.ZodArray<z.ZodObject<{
48
+ name: z.ZodString;
49
+ definition: z.ZodString;
50
+ }, z.core.$strip>>;
51
+ constraints: z.ZodArray<z.ZodObject<{
52
+ name: z.ZodString;
53
+ type: z.ZodString;
54
+ definition: z.ZodString;
55
+ }, z.core.$strip>>;
56
+ }, z.core.$strip>;
57
+ export type TableSnapshot = z.infer<typeof TableSnapshot>;
54
58
  /** Sequence metadata — `data_type` is `bigint` (BIGSERIAL) or `integer` (SERIAL). */
55
- export interface SequenceSnapshot {
56
- readonly data_type: string;
57
- }
58
- /** One row in the `schema_version` migration tracker. */
59
- export interface SchemaVersionRow {
60
- readonly namespace: string;
61
- readonly name: string;
62
- readonly sequence: number;
63
- }
59
+ export declare const SequenceSnapshot: z.ZodObject<{
60
+ data_type: z.ZodString;
61
+ }, z.core.$strip>;
62
+ export type SequenceSnapshot = z.infer<typeof SequenceSnapshot>;
64
63
  /**
65
- * Normalized database schema snapshot for parity comparison.
64
+ * Normalized database schema snapshot for parity comparison — the single
65
+ * source of truth for the snapshot shape across the introspection query
66
+ * (`query_schema_snapshot`), the diff comparator (`schema_parity.ts`), and
67
+ * the cross-impl RPC action's wire validator (`testing_reset_actions.ts`).
66
68
  *
67
69
  * All fields are deterministically ordered on capture so structural equality
68
70
  * via `JSON.stringify` or per-key comparison yields stable results.
69
71
  */
70
- export interface SchemaSnapshot {
71
- /** Migration tracker rows, sorted by `(namespace, sequence)`. */
72
- readonly schema_version: ReadonlyArray<SchemaVersionRow>;
73
- /** Tables keyed by name. */
74
- readonly tables: Record<string, TableSnapshot>;
75
- /** Sequences keyed by name. */
76
- readonly sequences: Record<string, SequenceSnapshot>;
77
- }
72
+ export declare const SchemaSnapshot: z.ZodObject<{
73
+ tables: z.ZodRecord<z.ZodString, z.ZodObject<{
74
+ columns: z.ZodRecord<z.ZodString, z.ZodObject<{
75
+ data_type: z.ZodString;
76
+ udt_name: z.ZodString;
77
+ is_nullable: z.ZodBoolean;
78
+ column_default: z.ZodNullable<z.ZodString>;
79
+ is_identity: z.ZodBoolean;
80
+ }, z.core.$strip>>;
81
+ indexes: z.ZodArray<z.ZodObject<{
82
+ name: z.ZodString;
83
+ definition: z.ZodString;
84
+ }, z.core.$strip>>;
85
+ constraints: z.ZodArray<z.ZodObject<{
86
+ name: z.ZodString;
87
+ type: z.ZodString;
88
+ definition: z.ZodString;
89
+ }, z.core.$strip>>;
90
+ }, z.core.$strip>>;
91
+ sequences: z.ZodRecord<z.ZodString, z.ZodObject<{
92
+ data_type: z.ZodString;
93
+ }, z.core.$strip>>;
94
+ }, z.core.$strip>;
95
+ export type SchemaSnapshot = z.infer<typeof SchemaSnapshot>;
78
96
  /** Filter options for `query_schema_snapshot`. */
79
97
  export interface QuerySchemaSnapshotOptions {
80
98
  /**
@@ -83,8 +101,10 @@ export interface QuerySchemaSnapshotOptions {
83
101
  */
84
102
  readonly schema?: string;
85
103
  /**
86
- * Tables to exclude from the snapshot. The `schema_version` table itself
87
- * is always excluded (its content is captured separately).
104
+ * Tables to exclude from the snapshot. The `schema_version` migration
105
+ * tracker is always excluded it's framework bookkeeping created by the
106
+ * migration runner, identical across impls, and not part of any
107
+ * consumer's domain schema.
88
108
  */
89
109
  readonly exclude_tables?: ReadonlyArray<string>;
90
110
  }
@@ -92,15 +112,11 @@ export interface QuerySchemaSnapshotOptions {
92
112
  * Introspect a live database into a deterministic `SchemaSnapshot`.
93
113
  *
94
114
  * Reads `information_schema` and `pg_catalog` to capture tables, columns,
95
- * indexes, constraints, sequences, and `schema_version` migration tracker
96
- * rows. The `applied_at` timestamp is deliberately excluded — only the set
97
- * of applied migrations matters for parity.
98
- *
99
- * The `schema_version` table itself never appears in the `tables` field;
100
- * its structure is identical across consumers and would only add noise.
115
+ * indexes, constraints, and sequences.
101
116
  *
102
- * @throws Error when the `schema_version` table is missing callers must
103
- * ensure migrations have run before introspecting.
117
+ * The `schema_version` migration tracker never appears in the `tables`
118
+ * field it's framework bookkeeping created by the migration runner,
119
+ * identical across consumers, and would only add noise.
104
120
  */
105
121
  export declare const query_schema_snapshot: (db: Db, options?: QuerySchemaSnapshotOptions) => Promise<SchemaSnapshot>;
106
122
  //# sourceMappingURL=schema_introspect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema_introspect.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_introspect.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAEpC,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC9B;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACtF,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC;QACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;KAC5B,CAAC,CAAC;CACH;AAED,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACzD,4BAA4B;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC/C,+BAA+B;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CACrD;AAED,kDAAkD;AAClD,MAAM,WAAW,0BAA0B;IAC1C;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChD;AAyDD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,GACjC,IAAI,EAAE,EACN,UAAS,0BAA+B,KACtC,OAAO,CAAC,cAAc,CA+GxB,CAAC"}
1
+ {"version":3,"file":"schema_introspect.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_introspect.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;;;iBAWzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,qCAAqC;AACrC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;iBAOxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D,qFAAqF;AACrF,eAAO,MAAM,gBAAgB;;iBAE3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;iBAKzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,kDAAkD;AAClD,MAAM,WAAW,0BAA0B;IAC1C;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChD;AAyDD;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,GACjC,IAAI,EAAE,EACN,UAAS,0BAA+B,KACtC,OAAO,CAAC,cAAc,CAuGxB,CAAC"}
@@ -1,4 +1,71 @@
1
1
  import './assert_dev_env.js';
2
+ /**
3
+ * PostgreSQL schema introspection — produces a normalized, JSON-serializable
4
+ * snapshot of a database's structure for cross-impl parity checks.
5
+ *
6
+ * The snapshot covers:
7
+ *
8
+ * - Tables with columns (data type, nullability, default, identity)
9
+ * - Indexes with canonical Postgres-rendered definitions
10
+ * - Constraints (CHECK, FOREIGN KEY, PRIMARY KEY, UNIQUE, EXCLUSION)
11
+ * - Sequences with data type — distinguishes `int4` (SERIAL) from `int8`
12
+ * (BIGSERIAL)
13
+ *
14
+ * Designed for `pg_catalog` introspection — works against both PostgreSQL
15
+ * and PGlite. The snapshot is fully deterministic: every collection sorts by
16
+ * a stable key and excludes time-varying fields like `applied_at`.
17
+ *
18
+ * Paired with `schema_parity.ts` for comparison + assertion helpers.
19
+ *
20
+ * @module
21
+ */
22
+ import { z } from 'zod';
23
+ /**
24
+ * Per-column structural metadata. The Zod schema is the canonical source
25
+ * for the column shape — `SchemaSnapshot` reuses it as the cross-impl
26
+ * `_testing_schema_snapshot` RPC action's wire validator, so the
27
+ * introspection type and the wire contract can't drift apart.
28
+ */
29
+ export const ColumnSnapshot = z.object({
30
+ /** SQL standard type name from `information_schema.columns.data_type`. */
31
+ data_type: z.string(),
32
+ /** Postgres-native type name from `information_schema.columns.udt_name`. */
33
+ udt_name: z.string(),
34
+ /** `true` when the column accepts NULL. */
35
+ is_nullable: z.boolean(),
36
+ /** Default-value expression as Postgres reports it, or `null` if none. */
37
+ column_default: z.string().nullable(),
38
+ /** `true` when the column was declared GENERATED ... AS IDENTITY. */
39
+ is_identity: z.boolean(),
40
+ });
41
+ /** Per-table structural metadata. */
42
+ export const TableSnapshot = z.object({
43
+ /** Column metadata keyed by column name (sorted on serialization). */
44
+ columns: z.record(z.string(), ColumnSnapshot),
45
+ /** Index definitions as Postgres renders them via `pg_indexes.indexdef`. */
46
+ indexes: z.array(z.object({ name: z.string(), definition: z.string() })),
47
+ /** Constraint definitions as Postgres renders them via `pg_get_constraintdef`. */
48
+ constraints: z.array(z.object({ name: z.string(), type: z.string(), definition: z.string() })),
49
+ });
50
+ /** Sequence metadata — `data_type` is `bigint` (BIGSERIAL) or `integer` (SERIAL). */
51
+ export const SequenceSnapshot = z.object({
52
+ data_type: z.string(),
53
+ });
54
+ /**
55
+ * Normalized database schema snapshot for parity comparison — the single
56
+ * source of truth for the snapshot shape across the introspection query
57
+ * (`query_schema_snapshot`), the diff comparator (`schema_parity.ts`), and
58
+ * the cross-impl RPC action's wire validator (`testing_reset_actions.ts`).
59
+ *
60
+ * All fields are deterministically ordered on capture so structural equality
61
+ * via `JSON.stringify` or per-key comparison yields stable results.
62
+ */
63
+ export const SchemaSnapshot = z.object({
64
+ /** Tables keyed by name. */
65
+ tables: z.record(z.string(), TableSnapshot),
66
+ /** Sequences keyed by name. */
67
+ sequences: z.record(z.string(), SequenceSnapshot),
68
+ });
2
69
  const sort_keys = (record) => {
3
70
  const sorted = {};
4
71
  for (const key of Object.keys(record).sort()) {
@@ -28,26 +95,16 @@ const contype_to_kind = (contype) => {
28
95
  * Introspect a live database into a deterministic `SchemaSnapshot`.
29
96
  *
30
97
  * Reads `information_schema` and `pg_catalog` to capture tables, columns,
31
- * indexes, constraints, sequences, and `schema_version` migration tracker
32
- * rows. The `applied_at` timestamp is deliberately excluded — only the set
33
- * of applied migrations matters for parity.
34
- *
35
- * The `schema_version` table itself never appears in the `tables` field;
36
- * its structure is identical across consumers and would only add noise.
98
+ * indexes, constraints, and sequences.
37
99
  *
38
- * @throws Error when the `schema_version` table is missing callers must
39
- * ensure migrations have run before introspecting.
100
+ * The `schema_version` migration tracker never appears in the `tables`
101
+ * field it's framework bookkeeping created by the migration runner,
102
+ * identical across consumers, and would only add noise.
40
103
  */
41
104
  export const query_schema_snapshot = async (db, options = {}) => {
42
105
  const schema = options.schema ?? 'public';
43
106
  const exclude_tables = new Set(options.exclude_tables ?? []);
44
107
  exclude_tables.add('schema_version');
45
- // schema_version rows — the migration tracker. Exclude `applied_at`
46
- // because timestamps differ across bootstraps even when the migration
47
- // set is identical.
48
- const schema_version_rows = await db.query(`SELECT namespace, name, sequence
49
- FROM schema_version
50
- ORDER BY namespace ASC, sequence ASC`);
51
108
  // All tables in the target schema, minus the excludes.
52
109
  const table_rows = await db.query(`SELECT table_name
53
110
  FROM information_schema.tables
@@ -68,6 +125,11 @@ export const query_schema_snapshot = async (db, options = {}) => {
68
125
  WHERE schemaname = $1
69
126
  ORDER BY tablename ASC, indexname ASC`, [schema]);
70
127
  // Constraints — pg_get_constraintdef produces a canonical text rendering.
128
+ // Skip NOT NULL constraints (`contype = 'n'`): PG17+ catalogs them as
129
+ // named `pg_constraint` rows while PGlite / older PG don't, and
130
+ // nullability is already captured per-column by `is_nullable` — including
131
+ // them would report a pure engine-cataloging artifact as cross-backend
132
+ // drift between a PGlite and a real-Postgres backend.
71
133
  const constraint_rows = await db.query(`SELECT c.conrelid::regclass::text AS table_name,
72
134
  c.conname,
73
135
  c.contype::text,
@@ -76,6 +138,7 @@ export const query_schema_snapshot = async (db, options = {}) => {
76
138
  JOIN pg_namespace n ON n.oid = c.connamespace
77
139
  WHERE n.nspname = $1
78
140
  AND c.conrelid != 0
141
+ AND c.contype != 'n'
79
142
  ORDER BY table_name ASC, conname ASC`, [schema]);
80
143
  // Sequences — data_type distinguishes bigint (BIGSERIAL) from integer (SERIAL).
81
144
  const sequence_rows = await db.query(`SELECT sequence_name, data_type
@@ -116,7 +179,6 @@ export const query_schema_snapshot = async (db, options = {}) => {
116
179
  sequences[row.sequence_name] = { data_type: row.data_type };
117
180
  }
118
181
  return {
119
- schema_version: schema_version_rows,
120
182
  tables: sort_keys(tables),
121
183
  sequences: sort_keys(sequences),
122
184
  };
@@ -6,7 +6,7 @@ import './assert_dev_env.js';
6
6
  * Two live impls (TS fuz_app vs Rust spine) are each other's parity
7
7
  * reference. After both bootstrap, snapshot each, diff, fail loudly on
8
8
  * drift. The diff entries name the specific divergence (column type,
9
- * missing index, schema_version row absent on one side) so the error
9
+ * missing index, constraint absent on one side) so the error
10
10
  * message points at the source.
11
11
  *
12
12
  * Consumer pattern (in zzz's integration runner or fuz_app's own
@@ -29,8 +29,8 @@ import './assert_dev_env.js';
29
29
  * impls with the same columns in different declaration order compare
30
30
  * equal (functional parity is preserved; `SELECT *` ordering is not)
31
31
  * - `COMMENT ON ...`
32
- * - the `schema_version` table's own structure (only its rows are
33
- * captured)
32
+ * - the `schema_version` migration tracker (always excluded framework
33
+ * bookkeeping, not domain schema)
34
34
  * - permissions / `GRANT`s
35
35
  *
36
36
  * None of these are used by the current fuz_app auth schema. Extend
@@ -40,19 +40,9 @@ import './assert_dev_env.js';
40
40
  *
41
41
  * @module
42
42
  */
43
- import type { ColumnSnapshot, SchemaSnapshot, SchemaVersionRow } from './schema_introspect.js';
43
+ import type { ColumnSnapshot, SchemaSnapshot } from './schema_introspect.js';
44
44
  /** Structured drift entry. `where` is the named source impl ('a' or 'b'). */
45
45
  export type SchemaDiff = {
46
- readonly kind: 'schema_version_only_in';
47
- readonly where: 'a' | 'b';
48
- readonly row: SchemaVersionRow;
49
- } | {
50
- readonly kind: 'schema_version_sequence_differs';
51
- readonly namespace: string;
52
- readonly name: string;
53
- readonly a: number;
54
- readonly b: number;
55
- } | {
56
46
  readonly kind: 'table_only_in';
57
47
  readonly where: 'a' | 'b';
58
48
  readonly table: string;
@@ -109,9 +99,9 @@ export type SchemaDiff = {
109
99
  /**
110
100
  * Structural diff between two snapshots — empty array means parity holds.
111
101
  *
112
- * Order of diffs is deterministic: schema_version first, then tables in
113
- * sorted order (with column/index/constraint sub-diffs grouped per table),
114
- * then sequences. Consumers can rely on this for stable diff output.
102
+ * Order of diffs is deterministic: tables in sorted order (with
103
+ * column/index/constraint sub-diffs grouped per table), then sequences.
104
+ * Consumers can rely on this for stable diff output.
115
105
  */
116
106
  export declare const diff_schema_snapshots: (a: SchemaSnapshot, b: SchemaSnapshot) => Array<SchemaDiff>;
117
107
  /** Labels used in formatted output — defaults to `'a'` and `'b'`. */
@@ -1 +1 @@
1
- {"version":3,"file":"schema_parity.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_parity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema_parity.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_parity.ts"],"names":[],"mappings":"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"}
@@ -2,13 +2,12 @@ import './assert_dev_env.js';
2
2
  /**
3
3
  * Structural diff between two snapshots — empty array means parity holds.
4
4
  *
5
- * Order of diffs is deterministic: schema_version first, then tables in
6
- * sorted order (with column/index/constraint sub-diffs grouped per table),
7
- * then sequences. Consumers can rely on this for stable diff output.
5
+ * Order of diffs is deterministic: tables in sorted order (with
6
+ * column/index/constraint sub-diffs grouped per table), then sequences.
7
+ * Consumers can rely on this for stable diff output.
8
8
  */
9
9
  export const diff_schema_snapshots = (a, b) => {
10
10
  const diffs = [];
11
- diff_schema_version(a.schema_version, b.schema_version, diffs);
12
11
  const all_tables = new Set([...Object.keys(a.tables), ...Object.keys(b.tables)]);
13
12
  for (const table of [...all_tables].sort()) {
14
13
  const ta = a.tables[table];
@@ -39,33 +38,6 @@ export const diff_schema_snapshots = (a, b) => {
39
38
  }
40
39
  return diffs;
41
40
  };
42
- const diff_schema_version = (a, b, out) => {
43
- const key = (r) => `${r.namespace}\x00${r.name}`;
44
- const a_by_key = new Map(a.map((r) => [key(r), r]));
45
- const b_by_key = new Map(b.map((r) => [key(r), r]));
46
- const keys = new Set([...a_by_key.keys(), ...b_by_key.keys()]);
47
- for (const k of [...keys].sort()) {
48
- const row_a = a_by_key.get(k);
49
- const row_b = b_by_key.get(k);
50
- if (!row_a) {
51
- out.push({ kind: 'schema_version_only_in', where: 'b', row: row_b });
52
- continue;
53
- }
54
- if (!row_b) {
55
- out.push({ kind: 'schema_version_only_in', where: 'a', row: row_a });
56
- continue;
57
- }
58
- if (row_a.sequence !== row_b.sequence) {
59
- out.push({
60
- kind: 'schema_version_sequence_differs',
61
- namespace: row_a.namespace,
62
- name: row_a.name,
63
- a: row_a.sequence,
64
- b: row_b.sequence,
65
- });
66
- }
67
- }
68
- };
69
41
  const COLUMN_FIELDS = [
70
42
  'data_type',
71
43
  'udt_name',
@@ -165,12 +137,6 @@ export const format_schema_diffs = (diffs, labels = {}) => {
165
137
  const lines = [];
166
138
  for (const d of diffs) {
167
139
  switch (d.kind) {
168
- case 'schema_version_only_in':
169
- lines.push(` schema_version row only in ${where_label(d.where)}: ${d.row.namespace}/${d.row.name} (sequence ${d.row.sequence})`);
170
- break;
171
- case 'schema_version_sequence_differs':
172
- lines.push(` schema_version sequence differs for ${d.namespace}/${d.name}: ${label_a}=${d.a}, ${label_b}=${d.b}`);
173
- break;
174
140
  case 'table_only_in':
175
141
  lines.push(` table ${d.table} only in ${where_label(d.where)}`);
176
142
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_app",
3
- "version": "0.69.0",
3
+ "version": "0.71.0",
4
4
  "description": "fullstack app library",
5
5
  "glyph": "🗝",
6
6
  "logo": "logo.svg",