@vrplatform/kysely 1.3.45-stage.7 → 1.3.45-stage.710

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 (72) hide show
  1. package/build/.data.tar +2 -2
  2. package/build/main/control-plane/index.d.ts +28 -6
  3. package/build/main/control-plane/index.js.map +1 -1
  4. package/build/main/index.d.ts +11 -0
  5. package/build/main/index.js +131 -26
  6. package/build/main/index.js.map +1 -1
  7. package/build/main/local/index.js +98 -8
  8. package/build/main/local/index.js.map +1 -1
  9. package/build/main/postgres-error.d.ts +3 -3
  10. package/build/main/postgres-error.js +4 -3
  11. package/build/main/postgres-error.js.map +1 -1
  12. package/build/main/query/tenant/status.d.ts +1 -1
  13. package/build/main/query/tenant/status.js +4 -2
  14. package/build/main/query/tenant/status.js.map +1 -1
  15. package/build/main/regional.d.ts +1 -0
  16. package/build/main/regional.js +1 -0
  17. package/build/main/regional.js.map +1 -1
  18. package/build/main/test/index.d.ts +25 -2
  19. package/build/main/test/index.js +36 -5
  20. package/build/main/test/index.js.map +1 -1
  21. package/build/main/v1.generated.d.ts +151 -19
  22. package/build/main/v1.generated.js.map +1 -1
  23. package/build/migrations-v2/0000000000031-ui-permission-role-simplification.ts +70 -0
  24. package/build/migrations-v2/0000000000032-tenant-delete-ownership-cascades.ts +44 -0
  25. package/build/migrations-v2/0000000000033-plaid-connect-session-telemetry.ts +31 -0
  26. package/build/migrations-v2/0000000000033-reservation-issue-seed-bucket-index.ts +19 -0
  27. package/build/migrations-v2/0000000000034-retire-recent-classification-indexes.ts +29 -0
  28. package/build/migrations-v2/0000000000035-core-change-autovacuum.ts +24 -0
  29. package/build/migrations-v2/0000000000036-journal-entry-inactive-reason-constraint.ts +33 -0
  30. package/build/migrations-v2/0000000000037-journal-entry-inactive-reasons.ts +19 -0
  31. package/build/migrations-v2/0000000000038-journal-entry-group-inactive-reason.ts +14 -0
  32. package/build/migrations-v2/0000000000039-reservation-guest-breakdown.ts +19 -0
  33. package/build/migrations-v2/0000000000040-csv-import-source-identity-index.ts +23 -0
  34. package/build/migrations-v2/0000000000041-payment-returns.ts +38 -0
  35. package/build/migrations-v2/0000000000042-operation-resource-types.ts +609 -0
  36. package/build/migrations-v2/0000000000043-reservation-journal-freshness.ts +149 -0
  37. package/build/migrations-v2/0000000000044-reservation-journal-freshness-backfill.ts +254 -0
  38. package/build/migrations-v2/0000000000045-reservation-journal-freshness-revision-repair.ts +83 -0
  39. package/build/migrations-v2/0000000000046-materialized-reservation-journal-operations.ts +709 -0
  40. package/build/migrations-v2/0000000000047-public-audit-completion.ts +77 -0
  41. package/build/migrations-v2/0000000000048-reservation-journal-full-refresh-repair.ts +136 -0
  42. package/build/migrations-v2/0000000000049-queued-journal-operation-failures.ts +60 -0
  43. package/build/migrations-v2/0000000000050-connection-oauth-state.ts +43 -0
  44. package/build/migrations-v2/0000000000051-owner-statement-email-delivery.ts +134 -0
  45. package/build/migrations-v2/0000000000052-fee-journal-lock-skip-operations.ts +59 -0
  46. package/build/migrations-v2/0000000000053-fee-journal-lock-skip-null-attempt.ts +44 -0
  47. package/build/migrations-v2/0000000000054-journal-refresh-issue-codes.ts +16 -0
  48. package/build/migrations-v2/0000000000055-tenant-billing-subscription.ts +8 -0
  49. package/build/migrations-v2/0000000000056-journal-operation-failure-precedence.ts +306 -0
  50. package/build/migrations-v2/0000000000057-journal-invalidation-failure-code.ts +28 -0
  51. package/build/module/control-plane/index.d.ts +28 -6
  52. package/build/module/control-plane/index.js.map +1 -1
  53. package/build/module/index.d.ts +11 -0
  54. package/build/module/index.js +131 -26
  55. package/build/module/index.js.map +1 -1
  56. package/build/module/local/index.js +98 -8
  57. package/build/module/local/index.js.map +1 -1
  58. package/build/module/postgres-error.d.ts +3 -3
  59. package/build/module/postgres-error.js +4 -3
  60. package/build/module/postgres-error.js.map +1 -1
  61. package/build/module/query/tenant/status.d.ts +1 -1
  62. package/build/module/query/tenant/status.js +4 -2
  63. package/build/module/query/tenant/status.js.map +1 -1
  64. package/build/module/regional.d.ts +1 -0
  65. package/build/module/regional.js +1 -0
  66. package/build/module/regional.js.map +1 -1
  67. package/build/module/test/index.d.ts +25 -2
  68. package/build/module/test/index.js +35 -5
  69. package/build/module/test/index.js.map +1 -1
  70. package/build/module/v1.generated.d.ts +151 -19
  71. package/build/module/v1.generated.js.map +1 -1
  72. package/package.json +4 -2
@@ -7,6 +7,7 @@ export declare function resolveTenantDatabaseUrl(dataRegion: TenantDataRegion, e
7
7
  export declare function resolveTenantApiBaseUrl(dataRegion: TenantDataRegion, env: RegionEnvironment): string;
8
8
  export declare function resolveConfiguredTenantDataRegions(env: RegionEnvironment): ("ap" | "crunchy" | "eu" | "hostaway" | "us")[];
9
9
  type UseAsyncRegionalKysely = (connectionString: string, options?: {
10
+ dataRegion?: TenantDataRegion;
10
11
  repositoryName?: string;
11
12
  probe?: true;
12
13
  }) => Promise<Kysely>;
@@ -81,6 +81,7 @@ async function defaultUseAsyncControlPlaneKysely(connectionString, options) {
81
81
  export async function useTenantDatabaseKysely(dataRegion, repositoryName, env, options = {}) {
82
82
  const open = options.useAsyncKysely ?? defaultUseAsyncKysely;
83
83
  return await open(resolveTenantDatabaseUrl(dataRegion, env), {
84
+ dataRegion,
84
85
  repositoryName,
85
86
  probe: options.probe,
86
87
  });
@@ -1 +1 @@
1
- {"version":3,"file":"regional.js","sourceRoot":"src/","sources":["regional.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ControlPlaneKysely, Kysely } from './index';\nimport { KyselyError } from './error';\n\n// The tenant-data-region contract lives here — the region set plus how a\n// region resolves to its database url, API base url, and how to fan a job out\n// across regions. Every runtime resolves regions through these functions;\n// @vrplatform/common re-exports them for app-facing imports, and the trigger\n// runtime wraps them only to default `env` to process.env.\n//\n// Region → resource keys are derived from the region name\n// (`DATABASE_URL_VRTRUST_<REGION>`, `API_BASE_URL_<REGION>`), so adding a\n// region means extending this array plus its env values and migrations — not\n// editing per-region branches.\nexport const tenantDataRegions = [\n 'ap',\n 'crunchy',\n 'eu',\n 'hostaway',\n 'us',\n] as const;\nexport type TenantDataRegion = (typeof tenantDataRegions)[number];\n\nexport type RegionEnvironment = Record<string, string | undefined>;\n\nexport function assertTenantDataRegion(\n value: string | undefined\n): asserts value is TenantDataRegion {\n if (!tenantDataRegions.includes(value as TenantDataRegion)) {\n throw new KyselyError('Missing or invalid tenant data region', { value });\n }\n}\n\nfunction databaseUrlEnvKey(dataRegion: TenantDataRegion) {\n return `DATABASE_URL_VRTRUST_${dataRegion.toUpperCase()}`;\n}\n\nfunction apiBaseUrlEnvKey(dataRegion: TenantDataRegion) {\n return `API_BASE_URL_${dataRegion.toUpperCase()}`;\n}\n\nexport function resolveTenantDatabaseUrl(\n dataRegion: TenantDataRegion,\n env: RegionEnvironment\n) {\n const databaseUrl = env[databaseUrlEnvKey(dataRegion)];\n if (!databaseUrl) {\n throw new KyselyError('Tenant database URL is missing', {\n dataRegion,\n key: databaseUrlEnvKey(dataRegion),\n });\n }\n return databaseUrl;\n}\n\nexport function resolveTenantApiBaseUrl(\n dataRegion: TenantDataRegion,\n env: RegionEnvironment\n) {\n const key = apiBaseUrlEnvKey(dataRegion);\n const baseUrl = env[key];\n if (!baseUrl) {\n throw new KyselyError('Tenant API base URL is missing', {\n dataRegion,\n key,\n });\n }\n return baseUrl;\n}\n\nexport function resolveConfiguredTenantDataRegions(env: RegionEnvironment) {\n const configured = tenantDataRegions.filter((region) =>\n Boolean(env[databaseUrlEnvKey(region)])\n );\n\n if (!configured.length) {\n throw new Error('No tenant data region database urls configured');\n }\n\n // Two regions sharing one URL means every region-fan-out job scans the\n // same physical DB twice (e.g. a stale dashboard env var re-merged into a\n // deploy). Regions must stay unset until they point at distinct databases.\n const regionsByUrl = new Map<string, TenantDataRegion[]>();\n for (const region of configured) {\n const url = env[databaseUrlEnvKey(region)]!;\n regionsByUrl.set(url, [...(regionsByUrl.get(url) ?? []), region]);\n }\n for (const aliased of regionsByUrl.values()) {\n if (aliased.length > 1) {\n throw new KyselyError('Tenant data regions share the same database URL', {\n dataRegions: aliased,\n });\n }\n }\n\n return configured;\n}\n\ntype UseAsyncRegionalKysely = (\n connectionString: string,\n options?: {\n repositoryName?: string;\n probe?: true;\n }\n) => Promise<Kysely>;\n\ntype UseAsyncControlPlaneKysely = (\n connectionString: string,\n options?: {\n repositoryName?: string;\n probe?: true;\n }\n) => Promise<ControlPlaneKysely>;\n\nasync function defaultUseAsyncKysely(\n connectionString: string,\n options?: Parameters<UseAsyncRegionalKysely>[1]\n) {\n const { useAsyncKysely } = await import('./index');\n return await useAsyncKysely(connectionString, options);\n}\n\nasync function defaultUseAsyncControlPlaneKysely(\n connectionString: string,\n options?: Parameters<UseAsyncControlPlaneKysely>[1]\n) {\n const { useAsyncControlPlaneKysely } = await import('./index');\n return await useAsyncControlPlaneKysely(connectionString, options);\n}\n\nexport async function useTenantDatabaseKysely(\n dataRegion: TenantDataRegion,\n repositoryName: string,\n env: RegionEnvironment,\n options: { useAsyncKysely?: UseAsyncRegionalKysely; probe?: true } = {}\n) {\n const open = options.useAsyncKysely ?? defaultUseAsyncKysely;\n return await open(resolveTenantDatabaseUrl(dataRegion, env), {\n repositoryName,\n probe: options.probe,\n });\n}\n\nexport type TenantKysely = {\n id: string;\n slug: string;\n dataRegion: TenantDataRegion;\n kysely: Kysely;\n};\n\n/**\n * Resolve a tenant's regional Kysely connection from a connection id, slug,\n * or tenant id. The control-plane connection is opened and destroyed\n * internally; the returned regional connection must be destroyed by the\n * caller.\n */\nexport async function resolveTenantKysely({\n connectionId,\n slug,\n tenantId,\n repositoryName,\n env,\n ...options\n}: {\n connectionId?: string;\n slug?: string;\n tenantId?: string;\n repositoryName: string;\n env: RegionEnvironment;\n useAsyncControlPlaneKysely?: UseAsyncControlPlaneKysely;\n useAsyncKysely?: UseAsyncRegionalKysely;\n probe?: true;\n}): Promise<TenantKysely> {\n if (!connectionId && !slug && !tenantId) {\n throw new Error('connectionId, slug, or tenantId is required');\n }\n\n const controlPlaneDatabaseUrl = env.CONTROL_PLANE_DATABASE_URL;\n if (!controlPlaneDatabaseUrl)\n throw new Error('CONTROL_PLANE_DATABASE_URL is required');\n\n const controlPlane = await (\n options.useAsyncControlPlaneKysely ?? defaultUseAsyncControlPlaneKysely\n )(controlPlaneDatabaseUrl, {\n repositoryName: `${repositoryName}/control-plane`,\n probe: options.probe,\n });\n let tenant: { id: string; slug: string; dataRegion: string } | undefined;\n try {\n const query = controlPlane\n .selectFrom('controlPlane.tenant as tenant')\n .select([\n 'tenant.id as id',\n 'tenant.slug as slug',\n 'tenant.dataRegion as dataRegion',\n ]);\n tenant = await (\n slug\n ? query.where('tenant.slug', '=', slug)\n : connectionId\n ? query\n .innerJoin(\n 'controlPlane.connectionRoute as connectionRoute',\n 'connectionRoute.tenantId',\n 'tenant.id'\n )\n .where('connectionRoute.connectionId', '=', connectionId)\n : query.where('tenant.id', '=', tenantId!)\n ).executeTakeFirst();\n } finally {\n await controlPlane.destroy();\n }\n if (!tenant) throw new Error('Tenant not found in control plane');\n\n assertTenantDataRegion(tenant.dataRegion);\n return {\n id: tenant.id,\n slug: tenant.slug,\n dataRegion: tenant.dataRegion,\n kysely: await useTenantDatabaseKysely(\n tenant.dataRegion,\n repositoryName,\n env,\n options\n ),\n };\n}\n\nexport type RegionRunError = {\n dataRegion: TenantDataRegion;\n error: string;\n};\n\n/**\n * Run a job once per configured tenant data region with per-region error\n * isolation: one region's outage must not stall the others (regions iterate\n * in a fixed order, so a failing first region would otherwise starve the\n * rest on every attempt). Throws only when every configured region failed.\n */\nexport async function forEachConfiguredRegion<T>(\n run: (dataRegion: TenantDataRegion) => Promise<T>,\n env: RegionEnvironment\n): Promise<{\n results: { dataRegion: TenantDataRegion; result: T }[];\n errors: RegionRunError[];\n}> {\n const results: { dataRegion: TenantDataRegion; result: T }[] = [];\n const errors: RegionRunError[] = [];\n\n for (const dataRegion of resolveConfiguredTenantDataRegions(env)) {\n try {\n results.push({ dataRegion, result: await run(dataRegion) });\n } catch (error) {\n errors.push({\n dataRegion,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (!results.length && errors.length) {\n throw new KyselyError('All configured tenant data regions failed', {\n errors,\n });\n }\n\n return { results, errors };\n}\n"]}
1
+ {"version":3,"file":"regional.js","sourceRoot":"src/","sources":["regional.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ControlPlaneKysely, Kysely } from './index';\nimport { KyselyError } from './error';\n\n// The tenant-data-region contract lives here — the region set plus how a\n// region resolves to its database url, API base url, and how to fan a job out\n// across regions. Every runtime resolves regions through these functions;\n// @vrplatform/common re-exports them for app-facing imports, and the trigger\n// runtime wraps them only to default `env` to process.env.\n//\n// Region → resource keys are derived from the region name\n// (`DATABASE_URL_VRTRUST_<REGION>`, `API_BASE_URL_<REGION>`), so adding a\n// region means extending this array plus its env values and migrations — not\n// editing per-region branches.\nexport const tenantDataRegions = [\n 'ap',\n 'crunchy',\n 'eu',\n 'hostaway',\n 'us',\n] as const;\nexport type TenantDataRegion = (typeof tenantDataRegions)[number];\n\nexport type RegionEnvironment = Record<string, string | undefined>;\n\nexport function assertTenantDataRegion(\n value: string | undefined\n): asserts value is TenantDataRegion {\n if (!tenantDataRegions.includes(value as TenantDataRegion)) {\n throw new KyselyError('Missing or invalid tenant data region', { value });\n }\n}\n\nfunction databaseUrlEnvKey(dataRegion: TenantDataRegion) {\n return `DATABASE_URL_VRTRUST_${dataRegion.toUpperCase()}`;\n}\n\nfunction apiBaseUrlEnvKey(dataRegion: TenantDataRegion) {\n return `API_BASE_URL_${dataRegion.toUpperCase()}`;\n}\n\nexport function resolveTenantDatabaseUrl(\n dataRegion: TenantDataRegion,\n env: RegionEnvironment\n) {\n const databaseUrl = env[databaseUrlEnvKey(dataRegion)];\n if (!databaseUrl) {\n throw new KyselyError('Tenant database URL is missing', {\n dataRegion,\n key: databaseUrlEnvKey(dataRegion),\n });\n }\n return databaseUrl;\n}\n\nexport function resolveTenantApiBaseUrl(\n dataRegion: TenantDataRegion,\n env: RegionEnvironment\n) {\n const key = apiBaseUrlEnvKey(dataRegion);\n const baseUrl = env[key];\n if (!baseUrl) {\n throw new KyselyError('Tenant API base URL is missing', {\n dataRegion,\n key,\n });\n }\n return baseUrl;\n}\n\nexport function resolveConfiguredTenantDataRegions(env: RegionEnvironment) {\n const configured = tenantDataRegions.filter((region) =>\n Boolean(env[databaseUrlEnvKey(region)])\n );\n\n if (!configured.length) {\n throw new Error('No tenant data region database urls configured');\n }\n\n // Two regions sharing one URL means every region-fan-out job scans the\n // same physical DB twice (e.g. a stale dashboard env var re-merged into a\n // deploy). Regions must stay unset until they point at distinct databases.\n const regionsByUrl = new Map<string, TenantDataRegion[]>();\n for (const region of configured) {\n const url = env[databaseUrlEnvKey(region)]!;\n regionsByUrl.set(url, [...(regionsByUrl.get(url) ?? []), region]);\n }\n for (const aliased of regionsByUrl.values()) {\n if (aliased.length > 1) {\n throw new KyselyError('Tenant data regions share the same database URL', {\n dataRegions: aliased,\n });\n }\n }\n\n return configured;\n}\n\ntype UseAsyncRegionalKysely = (\n connectionString: string,\n options?: {\n dataRegion?: TenantDataRegion;\n repositoryName?: string;\n probe?: true;\n }\n) => Promise<Kysely>;\n\ntype UseAsyncControlPlaneKysely = (\n connectionString: string,\n options?: {\n repositoryName?: string;\n probe?: true;\n }\n) => Promise<ControlPlaneKysely>;\n\nasync function defaultUseAsyncKysely(\n connectionString: string,\n options?: Parameters<UseAsyncRegionalKysely>[1]\n) {\n const { useAsyncKysely } = await import('./index');\n return await useAsyncKysely(connectionString, options);\n}\n\nasync function defaultUseAsyncControlPlaneKysely(\n connectionString: string,\n options?: Parameters<UseAsyncControlPlaneKysely>[1]\n) {\n const { useAsyncControlPlaneKysely } = await import('./index');\n return await useAsyncControlPlaneKysely(connectionString, options);\n}\n\nexport async function useTenantDatabaseKysely(\n dataRegion: TenantDataRegion,\n repositoryName: string,\n env: RegionEnvironment,\n options: { useAsyncKysely?: UseAsyncRegionalKysely; probe?: true } = {}\n) {\n const open = options.useAsyncKysely ?? defaultUseAsyncKysely;\n return await open(resolveTenantDatabaseUrl(dataRegion, env), {\n dataRegion,\n repositoryName,\n probe: options.probe,\n });\n}\n\nexport type TenantKysely = {\n id: string;\n slug: string;\n dataRegion: TenantDataRegion;\n kysely: Kysely;\n};\n\n/**\n * Resolve a tenant's regional Kysely connection from a connection id, slug,\n * or tenant id. The control-plane connection is opened and destroyed\n * internally; the returned regional connection must be destroyed by the\n * caller.\n */\nexport async function resolveTenantKysely({\n connectionId,\n slug,\n tenantId,\n repositoryName,\n env,\n ...options\n}: {\n connectionId?: string;\n slug?: string;\n tenantId?: string;\n repositoryName: string;\n env: RegionEnvironment;\n useAsyncControlPlaneKysely?: UseAsyncControlPlaneKysely;\n useAsyncKysely?: UseAsyncRegionalKysely;\n probe?: true;\n}): Promise<TenantKysely> {\n if (!connectionId && !slug && !tenantId) {\n throw new Error('connectionId, slug, or tenantId is required');\n }\n\n const controlPlaneDatabaseUrl = env.CONTROL_PLANE_DATABASE_URL;\n if (!controlPlaneDatabaseUrl)\n throw new Error('CONTROL_PLANE_DATABASE_URL is required');\n\n const controlPlane = await (\n options.useAsyncControlPlaneKysely ?? defaultUseAsyncControlPlaneKysely\n )(controlPlaneDatabaseUrl, {\n repositoryName: `${repositoryName}/control-plane`,\n probe: options.probe,\n });\n let tenant: { id: string; slug: string; dataRegion: string } | undefined;\n try {\n const query = controlPlane\n .selectFrom('controlPlane.tenant as tenant')\n .select([\n 'tenant.id as id',\n 'tenant.slug as slug',\n 'tenant.dataRegion as dataRegion',\n ]);\n tenant = await (\n slug\n ? query.where('tenant.slug', '=', slug)\n : connectionId\n ? query\n .innerJoin(\n 'controlPlane.connectionRoute as connectionRoute',\n 'connectionRoute.tenantId',\n 'tenant.id'\n )\n .where('connectionRoute.connectionId', '=', connectionId)\n : query.where('tenant.id', '=', tenantId!)\n ).executeTakeFirst();\n } finally {\n await controlPlane.destroy();\n }\n if (!tenant) throw new Error('Tenant not found in control plane');\n\n assertTenantDataRegion(tenant.dataRegion);\n return {\n id: tenant.id,\n slug: tenant.slug,\n dataRegion: tenant.dataRegion,\n kysely: await useTenantDatabaseKysely(\n tenant.dataRegion,\n repositoryName,\n env,\n options\n ),\n };\n}\n\nexport type RegionRunError = {\n dataRegion: TenantDataRegion;\n error: string;\n};\n\n/**\n * Run a job once per configured tenant data region with per-region error\n * isolation: one region's outage must not stall the others (regions iterate\n * in a fixed order, so a failing first region would otherwise starve the\n * rest on every attempt). Throws only when every configured region failed.\n */\nexport async function forEachConfiguredRegion<T>(\n run: (dataRegion: TenantDataRegion) => Promise<T>,\n env: RegionEnvironment\n): Promise<{\n results: { dataRegion: TenantDataRegion; result: T }[];\n errors: RegionRunError[];\n}> {\n const results: { dataRegion: TenantDataRegion; result: T }[] = [];\n const errors: RegionRunError[] = [];\n\n for (const dataRegion of resolveConfiguredTenantDataRegions(env)) {\n try {\n results.push({ dataRegion, result: await run(dataRegion) });\n } catch (error) {\n errors.push({\n dataRegion,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (!results.length && errors.length) {\n throw new KyselyError('All configured tenant data regions failed', {\n errors,\n });\n }\n\n return { results, errors };\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,8 +3,9 @@
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
+ export type AccountingReservationJournalInvalidationFailure = "journal_configuration_invalid";
8
9
  export type AccountingTransactionAttachmentStatus = "attached" | "deleting" | "ready" | "uploading";
9
10
  export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>;
10
11
  export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S[], I[], U[]> : T[];
@@ -14,10 +15,25 @@ export type AuditEffectStatus = "claimed" | "completed" | "dead_letter" | "faile
14
15
  export type AuditJournalDeltaOperation = "delete" | "insert" | "update";
15
16
  export type AuditPublicEventAccountingStatus = "blocked" | "changed" | "failed" | "mixed" | "not_applicable" | "pending" | "unchanged";
16
17
  export type AuditPublicEventOperation = "archive" | "create" | "delete" | "execute" | "recalculate" | "restore" | "update";
17
- export type AuditSourceType = "api" | "automation" | "integration" | "portal" | "sync" | "system";
18
+ export type AuditActorOrganizationType = "partner" | "system" | "team" | "vrplatform";
19
+ export type AuditSourceType = "api" | "automation" | "embedded" | "integration" | "portal" | "sync" | "system";
18
20
  export type BillingListingFactSourceType = "baseline_backfill" | "daily_reconciliation" | "legacy_tracking_import" | "listing_delete" | "listing_insert" | "listing_update" | "ownership_delete" | "ownership_insert" | "ownership_update" | "tenant_delete" | "tenant_insert" | "tenant_update";
21
+ export type CoreAsyncOperationResultStatus = "completed" | "failed" | "queued";
22
+ export type CoreCsvOperationResultKind = "import" | "preview";
23
+ export type CoreCsvOperationResultStatus = "completed" | "failed" | "processing" | "queued";
24
+ export type CoreEmailDeliveryFailureCode = "inactive_recipient" | "invalid_provider_response" | "postmark_not_configured" | "provider_rejected" | "task_failed" | "transport_failed";
25
+ export type CoreEmailDeliveryStatus = "accepted" | "canceled" | "failed" | "queued" | "rejected" | "retrying" | "sending";
26
+ export type CoreEmailNotificationStatus = "canceled" | "completed" | "failed" | "processing" | "queued";
27
+ export type CoreExportJobFormat = "csv" | "pdf" | "zip";
28
+ export type CoreExportJobTaskId = "api/export-journal-entries-csv" | "api/export-manager-statement-pdf" | "api/export-owner-statement-combined-csv" | "api/export-owner-statement-pdf" | "api/export-owner-statement-pdf-batch-zip" | "api/export-owner-statement-summary-pdf" | "api/export-owner-statement-summary-pdf-batch-zip" | "api/export-route" | "api/export-trust-reconciliation-pdf";
19
29
  export type CoreFlowEventOperationAction = "abandon" | "replay";
20
30
  export type CoreFlowEventStatus = "canceled" | "dead" | "pending" | "processing" | "succeeded";
31
+ export type CoreOperationResourceRole = "result" | "source" | "target";
32
+ export type CoreOperationResourceType = "bank-rule" | "connection" | "contact" | "file" | "flow" | "listing" | "recurring-fee" | "recurring-transaction-template" | "reservation" | "statement" | "team" | "transaction" | "webhook";
33
+ export type CoreOperationPublicIdFormat = "action" | "legacy";
34
+ export type CoreOperationSourceType = "audit-action" | "export-job" | "sync" | "webhook-delivery";
35
+ export type CoreOperationStatus = "completed" | "failed" | "queued" | "running";
36
+ export type CoreOperationType = "ach-verification" | "bank-rule-run" | "calendar-block" | "calendar-unblock" | "connection-archive" | "connection-connect" | "connection-extract" | "connection-sync" | "csv-import" | "csv-import-preview" | "export" | "flow-run" | "historical-gl-import" | "historical-statement-import" | "listing-journal-refresh" | "plaid-initial-sync" | "pms-cutover" | "pms-cutover-preview" | "provider-payment" | "provider-payment-recovery" | "recurring-transaction-run" | "reservation-journal-refresh" | "team-delete" | "team-demo-data" | "team-duplicate" | "team-initialize" | "transaction-journal-refresh" | "vri-statement-import" | "vri-team-migration" | "webhook-test";
21
37
  export type Generated<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
22
38
  export type HealthAccountingIntegrityActionability = "automatically_repairable" | "blocked" | "code_fix_required" | "manual_repair" | "unknown";
23
39
  export type HealthAccountingIntegrityCaseStatus = "open" | "resolved";
@@ -36,7 +52,7 @@ export type HealthAccountingIntegritySeverity = "critical" | "error" | "info" |
36
52
  export type HealthAccountingIntegrityTransitionType = "changed" | "opened" | "reopened" | "resolved" | "reviewed";
37
53
  export type HealthAccountingIntegrityUrgency = "backlog" | "immediate" | "next_triage" | "none";
38
54
  export type HealthTenantIssueCategory = "criticalToSystem" | "criticalToUser";
39
- export type HealthTenantIssueCode = "brokenConnections" | "cancelledReservationPaidWithoutAdjustment" | "closedPeriodUnattachedJournalEntries" | "duplicatedPayments" | "endedOwnershipNonZeroBalance" | "listingOwnershipPeriodNotFoundOnActiveJournals" | "missingOwnershipOrDeactivation" | "operatingBankAccountsWithoutOpex" | "outdatedConnections" | "partnerBillingInactive" | "partnerInactive" | "pmsMissingAccountingStart" | "publishedStatementUnpaid" | "reservationCurrencyMismatch" | "reservationGuestTotalsMismatch" | "reservationPaymentProjectionMismatch" | "teamInactive" | "unbalancedJournalEntries" | "unbalancedTransactionJournalEntries" | "unpaidReservations";
55
+ export type HealthTenantIssueCode = "brokenConnections" | "cancelledReservationPaidWithoutAdjustment" | "closedPeriodUnattachedJournalEntries" | "duplicatedPayments" | "endedOwnershipNonZeroBalance" | "journalConfigurationInvalid" | "journalLocked" | "journalUnbalanced" | "listingOwnershipPeriodNotFoundOnActiveJournals" | "missingOwnershipOrDeactivation" | "operatingBankAccountsWithoutOpex" | "outdatedConnections" | "partnerBillingInactive" | "partnerInactive" | "pmsMissingAccountingStart" | "publishedStatementUnpaid" | "reservationCurrencyMismatch" | "reservationGuestTotalsMismatch" | "reservationPaymentProjectionMismatch" | "teamInactive" | "unbalancedJournalEntries" | "unbalancedTransactionJournalEntries" | "unpaidReservations";
40
56
  export type HealthTenantIssueSeverity = "error" | "warning";
41
57
  export type HealthTenantIssueStatus = "open" | "resolved";
42
58
  export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>;
@@ -55,9 +71,9 @@ export type PublicRecurringFeeConditionOperator = "<" | "<=" | "=" | ">" | ">=";
55
71
  export type Timestamp = ColumnType<Date | string, Date | string, Date | string>;
56
72
  export type WebhookApiVersion = "2026-07-01";
57
73
  export type WebhookDeliveryStatus = "canceled" | "delivering" | "failed" | "queued" | "retrying" | "succeeded";
58
- export type WebhookEventType = "connection.changed" | "listing.changed" | "reservation.changed" | "statement.status.changed" | "sync.status.changed" | "team.issues.changed" | "transaction.changed" | "webhook.test";
59
- export type WebhookResourceType = "connection" | "listing" | "reservation" | "statement" | "sync" | "team" | "transaction" | "webhook";
60
- export type WebhookSubscriptionEventType = "connection.changed" | "listing.changed" | "reservation.changed" | "statement.status.changed" | "sync.status.changed" | "team.issues.changed" | "transaction.changed";
74
+ export type WebhookEventType = "audit.event.changed" | "connection.changed" | "listing.changed" | "reservation.changed" | "statement.status.changed" | "sync.status.changed" | "team.issues.changed" | "transaction.changed" | "webhook.test";
75
+ export type WebhookResourceType = "auditEvent" | "connection" | "listing" | "reservation" | "statement" | "sync" | "team" | "transaction" | "webhook";
76
+ export type WebhookSubscriptionEventType = "audit.event.changed" | "connection.changed" | "listing.changed" | "reservation.changed" | "statement.status.changed" | "sync.status.changed" | "team.issues.changed" | "transaction.changed";
61
77
  export type WebhookSubscriptionScope = "managedTeams" | "self";
62
78
  export type WebhookSubscriptionStatus = "active" | "disabled" | "pending";
63
79
  export interface AccountingAccount {
@@ -391,6 +407,45 @@ export interface AccountingRate {
391
407
  export interface AccountingRateType {
392
408
  name: string;
393
409
  }
410
+ export interface AccountingReservationJournalFreshnessControl {
411
+ createdAt: Generated<Timestamp>;
412
+ guardsEnabledAt: Timestamp | null;
413
+ tenantId: string;
414
+ updatedAt: Generated<Timestamp>;
415
+ }
416
+ export interface AccountingReservationJournalInvalidation {
417
+ actionId: string | null;
418
+ appliedAt: Timestamp | null;
419
+ coveredByEffectId: string | null;
420
+ createdAt: Generated<Timestamp>;
421
+ effectId: string | null;
422
+ failureCode: AccountingReservationJournalInvalidationFailure | null;
423
+ id: Generated<string>;
424
+ reservationId: string;
425
+ revision: Int8;
426
+ sourceResourceId: string | null;
427
+ sourceResourceType: CoreOperationResourceType | null;
428
+ tenantId: string;
429
+ }
430
+ export interface AccountingReservationJournalState {
431
+ appliedRevision: Generated<Int8>;
432
+ calculatedAt: Timestamp | null;
433
+ createdAt: Generated<Timestamp>;
434
+ desiredRevision: Generated<Int8>;
435
+ reservationId: string;
436
+ staleSince: Timestamp | null;
437
+ tenantId: string;
438
+ updatedAt: Generated<Timestamp>;
439
+ }
440
+ export interface AccountingReservationJournalStatementImpact {
441
+ createdAt: Generated<Timestamp>;
442
+ currency: string;
443
+ invalidationId: string;
444
+ listingId: string;
445
+ listingOwnershipPeriodId: string;
446
+ month: Timestamp;
447
+ tenantId: string;
448
+ }
394
449
  export interface AccountingTaxBehavior {
395
450
  name: string;
396
451
  }
@@ -417,6 +472,8 @@ export interface AccountingTransaction {
417
472
  recurringFeeId: string | null;
418
473
  recurringPattern: Json | null;
419
474
  recurringTemplateId: string | null;
475
+ returnedFromTransactionId: string | null;
476
+ returnEffectiveAt: Timestamp | null;
420
477
  /**
421
478
  * Human-readable system ID (EXP/DEP/PAY/TRF-XXX-XXXX-XXX depending on transaction.type).
422
479
  */
@@ -480,6 +537,9 @@ export interface AuditAction {
480
537
  actorId: string | null;
481
538
  actorLabel: string | null;
482
539
  actorName: string | null;
540
+ actorOrganizationId: string | null;
541
+ actorOrganizationName: string | null;
542
+ actorOrganizationType: AuditActorOrganizationType | null;
483
543
  actorType: AuditActionActorType;
484
544
  apiVersion: string;
485
545
  createdAt: Generated<Timestamp>;
@@ -585,6 +645,7 @@ export interface AuditMutation {
585
645
  id: Generated<string>;
586
646
  op: string;
587
647
  publicChanges: Generated<Json>;
648
+ publicOutcome: Json | null;
588
649
  rootEntityId: string | null;
589
650
  rootEntityType: string | null;
590
651
  subjectId: string;
@@ -600,8 +661,13 @@ export interface AuditPublicEvent {
600
661
  actorId: string | null;
601
662
  actorLabel: string | null;
602
663
  actorName: string | null;
664
+ actorOrganizationId: string | null;
665
+ actorOrganizationName: string | null;
666
+ actorOrganizationType: AuditActorOrganizationType | null;
603
667
  actorType: AuditActionActorType;
604
668
  affectedAccountIds: Generated<string[]>;
669
+ attemptedEntityChanges: Generated<Json>;
670
+ blockedBy: Generated<Json>;
605
671
  changedEntityTypes: Generated<string[]>;
606
672
  changedPaths: Generated<string[]>;
607
673
  entityChanges: Generated<Json>;
@@ -616,6 +682,7 @@ export interface AuditPublicEvent {
616
682
  projectionFingerprint: string;
617
683
  projectionVersion: Generated<number>;
618
684
  requestId: string | null;
685
+ recovery: Generated<Json>;
619
686
  revision: Generated<number>;
620
687
  rootEntityId: string;
621
688
  rootEntityType: string;
@@ -677,9 +744,9 @@ export interface CoreAsyncOperationResult {
677
744
  errorMessage: string | null;
678
745
  operationId: string;
679
746
  result: Json | null;
680
- status: Generated<string>;
747
+ status: Generated<CoreAsyncOperationResultStatus>;
681
748
  tenantId: string;
682
- type: string;
749
+ type: CoreOperationType;
683
750
  updatedAt: Generated<Timestamp>;
684
751
  }
685
752
  export interface CoreChange {
@@ -737,25 +804,55 @@ export interface CoreCsvOperationResult {
737
804
  connectionId: string;
738
805
  createdAt: Generated<Timestamp>;
739
806
  errorMessage: string | null;
740
- kind: string;
807
+ kind: CoreCsvOperationResultKind;
741
808
  result: Json | null;
742
- status: Generated<string>;
809
+ status: Generated<CoreCsvOperationResultStatus>;
743
810
  syncId: string;
744
811
  tenantId: string;
745
812
  updatedAt: Generated<Timestamp>;
746
813
  }
814
+ export interface CoreEmailDelivery {
815
+ attemptCount: Generated<number>;
816
+ createdAt: Generated<Timestamp>;
817
+ failureCode: CoreEmailDeliveryFailureCode | null;
818
+ finishedAt: Timestamp | null;
819
+ httpStatus: number | null;
820
+ id: Generated<string>;
821
+ lastAttemptAt: Timestamp | null;
822
+ notificationId: string;
823
+ postmarkErrorCode: number | null;
824
+ postmarkMessageId: string | null;
825
+ status: Generated<CoreEmailDeliveryStatus>;
826
+ submittedAt: Timestamp | null;
827
+ tenantId: string;
828
+ triggerRunId: string | null;
829
+ updatedAt: Generated<Timestamp>;
830
+ userId: string;
831
+ }
832
+ export interface CoreEmailNotification {
833
+ createdAt: Generated<Timestamp>;
834
+ finishedAt: Timestamp | null;
835
+ id: string;
836
+ ownerStatementId: string;
837
+ recipientsResolvedAt: Timestamp | null;
838
+ startedAt: Timestamp | null;
839
+ status: Generated<CoreEmailNotificationStatus>;
840
+ tenantId: string;
841
+ triggerRunId: string | null;
842
+ updatedAt: Generated<Timestamp>;
843
+ }
747
844
  export interface CoreExportJob {
748
845
  createdAt: Generated<Timestamp>;
749
846
  errorMessage: string | null;
750
847
  fileId: string;
751
848
  filename: string;
752
849
  finishedAt: Timestamp | null;
753
- format: string;
850
+ format: CoreExportJobFormat;
754
851
  id: string;
755
852
  payload: Json;
756
853
  startedAt: Timestamp | null;
757
- status: Generated<string>;
758
- taskId: string;
854
+ status: Generated<CoreOperationStatus>;
855
+ taskId: CoreExportJobTaskId;
759
856
  tenantId: string;
760
857
  updatedAt: Generated<Timestamp>;
761
858
  }
@@ -878,12 +975,19 @@ export interface CoreOperation {
878
975
  finishedAt: Timestamp | null;
879
976
  id: Generated<string>;
880
977
  initiatedByUserId: string | null;
978
+ publicIdFormat: Generated<CoreOperationPublicIdFormat>;
881
979
  retainUntil: Timestamp | null;
882
980
  sourceVersion: Generated<Int8>;
883
981
  startedAt: Timestamp | null;
884
- status: Generated<string>;
982
+ status: Generated<CoreOperationStatus>;
885
983
  tenantId: string;
886
- type: string;
984
+ type: CoreOperationType;
985
+ updatedAt: Generated<Timestamp>;
986
+ }
987
+ export interface CoreOperationBackfill {
988
+ completedAt: Timestamp | null;
989
+ createdAt: Generated<Timestamp>;
990
+ name: string;
887
991
  updatedAt: Generated<Timestamp>;
888
992
  }
889
993
  export interface CoreOperationProjectionOutbox {
@@ -901,18 +1005,18 @@ export interface CoreOperationResource {
901
1005
  isPrimary: Generated<boolean>;
902
1006
  operationId: string;
903
1007
  resourceId: string;
904
- resourceType: string;
905
- role: string;
1008
+ resourceType: CoreOperationResourceType;
1009
+ role: CoreOperationResourceRole;
906
1010
  }
907
1011
  export interface CoreOperationSource {
908
1012
  finishedAt: Timestamp | null;
909
1013
  operationId: string;
910
1014
  required: Generated<boolean>;
911
1015
  sourceId: string;
912
- sourceType: string;
1016
+ sourceType: CoreOperationSourceType;
913
1017
  sourceVersion: Generated<Int8>;
914
1018
  startedAt: Timestamp | null;
915
- status: Generated<string>;
1019
+ status: Generated<CoreOperationStatus>;
916
1020
  }
917
1021
  export interface CoreSync {
918
1022
  automationId: string | null;
@@ -1938,8 +2042,15 @@ export interface PublicPlaidConnectSession {
1938
2042
  environment: string;
1939
2043
  errorCode: string | null;
1940
2044
  errorRetryable: boolean | null;
2045
+ exitedAt: Timestamp | null;
2046
+ exitErrorCode: string | null;
2047
+ exitErrorType: string | null;
2048
+ exitRequestId: string | null;
2049
+ exitView: string | null;
1941
2050
  expiresAt: Timestamp;
1942
2051
  id: Generated<string>;
2052
+ institutionId: string | null;
2053
+ institutionName: string | null;
1943
2054
  itemId: string | null;
1944
2055
  leaseExpiresAt: Timestamp | null;
1945
2056
  linkSessionId: string | null;
@@ -2008,6 +2119,7 @@ export interface PublicRecurringFeeType {
2008
2119
  name: string;
2009
2120
  }
2010
2121
  export interface PublicReservation {
2122
+ adults: number | null;
2011
2123
  bookedAt: Generated<Timestamp | null>;
2012
2124
  bookerName: string | null;
2013
2125
  bookingPlatform: string | null;
@@ -2026,6 +2138,7 @@ export interface PublicReservation {
2026
2138
  channelId: string | null;
2027
2139
  checkIn: Timestamp | null;
2028
2140
  checkOut: Timestamp | null;
2141
+ children: number | null;
2029
2142
  confirmationCode: string | null;
2030
2143
  connectionId: string | null;
2031
2144
  createdAt: Generated<Timestamp | null>;
@@ -2212,6 +2325,7 @@ export interface PublicTenant {
2212
2325
  billingAddressData: Json | null;
2213
2326
  billingAddressId: string | null;
2214
2327
  billingCustomerId: string | null;
2328
+ billingSubscriptionId: string | null;
2215
2329
  billingPartnerId: string | null;
2216
2330
  billingPaymentMethodType: string | null;
2217
2331
  billingPlan: string | null;
@@ -2292,6 +2406,16 @@ export interface PublicTenantUser {
2292
2406
  updatedAt: Generated<Timestamp | null>;
2293
2407
  userId: string;
2294
2408
  }
2409
+ export interface PublicConnectionOauthState {
2410
+ appId: string;
2411
+ connectionId: string | null;
2412
+ expiresAt: Timestamp;
2413
+ params: JsonObject;
2414
+ redirectUri: string;
2415
+ stateHash: string;
2416
+ tenantId: string;
2417
+ userId: string;
2418
+ }
2295
2419
  export interface PublicToken {
2296
2420
  createdAt: Generated<Timestamp>;
2297
2421
  expiresAt: Timestamp | null;
@@ -2534,6 +2658,7 @@ export interface WebhookSubscriptionSecret {
2534
2658
  subscriptionId: string;
2535
2659
  }
2536
2660
  export interface DB {
2661
+ "public.connectionOauthState": PublicConnectionOauthState;
2537
2662
  "accounting.account": AccountingAccount;
2538
2663
  "accounting.accountAssignment": AccountingAccountAssignment;
2539
2664
  "accounting.accountAssignmentLineType": AccountingAccountAssignmentLineType;
@@ -2571,6 +2696,10 @@ export interface DB {
2571
2696
  "accounting.party": AccountingParty;
2572
2697
  "accounting.rate": AccountingRate;
2573
2698
  "accounting.rateType": AccountingRateType;
2699
+ "accounting.reservationJournalFreshnessControl": AccountingReservationJournalFreshnessControl;
2700
+ "accounting.reservationJournalInvalidation": AccountingReservationJournalInvalidation;
2701
+ "accounting.reservationJournalState": AccountingReservationJournalState;
2702
+ "accounting.reservationJournalStatementImpact": AccountingReservationJournalStatementImpact;
2574
2703
  "accounting.taxBehavior": AccountingTaxBehavior;
2575
2704
  "accounting.transaction": AccountingTransaction;
2576
2705
  "accounting.transactionAttachment": AccountingTransactionAttachment;
@@ -2596,6 +2725,8 @@ export interface DB {
2596
2725
  "core.changeSyncType": CoreChangeSyncType;
2597
2726
  "core.changeType": CoreChangeType;
2598
2727
  "core.csvOperationResult": CoreCsvOperationResult;
2728
+ "core.emailDelivery": CoreEmailDelivery;
2729
+ "core.emailNotification": CoreEmailNotification;
2599
2730
  "core.exportJob": CoreExportJob;
2600
2731
  "core.flow": CoreFlow;
2601
2732
  "core.flowEvent": CoreFlowEvent;
@@ -2606,6 +2737,7 @@ export interface DB {
2606
2737
  "core.flowSetting": CoreFlowSetting;
2607
2738
  "core.issueMessageOverwrite": CoreIssueMessageOverwrite;
2608
2739
  "core.operation": CoreOperation;
2740
+ "core.operationBackfill": CoreOperationBackfill;
2609
2741
  "core.operationProjectionOutbox": CoreOperationProjectionOutbox;
2610
2742
  "core.operationResource": CoreOperationResource;
2611
2743
  "core.operationSource": CoreOperationSource;