@vrplatform/kysely 1.3.45-stage.25 → 1.3.45-stage.255

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 (32) hide show
  1. package/build/main/index.js +2 -1
  2. package/build/main/index.js.map +1 -1
  3. package/build/main/local/index.js +98 -8
  4. package/build/main/local/index.js.map +1 -1
  5. package/build/main/postgres-error.d.ts +3 -3
  6. package/build/main/postgres-error.js +4 -3
  7. package/build/main/postgres-error.js.map +1 -1
  8. package/build/main/test/index.d.ts +25 -2
  9. package/build/main/test/index.js +36 -5
  10. package/build/main/test/index.js.map +1 -1
  11. package/build/main/v1.generated.d.ts +1 -1
  12. package/build/main/v1.generated.js.map +1 -1
  13. package/build/migrations-v2/0000000000032-tenant-delete-ownership-cascades.ts +44 -0
  14. package/build/migrations-v2/0000000000033-reservation-issue-seed-bucket-index.ts +19 -0
  15. package/build/migrations-v2/0000000000034-retire-recent-classification-indexes.ts +29 -0
  16. package/build/migrations-v2/0000000000035-core-change-autovacuum.ts +24 -0
  17. package/build/migrations-v2/0000000000036-journal-entry-inactive-reason-constraint.ts +33 -0
  18. package/build/migrations-v2/0000000000037-journal-entry-inactive-reasons.ts +19 -0
  19. package/build/migrations-v2/0000000000038-journal-entry-group-inactive-reason.ts +14 -0
  20. package/build/module/index.js +2 -1
  21. package/build/module/index.js.map +1 -1
  22. package/build/module/local/index.js +98 -8
  23. package/build/module/local/index.js.map +1 -1
  24. package/build/module/postgres-error.d.ts +3 -3
  25. package/build/module/postgres-error.js +4 -3
  26. package/build/module/postgres-error.js.map +1 -1
  27. package/build/module/test/index.d.ts +25 -2
  28. package/build/module/test/index.js +35 -5
  29. package/build/module/test/index.js.map +1 -1
  30. package/build/module/v1.generated.d.ts +1 -1
  31. package/build/module/v1.generated.js.map +1 -1
  32. package/package.json +1 -1
@@ -0,0 +1,19 @@
1
+ import type { Kysely } from 'kysely';
2
+ import { sql } from 'kysely';
3
+
4
+ export async function up(db: Kysely<unknown>): Promise<void> {
5
+ await sql`
6
+ alter type accounting.journal_entry_inactive_reason
7
+ add value if not exists 'historicalLedger'
8
+ before 'unknownInactiveReason'
9
+ `.execute(db);
10
+ await sql`
11
+ alter type accounting.journal_entry_inactive_reason
12
+ add value if not exists 'listingOwnershipPeriodNotFound'
13
+ before 'unknownInactiveReason'
14
+ `.execute(db);
15
+ }
16
+
17
+ export async function down(_db: Kysely<unknown>): Promise<void> {
18
+ // PostgreSQL enum values cannot be removed safely without rebuilding the type.
19
+ }
@@ -0,0 +1,14 @@
1
+ import type { Kysely } from 'kysely';
2
+ import { sql } from 'kysely';
3
+
4
+ export async function up(db: Kysely<unknown>): Promise<void> {
5
+ await sql`
6
+ alter type accounting.journal_entry_inactive_reason
7
+ add value if not exists 'unbalancedGroupInactiveLeg'
8
+ before 'unknownInactiveReason'
9
+ `.execute(db);
10
+ }
11
+
12
+ export async function down(_db: Kysely<unknown>): Promise<void> {
13
+ // PostgreSQL enum values cannot be removed safely without rebuilding the type.
14
+ }
@@ -60,7 +60,8 @@ class RetryingPostgresJSDialect extends PostgresJSDialect {
60
60
  (compiledQuery.query.kind !== 'SelectQueryNode' ||
61
61
  (message !==
62
62
  'Egress connection severed outside of Hyperdrive' &&
63
- message !== 'Network connection lost.')))) {
63
+ message !== 'Network connection lost.' &&
64
+ message !== 'Node shutting down')))) {
64
65
  return false;
65
66
  }
66
67
  // Postgres.js already ejects a severed reserved connection.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { backOff } from 'exponential-backoff';\nimport type {\n DatabaseConnection,\n Driver,\n Kysely as K,\n LogConfig,\n Transaction as T,\n} from 'kysely';\nimport {\n PostgresJSDialect,\n type PostgresJSDialectConfig,\n PostgresJSDriver,\n} from 'kysely-postgres-js';\nimport postgres, { type Sql } from 'postgres';\nimport { type ControlPlaneDB, withControlPlaneSchema } from './control-plane';\nimport { KyselyError } from './error';\nimport { getKysely } from './plugins';\n\nexport type { Insertable, LogEvent } from 'kysely';\nexport * from './error';\nexport * from './isomorphic';\nexport * from './postgres-error';\nexport * from './query';\nexport * from './regional';\nexport * from './transaction';\n\nimport { parseDuration } from '@vrplatform/utils';\nimport type { DB } from './v1.generated';\n\ntype KyselyOpts = {\n hyperdrive?: true;\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\ntype PgOpt = {\n forceDisableSSL?: boolean;\n probe?: true;\n retries?: false | number;\n} & Pick<KyselyOpts, 'hyperdrive'>;\n\nconst retryableMessages = [\n 'CONNECTION_CLOSED',\n 'CONNECT_TIMEOUT',\n 'Idle connection closed by Hyperdrive.',\n 'server_login_retry',\n];\nconst postgresRetryAttempts = 3;\n\nfunction isRetryableConnectionError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return retryableMessages.some((retryable) => message.includes(retryable));\n}\n\nfunction retryPostgres<T>(\n operation: () => Promise<T>,\n retry: (error: unknown, attemptNumber: number) => boolean | Promise<boolean>\n) {\n return backOff(operation, {\n numOfAttempts: postgresRetryAttempts,\n startingDelay: parseDuration('1s'),\n maxDelay: parseDuration('5s'),\n retry: (error, attemptNumber) =>\n attemptNumber < postgresRetryAttempts && retry(error, attemptNumber),\n });\n}\n\nclass RetryingPostgresJSDialect extends PostgresJSDialect {\n constructor(private readonly config: PostgresJSDialectConfig) {\n super(config);\n }\n\n override createDriver(): Driver {\n const driver = new PostgresJSDriver(this.config);\n const connections = new WeakMap<\n DatabaseConnection,\n { connection: DatabaseConnection; inTransaction: boolean }\n >();\n const getConnection = (connection: DatabaseConnection) => {\n const state = connections.get(connection);\n if (!state) throw new Error('Postgres connection state is unavailable');\n return state;\n };\n\n return {\n init: () => driver.init(),\n acquireConnection: async () => {\n const state = {\n connection: await driver.acquireConnection(),\n inTransaction: false,\n };\n const connection: DatabaseConnection = {\n executeQuery: (compiledQuery) =>\n retryPostgres(\n () => state.connection.executeQuery(compiledQuery),\n async (error) => {\n const message =\n error instanceof Error ? error.message : String(error);\n if (\n state.inTransaction ||\n (!isRetryableConnectionError(error) &&\n (compiledQuery.query.kind !== 'SelectQueryNode' ||\n (message !==\n 'Egress connection severed outside of Hyperdrive' &&\n message !== 'Network connection lost.')))\n ) {\n return false;\n }\n\n // Postgres.js already ejects a severed reserved connection.\n // Acquire a new reservation before replaying the safe read.\n state.connection = await driver.acquireConnection();\n return true;\n }\n ),\n streamQuery: (compiledQuery, chunkSize) => {\n if (chunkSize === undefined) {\n throw new Error('Postgres stream chunk size is required');\n }\n return state.connection.streamQuery(compiledQuery, chunkSize);\n },\n };\n connections.set(connection, state);\n return connection;\n },\n beginTransaction: async (connection, settings) => {\n const state = getConnection(connection);\n state.inTransaction = true;\n try {\n await driver.beginTransaction(state.connection, settings);\n } catch (error) {\n state.inTransaction = false;\n throw error;\n }\n },\n commitTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.commitTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n rollbackTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.rollbackTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n savepoint: (connection, savepointName, compileQuery) =>\n driver.savepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n rollbackToSavepoint: (connection, savepointName, compileQuery) =>\n driver.rollbackToSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseSavepoint: (connection, savepointName, compileQuery) =>\n driver.releaseSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseConnection: async (connection) => {\n await driver.releaseConnection(getConnection(connection).connection);\n connections.delete(connection);\n },\n destroy: () => driver.destroy(),\n };\n }\n}\n\nexport type Kysely = K<DB>;\nexport type ControlPlaneKysely = K<ControlPlaneDB>;\nexport type ControlPlaneTransaction = T<ControlPlaneDB>;\nexport function useKysely<Database = DB>(postgres: Sql, options?: KyselyOpts) {\n console.debug('Creating Kysely instance');\n const reserveConnection = postgres.reserve.bind(postgres);\n postgres.reserve = async () => {\n const connection = await retryPostgres(\n reserveConnection,\n isRetryableConnectionError\n );\n if (options?.hyperdrive) {\n const unsafe = connection.unsafe;\n connection.unsafe = (query, parameters, queryOptions) =>\n unsafe(query, parameters, { ...queryOptions, prepare: true });\n }\n return connection;\n };\n const kysely = getKysely<Database>(\n new RetryingPostgresJSDialect({ postgres }),\n {\n repositoryName: options?.repositoryName,\n log: options?.log,\n }\n );\n kysely.destroy = async () => {\n console.debug('Closing Kysely connection');\n await postgres.end({ timeout: 5 }).catch(() => undefined);\n const index = _connections.indexOf(postgres);\n if (index !== -1) _connections.splice(index, 1);\n };\n\n return kysely;\n}\n\nlet _connections: postgres.Sql[] = [];\nexport async function useAsyncPostgres(connectionString: string, opt?: PgOpt) {\n const delayMs = 2500;\n const probe = opt?.probe === true;\n const retries = probe ? (opt?.retries === false ? 0 : opt?.retries || 3) : 1;\n const ssl = opt?.forceDisableSSL !== true && opt?.hyperdrive !== true;\n const url = new URL(connectionString);\n\n console.debug(\n `Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${ssl}, and port=${url.port}`\n );\n if (_connections.length > 0)\n console.warn(`We already have ${_connections.length} Postgres connections`);\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const sql = postgres(connectionString, {\n ssl: ssl ? 'require' : false,\n target_session_attrs: 'read-write',\n // enable prepare statements, pgbouncer on crunchy allows for prepared statements\n prepare: true,\n ...(opt?.hyperdrive\n ? {\n max: 5,\n // Retire idle clients before Hyperdrive can close them asynchronously.\n idle_timeout: 10,\n }\n : {\n connect_timeout: 10,\n idle_timeout: 60,\n }),\n });\n\n if (probe) {\n await sql`select 1`;\n }\n // statement_timeout/lock_timeout are role-level settings on the cluster\n // (ALTER ROLE application SET ...) so they cover every pooled\n // connection; per-session SETs here only ever applied to one of them\n\n _connections.push(sql);\n return sql;\n } catch (err) {\n if (attempt === retries) throw err;\n console.warn(\n `Postgres connection failed (attempt ${attempt}), retrying...`\n );\n console.error('error', err);\n await new Promise((res) => setTimeout(res, delayMs));\n }\n }\n throw new KyselyError('Unable to connect to Postgres');\n}\n\nexport async function useAsyncKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return useKysely(sql, opt);\n}\n\nexport async function useAsyncControlPlaneKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return withControlPlaneSchema(useKysely<ControlPlaneDB>(sql, opt), 'public');\n}\n\nexport async function forceCloseAllPostgres(timeoutMs = 5000) {\n await Promise.race([\n Promise.all(\n _connections.map((pg) =>\n pg.end({ timeout: timeoutMs / 1000 }).catch(() => undefined)\n )\n ),\n new Promise((res) => setTimeout(res, timeoutMs + 1000)),\n ]);\n _connections = [];\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { backOff } from 'exponential-backoff';\nimport type {\n DatabaseConnection,\n Driver,\n Kysely as K,\n LogConfig,\n Transaction as T,\n} from 'kysely';\nimport {\n PostgresJSDialect,\n type PostgresJSDialectConfig,\n PostgresJSDriver,\n} from 'kysely-postgres-js';\nimport postgres, { type Sql } from 'postgres';\nimport { type ControlPlaneDB, withControlPlaneSchema } from './control-plane';\nimport { KyselyError } from './error';\nimport { getKysely } from './plugins';\n\nexport type { Insertable, LogEvent } from 'kysely';\nexport * from './error';\nexport * from './isomorphic';\nexport * from './postgres-error';\nexport * from './query';\nexport * from './regional';\nexport * from './transaction';\n\nimport { parseDuration } from '@vrplatform/utils';\nimport type { DB } from './v1.generated';\n\ntype KyselyOpts = {\n hyperdrive?: true;\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\ntype PgOpt = {\n forceDisableSSL?: boolean;\n probe?: true;\n retries?: false | number;\n} & Pick<KyselyOpts, 'hyperdrive'>;\n\nconst retryableMessages = [\n 'CONNECTION_CLOSED',\n 'CONNECT_TIMEOUT',\n 'Idle connection closed by Hyperdrive.',\n 'server_login_retry',\n];\nconst postgresRetryAttempts = 3;\n\nfunction isRetryableConnectionError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return retryableMessages.some((retryable) => message.includes(retryable));\n}\n\nfunction retryPostgres<T>(\n operation: () => Promise<T>,\n retry: (error: unknown, attemptNumber: number) => boolean | Promise<boolean>\n) {\n return backOff(operation, {\n numOfAttempts: postgresRetryAttempts,\n startingDelay: parseDuration('1s'),\n maxDelay: parseDuration('5s'),\n retry: (error, attemptNumber) =>\n attemptNumber < postgresRetryAttempts && retry(error, attemptNumber),\n });\n}\n\nclass RetryingPostgresJSDialect extends PostgresJSDialect {\n constructor(private readonly config: PostgresJSDialectConfig) {\n super(config);\n }\n\n override createDriver(): Driver {\n const driver = new PostgresJSDriver(this.config);\n const connections = new WeakMap<\n DatabaseConnection,\n { connection: DatabaseConnection; inTransaction: boolean }\n >();\n const getConnection = (connection: DatabaseConnection) => {\n const state = connections.get(connection);\n if (!state) throw new Error('Postgres connection state is unavailable');\n return state;\n };\n\n return {\n init: () => driver.init(),\n acquireConnection: async () => {\n const state = {\n connection: await driver.acquireConnection(),\n inTransaction: false,\n };\n const connection: DatabaseConnection = {\n executeQuery: (compiledQuery) =>\n retryPostgres(\n () => state.connection.executeQuery(compiledQuery),\n async (error) => {\n const message =\n error instanceof Error ? error.message : String(error);\n if (\n state.inTransaction ||\n (!isRetryableConnectionError(error) &&\n (compiledQuery.query.kind !== 'SelectQueryNode' ||\n (message !==\n 'Egress connection severed outside of Hyperdrive' &&\n message !== 'Network connection lost.' &&\n message !== 'Node shutting down')))\n ) {\n return false;\n }\n\n // Postgres.js already ejects a severed reserved connection.\n // Acquire a new reservation before replaying the safe read.\n state.connection = await driver.acquireConnection();\n return true;\n }\n ),\n streamQuery: (compiledQuery, chunkSize) => {\n if (chunkSize === undefined) {\n throw new Error('Postgres stream chunk size is required');\n }\n return state.connection.streamQuery(compiledQuery, chunkSize);\n },\n };\n connections.set(connection, state);\n return connection;\n },\n beginTransaction: async (connection, settings) => {\n const state = getConnection(connection);\n state.inTransaction = true;\n try {\n await driver.beginTransaction(state.connection, settings);\n } catch (error) {\n state.inTransaction = false;\n throw error;\n }\n },\n commitTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.commitTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n rollbackTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.rollbackTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n savepoint: (connection, savepointName, compileQuery) =>\n driver.savepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n rollbackToSavepoint: (connection, savepointName, compileQuery) =>\n driver.rollbackToSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseSavepoint: (connection, savepointName, compileQuery) =>\n driver.releaseSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseConnection: async (connection) => {\n await driver.releaseConnection(getConnection(connection).connection);\n connections.delete(connection);\n },\n destroy: () => driver.destroy(),\n };\n }\n}\n\nexport type Kysely = K<DB>;\nexport type ControlPlaneKysely = K<ControlPlaneDB>;\nexport type ControlPlaneTransaction = T<ControlPlaneDB>;\nexport function useKysely<Database = DB>(postgres: Sql, options?: KyselyOpts) {\n console.debug('Creating Kysely instance');\n const reserveConnection = postgres.reserve.bind(postgres);\n postgres.reserve = async () => {\n const connection = await retryPostgres(\n reserveConnection,\n isRetryableConnectionError\n );\n if (options?.hyperdrive) {\n const unsafe = connection.unsafe;\n connection.unsafe = (query, parameters, queryOptions) =>\n unsafe(query, parameters, { ...queryOptions, prepare: true });\n }\n return connection;\n };\n const kysely = getKysely<Database>(\n new RetryingPostgresJSDialect({ postgres }),\n {\n repositoryName: options?.repositoryName,\n log: options?.log,\n }\n );\n kysely.destroy = async () => {\n console.debug('Closing Kysely connection');\n await postgres.end({ timeout: 5 }).catch(() => undefined);\n const index = _connections.indexOf(postgres);\n if (index !== -1) _connections.splice(index, 1);\n };\n\n return kysely;\n}\n\nlet _connections: postgres.Sql[] = [];\nexport async function useAsyncPostgres(connectionString: string, opt?: PgOpt) {\n const delayMs = 2500;\n const probe = opt?.probe === true;\n const retries = probe ? (opt?.retries === false ? 0 : opt?.retries || 3) : 1;\n const ssl = opt?.forceDisableSSL !== true && opt?.hyperdrive !== true;\n const url = new URL(connectionString);\n\n console.debug(\n `Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${ssl}, and port=${url.port}`\n );\n if (_connections.length > 0)\n console.warn(`We already have ${_connections.length} Postgres connections`);\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const sql = postgres(connectionString, {\n ssl: ssl ? 'require' : false,\n target_session_attrs: 'read-write',\n // enable prepare statements, pgbouncer on crunchy allows for prepared statements\n prepare: true,\n ...(opt?.hyperdrive\n ? {\n max: 5,\n // Retire idle clients before Hyperdrive can close them asynchronously.\n idle_timeout: 10,\n }\n : {\n connect_timeout: 10,\n idle_timeout: 60,\n }),\n });\n\n if (probe) {\n await sql`select 1`;\n }\n // statement_timeout/lock_timeout are role-level settings on the cluster\n // (ALTER ROLE application SET ...) so they cover every pooled\n // connection; per-session SETs here only ever applied to one of them\n\n _connections.push(sql);\n return sql;\n } catch (err) {\n if (attempt === retries) throw err;\n console.warn(\n `Postgres connection failed (attempt ${attempt}), retrying...`\n );\n console.error('error', err);\n await new Promise((res) => setTimeout(res, delayMs));\n }\n }\n throw new KyselyError('Unable to connect to Postgres');\n}\n\nexport async function useAsyncKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return useKysely(sql, opt);\n}\n\nexport async function useAsyncControlPlaneKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return withControlPlaneSchema(useKysely<ControlPlaneDB>(sql, opt), 'public');\n}\n\nexport async function forceCloseAllPostgres(timeoutMs = 5000) {\n await Promise.race([\n Promise.all(\n _connections.map((pg) =>\n pg.end({ timeout: timeoutMs / 1000 }).catch(() => undefined)\n )\n ),\n new Promise((res) => setTimeout(res, timeoutMs + 1000)),\n ]);\n _connections = [];\n}\n"]}
@@ -27,17 +27,68 @@ async function migrateToLatest(kysely) {
27
27
  throw error;
28
28
  }
29
29
  }
30
- export async function useLocalKysely(args = {}) {
31
- let isDestroyed = false;
32
- // const now = performance.now();
33
- const dump = Bun.file(dumpPath);
30
+ // Every spec file used to replay this identical bootstrap - migrations, the
31
+ // schema surgery, and the control-plane seed copies - against a freshly loaded
32
+ // snapshot, which measured ~345ms per file against ~185ms for the snapshot load
33
+ // alone. None of it depends on the caller, so it runs once and is cached as a
34
+ // prepared snapshot keyed by everything that determines its content.
35
+ const preparedDumpPrefix = '.data.prepared.';
36
+ let preparedDumpPromise;
37
+ async function preparedDumpKey() {
38
+ const [snapshot, appMigrations, controlPlaneMigrations] = await Promise.all([
39
+ fs.stat(dumpPath),
40
+ fs.readdir(path.join(root, appMigrationEpoch.folder)),
41
+ fs.readdir(path.join(root, 'control-plane-migrations')),
42
+ ]);
43
+ const hasher = new Bun.CryptoHasher('sha256');
44
+ hasher.update(`${snapshot.size}:${snapshot.mtimeMs}`);
45
+ hasher.update(appMigrations.sort().join(','));
46
+ hasher.update(controlPlaneMigrations.sort().join(','));
47
+ // Source of the bootstrap itself, so editing the surgery rebuilds the
48
+ // snapshot. Read through toString() rather than the file: this module is also
49
+ // published as CommonJS, where import.meta is a compile error.
50
+ for (const step of [
51
+ buildPreparedDump,
52
+ migrateToLatest,
53
+ ensureDigestFunction,
54
+ ensureGenRandomBytesFunction,
55
+ ]) {
56
+ hasher.update(step.toString());
57
+ }
58
+ return hasher.digest('hex').slice(0, 16);
59
+ }
60
+ async function resolvePreparedDump() {
61
+ const key = await preparedDumpKey();
62
+ const target = path.join(root, `${preparedDumpPrefix}${key}.tar`);
63
+ const cached = Bun.file(target);
64
+ if (await cached.exists()) {
65
+ return cached;
66
+ }
67
+ const content = await buildPreparedDump();
68
+ // Sibling workers build this concurrently on a cold cache; rename is atomic,
69
+ // so a reader never observes a half-written snapshot.
70
+ const staging = `${target}.${process.pid}.tmp`;
71
+ await Bun.write(staging, content);
72
+ await fs.rename(staging, target);
73
+ // Only finished snapshots: a sibling worker's staging file also carries the
74
+ // prefix, and removing it would break its rename.
75
+ const current = path.basename(target);
76
+ for (const entry of await fs.readdir(root)) {
77
+ if (entry.startsWith(preparedDumpPrefix) &&
78
+ entry.endsWith('.tar') &&
79
+ entry !== current) {
80
+ await fs.rm(path.join(root, entry), { force: true });
81
+ }
82
+ }
83
+ return content;
84
+ }
85
+ async function buildPreparedDump() {
34
86
  const pglite = new PGlite({
35
- loadDataDir: dump,
87
+ loadDataDir: Bun.file(dumpPath),
36
88
  });
37
89
  const dialect = new PGliteDialect(pglite);
38
90
  const kysely = getKysely(dialect, {
39
- repositoryName: args?.repositoryName ?? 'localTesting',
40
- log: args?.log,
91
+ repositoryName: 'localTestingPrepare',
41
92
  });
42
93
  await ensureDigestFunction(kysely);
43
94
  await ensureGenRandomBytesFunction(kysely);
@@ -47,7 +98,7 @@ export async function useLocalKysely(args = {}) {
47
98
  await sql `create schema public`.execute(kysely);
48
99
  await sql `create schema core`.execute(kysely);
49
100
  const controlPlaneBootstrapKysely = getKysely(dialect, {
50
- repositoryName: `${args.repositoryName ?? 'localTesting'}/control-plane-bootstrap`,
101
+ repositoryName: 'localTestingPrepare/control-plane-bootstrap',
51
102
  });
52
103
  const controlPlaneMigrator = new Migrator({
53
104
  db: controlPlaneBootstrapKysely,
@@ -97,6 +148,26 @@ export async function useLocalKysely(args = {}) {
97
148
  end;
98
149
  $$;
99
150
  `.execute(controlPlaneBootstrapKysely);
151
+ // The canonical VRPlatform tenant. Production code falls back to this exact id
152
+ // in getCalculatedBillingPartnerId, so specs need it to exist without each of
153
+ // them creating - and mutating - their own copy of a shared singleton.
154
+ await kysely
155
+ .insertInto('public.tenant')
156
+ .values({
157
+ id: '7bfec41f-aa3f-4602-95d2-f7996e4f0e59',
158
+ name: 'VRPlatform',
159
+ type: 'partner',
160
+ status: 'active',
161
+ isActive: true,
162
+ isGeneralLedger: false,
163
+ isOnboarding: false,
164
+ partnerId: null,
165
+ billingPartnerId: null,
166
+ defaultCurrency: 'usd',
167
+ statementStartAt: new Date('2020-01-01T00:00:00Z'),
168
+ })
169
+ .onConflict((oc) => oc.column('id').doNothing())
170
+ .execute();
100
171
  await sql `
101
172
  insert into control_plane.app (
102
173
  authentication,
@@ -252,6 +323,25 @@ export async function useLocalKysely(args = {}) {
252
323
  from public.token
253
324
  on conflict (id) do nothing;
254
325
  `.execute(controlPlaneBootstrapKysely);
326
+ const content = await pglite.dumpDataDir('none');
327
+ await kysely.destroy();
328
+ return content;
329
+ }
330
+ export async function useLocalKysely(args = {}) {
331
+ let isDestroyed = false;
332
+ preparedDumpPromise ??= resolvePreparedDump();
333
+ const pglite = new PGlite({
334
+ loadDataDir: await preparedDumpPromise,
335
+ });
336
+ // The constructor is lazy. The bootstrap this replaced forced the snapshot to
337
+ // load before returning, so keep that contract: a returned handle is usable,
338
+ // and a bad snapshot fails here instead of inside an unrelated test.
339
+ await pglite.waitReady;
340
+ const dialect = new PGliteDialect(pglite);
341
+ const kysely = getKysely(dialect, {
342
+ repositoryName: args?.repositoryName ?? 'localTesting',
343
+ log: args?.log,
344
+ });
255
345
  const controlPlaneKysely = withControlPlaneSchema(getKysely(dialect, {
256
346
  repositoryName: `${args.repositoryName ?? 'localTesting'}/control-plane`,
257
347
  log: args.log,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"src/","sources":["local/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport * as path from 'node:path';\nimport { PGlite } from '@electric-sql/pglite';\nimport { FileMigrationProvider, type LogConfig, Migrator, sql } from 'kysely';\nimport { PGliteDialect } from 'kysely-pglite-dialect';\nimport { type ControlPlaneDB, withControlPlaneSchema } from '../control-plane';\nimport type { ControlPlaneKysely } from '../index';\nimport { appMigrationEpoch } from '../migration';\nimport { getKysely } from '../plugins';\nimport type { DB } from '../v1.generated';\nimport { ensureDigestFunction, ensureGenRandomBytesFunction } from './digest';\n\nexport const root = path.join(__dirname, '../..');\nexport const dumpPath = path.join(root, '.data.tar');\n\nexport type UseLocalKyselyOptions = {\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\nexport type LocalKysely = import('kysely').Kysely<DB> & {\n controlPlaneKysely: ControlPlaneKysely;\n};\n\nasync function migrateToLatest<Database>(\n kysely: import('kysely').Kysely<Database>\n) {\n const migrator = new Migrator({\n allowUnorderedMigrations: true,\n db: kysely,\n migrationTableSchema: appMigrationEpoch.tableSchema,\n migrationTableName: appMigrationEpoch.tableName,\n migrationLockTableName: appMigrationEpoch.lockTableName,\n provider: new FileMigrationProvider({\n fs,\n path,\n migrationFolder: path.join(root, appMigrationEpoch.folder),\n }),\n });\n\n const { error } = await migrator.migrateToLatest();\n if (error) {\n throw error;\n }\n}\n\nexport async function useLocalKysely(\n args: UseLocalKyselyOptions = {}\n): Promise<LocalKysely> {\n let isDestroyed = false;\n // const now = performance.now();\n\n const dump = Bun.file(dumpPath);\n\n const pglite = new PGlite({\n loadDataDir: dump,\n });\n const dialect = new PGliteDialect(pglite);\n const kysely = getKysely<DB>(dialect, {\n repositoryName: args?.repositoryName ?? 'localTesting',\n log: args?.log,\n });\n await ensureDigestFunction(kysely);\n await ensureGenRandomBytesFunction(kysely);\n await migrateToLatest(kysely);\n\n await sql`alter schema public rename to regional_public`.execute(kysely);\n await sql`alter schema core rename to regional_core`.execute(kysely);\n await sql`create schema public`.execute(kysely);\n await sql`create schema core`.execute(kysely);\n\n const controlPlaneBootstrapKysely = getKysely<ControlPlaneDB>(dialect, {\n repositoryName: `${args.repositoryName ?? 'localTesting'}/control-plane-bootstrap`,\n });\n const controlPlaneMigrator = new Migrator({\n db: controlPlaneBootstrapKysely,\n migrationTableSchema: 'public',\n migrationTableName: 'control_plane_kysely_migration',\n migrationLockTableName: 'control_plane_kysely_migration_lock',\n provider: new FileMigrationProvider({\n fs,\n path,\n migrationFolder: path.join(root, 'control-plane-migrations'),\n }),\n });\n const { error: controlPlaneMigrationError } =\n await controlPlaneMigrator.migrateToLatest();\n if (controlPlaneMigrationError) {\n throw controlPlaneMigrationError;\n }\n\n await sql`alter table core.flow set schema public`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`alter table core.issue_message_overwrite set schema public`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`drop schema core`.execute(controlPlaneBootstrapKysely);\n await sql`alter schema public rename to control_plane`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`alter schema regional_public rename to public`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`alter schema regional_core rename to core`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`\n do $$\n declare\n definition text;\n begin\n select pg_get_functiondef(\n 'control_plane.normalize_tenant_slug(text)'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n\n select pg_get_functiondef(\n 'control_plane.build_unique_tenant_slug(text,uuid)'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n\n select pg_get_functiondef(\n 'control_plane.refresh_operation_state(uuid)'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n\n select pg_get_functiondef(\n 'control_plane.refresh_destructive_job_operation()'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n end;\n $$;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.app (\n authentication,\n category,\n color,\n created_at,\n icon,\n icon_round,\n id,\n info,\n name,\n type,\n version\n )\n select\n authentication,\n category,\n color,\n created_at,\n icon,\n icon_round,\n id,\n info,\n name,\n type,\n version\n from public.app\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.currency (name)\n select name\n from public.currency\n on conflict (name) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.booking_channel (\n channel_ref,\n color,\n created_at,\n icon,\n icon_provider,\n id,\n last_generate_run,\n logo,\n logo_provider,\n selected_booking_channel_icon_candidate_id,\n selected_booking_channel_logo_candidate_id,\n unique_ref,\n updated_at\n )\n select\n channel_ref,\n color,\n created_at,\n icon,\n icon_provider,\n id,\n last_generate_run,\n logo,\n logo_provider,\n selected_booking_channel_icon_candidate_id,\n selected_booking_channel_logo_candidate_id,\n unique_ref,\n updated_at\n from public.booking_channel\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.booking_channel_icon_candidate (\n booking_channel_id,\n cloudflare_image_id,\n color,\n comment,\n created_at,\n external_icon,\n height,\n id,\n provider,\n source,\n updated_at,\n width\n )\n select\n booking_channel_id,\n cloudflare_image_id,\n color,\n comment,\n created_at,\n external_icon,\n height,\n id,\n provider,\n source,\n updated_at,\n width\n from public.booking_channel_icon_candidate\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.tenant (\n billing_partner_id,\n billing_plan,\n created_at,\n data_region,\n id,\n name,\n partner_id,\n slug,\n status,\n storage_realm,\n type,\n unique_ref,\n updated_at\n )\n select\n billing_partner_id,\n billing_plan,\n created_at,\n data_region,\n id,\n name,\n partner_id,\n slug,\n status,\n storage_realm,\n type,\n unique_ref,\n updated_at\n from public.tenant\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.token (\n created_at,\n expires_at,\n id,\n nano_id,\n payload,\n tenant_id,\n type,\n user_id\n )\n select\n created_at,\n expires_at,\n id,\n nano_id,\n payload,\n tenant_id,\n type,\n user_id\n from public.token\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n\n const controlPlaneKysely = withControlPlaneSchema(\n getKysely<ControlPlaneDB>(dialect, {\n repositoryName: `${args.repositoryName ?? 'localTesting'}/control-plane`,\n log: args.log,\n }),\n 'control_plane',\n 'control_plane'\n );\n controlPlaneKysely.destroy = async () => {};\n Object.defineProperty(kysely, 'controlPlaneKysely', {\n value: controlPlaneKysely,\n });\n\n const originalDestroy = kysely.destroy.bind(kysely);\n kysely.destroy = async () => {\n if (isDestroyed) return;\n isDestroyed = true;\n //const destroyTime = performance.now();\n await originalDestroy();\n //console.log(\n // `Database destroyed: ${Math.round(performance.now() - destroyTime)}ms`\n //);\n };\n\n // console.log(`Database initialized: ${Math.round(performance.now() - now)}ms`);\n\n return kysely as LocalKysely;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"src/","sources":["local/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport * as path from 'node:path';\nimport { PGlite } from '@electric-sql/pglite';\nimport { FileMigrationProvider, type LogConfig, Migrator, sql } from 'kysely';\nimport { PGliteDialect } from 'kysely-pglite-dialect';\nimport { type ControlPlaneDB, withControlPlaneSchema } from '../control-plane';\nimport type { ControlPlaneKysely } from '../index';\nimport { appMigrationEpoch } from '../migration';\nimport { getKysely } from '../plugins';\nimport type { DB } from '../v1.generated';\nimport { ensureDigestFunction, ensureGenRandomBytesFunction } from './digest';\n\nexport const root = path.join(__dirname, '../..');\nexport const dumpPath = path.join(root, '.data.tar');\n\nexport type UseLocalKyselyOptions = {\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\nexport type LocalKysely = import('kysely').Kysely<DB> & {\n controlPlaneKysely: ControlPlaneKysely;\n};\n\nasync function migrateToLatest<Database>(\n kysely: import('kysely').Kysely<Database>\n) {\n const migrator = new Migrator({\n allowUnorderedMigrations: true,\n db: kysely,\n migrationTableSchema: appMigrationEpoch.tableSchema,\n migrationTableName: appMigrationEpoch.tableName,\n migrationLockTableName: appMigrationEpoch.lockTableName,\n provider: new FileMigrationProvider({\n fs,\n path,\n migrationFolder: path.join(root, appMigrationEpoch.folder),\n }),\n });\n\n const { error } = await migrator.migrateToLatest();\n if (error) {\n throw error;\n }\n}\n\n// Every spec file used to replay this identical bootstrap - migrations, the\n// schema surgery, and the control-plane seed copies - against a freshly loaded\n// snapshot, which measured ~345ms per file against ~185ms for the snapshot load\n// alone. None of it depends on the caller, so it runs once and is cached as a\n// prepared snapshot keyed by everything that determines its content.\nconst preparedDumpPrefix = '.data.prepared.';\n\nlet preparedDumpPromise: Promise<Blob> | undefined;\n\nasync function preparedDumpKey(): Promise<string> {\n const [snapshot, appMigrations, controlPlaneMigrations] = await Promise.all([\n fs.stat(dumpPath),\n fs.readdir(path.join(root, appMigrationEpoch.folder)),\n fs.readdir(path.join(root, 'control-plane-migrations')),\n ]);\n\n const hasher = new Bun.CryptoHasher('sha256');\n hasher.update(`${snapshot.size}:${snapshot.mtimeMs}`);\n hasher.update(appMigrations.sort().join(','));\n hasher.update(controlPlaneMigrations.sort().join(','));\n // Source of the bootstrap itself, so editing the surgery rebuilds the\n // snapshot. Read through toString() rather than the file: this module is also\n // published as CommonJS, where import.meta is a compile error.\n for (const step of [\n buildPreparedDump,\n migrateToLatest,\n ensureDigestFunction,\n ensureGenRandomBytesFunction,\n ]) {\n hasher.update(step.toString());\n }\n return hasher.digest('hex').slice(0, 16);\n}\n\nasync function resolvePreparedDump(): Promise<Blob> {\n const key = await preparedDumpKey();\n const target = path.join(root, `${preparedDumpPrefix}${key}.tar`);\n const cached = Bun.file(target);\n if (await cached.exists()) {\n return cached;\n }\n\n const content = await buildPreparedDump();\n // Sibling workers build this concurrently on a cold cache; rename is atomic,\n // so a reader never observes a half-written snapshot.\n const staging = `${target}.${process.pid}.tmp`;\n await Bun.write(staging, content);\n await fs.rename(staging, target);\n\n // Only finished snapshots: a sibling worker's staging file also carries the\n // prefix, and removing it would break its rename.\n const current = path.basename(target);\n for (const entry of await fs.readdir(root)) {\n if (\n entry.startsWith(preparedDumpPrefix) &&\n entry.endsWith('.tar') &&\n entry !== current\n ) {\n await fs.rm(path.join(root, entry), { force: true });\n }\n }\n\n return content;\n}\n\nasync function buildPreparedDump(): Promise<Blob> {\n const pglite = new PGlite({\n loadDataDir: Bun.file(dumpPath),\n });\n const dialect = new PGliteDialect(pglite);\n const kysely = getKysely<DB>(dialect, {\n repositoryName: 'localTestingPrepare',\n });\n await ensureDigestFunction(kysely);\n await ensureGenRandomBytesFunction(kysely);\n await migrateToLatest(kysely);\n\n await sql`alter schema public rename to regional_public`.execute(kysely);\n await sql`alter schema core rename to regional_core`.execute(kysely);\n await sql`create schema public`.execute(kysely);\n await sql`create schema core`.execute(kysely);\n\n const controlPlaneBootstrapKysely = getKysely<ControlPlaneDB>(dialect, {\n repositoryName: 'localTestingPrepare/control-plane-bootstrap',\n });\n const controlPlaneMigrator = new Migrator({\n db: controlPlaneBootstrapKysely,\n migrationTableSchema: 'public',\n migrationTableName: 'control_plane_kysely_migration',\n migrationLockTableName: 'control_plane_kysely_migration_lock',\n provider: new FileMigrationProvider({\n fs,\n path,\n migrationFolder: path.join(root, 'control-plane-migrations'),\n }),\n });\n const { error: controlPlaneMigrationError } =\n await controlPlaneMigrator.migrateToLatest();\n if (controlPlaneMigrationError) {\n throw controlPlaneMigrationError;\n }\n\n await sql`alter table core.flow set schema public`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`alter table core.issue_message_overwrite set schema public`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`drop schema core`.execute(controlPlaneBootstrapKysely);\n await sql`alter schema public rename to control_plane`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`alter schema regional_public rename to public`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`alter schema regional_core rename to core`.execute(\n controlPlaneBootstrapKysely\n );\n await sql`\n do $$\n declare\n definition text;\n begin\n select pg_get_functiondef(\n 'control_plane.normalize_tenant_slug(text)'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n\n select pg_get_functiondef(\n 'control_plane.build_unique_tenant_slug(text,uuid)'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n\n select pg_get_functiondef(\n 'control_plane.refresh_operation_state(uuid)'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n\n select pg_get_functiondef(\n 'control_plane.refresh_destructive_job_operation()'::regprocedure\n ) into definition;\n execute replace(definition, 'public.', 'control_plane.');\n end;\n $$;\n `.execute(controlPlaneBootstrapKysely);\n // The canonical VRPlatform tenant. Production code falls back to this exact id\n // in getCalculatedBillingPartnerId, so specs need it to exist without each of\n // them creating - and mutating - their own copy of a shared singleton.\n await kysely\n .insertInto('public.tenant')\n .values({\n id: '7bfec41f-aa3f-4602-95d2-f7996e4f0e59',\n name: 'VRPlatform',\n type: 'partner',\n status: 'active',\n isActive: true,\n isGeneralLedger: false,\n isOnboarding: false,\n partnerId: null,\n billingPartnerId: null,\n defaultCurrency: 'usd',\n statementStartAt: new Date('2020-01-01T00:00:00Z'),\n })\n .onConflict((oc) => oc.column('id').doNothing())\n .execute();\n\n await sql`\n insert into control_plane.app (\n authentication,\n category,\n color,\n created_at,\n icon,\n icon_round,\n id,\n info,\n name,\n type,\n version\n )\n select\n authentication,\n category,\n color,\n created_at,\n icon,\n icon_round,\n id,\n info,\n name,\n type,\n version\n from public.app\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.currency (name)\n select name\n from public.currency\n on conflict (name) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.booking_channel (\n channel_ref,\n color,\n created_at,\n icon,\n icon_provider,\n id,\n last_generate_run,\n logo,\n logo_provider,\n selected_booking_channel_icon_candidate_id,\n selected_booking_channel_logo_candidate_id,\n unique_ref,\n updated_at\n )\n select\n channel_ref,\n color,\n created_at,\n icon,\n icon_provider,\n id,\n last_generate_run,\n logo,\n logo_provider,\n selected_booking_channel_icon_candidate_id,\n selected_booking_channel_logo_candidate_id,\n unique_ref,\n updated_at\n from public.booking_channel\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.booking_channel_icon_candidate (\n booking_channel_id,\n cloudflare_image_id,\n color,\n comment,\n created_at,\n external_icon,\n height,\n id,\n provider,\n source,\n updated_at,\n width\n )\n select\n booking_channel_id,\n cloudflare_image_id,\n color,\n comment,\n created_at,\n external_icon,\n height,\n id,\n provider,\n source,\n updated_at,\n width\n from public.booking_channel_icon_candidate\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.tenant (\n billing_partner_id,\n billing_plan,\n created_at,\n data_region,\n id,\n name,\n partner_id,\n slug,\n status,\n storage_realm,\n type,\n unique_ref,\n updated_at\n )\n select\n billing_partner_id,\n billing_plan,\n created_at,\n data_region,\n id,\n name,\n partner_id,\n slug,\n status,\n storage_realm,\n type,\n unique_ref,\n updated_at\n from public.tenant\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n await sql`\n insert into control_plane.token (\n created_at,\n expires_at,\n id,\n nano_id,\n payload,\n tenant_id,\n type,\n user_id\n )\n select\n created_at,\n expires_at,\n id,\n nano_id,\n payload,\n tenant_id,\n type,\n user_id\n from public.token\n on conflict (id) do nothing;\n `.execute(controlPlaneBootstrapKysely);\n\n const content = await pglite.dumpDataDir('none');\n await kysely.destroy();\n return content;\n}\n\nexport async function useLocalKysely(\n args: UseLocalKyselyOptions = {}\n): Promise<LocalKysely> {\n let isDestroyed = false;\n\n preparedDumpPromise ??= resolvePreparedDump();\n const pglite = new PGlite({\n loadDataDir: await preparedDumpPromise,\n });\n // The constructor is lazy. The bootstrap this replaced forced the snapshot to\n // load before returning, so keep that contract: a returned handle is usable,\n // and a bad snapshot fails here instead of inside an unrelated test.\n await pglite.waitReady;\n const dialect = new PGliteDialect(pglite);\n const kysely = getKysely<DB>(dialect, {\n repositoryName: args?.repositoryName ?? 'localTesting',\n log: args?.log,\n });\n\n const controlPlaneKysely = withControlPlaneSchema(\n getKysely<ControlPlaneDB>(dialect, {\n repositoryName: `${args.repositoryName ?? 'localTesting'}/control-plane`,\n log: args.log,\n }),\n 'control_plane',\n 'control_plane'\n );\n controlPlaneKysely.destroy = async () => {};\n Object.defineProperty(kysely, 'controlPlaneKysely', {\n value: controlPlaneKysely,\n });\n\n const originalDestroy = kysely.destroy.bind(kysely);\n kysely.destroy = async () => {\n if (isDestroyed) return;\n isDestroyed = true;\n //const destroyTime = performance.now();\n await originalDestroy();\n //console.log(\n // `Database destroyed: ${Math.round(performance.now() - destroyTime)}ms`\n //);\n };\n\n // console.log(`Database initialized: ${Math.round(performance.now() - now)}ms`);\n\n return kysely as LocalKysely;\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Matches PostgreSQL errors from both production's postgres.js driver and
3
- * PGlite, which expose constraint names under different property names.
2
+ * Matches PostgreSQL errors by code and, when requested, constraint. Production
3
+ * postgres.js and PGlite expose constraint names under different properties.
4
4
  */
5
5
  export declare function isPostgresError(error: unknown, expected: {
6
6
  code: string;
7
- constraint: string;
7
+ constraint?: string;
8
8
  }): boolean;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Matches PostgreSQL errors from both production's postgres.js driver and
3
- * PGlite, which expose constraint names under different property names.
2
+ * Matches PostgreSQL errors by code and, when requested, constraint. Production
3
+ * postgres.js and PGlite expose constraint names under different properties.
4
4
  */
5
5
  export function isPostgresError(error, expected) {
6
6
  if (!(error instanceof Error) ||
@@ -13,6 +13,7 @@ export function isPostgresError(error, expected) {
13
13
  : 'constraint_name' in error && typeof error.constraint_name === 'string'
14
14
  ? error.constraint_name
15
15
  : undefined;
16
- return error.code === expected.code && constraint === expected.constraint;
16
+ return (error.code === expected.code &&
17
+ (expected.constraint === undefined || constraint === expected.constraint));
17
18
  }
18
19
  //# sourceMappingURL=postgres-error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-error.js","sourceRoot":"src/","sources":["postgres-error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAc,EACd,QAA8C;IAE9C,IACE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QACzB,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;QAClB,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GACd,YAAY,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QAC3D,CAAC,CAAC,KAAK,CAAC,UAAU;QAClB,CAAC,CAAC,iBAAiB,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,eAAe,KAAK,QAAQ;YACvE,CAAC,CAAC,KAAK,CAAC,eAAe;YACvB,CAAC,CAAC,SAAS,CAAC;IAElB,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,IAAI,UAAU,KAAK,QAAQ,CAAC,UAAU,CAAC;AAC5E,CAAC","sourcesContent":["/**\n * Matches PostgreSQL errors from both production's postgres.js driver and\n * PGlite, which expose constraint names under different property names.\n */\nexport function isPostgresError(\n error: unknown,\n expected: { code: string; constraint: string }\n): boolean {\n if (\n !(error instanceof Error) ||\n !('code' in error) ||\n typeof error.code !== 'string'\n ) {\n return false;\n }\n\n const constraint =\n 'constraint' in error && typeof error.constraint === 'string'\n ? error.constraint\n : 'constraint_name' in error && typeof error.constraint_name === 'string'\n ? error.constraint_name\n : undefined;\n\n return error.code === expected.code && constraint === expected.constraint;\n}\n"]}
1
+ {"version":3,"file":"postgres-error.js","sourceRoot":"src/","sources":["postgres-error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAc,EACd,QAA+C;IAE/C,IACE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QACzB,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;QAClB,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GACd,YAAY,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QAC3D,CAAC,CAAC,KAAK,CAAC,UAAU;QAClB,CAAC,CAAC,iBAAiB,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,eAAe,KAAK,QAAQ;YACvE,CAAC,CAAC,KAAK,CAAC,eAAe;YACvB,CAAC,CAAC,SAAS,CAAC;IAElB,OAAO,CACL,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI;QAC5B,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,QAAQ,CAAC,UAAU,CAAC,CAC1E,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Matches PostgreSQL errors by code and, when requested, constraint. Production\n * postgres.js and PGlite expose constraint names under different properties.\n */\nexport function isPostgresError(\n error: unknown,\n expected: { code: string; constraint?: string }\n): boolean {\n if (\n !(error instanceof Error) ||\n !('code' in error) ||\n typeof error.code !== 'string'\n ) {\n return false;\n }\n\n const constraint =\n 'constraint' in error && typeof error.constraint === 'string'\n ? error.constraint\n : 'constraint_name' in error && typeof error.constraint_name === 'string'\n ? error.constraint_name\n : undefined;\n\n return (\n error.code === expected.code &&\n (expected.constraint === undefined || constraint === expected.constraint)\n );\n}\n"]}
@@ -1,7 +1,30 @@
1
1
  import { type LocalKysely, type UseLocalKyselyOptions } from '../local';
2
- export declare function useTestAutoCleanupKysely(args?: UseLocalKyselyOptions): Promise<LocalKysely>;
2
+ type UseTestKyselyOptions = UseLocalKyselyOptions & {
3
+ /**
4
+ * Force a private database even when the worker shares one. Required by specs
5
+ * that model several regions at once, where two handles must be two distinct
6
+ * physical databases.
7
+ */
8
+ isolated?: boolean;
9
+ };
10
+ declare global {
11
+ var __vrplatformSharedKysely: Promise<LocalKysely> | undefined;
12
+ }
13
+ /**
14
+ * Locally each worker process shares one database, because specs isolate by
15
+ * tenant and the faster suite is what makes running it before a push realistic.
16
+ *
17
+ * CI keeps a database per spec file. It retries nothing, so a badly scoped spec
18
+ * would surface there as a red build in an unrelated file rather than as a
19
+ * local failure the author can reproduce.
20
+ *
21
+ * VR_TEST_SHARED_KYSELY overrides either way; `isolated: true` opts a single
22
+ * call out when a spec genuinely needs two physical databases at once.
23
+ */
24
+ export declare function resolveSharedKysely(env: Record<string, string | undefined>): boolean;
25
+ export declare function useTestAutoCleanupKysely(args?: UseTestKyselyOptions): Promise<LocalKysely>;
3
26
  type ReturnType = LocalKysely & {
4
27
  [Symbol.dispose]: () => Promise<void>;
5
28
  };
6
- export declare function useLocalKyselyResource(args?: UseLocalKyselyOptions): Promise<ReturnType>;
29
+ export declare function useLocalKyselyResource(args?: UseTestKyselyOptions): Promise<ReturnType>;
7
30
  export {};
@@ -1,19 +1,49 @@
1
1
  import { afterAll } from 'bun:test';
2
2
  import { useLocalKysely, } from '../local';
3
+ /**
4
+ * Locally each worker process shares one database, because specs isolate by
5
+ * tenant and the faster suite is what makes running it before a push realistic.
6
+ *
7
+ * CI keeps a database per spec file. It retries nothing, so a badly scoped spec
8
+ * would surface there as a red build in an unrelated file rather than as a
9
+ * local failure the author can reproduce.
10
+ *
11
+ * VR_TEST_SHARED_KYSELY overrides either way; `isolated: true` opts a single
12
+ * call out when a spec genuinely needs two physical databases at once.
13
+ */
14
+ export function resolveSharedKysely(env) {
15
+ if (env.VR_TEST_SHARED_KYSELY)
16
+ return env.VR_TEST_SHARED_KYSELY !== '0';
17
+ return !(env.CI || env.GITHUB_ACTIONS);
18
+ }
19
+ const sharedKysely = resolveSharedKysely(process.env);
20
+ function acquireKysely(args) {
21
+ if (!sharedKysely || args?.isolated)
22
+ return useLocalKysely(args);
23
+ globalThis.__vrplatformSharedKysely ??= useLocalKysely(args);
24
+ return globalThis.__vrplatformSharedKysely;
25
+ }
26
+ function ownsKysely(args) {
27
+ return !sharedKysely || Boolean(args?.isolated);
28
+ }
3
29
  export async function useTestAutoCleanupKysely(args) {
4
- const kysely = await useLocalKysely(args);
5
- afterAll(async () => {
6
- await kysely.destroy();
7
- });
30
+ const kysely = await acquireKysely(args);
31
+ if (ownsKysely(args)) {
32
+ afterAll(async () => {
33
+ await kysely.destroy();
34
+ });
35
+ }
8
36
  return kysely;
9
37
  }
10
38
  export async function useLocalKyselyResource(args) {
11
- const kysely = await useLocalKysely(args);
39
+ const kysely = await acquireKysely(args);
12
40
  return new Proxy({}, {
13
41
  get(_target, prop) {
14
42
  // somehow not working if using Symbol.dispose
15
43
  if (prop === Symbol.asyncDispose) {
16
44
  return async () => {
45
+ if (!ownsKysely(args))
46
+ return;
17
47
  await kysely.destroy();
18
48
  };
19
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"src/","sources":["test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAGL,cAAc,GACf,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,IAA4B;IACzE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAE1C,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAA4B;IAE5B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAE1C,OAAO,IAAI,KAAK,CACd,EAAE,EACF;QACE,GAAG,CAAC,OAAO,EAAE,IAAI;YACf,8CAA8C;YAC9C,IAAI,IAAI,KAAK,MAAM,CAAC,YAAY,EAAE,CAAC;gBACjC,OAAO,KAAK,IAAI,EAAE;oBAChB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;gBACzB,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;gBACvC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;KACF,CACY,CAAC;AAClB,CAAC","sourcesContent":["import { afterAll } from 'bun:test';\nimport {\n type LocalKysely,\n type UseLocalKyselyOptions,\n useLocalKysely,\n} from '../local';\n\nexport async function useTestAutoCleanupKysely(args?: UseLocalKyselyOptions) {\n const kysely = await useLocalKysely(args);\n\n afterAll(async () => {\n await kysely.destroy();\n });\n\n return kysely;\n}\n\ntype ReturnType = LocalKysely & {\n [Symbol.dispose]: () => Promise<void>;\n};\n\nexport async function useLocalKyselyResource(\n args?: UseLocalKyselyOptions\n): Promise<ReturnType> {\n const kysely = await useLocalKysely(args);\n\n return new Proxy(\n {},\n {\n get(_target, prop) {\n // somehow not working if using Symbol.dispose\n if (prop === Symbol.asyncDispose) {\n return async () => {\n await kysely.destroy();\n };\n }\n if (prop === 'kysely') {\n return kysely;\n }\n if (typeof kysely[prop] === 'function') {\n return kysely[prop].bind(kysely);\n }\n return kysely[prop];\n },\n }\n ) as ReturnType;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"src/","sources":["test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAGL,cAAc,GACf,MAAM,UAAU,CAAC;AAelB;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAuC;IAEvC,IAAI,GAAG,CAAC,qBAAqB;QAAE,OAAO,GAAG,CAAC,qBAAqB,KAAK,GAAG,CAAC;IACxE,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,YAAY,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAEtD,SAAS,aAAa,CAAC,IAA2B;IAChD,IAAI,CAAC,YAAY,IAAI,IAAI,EAAE,QAAQ;QAAE,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;IACjE,UAAU,CAAC,wBAAwB,KAAK,cAAc,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO,UAAU,CAAC,wBAAwB,CAAC;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,IAA2B;IAC7C,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,IAA2B;IACxE,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,QAAQ,CAAC,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAA2B;IAE3B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAEzC,OAAO,IAAI,KAAK,CACd,EAAE,EACF;QACE,GAAG,CAAC,OAAO,EAAE,IAAI;YACf,8CAA8C;YAC9C,IAAI,IAAI,KAAK,MAAM,CAAC,YAAY,EAAE,CAAC;gBACjC,OAAO,KAAK,IAAI,EAAE;oBAChB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;wBAAE,OAAO;oBAC9B,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;gBACzB,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;gBACvC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;KACF,CACY,CAAC;AAClB,CAAC","sourcesContent":["import { afterAll } from 'bun:test';\nimport {\n type LocalKysely,\n type UseLocalKyselyOptions,\n useLocalKysely,\n} from '../local';\n\ntype UseTestKyselyOptions = UseLocalKyselyOptions & {\n /**\n * Force a private database even when the worker shares one. Required by specs\n * that model several regions at once, where two handles must be two distinct\n * physical databases.\n */\n isolated?: boolean;\n};\n\ndeclare global {\n var __vrplatformSharedKysely: Promise<LocalKysely> | undefined;\n}\n\n/**\n * Locally each worker process shares one database, because specs isolate by\n * tenant and the faster suite is what makes running it before a push realistic.\n *\n * CI keeps a database per spec file. It retries nothing, so a badly scoped spec\n * would surface there as a red build in an unrelated file rather than as a\n * local failure the author can reproduce.\n *\n * VR_TEST_SHARED_KYSELY overrides either way; `isolated: true` opts a single\n * call out when a spec genuinely needs two physical databases at once.\n */\nexport function resolveSharedKysely(\n env: Record<string, string | undefined>\n): boolean {\n if (env.VR_TEST_SHARED_KYSELY) return env.VR_TEST_SHARED_KYSELY !== '0';\n return !(env.CI || env.GITHUB_ACTIONS);\n}\n\nconst sharedKysely = resolveSharedKysely(process.env);\n\nfunction acquireKysely(args?: UseTestKyselyOptions): Promise<LocalKysely> {\n if (!sharedKysely || args?.isolated) return useLocalKysely(args);\n globalThis.__vrplatformSharedKysely ??= useLocalKysely(args);\n return globalThis.__vrplatformSharedKysely;\n}\n\nfunction ownsKysely(args?: UseTestKyselyOptions): boolean {\n return !sharedKysely || Boolean(args?.isolated);\n}\n\nexport async function useTestAutoCleanupKysely(args?: UseTestKyselyOptions) {\n const kysely = await acquireKysely(args);\n\n if (ownsKysely(args)) {\n afterAll(async () => {\n await kysely.destroy();\n });\n }\n\n return kysely;\n}\n\ntype ReturnType = LocalKysely & {\n [Symbol.dispose]: () => Promise<void>;\n};\n\nexport async function useLocalKyselyResource(\n args?: UseTestKyselyOptions\n): Promise<ReturnType> {\n const kysely = await acquireKysely(args);\n\n return new Proxy(\n {},\n {\n get(_target, prop) {\n // somehow not working if using Symbol.dispose\n if (prop === Symbol.asyncDispose) {\n return async () => {\n if (!ownsKysely(args)) return;\n await kysely.destroy();\n };\n }\n if (prop === 'kysely') {\n return kysely;\n }\n if (typeof kysely[prop] === 'function') {\n return kysely[prop].bind(kysely);\n }\n return kysely[prop];\n },\n }\n ) as ReturnType;\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  * Please do not edit it manually.
4
4
  */
5
5
  import type { ColumnType } from "kysely";
6
- export type AccountingJournalEntryInactiveReason = "cancelledReservationLine" | "currencyMismatch" | "generalLedgerStartAt" | "inactiveAccount" | "listingInactive" | "nonPostingAccount" | "reservationGeneralLedgerStatusInactive" | "transactionInactive" | "unknownInactiveReason";
6
+ export type AccountingJournalEntryInactiveReason = "cancelledReservationLine" | "currencyMismatch" | "generalLedgerStartAt" | "historicalLedger" | "inactiveAccount" | "listingInactive" | "listingOwnershipPeriodNotFound" | "nonPostingAccount" | "reservationGeneralLedgerStatusInactive" | "transactionInactive" | "unbalancedGroupInactiveLeg" | "unknownInactiveReason";
7
7
  export type AccountingJournalEntryLedger = "historical" | "operating" | "trust";
8
8
  export type AccountingTransactionAttachmentStatus = "attached" | "deleting" | "ready" | "uploading";
9
9
  export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>;