viyv-db-postgres 0.1.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 (98) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config.d.ts +37 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +15 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/db.d.ts +9 -0
  7. package/dist/db.d.ts.map +1 -0
  8. package/dist/db.js +13 -0
  9. package/dist/db.js.map +1 -0
  10. package/dist/error-mapper.d.ts +2 -0
  11. package/dist/error-mapper.d.ts.map +1 -0
  12. package/dist/error-mapper.js +24 -0
  13. package/dist/error-mapper.js.map +1 -0
  14. package/dist/index.d.ts +8 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +19 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/logical/cte-builder.d.ts +57 -0
  19. package/dist/logical/cte-builder.d.ts.map +1 -0
  20. package/dist/logical/cte-builder.js +167 -0
  21. package/dist/logical/cte-builder.js.map +1 -0
  22. package/dist/logical/data-ops.d.ts +19 -0
  23. package/dist/logical/data-ops.d.ts.map +1 -0
  24. package/dist/logical/data-ops.js +124 -0
  25. package/dist/logical/data-ops.js.map +1 -0
  26. package/dist/logical/embedding-ops.d.ts +24 -0
  27. package/dist/logical/embedding-ops.d.ts.map +1 -0
  28. package/dist/logical/embedding-ops.js +94 -0
  29. package/dist/logical/embedding-ops.js.map +1 -0
  30. package/dist/logical/migration-ops.d.ts +10 -0
  31. package/dist/logical/migration-ops.d.ts.map +1 -0
  32. package/dist/logical/migration-ops.js +201 -0
  33. package/dist/logical/migration-ops.js.map +1 -0
  34. package/dist/logical/query-ops.d.ts +18 -0
  35. package/dist/logical/query-ops.d.ts.map +1 -0
  36. package/dist/logical/query-ops.js +193 -0
  37. package/dist/logical/query-ops.js.map +1 -0
  38. package/dist/logical/registry.d.ts +27 -0
  39. package/dist/logical/registry.d.ts.map +1 -0
  40. package/dist/logical/registry.js +79 -0
  41. package/dist/logical/registry.js.map +1 -0
  42. package/dist/logical/schema-ops.d.ts +7 -0
  43. package/dist/logical/schema-ops.d.ts.map +1 -0
  44. package/dist/logical/schema-ops.js +311 -0
  45. package/dist/logical/schema-ops.js.map +1 -0
  46. package/dist/logical/sql-parser.d.ts +11 -0
  47. package/dist/logical/sql-parser.d.ts.map +1 -0
  48. package/dist/logical/sql-parser.js +37 -0
  49. package/dist/logical/sql-parser.js.map +1 -0
  50. package/dist/logical/sql-table-refs.d.ts +18 -0
  51. package/dist/logical/sql-table-refs.d.ts.map +1 -0
  52. package/dist/logical/sql-table-refs.js +203 -0
  53. package/dist/logical/sql-table-refs.js.map +1 -0
  54. package/dist/logical/sql-tokenizer.d.ts +20 -0
  55. package/dist/logical/sql-tokenizer.d.ts.map +1 -0
  56. package/dist/logical/sql-tokenizer.js +249 -0
  57. package/dist/logical/sql-tokenizer.js.map +1 -0
  58. package/dist/logical/type-utils.d.ts +11 -0
  59. package/dist/logical/type-utils.d.ts.map +1 -0
  60. package/dist/logical/type-utils.js +42 -0
  61. package/dist/logical/type-utils.js.map +1 -0
  62. package/dist/logical/where-builder.d.ts +6 -0
  63. package/dist/logical/where-builder.d.ts.map +1 -0
  64. package/dist/logical/where-builder.js +20 -0
  65. package/dist/logical/where-builder.js.map +1 -0
  66. package/dist/schema.d.ts +926 -0
  67. package/dist/schema.d.ts.map +1 -0
  68. package/dist/schema.js +78 -0
  69. package/dist/schema.js.map +1 -0
  70. package/dist/services/postgres-service.d.ts +40 -0
  71. package/dist/services/postgres-service.d.ts.map +1 -0
  72. package/dist/services/postgres-service.js +479 -0
  73. package/dist/services/postgres-service.js.map +1 -0
  74. package/dist/services/semantic-search-service.d.ts +16 -0
  75. package/dist/services/semantic-search-service.d.ts.map +1 -0
  76. package/dist/services/semantic-search-service.js +94 -0
  77. package/dist/services/semantic-search-service.js.map +1 -0
  78. package/dist/system-migrations/001_composite_pk.d.ts +4 -0
  79. package/dist/system-migrations/001_composite_pk.d.ts.map +1 -0
  80. package/dist/system-migrations/001_composite_pk.js +23 -0
  81. package/dist/system-migrations/001_composite_pk.js.map +1 -0
  82. package/dist/system-migrations/002_schema_log_index.d.ts +4 -0
  83. package/dist/system-migrations/002_schema_log_index.d.ts.map +1 -0
  84. package/dist/system-migrations/002_schema_log_index.js +13 -0
  85. package/dist/system-migrations/002_schema_log_index.js.map +1 -0
  86. package/dist/system-migrations/index.d.ts +9 -0
  87. package/dist/system-migrations/index.d.ts.map +1 -0
  88. package/dist/system-migrations/index.js +9 -0
  89. package/dist/system-migrations/index.js.map +1 -0
  90. package/dist/system-migrations/types.d.ts +18 -0
  91. package/dist/system-migrations/types.d.ts.map +1 -0
  92. package/dist/system-migrations/types.js +28 -0
  93. package/dist/system-migrations/types.js.map +1 -0
  94. package/dist/system-migrations.d.ts +25 -0
  95. package/dist/system-migrations.d.ts.map +1 -0
  96. package/dist/system-migrations.js +66 -0
  97. package/dist/system-migrations.js.map +1 -0
  98. package/package.json +44 -0
@@ -0,0 +1,16 @@
1
+ import type { IEmbeddingProvider, ISemanticSearchService, SemanticSearchOptions, SemanticSearchResult } from 'viyv-db-core';
2
+ import type { DrizzleDb } from '../db.js';
3
+ import type { LogicalTableRegistry } from '../logical/registry.js';
4
+ export declare class PostgresSemanticSearchService implements ISemanticSearchService {
5
+ private readonly db;
6
+ private readonly registry;
7
+ private readonly embeddingProvider;
8
+ private readonly tenantId;
9
+ private readonly dimensions;
10
+ constructor(db: DrizzleDb, registry: LogicalTableRegistry, embeddingProvider: IEmbeddingProvider, tenantId: string, dimensions: number);
11
+ initialize(): Promise<void>;
12
+ semanticSearch(options: SemanticSearchOptions): Promise<SemanticSearchResult[]>;
13
+ embedRows(table: string, rowIds: string[]): Promise<void>;
14
+ deleteEmbeddings(rowIds: string[]): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=semantic-search-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-search-service.d.ts","sourceRoot":"","sources":["../../src/services/semantic-search-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAO1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,qBAAa,6BAA8B,YAAW,sBAAsB;IAE1E,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAJV,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,oBAAoB,EAC9B,iBAAiB,EAAE,kBAAkB,EACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM;IAG9B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAoC/E,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkDzD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAGvD"}
@@ -0,0 +1,94 @@
1
+ import { and, eq, inArray } from 'drizzle-orm';
2
+ import { buildEmbeddingText } from 'viyv-db-core';
3
+ import { deleteEmbeddingsByRowIds, initializeEmbeddingTable, searchSimilar, storeEmbeddings, } from '../logical/embedding-ops.js';
4
+ import { logicalRows, logicalTables } from '../schema.js';
5
+ export class PostgresSemanticSearchService {
6
+ db;
7
+ registry;
8
+ embeddingProvider;
9
+ tenantId;
10
+ dimensions;
11
+ constructor(db, registry, embeddingProvider, tenantId, dimensions) {
12
+ this.db = db;
13
+ this.registry = registry;
14
+ this.embeddingProvider = embeddingProvider;
15
+ this.tenantId = tenantId;
16
+ this.dimensions = dimensions;
17
+ }
18
+ async initialize() {
19
+ await initializeEmbeddingTable(this.db, this.dimensions);
20
+ }
21
+ async semanticSearch(options) {
22
+ const limit = options.limit ?? 10;
23
+ const threshold = options.threshold ?? 0.0;
24
+ await this.registry.ensureLoaded(this.db, this.tenantId);
25
+ // Resolve table IDs if table names are specified
26
+ let tableIds;
27
+ if (options.tables && options.tables.length > 0) {
28
+ tableIds = [];
29
+ for (const name of options.tables) {
30
+ const id = this.registry.getTableId(name);
31
+ if (id)
32
+ tableIds.push(id);
33
+ }
34
+ if (tableIds.length === 0)
35
+ return [];
36
+ }
37
+ // Embed the query text
38
+ const queryPrefix = `query: ${options.query}`;
39
+ const [queryVector] = await this.embeddingProvider.embed([queryPrefix]);
40
+ const results = await searchSimilar(this.db, this.tenantId, queryVector, {
41
+ tableIds,
42
+ limit,
43
+ threshold,
44
+ });
45
+ return results.map((r) => ({
46
+ tableName: r.tableName,
47
+ tablePurpose: r.tablePurpose,
48
+ row: r.data,
49
+ similarity: r.similarity,
50
+ rowId: r.rowId,
51
+ }));
52
+ }
53
+ async embedRows(table, rowIds) {
54
+ if (rowIds.length === 0)
55
+ return;
56
+ await this.registry.ensureLoaded(this.db, this.tenantId);
57
+ const entry = this.registry.getTable(table);
58
+ if (!entry)
59
+ return;
60
+ // Get table metadata for purpose
61
+ const [tableRow] = await this.db
62
+ .select({ purpose: logicalTables.purpose })
63
+ .from(logicalTables)
64
+ .where(eq(logicalTables.id, entry.id));
65
+ const purpose = tableRow?.purpose ?? null;
66
+ // Fetch the actual row data
67
+ const rows = await this.db
68
+ .select({ id: logicalRows.id, data: logicalRows.data })
69
+ .from(logicalRows)
70
+ .where(and(eq(logicalRows.tenantId, this.tenantId), eq(logicalRows.tableId, entry.id), inArray(logicalRows.id, rowIds)));
71
+ if (rows.length === 0)
72
+ return;
73
+ // Build embedding texts
74
+ const columns = entry.columns.map((c) => ({ name: c.name, description: c.description }));
75
+ const texts = rows.map((r) => {
76
+ const data = r.data;
77
+ return `passage: ${buildEmbeddingText(table, purpose, columns, data)}`;
78
+ });
79
+ // Generate embeddings
80
+ const embeddings = await this.embeddingProvider.embed(texts);
81
+ // Store embeddings
82
+ const entries = rows.map((r, i) => ({
83
+ rowId: r.id,
84
+ tableId: entry.id,
85
+ embedding: embeddings[i],
86
+ embeddingText: texts[i],
87
+ }));
88
+ await storeEmbeddings(this.db, this.tenantId, entries);
89
+ }
90
+ async deleteEmbeddings(rowIds) {
91
+ await deleteEmbeddingsByRowIds(this.db, this.tenantId, rowIds);
92
+ }
93
+ }
94
+ //# sourceMappingURL=semantic-search-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-search-service.js","sourceRoot":"","sources":["../../src/services/semantic-search-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SystemMigration } from './types.js';
2
+ /** Convert _viyv_logical_rows PK from (id) to (id, tenant_id) for partitioning support */
3
+ export declare const migration: SystemMigration;
4
+ //# sourceMappingURL=001_composite_pk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"001_composite_pk.d.ts","sourceRoot":"","sources":["../../src/system-migrations/001_composite_pk.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,0FAA0F;AAC1F,eAAO,MAAM,SAAS,EAAE,eAmBvB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { sql } from 'drizzle-orm';
2
+ /** Convert _viyv_logical_rows PK from (id) to (id, tenant_id) for partitioning support */
3
+ export const migration = {
4
+ version: '001',
5
+ description: 'Composite PK (id, tenant_id) on _viyv_logical_rows',
6
+ up: async (tx) => {
7
+ await tx.execute(sql `
8
+ DO $$
9
+ BEGIN
10
+ IF EXISTS (
11
+ SELECT 1 FROM pg_constraint
12
+ WHERE conrelid = '_viyv_logical_rows'::regclass
13
+ AND contype = 'p'
14
+ AND array_length(conkey, 1) = 1
15
+ ) THEN
16
+ ALTER TABLE _viyv_logical_rows DROP CONSTRAINT _viyv_logical_rows_pkey;
17
+ ALTER TABLE _viyv_logical_rows ADD PRIMARY KEY (id, tenant_id);
18
+ END IF;
19
+ END $$
20
+ `);
21
+ },
22
+ };
23
+ //# sourceMappingURL=001_composite_pk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"001_composite_pk.js","sourceRoot":"","sources":["../../src/system-migrations/001_composite_pk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC,0FAA0F;AAC1F,MAAM,CAAC,MAAM,SAAS,GAAoB;IACzC,OAAO,EAAE,KAAK;IACd,WAAW,EAAE,oDAAoD;IACjE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAChB,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;;;;;;;;;;;GAanB,CAAC,CAAC;IACJ,CAAC;CACD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SystemMigration } from './types.js';
2
+ /** Add descending index on _viyv_schema_log.applied_at for time-series queries */
3
+ export declare const migration: SystemMigration;
4
+ //# sourceMappingURL=002_schema_log_index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002_schema_log_index.d.ts","sourceRoot":"","sources":["../../src/system-migrations/002_schema_log_index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,kFAAkF;AAClF,eAAO,MAAM,SAAS,EAAE,eASvB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { sql } from 'drizzle-orm';
2
+ /** Add descending index on _viyv_schema_log.applied_at for time-series queries */
3
+ export const migration = {
4
+ version: '002',
5
+ description: 'Index on _viyv_schema_log(applied_at DESC)',
6
+ up: async (tx) => {
7
+ await tx.execute(sql `
8
+ CREATE INDEX IF NOT EXISTS idx_schema_log_applied_at
9
+ ON _viyv_schema_log (applied_at DESC)
10
+ `);
11
+ },
12
+ };
13
+ //# sourceMappingURL=002_schema_log_index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002_schema_log_index.js","sourceRoot":"","sources":["../../src/system-migrations/002_schema_log_index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAoB;IACzC,OAAO,EAAE,KAAK;IACd,WAAW,EAAE,4CAA4C;IACzD,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAChB,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;GAGnB,CAAC,CAAC;IACJ,CAAC;CACD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { runSystemMigrations } from './types.js';
2
+ export type { SystemMigration } from './types.js';
3
+ import type { SystemMigration } from './types.js';
4
+ /**
5
+ * All system migrations in order.
6
+ * Add new migrations to the END — never reorder or remove.
7
+ */
8
+ export declare const systemMigrations: SystemMigration[];
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/system-migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAAiB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { runSystemMigrations } from './types.js';
2
+ import { migration as m001 } from './001_composite_pk.js';
3
+ import { migration as m002 } from './002_schema_log_index.js';
4
+ /**
5
+ * All system migrations in order.
6
+ * Add new migrations to the END — never reorder or remove.
7
+ */
8
+ export const systemMigrations = [m001, m002];
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/system-migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAG9D;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { SQL } from 'drizzle-orm';
2
+ /** Minimal interface covering both DrizzleDb and PgTransaction */
3
+ export interface Executor {
4
+ execute: (query: SQL) => Promise<{
5
+ rows: unknown[];
6
+ }>;
7
+ }
8
+ export interface SystemMigration {
9
+ version: string;
10
+ description: string;
11
+ up: (tx: Executor) => Promise<void>;
12
+ }
13
+ /**
14
+ * Run pending system migrations inside the given transaction.
15
+ * Call after all base `CREATE TABLE IF NOT EXISTS` statements.
16
+ */
17
+ export declare function runSystemMigrations(tx: Executor, migrations: SystemMigration[]): Promise<void>;
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/system-migrations/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGvC,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACxB,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,QAAQ,EACZ,UAAU,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAwBf"}
@@ -0,0 +1,28 @@
1
+ import { sql } from 'drizzle-orm';
2
+ /**
3
+ * Run pending system migrations inside the given transaction.
4
+ * Call after all base `CREATE TABLE IF NOT EXISTS` statements.
5
+ */
6
+ export async function runSystemMigrations(tx, migrations) {
7
+ // Bootstrap the tracking table
8
+ await tx.execute(sql `
9
+ CREATE TABLE IF NOT EXISTS _viyv_system_migrations (
10
+ version TEXT PRIMARY KEY,
11
+ description TEXT NOT NULL,
12
+ applied_at TIMESTAMPTZ NOT NULL DEFAULT now()
13
+ )
14
+ `);
15
+ // Fetch already-applied versions
16
+ const applied = await tx.execute(sql `
17
+ SELECT version FROM _viyv_system_migrations
18
+ `);
19
+ const appliedSet = new Set(applied.rows.map((r) => r.version));
20
+ // Run pending migrations in order
21
+ for (const m of migrations) {
22
+ if (appliedSet.has(m.version))
23
+ continue;
24
+ await m.up(tx);
25
+ await tx.execute(sql `INSERT INTO _viyv_system_migrations (version, description) VALUES (${m.version}, ${m.description})`);
26
+ }
27
+ }
28
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/system-migrations/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAalC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,EAAY,EACZ,UAA6B;IAE7B,+BAA+B;IAC/B,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;;;;EAMnB,CAAC,CAAC;IAEH,iCAAiC;IACjC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;EAEnC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAE,OAAO,CAAC,IAAmC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAE/F,kCAAkC;IAClC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC5B,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,SAAS;QACxC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACf,MAAM,EAAE,CAAC,OAAO,CACf,GAAG,CAAA,sEAAsE,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,WAAW,GAAG,CACvG,CAAC;IACH,CAAC;AACF,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { SQL } from 'drizzle-orm';
2
+ /** Minimal interface covering both DrizzleDb and PgTransaction */
3
+ interface Executor {
4
+ execute: (query: SQL) => Promise<{
5
+ rows: unknown[];
6
+ }>;
7
+ }
8
+ export interface SystemMigration {
9
+ version: string;
10
+ description: string;
11
+ up: (tx: Executor) => Promise<void>;
12
+ }
13
+ /**
14
+ * Ordered list of system schema migrations.
15
+ * Each migration runs once and is recorded in `_viyv_system_migrations`.
16
+ * Add new migrations to the END of this array — never reorder or remove.
17
+ */
18
+ export declare const systemMigrations: SystemMigration[];
19
+ /**
20
+ * Run pending system migrations inside the given transaction.
21
+ * Call after all base `CREATE TABLE IF NOT EXISTS` statements.
22
+ */
23
+ export declare function runSystemMigrations(tx: Executor): Promise<void>;
24
+ export {};
25
+ //# sourceMappingURL=system-migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-migrations.d.ts","sourceRoot":"","sources":["../src/system-migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGvC,kEAAkE;AAClE,UAAU,QAAQ;IACjB,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAgC7C,CAAC;AAEF;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBrE"}
@@ -0,0 +1,66 @@
1
+ import { sql } from 'drizzle-orm';
2
+ /**
3
+ * Ordered list of system schema migrations.
4
+ * Each migration runs once and is recorded in `_viyv_system_migrations`.
5
+ * Add new migrations to the END of this array — never reorder or remove.
6
+ */
7
+ export const systemMigrations = [
8
+ {
9
+ version: '001',
10
+ description: 'Composite PK (id, tenant_id) on _viyv_logical_rows',
11
+ up: async (tx) => {
12
+ // Only alter if PK is still single-column (idempotent guard)
13
+ await tx.execute(sql `
14
+ DO $$
15
+ BEGIN
16
+ IF EXISTS (
17
+ SELECT 1 FROM pg_constraint
18
+ WHERE conrelid = '_viyv_logical_rows'::regclass
19
+ AND contype = 'p'
20
+ AND array_length(conkey, 1) = 1
21
+ ) THEN
22
+ ALTER TABLE _viyv_logical_rows DROP CONSTRAINT _viyv_logical_rows_pkey;
23
+ ALTER TABLE _viyv_logical_rows ADD PRIMARY KEY (id, tenant_id);
24
+ END IF;
25
+ END $$
26
+ `);
27
+ },
28
+ },
29
+ {
30
+ version: '002',
31
+ description: 'Index on _viyv_schema_log(applied_at DESC)',
32
+ up: async (tx) => {
33
+ await tx.execute(sql `
34
+ CREATE INDEX IF NOT EXISTS idx_schema_log_applied_at
35
+ ON _viyv_schema_log (applied_at DESC)
36
+ `);
37
+ },
38
+ },
39
+ ];
40
+ /**
41
+ * Run pending system migrations inside the given transaction.
42
+ * Call after all base `CREATE TABLE IF NOT EXISTS` statements.
43
+ */
44
+ export async function runSystemMigrations(tx) {
45
+ // Bootstrap the tracking table
46
+ await tx.execute(sql `
47
+ CREATE TABLE IF NOT EXISTS _viyv_system_migrations (
48
+ version TEXT PRIMARY KEY,
49
+ description TEXT NOT NULL,
50
+ applied_at TIMESTAMPTZ NOT NULL DEFAULT now()
51
+ )
52
+ `);
53
+ // Fetch already-applied versions
54
+ const applied = await tx.execute(sql `
55
+ SELECT version FROM _viyv_system_migrations
56
+ `);
57
+ const appliedSet = new Set(applied.rows.map((r) => r.version));
58
+ // Run pending migrations in order
59
+ for (const m of systemMigrations) {
60
+ if (appliedSet.has(m.version))
61
+ continue;
62
+ await m.up(tx);
63
+ await tx.execute(sql `INSERT INTO _viyv_system_migrations (version, description) VALUES (${m.version}, ${m.description})`);
64
+ }
65
+ }
66
+ //# sourceMappingURL=system-migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-migrations.js","sourceRoot":"","sources":["../src/system-migrations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAalC;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAsB;IAClD;QACC,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,oDAAoD;QACjE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YAChB,6DAA6D;YAC7D,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;;;;;;;;;;;IAanB,CAAC,CAAC;QACJ,CAAC;KACD;IACD;QACC,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,4CAA4C;QACzD,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YAChB,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;IAGnB,CAAC,CAAC;QACJ,CAAC;KACD;CACD,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EAAY;IACrD,+BAA+B;IAC/B,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;;;;EAMnB,CAAC,CAAC;IAEH,iCAAiC;IACjC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;EAEnC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAE,OAAO,CAAC,IAAmC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAE/F,kCAAkC;IAClC,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAClC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,SAAS;QACxC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACf,MAAM,EAAE,CAAC,OAAO,CACf,GAAG,CAAA,sEAAsE,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,WAAW,GAAG,CACvG,CAAC;IACH,CAAC;AACF,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "viyv-db-postgres",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "PostgreSQL logical table implementation for viyv-db",
6
+ "license": "MIT",
7
+ "author": "viyv",
8
+ "engines": {
9
+ "node": ">=20"
10
+ },
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "!dist/__tests__"
22
+ ],
23
+ "dependencies": {
24
+ "pg": "^8.13.0",
25
+ "drizzle-orm": "^0.38.0",
26
+ "nanoid": "^5.0.0",
27
+ "zod": "^3.23.0",
28
+ "viyv-db-core": "0.1.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/pg": "^8.11.0",
32
+ "drizzle-kit": "^0.30.0",
33
+ "typescript": "^5.7.0",
34
+ "vitest": "^2.1.0"
35
+ },
36
+ "scripts": {
37
+ "build": "tsc",
38
+ "typecheck": "tsc --noEmit",
39
+ "test": "vitest run",
40
+ "clean": "rm -rf dist",
41
+ "db:generate": "drizzle-kit generate",
42
+ "db:migrate": "drizzle-kit migrate"
43
+ }
44
+ }