@vrplatform/kysely 1.3.45-stage.4897 → 1.3.45-stage.490

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 (219) hide show
  1. package/build/.data.tar +0 -0
  2. package/build/main/camel-case/index.js +1 -1
  3. package/build/main/camel-case/index.js.map +1 -1
  4. package/build/main/control-plane/index.d.ts +344 -16
  5. package/build/main/control-plane/index.js +61 -0
  6. package/build/main/control-plane/index.js.map +1 -1
  7. package/build/main/domain.d.ts +4 -0
  8. package/build/main/domain.js +3 -0
  9. package/build/main/domain.js.map +1 -0
  10. package/build/main/error.d.ts +2 -1
  11. package/build/main/error.js +2 -1
  12. package/build/main/error.js.map +1 -1
  13. package/build/main/index.d.ts +19 -14
  14. package/build/main/index.js +235 -59
  15. package/build/main/index.js.map +1 -1
  16. package/build/main/isomorphic.d.ts +5 -5
  17. package/build/main/isomorphic.js +2 -8
  18. package/build/main/isomorphic.js.map +1 -1
  19. package/build/main/local/digest.d.ts +3 -3
  20. package/build/main/local/digest.js.map +1 -1
  21. package/build/main/local/generate.js +10 -8
  22. package/build/main/local/generate.js.map +1 -1
  23. package/build/main/local/index.d.ts +5 -1
  24. package/build/main/local/index.js +321 -10
  25. package/build/main/local/index.js.map +1 -1
  26. package/build/main/local/prune-pulled-schema.js +4 -1
  27. package/build/main/local/prune-pulled-schema.js.map +1 -1
  28. package/build/main/migration.d.ts +7 -0
  29. package/build/main/migration.js +11 -0
  30. package/build/main/migration.js.map +1 -0
  31. package/build/main/plugins.d.ts +2 -2
  32. package/build/main/plugins.js.map +1 -1
  33. package/build/main/postgres-error.d.ts +3 -3
  34. package/build/main/postgres-error.js +4 -3
  35. package/build/main/postgres-error.js.map +1 -1
  36. package/build/main/query/listing/status.d.ts +0 -10
  37. package/build/main/query/listing/status.js +2 -14
  38. package/build/main/query/listing/status.js.map +1 -1
  39. package/build/main/query/tenant/status.d.ts +5 -8
  40. package/build/main/query/tenant/status.js +18 -21
  41. package/build/main/query/tenant/status.js.map +1 -1
  42. package/build/main/regional.d.ts +7 -1
  43. package/build/main/regional.js +30 -17
  44. package/build/main/regional.js.map +1 -1
  45. package/build/main/test/index.d.ts +23 -11
  46. package/build/main/test/index.js +31 -23
  47. package/build/main/test/index.js.map +1 -1
  48. package/build/main/transaction.d.ts +3 -3
  49. package/build/main/transaction.js.map +1 -1
  50. package/build/main/v1.generated.d.ts +771 -139
  51. package/build/main/v1.generated.js.map +1 -1
  52. package/build/migrations-v2/0000000000000-baseline.ts +5 -0
  53. package/build/migrations-v2/0000000000001-public-audit-events-v2.ts +137 -0
  54. package/build/migrations-v2/0000000000002-audit-recovery-watermarks.ts +30 -0
  55. package/build/migrations-v2/0000000000003-audit-effect-recovery-watermark.ts +13 -0
  56. package/build/migrations-v2/0000000000004-audit-event-projected-at.ts +15 -0
  57. package/build/migrations-v2/0000000000005-audit-recovery-indexes.ts +63 -0
  58. package/build/migrations-v2/0000000000006-audit-action-public-event-projected-at.ts +22 -0
  59. package/build/migrations-v2/0000000000007-audit-action-public-event-projected-at-backfill.ts +35 -0
  60. package/build/migrations-v2/0000000000008-global-user-attribution.ts +33 -0
  61. package/build/migrations-v2/0000000000008-team-issue-rule-state.ts +52 -0
  62. package/build/migrations-v2/0000000000009-reservation-issue-projections.ts +45 -0
  63. package/build/migrations-v2/0000000000010-bank-rule-application-bank-record-delete-cascade.ts +26 -0
  64. package/build/migrations-v2/0000000000011-guest-balance-journal-entry-lookup-index.ts +25 -0
  65. package/build/migrations-v2/0000000000012-trial-free-analytics-billing-status.ts +72 -0
  66. package/build/migrations-v2/0000000000013-ui-permission-bundles.ts +45 -0
  67. package/build/migrations-v2/0000000000014-ui-permission-bundle-top-up.ts +32 -0
  68. package/build/migrations-v2/0000000000015-durable-flow-events.ts +163 -0
  69. package/build/migrations-v2/0000000000016-billing-listing-facts.ts +539 -0
  70. package/build/migrations-v2/0000000000016-managed-team-access.ts +34 -0
  71. package/build/migrations-v2/0000000000017-drop-trial-until.ts +42 -0
  72. package/build/migrations-v2/0000000000017-webhook-secret-reencryption-failures.ts +18 -0
  73. package/build/migrations-v2/0000000000018-accounting-integrity-monitoring.ts +276 -0
  74. package/build/migrations-v2/0000000000018-durable-flow-event-sensitive-input.ts +28 -0
  75. package/build/migrations-v2/0000000000019-accounting-integrity-run-shards.ts +26 -0
  76. package/build/migrations-v2/0000000000019-asynchronous-operations.ts +736 -0
  77. package/build/migrations-v2/0000000000020-accounting-integrity-case-classification.ts +52 -0
  78. package/build/migrations-v2/0000000000021-payment-line-classification-monitor-indexes.ts +31 -0
  79. package/build/migrations-v2/0000000000022-accounting-integrity-controlled-repairs.ts +281 -0
  80. package/build/migrations-v2/0000000000023-line-classification-usage.ts +325 -0
  81. package/build/migrations-v2/0000000000024-tenant-region-migration.ts +108 -0
  82. package/build/migrations-v2/0000000000025-partner-ach-denial-default.ts +30 -0
  83. package/build/migrations-v2/0000000000026-line-classification-usage-capture.ts +399 -0
  84. package/build/migrations-v2/0000000000027-payout-replacement-chain.ts +27 -0
  85. package/build/migrations-v2/0000000000028-accounting-integrity-operator-workflow.ts +108 -0
  86. package/build/migrations-v2/0000000000029-accounting-integrity-definition-artifacts.ts +40 -0
  87. package/build/migrations-v2/0000000000030-accounting-integrity-review-metadata-compatibility.ts +49 -0
  88. package/build/migrations-v2/0000000000031-ui-permission-role-simplification.ts +70 -0
  89. package/build/migrations-v2/0000000000032-tenant-delete-ownership-cascades.ts +44 -0
  90. package/build/migrations-v2/0000000000033-reservation-issue-seed-bucket-index.ts +19 -0
  91. package/build/migrations-v2/0000000000034-retire-recent-classification-indexes.ts +29 -0
  92. package/build/migrations-v2/0000000000035-core-change-autovacuum.ts +24 -0
  93. package/build/migrations-v2/0000000000036-journal-entry-inactive-reason-constraint.ts +33 -0
  94. package/build/migrations-v2/0000000000037-journal-entry-inactive-reasons.ts +19 -0
  95. package/build/{migrations/0000000000023-journal-entry-currency-mismatch-reason.ts → migrations-v2/0000000000038-journal-entry-group-inactive-reason.ts} +4 -4
  96. package/build/migrations-v2/0000000000039-reservation-guest-breakdown.ts +19 -0
  97. package/build/migrations-v2/0000000000040-csv-import-source-identity-index.ts +23 -0
  98. package/build/migrations-v2/0000000000041-payment-returns.ts +38 -0
  99. package/build/migrations-v2/0000000000042-operation-resource-types.ts +609 -0
  100. package/build/migrations-v2/0000000000043-reservation-journal-freshness.ts +149 -0
  101. package/build/migrations-v2/0000000000044-reservation-journal-freshness-backfill.ts +254 -0
  102. package/build/migrations-v2/0000000000045-reservation-journal-freshness-revision-repair.ts +83 -0
  103. package/build/migrations-v2/0000000000046-materialized-reservation-journal-operations.ts +709 -0
  104. package/build/migrations-v2/0000000000047-public-audit-completion.ts +77 -0
  105. package/build/migrations-v2/0000000000048-reservation-journal-full-refresh-repair.ts +136 -0
  106. package/build/migrations-v2/0000000000049-queued-journal-operation-failures.ts +60 -0
  107. package/build/migrations-v2/0000000000050-connection-oauth-state.ts +43 -0
  108. package/build/module/camel-case/index.js +1 -1
  109. package/build/module/camel-case/index.js.map +1 -1
  110. package/build/module/control-plane/index.d.ts +344 -16
  111. package/build/module/control-plane/index.js +49 -1
  112. package/build/module/control-plane/index.js.map +1 -1
  113. package/build/module/domain.d.ts +4 -0
  114. package/build/module/domain.js +2 -0
  115. package/build/module/domain.js.map +1 -0
  116. package/build/module/error.d.ts +2 -1
  117. package/build/module/error.js +3 -1
  118. package/build/module/error.js.map +1 -1
  119. package/build/module/index.d.ts +19 -14
  120. package/build/module/index.js +236 -57
  121. package/build/module/index.js.map +1 -1
  122. package/build/module/isomorphic.d.ts +5 -5
  123. package/build/module/isomorphic.js +1 -6
  124. package/build/module/isomorphic.js.map +1 -1
  125. package/build/module/local/digest.d.ts +3 -3
  126. package/build/module/local/digest.js.map +1 -1
  127. package/build/module/local/generate.js +10 -8
  128. package/build/module/local/generate.js.map +1 -1
  129. package/build/module/local/index.d.ts +5 -1
  130. package/build/module/local/index.js +322 -11
  131. package/build/module/local/index.js.map +1 -1
  132. package/build/module/local/prune-pulled-schema.js +4 -1
  133. package/build/module/local/prune-pulled-schema.js.map +1 -1
  134. package/build/module/migration.d.ts +7 -0
  135. package/build/module/migration.js +8 -0
  136. package/build/module/migration.js.map +1 -0
  137. package/build/module/plugins.d.ts +2 -2
  138. package/build/module/plugins.js.map +1 -1
  139. package/build/module/postgres-error.d.ts +3 -3
  140. package/build/module/postgres-error.js +4 -3
  141. package/build/module/postgres-error.js.map +1 -1
  142. package/build/module/query/listing/status.d.ts +0 -10
  143. package/build/module/query/listing/status.js +2 -12
  144. package/build/module/query/listing/status.js.map +1 -1
  145. package/build/module/query/tenant/status.d.ts +5 -8
  146. package/build/module/query/tenant/status.js +18 -21
  147. package/build/module/query/tenant/status.js.map +1 -1
  148. package/build/module/regional.d.ts +7 -1
  149. package/build/module/regional.js +30 -17
  150. package/build/module/regional.js.map +1 -1
  151. package/build/module/test/index.d.ts +23 -11
  152. package/build/module/test/index.js +31 -23
  153. package/build/module/test/index.js.map +1 -1
  154. package/build/module/transaction.d.ts +3 -3
  155. package/build/module/transaction.js.map +1 -1
  156. package/build/module/v1.generated.d.ts +771 -139
  157. package/build/module/v1.generated.js.map +1 -1
  158. package/package.json +5 -4
  159. package/build/migrations/0000000000001-init.ts +0 -5
  160. package/build/migrations/0000000000009-drop-store-schema.ts +0 -14
  161. package/build/migrations/0000000000010-bank-rules.ts +0 -190
  162. package/build/migrations/0000000000011-bank-rule-line-adjustments.ts +0 -65
  163. package/build/migrations/0000000000012-bank-rule-conditions.ts +0 -45
  164. package/build/migrations/0000000000013-bank-rule-name-unique.ts +0 -15
  165. package/build/migrations/0000000000014-bank-rule-drop-legacy-conditions.ts +0 -41
  166. package/build/migrations/0000000000015-booking-channel-logo-dev-provider.ts +0 -70
  167. package/build/migrations/0000000000016-owner-statement-draft-status.ts +0 -22
  168. package/build/migrations/0000000000017-tenant-migration-markers.ts +0 -18
  169. package/build/migrations/0000000000018-security-deposits-payable-category.ts +0 -63
  170. package/build/migrations/0000000000019-tenant-app-settings.ts +0 -76
  171. package/build/migrations/0000000000020-operating-opening-trial-balance.ts +0 -36
  172. package/build/migrations/0000000000021-audit-foreign-key-indexes.ts +0 -77
  173. package/build/migrations/0000000000022-opening-trial-balance-combined-columns.ts +0 -30
  174. package/build/migrations/0000000000024-listing-parent.ts +0 -37
  175. package/build/migrations/0000000000025-journal-entry-parent-listing.ts +0 -26
  176. package/build/migrations/0000000000026-booking-channel-logo-slots.ts +0 -89
  177. package/build/migrations/0000000000027-list-browse-performance-indexes.ts +0 -52
  178. package/build/migrations/0000000000028-flow-setting-status-jsonb.ts +0 -20
  179. package/build/migrations/0000000000029-tenant-slug.ts +0 -328
  180. package/build/migrations/0000000000030-pms-accounting-windows.ts +0 -50
  181. package/build/migrations/0000000000031-owner-statement-projection-listing-revision.ts +0 -20
  182. package/build/migrations/0000000000032-flow-event-listening.ts +0 -28
  183. package/build/migrations/0000000000033-opening-trial-balance-transaction.ts +0 -272
  184. package/build/migrations/0000000000034-historic-general-ledger.ts +0 -24
  185. package/build/migrations/0000000000035-tenant-regional-placement.ts +0 -37
  186. package/build/migrations/0000000000036-control-plane-projection-events.ts +0 -43
  187. package/build/migrations/0000000000037-tenant-guide-onboarding.ts +0 -21
  188. package/build/migrations/0000000000038-tracking-event-analytics-sink.ts +0 -31
  189. package/build/migrations/0000000000039-crunchy-region.ts +0 -86
  190. package/build/migrations/0000000000040-hostaway-region.ts +0 -72
  191. package/build/migrations/0000000000041-audit-tenant-fk.ts +0 -66
  192. package/build/migrations/0000000000042-ramp-staging-connect-params.ts +0 -35
  193. package/build/migrations/0000000000043-gl-pms-accounting-window-guard.ts +0 -125
  194. package/build/migrations/0000000000044-tenant-cross-region-fks.ts +0 -45
  195. package/build/migrations/0000000000045-cloudflare-region-env.ts +0 -100
  196. package/build/migrations/0000000000046-control-plane-outbox-alias.ts +0 -46
  197. package/build/migrations/0000000000047-ramp-contact-last-4-digits.ts +0 -16
  198. package/build/migrations/0000000000047-tenant-status-backfill.ts +0 -40
  199. package/build/migrations/0000000000048-tenant-status-constraint.ts +0 -24
  200. package/build/migrations/0000000000049-health-tenant-issues.ts +0 -69
  201. package/build/migrations/0000000000050-partner-webhooks.ts +0 -135
  202. package/build/migrations/0000000000051-health-webhook-runtime-grants.ts +0 -42
  203. package/build/migrations/0000000000052-feature-approval-team-enablement.ts +0 -13
  204. package/build/migrations/0000000000053-health-webhook-enums.ts +0 -296
  205. package/build/migrations/0000000000054-user-secondary-emails-jsonb.ts +0 -25
  206. package/build/migrations/0000000000055-outbound-webhooks-v1.ts +0 -221
  207. package/build/migrations/0000000000056-connection-webhook-version.ts +0 -18
  208. package/build/migrations/0000000000057-sync-webhook-version.ts +0 -18
  209. package/build/migrations/0000000000058-reservation-webhook-version.ts +0 -18
  210. package/build/migrations/0000000000059-listing-webhook-version.ts +0 -18
  211. package/build/migrations/0000000000060-owner-statement-webhook-version.ts +0 -19
  212. package/build/migrations/0000000000061-transaction-webhook-version.ts +0 -18
  213. package/build/migrations/0000000000062-plaid-connect-session.ts +0 -102
  214. package/build/migrations/0000000000063-pgcrypto.ts +0 -27
  215. package/build/migrations/0000000000064-partner-api-foundation.ts +0 -36
  216. package/build/migrations/0000000000065-canonical-jsonb-shapes.ts +0 -231
  217. package/build/migrations/0000000000066-source-delete-fk-indexes.ts +0 -20
  218. package/build/migrations/0000000000067-remove-opening-trial-balance-account-columns.ts +0 -34
  219. package/build/migrations/0000000000068-bank-record-account-delete-cascade.ts +0 -26
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-error.js","sourceRoot":"src/","sources":["postgres-error.ts"],"names":[],"mappings":";;AAIA,0CAoBC;AAxBD;;;GAGG;AACH,SAAgB,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":";;AAIA,0CAuBC;AA3BD;;;GAGG;AACH,SAAgB,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"]}
@@ -9,16 +9,6 @@ export declare function whereListingIsActive(eb: ExpressionBuilder<DB & {
9
9
  }, 'l'>, today?: string): import("kysely").ExpressionWrapper<DB & {
10
10
  l: PublicListing;
11
11
  }, "l", import("kysely/dist/cjs/util/type-utils").SqlBool>;
12
- export declare function selectListingIsInactive(eb: ExpressionBuilder<DB & {
13
- l: PublicListing;
14
- }, 'l'>, today?: string): import("kysely").ExpressionWrapper<DB & {
15
- l: PublicListing;
16
- }, "l", import("kysely/dist/cjs/util/type-utils").SqlBool>;
17
- export declare function selectListingIsActive(eb: ExpressionBuilder<DB & {
18
- l: PublicListing;
19
- }, 'l'>, today?: string): import("kysely").ExpressionWrapper<DB & {
20
- l: PublicListing;
21
- }, "l", import("kysely/dist/cjs/util/type-utils").SqlBool>;
22
12
  export declare function selectListingStatus(eb: ExpressionBuilder<DB & {
23
13
  l: PublicListing;
24
14
  }, 'l'>, today?: string): import("kysely").ExpressionWrapper<DB & {
@@ -2,22 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.whereListingIsInactive = whereListingIsInactive;
4
4
  exports.whereListingIsActive = whereListingIsActive;
5
- exports.selectListingIsInactive = selectListingIsInactive;
6
- exports.selectListingIsActive = selectListingIsActive;
7
5
  exports.selectListingStatus = selectListingStatus;
8
6
  const utils_1 = require("@vrplatform/utils");
9
7
  const isomorphic_1 = require("../../isomorphic");
8
+ const status_1 = require("../tenant/status");
10
9
  function hasActiveListing(eb, today) {
11
10
  return eb.exists(eb
12
11
  .selectFrom('public.tenant as tenant')
13
- .leftJoin('public.tenant as billingPartner', 'billingPartner.id', 'tenant.calculatedBillingPartnerId')
14
12
  .select('tenant.id')
15
13
  .whereRef('tenant.id', '=', 'l.tenantId')
16
- .where('tenant.calculatedStatus', '=', 'active')
17
- .where((eb2) => eb2.or([
18
- eb2('tenant.calculatedBillingPartnerId', 'is', null),
19
- eb2('billingPartner.calculatedStatus', '=', 'active'),
20
- ]))
14
+ .where(status_1.whereTenantActive)
21
15
  .where((eb2) => eb2.or([
22
16
  eb2.and([
23
17
  eb2('tenant.isGeneralLedger', '=', false),
@@ -72,12 +66,6 @@ function whereListingIsInactive(eb, today = (0, utils_1.day)().yyyymmdd()) {
72
66
  function whereListingIsActive(eb, today = (0, utils_1.day)().yyyymmdd()) {
73
67
  return hasActiveListing(eb, today);
74
68
  }
75
- function selectListingIsInactive(eb, today = (0, utils_1.day)().yyyymmdd()) {
76
- return whereListingIsInactive(eb, today);
77
- }
78
- function selectListingIsActive(eb, today = (0, utils_1.day)().yyyymmdd()) {
79
- return whereListingIsActive(eb, today);
80
- }
81
69
  function selectListingStatus(eb, today = (0, utils_1.day)().yyyymmdd()) {
82
70
  return eb
83
71
  .case()
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"src/","sources":["query/listing/status.ts"],"names":[],"mappings":"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","sourcesContent":["import { day } from '@vrplatform/utils';\nimport type { DB, ExpressionBuilder, PublicListing } from '../../isomorphic';\nimport { sql } from '../../isomorphic';\n\nfunction hasActiveListing(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string\n) {\n return eb.exists(\n eb\n .selectFrom('public.tenant as tenant')\n .leftJoin(\n 'public.tenant as billingPartner',\n 'billingPartner.id',\n 'tenant.calculatedBillingPartnerId'\n )\n .select('tenant.id')\n .whereRef('tenant.id', '=', 'l.tenantId')\n .where('tenant.calculatedStatus', '=', 'active')\n .where((eb2) =>\n eb2.or([\n eb2('tenant.calculatedBillingPartnerId', 'is', null),\n eb2('billingPartner.calculatedStatus', '=', 'active'),\n ])\n )\n .where((eb2) =>\n eb2.or([\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', false),\n eb('l.calculatedStatus', '=', 'active'),\n ]),\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', true),\n eb.not(hasInactiveOwnership(eb, today)),\n ]),\n ])\n )\n .limit(1)\n );\n}\n\nfunction hasInactiveOwnership(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string\n) {\n const onDate = day(today).toDate();\n return eb.exists(\n eb\n .selectFrom('public.listingOwnershipPeriod as lop')\n .select('lop.id')\n .where(\n 'lop.listingId',\n '=',\n sql<string>`coalesce(${sql.ref('l.parentId')}, ${sql.ref('l.id')})`\n )\n .whereRef('lop.tenantId', '=', 'l.tenantId')\n .where('lop.setListingInactive', '=', true)\n .where((eb2) =>\n eb2.or([\n eb2.and([\n eb2('lop.startAt', '<=', onDate),\n eb2('lop.endAt', '>=', onDate),\n ]),\n eb2.and([\n eb2('lop.startAt', '<=', onDate),\n eb2('lop.endAt', 'is', null),\n ]),\n ])\n )\n .limit(1)\n );\n}\n\nfunction hasInactiveListing(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string\n) {\n return eb.exists(\n eb\n .selectFrom('public.tenant as tenant')\n .select('tenant.id')\n .whereRef('tenant.id', '=', 'l.tenantId')\n .where((eb2) =>\n eb2.or([\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', false),\n eb('l.calculatedStatus', '=', 'inactive'),\n ]),\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', true),\n hasInactiveOwnership(eb, today),\n ]),\n ])\n )\n );\n}\n\nexport function whereListingIsInactive(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return hasInactiveListing(eb, today);\n}\n\nexport function whereListingIsActive(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return hasActiveListing(eb, today);\n}\n\nexport function selectListingIsInactive(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return whereListingIsInactive(eb, today);\n}\n\nexport function selectListingIsActive(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return whereListingIsActive(eb, today);\n}\n\nexport function selectListingStatus(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return eb\n .case()\n .when(whereListingIsInactive(eb, today))\n .then('inactive')\n .else('active')\n .end();\n}\n"]}
1
+ {"version":3,"file":"status.js","sourceRoot":"src/","sources":["query/listing/status.ts"],"names":[],"mappings":"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","sourcesContent":["import { day } from '@vrplatform/utils';\nimport type { DB, ExpressionBuilder, PublicListing } from '../../isomorphic';\nimport { sql } from '../../isomorphic';\nimport { whereTenantActive } from '../tenant/status';\n\nfunction hasActiveListing(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string\n) {\n return eb.exists(\n eb\n .selectFrom('public.tenant as tenant')\n .select('tenant.id')\n .whereRef('tenant.id', '=', 'l.tenantId')\n .where(whereTenantActive)\n .where((eb2) =>\n eb2.or([\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', false),\n eb('l.calculatedStatus', '=', 'active'),\n ]),\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', true),\n eb.not(hasInactiveOwnership(eb, today)),\n ]),\n ])\n )\n .limit(1)\n );\n}\n\nfunction hasInactiveOwnership(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string\n) {\n const onDate = day(today).toDate();\n return eb.exists(\n eb\n .selectFrom('public.listingOwnershipPeriod as lop')\n .select('lop.id')\n .where(\n 'lop.listingId',\n '=',\n sql<string>`coalesce(${sql.ref('l.parentId')}, ${sql.ref('l.id')})`\n )\n .whereRef('lop.tenantId', '=', 'l.tenantId')\n .where('lop.setListingInactive', '=', true)\n .where((eb2) =>\n eb2.or([\n eb2.and([\n eb2('lop.startAt', '<=', onDate),\n eb2('lop.endAt', '>=', onDate),\n ]),\n eb2.and([\n eb2('lop.startAt', '<=', onDate),\n eb2('lop.endAt', 'is', null),\n ]),\n ])\n )\n .limit(1)\n );\n}\n\nfunction hasInactiveListing(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string\n) {\n return eb.exists(\n eb\n .selectFrom('public.tenant as tenant')\n .select('tenant.id')\n .whereRef('tenant.id', '=', 'l.tenantId')\n .where((eb2) =>\n eb2.or([\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', false),\n eb('l.calculatedStatus', '=', 'inactive'),\n ]),\n eb2.and([\n eb2('tenant.isGeneralLedger', '=', true),\n hasInactiveOwnership(eb, today),\n ]),\n ])\n )\n );\n}\n\nexport function whereListingIsInactive(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return hasInactiveListing(eb, today);\n}\n\nexport function whereListingIsActive(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return hasActiveListing(eb, today);\n}\n\nexport function selectListingStatus(\n eb: ExpressionBuilder<DB & { l: PublicListing }, 'l'>,\n today: string = day().yyyymmdd()\n) {\n return eb\n .case()\n .when(whereListingIsInactive(eb, today))\n .then('inactive')\n .else('active')\n .end();\n}\n"]}
@@ -1,17 +1,14 @@
1
- import type { DB, ExpressionBuilder, PublicTenant } from '../../isomorphic';
1
+ import { type DB, type ExpressionBuilder, type PublicTenant, type SqlBool } from '../../isomorphic';
2
2
  type TenantExpressionBuilder = ExpressionBuilder<DB & {
3
3
  tenant: PublicTenant;
4
4
  }, 'tenant'>;
5
5
  export declare function whereTenantActive(eb: TenantExpressionBuilder): import("kysely").ExpressionWrapper<DB & {
6
6
  tenant: PublicTenant;
7
- }, "tenant", import("kysely/dist/cjs/util/type-utils").SqlBool>;
8
- export declare function whereTenantNotTestTeam(eb: TenantExpressionBuilder, testTeamId: string): import("kysely").ExpressionWrapper<DB & {
9
- tenant: PublicTenant;
10
- }, "tenant", import("kysely/dist/cjs/util/type-utils").SqlBool>;
11
- export declare function whereTenantShouldBePaid(eb: TenantExpressionBuilder, { includePartnerTeams, today, }?: {
7
+ }, "tenant", SqlBool>;
8
+ export declare function whereTenantNotTestTeam(testTeamId: string): import("kysely").RawBuilder<SqlBool>;
9
+ export declare function whereTenantShouldBePaid(eb: TenantExpressionBuilder, { includePartnerTeams, }?: {
12
10
  includePartnerTeams?: boolean;
13
- today?: Date | string;
14
11
  }): import("kysely").ExpressionWrapper<DB & {
15
12
  tenant: PublicTenant;
16
- }, "tenant", import("kysely/dist/cjs/util/type-utils").SqlBool>;
13
+ }, "tenant", SqlBool>;
17
14
  export {};
@@ -3,38 +3,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.whereTenantActive = whereTenantActive;
4
4
  exports.whereTenantNotTestTeam = whereTenantNotTestTeam;
5
5
  exports.whereTenantShouldBePaid = whereTenantShouldBePaid;
6
- const utils_1 = require("@vrplatform/utils");
6
+ const isomorphic_1 = require("../../isomorphic");
7
+ const billing_partner_1 = require("./billing-partner");
7
8
  function whereTenantActive(eb) {
8
9
  return eb.and([
9
10
  eb('tenant.calculatedStatus', '=', 'active'),
10
- eb.exists(eb
11
+ eb.not(eb.exists(eb
11
12
  .selectFrom('public.tenant as billingPartner')
12
13
  .select('billingPartner.id')
13
- .whereRef('billingPartner.id', '=', 'tenant.calculatedBillingPartnerId')
14
- .where('billingPartner.calculatedStatus', '=', 'active')),
14
+ .where('billingPartner.id', '=', eb.fn.coalesce('tenant.calculatedBillingPartnerId', eb.val((0, billing_partner_1.getCalculatedBillingPartnerId)({}))))
15
+ .where('billingPartner.calculatedStatus', 'is distinct from', 'active'))),
15
16
  ]);
16
17
  }
17
- function whereTenantNotTestTeam(eb, testTeamId) {
18
- return eb.and([
19
- eb('tenant.id', '!=', testTeamId),
20
- eb.or([
21
- eb('tenant.partnerId', 'is', null),
22
- eb('tenant.partnerId', '!=', testTeamId),
23
- ]),
24
- eb.or([
25
- eb('tenant.billingPartnerId', 'is', null),
26
- eb('tenant.billingPartnerId', '!=', testTeamId),
27
- ]),
28
- ]);
18
+ function whereTenantNotTestTeam(testTeamId) {
19
+ return (0, isomorphic_1.sql) `(
20
+ ${isomorphic_1.sql.ref('tenant.id')} != ${testTeamId}
21
+ and (
22
+ ${isomorphic_1.sql.ref('tenant.partnerId')} is null
23
+ or ${isomorphic_1.sql.ref('tenant.partnerId')} != ${testTeamId}
24
+ )
25
+ and (
26
+ ${isomorphic_1.sql.ref('tenant.billingPartnerId')} is null
27
+ or ${isomorphic_1.sql.ref('tenant.billingPartnerId')} != ${testTeamId}
28
+ )
29
+ )`;
29
30
  }
30
- function whereTenantShouldBePaid(eb, { includePartnerTeams = false, today = (0, utils_1.day)().yyyymmdd(), } = {}) {
31
+ function whereTenantShouldBePaid(eb, { includePartnerTeams = false, } = {}) {
31
32
  return eb.and([
32
33
  whereTenantActive(eb),
33
34
  eb('tenant.isOnboarding', '=', false),
34
- eb.or([
35
- eb('tenant.trialUntil', '<', today),
36
- eb('tenant.trialUntil', 'is', null),
37
- ]),
38
35
  ...(includePartnerTeams
39
36
  ? []
40
37
  : [eb('tenant.calculatedIsBillable', '=', true)]),
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"src/","sources":["query/tenant/status.ts"],"names":[],"mappings":";;AAQA,8CAWC;AAED,wDAeC;AAED,0DAqBC;AA3DD,6CAAwC;AAQxC,SAAgB,iBAAiB,CAAC,EAA2B;IAC3D,OAAO,EAAE,CAAC,GAAG,CAAC;QACZ,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE,QAAQ,CAAC;QAC5C,EAAE,CAAC,MAAM,CACP,EAAE;aACC,UAAU,CAAC,iCAAiC,CAAC;aAC7C,MAAM,CAAC,mBAAmB,CAAC;aAC3B,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE,mCAAmC,CAAC;aACvE,KAAK,CAAC,iCAAiC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAC3D;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,sBAAsB,CACpC,EAA2B,EAC3B,UAAkB;IAElB,OAAO,EAAE,CAAC,GAAG,CAAC;QACZ,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC;QACjC,EAAE,CAAC,EAAE,CAAC;YACJ,EAAE,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,CAAC;YAClC,EAAE,CAAC,kBAAkB,EAAE,IAAI,EAAE,UAAU,CAAC;SACzC,CAAC;QACF,EAAE,CAAC,EAAE,CAAC;YACJ,EAAE,CAAC,yBAAyB,EAAE,IAAI,EAAE,IAAI,CAAC;YACzC,EAAE,CAAC,yBAAyB,EAAE,IAAI,EAAE,UAAU,CAAC;SAChD,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,uBAAuB,CACrC,EAA2B,EAC3B,EACE,mBAAmB,GAAG,KAAK,EAC3B,KAAK,GAAG,IAAA,WAAG,GAAE,CAAC,QAAQ,EAAE,MAItB,EAAE;IAEN,OAAO,EAAE,CAAC,GAAG,CAAC;QACZ,iBAAiB,CAAC,EAAE,CAAC;QACrB,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE,KAAK,CAAC;QACrC,EAAE,CAAC,EAAE,CAAC;YACJ,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE,KAAK,CAAC;YACnC,EAAE,CAAC,mBAAmB,EAAE,IAAI,EAAE,IAAI,CAAC;SACpC,CAAC;QACF,GAAG,CAAC,mBAAmB;YACrB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;KACpD,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { day } from '@vrplatform/utils';\nimport type { DB, ExpressionBuilder, PublicTenant } from '../../isomorphic';\n\ntype TenantExpressionBuilder = ExpressionBuilder<\n DB & { tenant: PublicTenant },\n 'tenant'\n>;\n\nexport function whereTenantActive(eb: TenantExpressionBuilder) {\n return eb.and([\n eb('tenant.calculatedStatus', '=', 'active'),\n eb.exists(\n eb\n .selectFrom('public.tenant as billingPartner')\n .select('billingPartner.id')\n .whereRef('billingPartner.id', '=', 'tenant.calculatedBillingPartnerId')\n .where('billingPartner.calculatedStatus', '=', 'active')\n ),\n ]);\n}\n\nexport function whereTenantNotTestTeam(\n eb: TenantExpressionBuilder,\n testTeamId: string\n) {\n return eb.and([\n eb('tenant.id', '!=', testTeamId),\n eb.or([\n eb('tenant.partnerId', 'is', null),\n eb('tenant.partnerId', '!=', testTeamId),\n ]),\n eb.or([\n eb('tenant.billingPartnerId', 'is', null),\n eb('tenant.billingPartnerId', '!=', testTeamId),\n ]),\n ]);\n}\n\nexport function whereTenantShouldBePaid(\n eb: TenantExpressionBuilder,\n {\n includePartnerTeams = false,\n today = day().yyyymmdd(),\n }: {\n includePartnerTeams?: boolean;\n today?: Date | string;\n } = {}\n) {\n return eb.and([\n whereTenantActive(eb),\n eb('tenant.isOnboarding', '=', false),\n eb.or([\n eb('tenant.trialUntil', '<', today),\n eb('tenant.trialUntil', 'is', null),\n ]),\n ...(includePartnerTeams\n ? []\n : [eb('tenant.calculatedIsBillable', '=', true)]),\n ]);\n}\n"]}
1
+ {"version":3,"file":"status.js","sourceRoot":"src/","sources":["query/tenant/status.ts"],"names":[],"mappings":";;AAcA,8CAwBC;AAED,wDAYC;AAED,0DAeC;AArED,iDAM0B;AAC1B,uDAAkE;AAOlE,SAAgB,iBAAiB,CAAC,EAA2B;IAC3D,OAAO,EAAE,CAAC,GAAG,CAAC;QACZ,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE,QAAQ,CAAC;QAC5C,EAAE,CAAC,GAAG,CACJ,EAAE,CAAC,MAAM,CACP,EAAE;aACC,UAAU,CAAC,iCAAiC,CAAC;aAC7C,MAAM,CAAC,mBAAmB,CAAC;aAC3B,KAAK,CACJ,mBAAmB,EACnB,GAAG,EACH,EAAE,CAAC,EAAE,CAAC,QAAQ,CACZ,mCAAmC,EACnC,EAAE,CAAC,GAAG,CAAC,IAAA,+CAA6B,EAAC,EAAE,CAAC,CAAC,CAC1C,CACF;aACA,KAAK,CACJ,iCAAiC,EACjC,kBAAkB,EAClB,QAAQ,CACT,CACJ,CACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,sBAAsB,CAAC,UAAkB;IACvD,OAAO,IAAA,gBAAG,EAAS;MACf,gBAAG,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,UAAU;;QAEnC,gBAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC;WACxB,gBAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,UAAU;;;QAG/C,gBAAG,CAAC,GAAG,CAAC,yBAAyB,CAAC;WAC/B,gBAAG,CAAC,GAAG,CAAC,yBAAyB,CAAC,OAAO,UAAU;;IAE1D,CAAC;AACL,CAAC;AAED,SAAgB,uBAAuB,CACrC,EAA2B,EAC3B,EACE,mBAAmB,GAAG,KAAK,MAGzB,EAAE;IAEN,OAAO,EAAE,CAAC,GAAG,CAAC;QACZ,iBAAiB,CAAC,EAAE,CAAC;QACrB,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE,KAAK,CAAC;QACrC,GAAG,CAAC,mBAAmB;YACrB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;KACpD,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n sql,\n type DB,\n type ExpressionBuilder,\n type PublicTenant,\n type SqlBool,\n} from '../../isomorphic';\nimport { getCalculatedBillingPartnerId } from './billing-partner';\n\ntype TenantExpressionBuilder = ExpressionBuilder<\n DB & { tenant: PublicTenant },\n 'tenant'\n>;\n\nexport function whereTenantActive(eb: TenantExpressionBuilder) {\n return eb.and([\n eb('tenant.calculatedStatus', '=', 'active'),\n eb.not(\n eb.exists(\n eb\n .selectFrom('public.tenant as billingPartner')\n .select('billingPartner.id')\n .where(\n 'billingPartner.id',\n '=',\n eb.fn.coalesce(\n 'tenant.calculatedBillingPartnerId',\n eb.val(getCalculatedBillingPartnerId({}))\n )\n )\n .where(\n 'billingPartner.calculatedStatus',\n 'is distinct from',\n 'active'\n )\n )\n ),\n ]);\n}\n\nexport function whereTenantNotTestTeam(testTeamId: string) {\n return sql<SqlBool>`(\n ${sql.ref('tenant.id')} != ${testTeamId}\n and (\n ${sql.ref('tenant.partnerId')} is null\n or ${sql.ref('tenant.partnerId')} != ${testTeamId}\n )\n and (\n ${sql.ref('tenant.billingPartnerId')} is null\n or ${sql.ref('tenant.billingPartnerId')} != ${testTeamId}\n )\n )`;\n}\n\nexport function whereTenantShouldBePaid(\n eb: TenantExpressionBuilder,\n {\n includePartnerTeams = false,\n }: {\n includePartnerTeams?: boolean;\n } = {}\n) {\n return eb.and([\n whereTenantActive(eb),\n eb('tenant.isOnboarding', '=', false),\n ...(includePartnerTeams\n ? []\n : [eb('tenant.calculatedIsBillable', '=', true)]),\n ]);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { Kysely } from './index';
1
+ import type { ControlPlaneKysely, Kysely } from './index';
2
2
  export declare const tenantDataRegions: readonly ["ap", "crunchy", "eu", "hostaway", "us"];
3
3
  export type TenantDataRegion = (typeof tenantDataRegions)[number];
4
4
  export type RegionEnvironment = Record<string, string | undefined>;
@@ -7,9 +7,14 @@ 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>;
14
+ type UseAsyncControlPlaneKysely = (connectionString: string, options?: {
15
+ repositoryName?: string;
16
+ probe?: true;
17
+ }) => Promise<ControlPlaneKysely>;
13
18
  export declare function useTenantDatabaseKysely(dataRegion: TenantDataRegion, repositoryName: string, env: RegionEnvironment, options?: {
14
19
  useAsyncKysely?: UseAsyncRegionalKysely;
15
20
  probe?: true;
@@ -32,6 +37,7 @@ export declare function resolveTenantKysely({ connectionId, slug, tenantId, repo
32
37
  tenantId?: string;
33
38
  repositoryName: string;
34
39
  env: RegionEnvironment;
40
+ useAsyncControlPlaneKysely?: UseAsyncControlPlaneKysely;
35
41
  useAsyncKysely?: UseAsyncRegionalKysely;
36
42
  probe?: true;
37
43
  }): Promise<TenantKysely>;
@@ -41,6 +41,7 @@ exports.resolveConfiguredTenantDataRegions = resolveConfiguredTenantDataRegions;
41
41
  exports.useTenantDatabaseKysely = useTenantDatabaseKysely;
42
42
  exports.resolveTenantKysely = resolveTenantKysely;
43
43
  exports.forEachConfiguredRegion = forEachConfiguredRegion;
44
+ const error_1 = require("./error");
44
45
  // The tenant-data-region contract lives here — the region set plus how a
45
46
  // region resolves to its database url, API base url, and how to fan a job out
46
47
  // across regions. Every runtime resolves regions through these functions;
@@ -60,7 +61,7 @@ exports.tenantDataRegions = [
60
61
  ];
61
62
  function assertTenantDataRegion(value) {
62
63
  if (!exports.tenantDataRegions.includes(value)) {
63
- throw new Error(`Missing or invalid tenant data region: ${value ?? ''}`);
64
+ throw new error_1.KyselyError('Missing or invalid tenant data region', { value });
64
65
  }
65
66
  }
66
67
  function databaseUrlEnvKey(dataRegion) {
@@ -72,7 +73,10 @@ function apiBaseUrlEnvKey(dataRegion) {
72
73
  function resolveTenantDatabaseUrl(dataRegion, env) {
73
74
  const databaseUrl = env[databaseUrlEnvKey(dataRegion)];
74
75
  if (!databaseUrl) {
75
- throw new Error(`Missing database url for ${dataRegion}`);
76
+ throw new error_1.KyselyError('Tenant database URL is missing', {
77
+ dataRegion,
78
+ key: databaseUrlEnvKey(dataRegion),
79
+ });
76
80
  }
77
81
  return databaseUrl;
78
82
  }
@@ -80,7 +84,10 @@ function resolveTenantApiBaseUrl(dataRegion, env) {
80
84
  const key = apiBaseUrlEnvKey(dataRegion);
81
85
  const baseUrl = env[key];
82
86
  if (!baseUrl) {
83
- throw new Error(`Missing ${key}`);
87
+ throw new error_1.KyselyError('Tenant API base URL is missing', {
88
+ dataRegion,
89
+ key,
90
+ });
84
91
  }
85
92
  return baseUrl;
86
93
  }
@@ -99,8 +106,9 @@ function resolveConfiguredTenantDataRegions(env) {
99
106
  }
100
107
  for (const aliased of regionsByUrl.values()) {
101
108
  if (aliased.length > 1) {
102
- throw new Error(`Tenant data regions ${aliased.join(', ')} share the same database url; ` +
103
- 'each configured region must point at a distinct database');
109
+ throw new error_1.KyselyError('Tenant data regions share the same database URL', {
110
+ dataRegions: aliased,
111
+ });
104
112
  }
105
113
  }
106
114
  return configured;
@@ -109,9 +117,14 @@ async function defaultUseAsyncKysely(connectionString, options) {
109
117
  const { useAsyncKysely } = await Promise.resolve().then(() => __importStar(require('./index')));
110
118
  return await useAsyncKysely(connectionString, options);
111
119
  }
120
+ async function defaultUseAsyncControlPlaneKysely(connectionString, options) {
121
+ const { useAsyncControlPlaneKysely } = await Promise.resolve().then(() => __importStar(require('./index')));
122
+ return await useAsyncControlPlaneKysely(connectionString, options);
123
+ }
112
124
  async function useTenantDatabaseKysely(dataRegion, repositoryName, env, options = {}) {
113
125
  const open = options.useAsyncKysely ?? defaultUseAsyncKysely;
114
126
  return await open(resolveTenantDatabaseUrl(dataRegion, env), {
127
+ dataRegion,
115
128
  repositoryName,
116
129
  probe: options.probe,
117
130
  });
@@ -129,26 +142,26 @@ async function resolveTenantKysely({ connectionId, slug, tenantId, repositoryNam
129
142
  const controlPlaneDatabaseUrl = env.CONTROL_PLANE_DATABASE_URL;
130
143
  if (!controlPlaneDatabaseUrl)
131
144
  throw new Error('CONTROL_PLANE_DATABASE_URL is required');
132
- const controlPlane = await (options.useAsyncKysely ?? defaultUseAsyncKysely)(controlPlaneDatabaseUrl, {
145
+ const controlPlane = await (options.useAsyncControlPlaneKysely ?? defaultUseAsyncControlPlaneKysely)(controlPlaneDatabaseUrl, {
133
146
  repositoryName: `${repositoryName}/control-plane`,
134
147
  probe: options.probe,
135
148
  });
136
149
  let tenant;
137
150
  try {
138
151
  const query = controlPlane
139
- .selectFrom('public.tenant')
152
+ .selectFrom('controlPlane.tenant as tenant')
140
153
  .select([
141
- 'public.tenant.id as id',
142
- 'public.tenant.slug as slug',
143
- 'public.tenant.dataRegion as dataRegion',
154
+ 'tenant.id as id',
155
+ 'tenant.slug as slug',
156
+ 'tenant.dataRegion as dataRegion',
144
157
  ]);
145
158
  tenant = await (slug
146
- ? query.where('public.tenant.slug', '=', slug)
159
+ ? query.where('tenant.slug', '=', slug)
147
160
  : connectionId
148
161
  ? query
149
- .innerJoin('public.connectionRoute', 'public.connectionRoute.tenantId', 'public.tenant.id')
150
- .where('public.connectionRoute.connectionId', '=', connectionId)
151
- : query.where('public.tenant.id', '=', tenantId)).executeTakeFirst();
162
+ .innerJoin('controlPlane.connectionRoute as connectionRoute', 'connectionRoute.tenantId', 'tenant.id')
163
+ .where('connectionRoute.connectionId', '=', connectionId)
164
+ : query.where('tenant.id', '=', tenantId)).executeTakeFirst();
152
165
  }
153
166
  finally {
154
167
  await controlPlane.destroy();
@@ -184,9 +197,9 @@ async function forEachConfiguredRegion(run, env) {
184
197
  }
185
198
  }
186
199
  if (!results.length && errors.length) {
187
- throw new Error(`All configured tenant data regions failed: ${errors
188
- .map((regionError) => `${regionError.dataRegion}: ${regionError.error}`)
189
- .join('; ')}`);
200
+ throw new error_1.KyselyError('All configured tenant data regions failed', {
201
+ errors,
202
+ });
190
203
  }
191
204
  return { results, errors };
192
205
  }
@@ -1 +1 @@
1
- {"version":3,"file":"regional.js","sourceRoot":"src/","sources":["regional.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Kysely } from './index';\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 Error(`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 Error(`Missing database url for ${dataRegion}`);\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 Error(`Missing ${key}`);\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 Error(\n `Tenant data regions ${aliased.join(', ')} share the same database url; ` +\n 'each configured region must point at a distinct database'\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\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\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 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 (options.useAsyncKysely ?? defaultUseAsyncKysely)(\n controlPlaneDatabaseUrl,\n {\n repositoryName: `${repositoryName}/control-plane`,\n probe: options.probe,\n }\n );\n let tenant: { id: string; slug: string; dataRegion: string } | undefined;\n try {\n const query = controlPlane\n .selectFrom('public.tenant')\n .select([\n 'public.tenant.id as id',\n 'public.tenant.slug as slug',\n 'public.tenant.dataRegion as dataRegion',\n ]);\n tenant = await (\n slug\n ? query.where('public.tenant.slug', '=', slug)\n : connectionId\n ? query\n .innerJoin(\n 'public.connectionRoute',\n 'public.connectionRoute.tenantId',\n 'public.tenant.id'\n )\n .where('public.connectionRoute.connectionId', '=', connectionId)\n : query.where('public.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 Error(\n `All configured tenant data regions failed: ${errors\n .map((regionError) => `${regionError.dataRegion}: ${regionError.error}`)\n .join('; ')}`\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,18 +1,30 @@
1
- import type { Kysely } from 'kysely';
2
- import { type UseLocalKyselyOptions } from '../local';
3
- import type { DB } from '../v1.generated';
1
+ import { type LocalKysely, type UseLocalKyselyOptions } from '../local';
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
+ };
4
10
  declare global {
5
- var __vrplatform_testSharedKysely: Promise<Kysely<DB>> | Kysely<DB> | undefined;
11
+ var __vrplatformSharedKysely: Promise<LocalKysely> | undefined;
6
12
  }
7
13
  /**
8
- * @deprecated Use `useLocalKyselyResource` instead.
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.
9
23
  */
10
- export declare function useTestKysely(cleanupStrategy: 'afterAll', args?: UseLocalKyselyOptions): Promise<{
11
- kysely: Kysely<DB>;
12
- }>;
13
- export declare function useTestAutoCleanupKysely(args?: UseLocalKyselyOptions): Promise<Kysely<DB>>;
14
- type ReturnType = Kysely<DB> & {
24
+ export declare function resolveSharedKysely(env: Record<string, string | undefined>): boolean;
25
+ export declare function useTestAutoCleanupKysely(args?: UseTestKyselyOptions): Promise<LocalKysely>;
26
+ type ReturnType = LocalKysely & {
15
27
  [Symbol.dispose]: () => Promise<void>;
16
28
  };
17
- export declare function useLocalKyselyResource(args?: UseLocalKyselyOptions): Promise<ReturnType>;
29
+ export declare function useLocalKyselyResource(args?: UseTestKyselyOptions): Promise<ReturnType>;
18
30
  export {};
@@ -1,46 +1,54 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useTestKysely = useTestKysely;
3
+ exports.resolveSharedKysely = resolveSharedKysely;
4
4
  exports.useTestAutoCleanupKysely = useTestAutoCleanupKysely;
5
5
  exports.useLocalKyselyResource = useLocalKyselyResource;
6
6
  const bun_test_1 = require("bun:test");
7
7
  const local_1 = require("../local");
8
8
  /**
9
- * @deprecated Use `useLocalKyselyResource` instead.
9
+ * Locally each worker process shares one database, because specs isolate by
10
+ * tenant and the faster suite is what makes running it before a push realistic.
11
+ *
12
+ * CI keeps a database per spec file. It retries nothing, so a badly scoped spec
13
+ * would surface there as a red build in an unrelated file rather than as a
14
+ * local failure the author can reproduce.
15
+ *
16
+ * VR_TEST_SHARED_KYSELY overrides either way; `isolated: true` opts a single
17
+ * call out when a spec genuinely needs two physical databases at once.
10
18
  */
11
- async function useTestKysely(cleanupStrategy, args) {
12
- const kysely = await (0, local_1.useLocalKysely)(args);
13
- if (cleanupStrategy === 'afterAll')
19
+ function resolveSharedKysely(env) {
20
+ if (env.VR_TEST_SHARED_KYSELY)
21
+ return env.VR_TEST_SHARED_KYSELY !== '0';
22
+ return !(env.CI || env.GITHUB_ACTIONS);
23
+ }
24
+ const sharedKysely = resolveSharedKysely(process.env);
25
+ function acquireKysely(args) {
26
+ if (!sharedKysely || args?.isolated)
27
+ return (0, local_1.useLocalKysely)(args);
28
+ globalThis.__vrplatformSharedKysely ?? (globalThis.__vrplatformSharedKysely = (0, local_1.useLocalKysely)(args));
29
+ return globalThis.__vrplatformSharedKysely;
30
+ }
31
+ function ownsKysely(args) {
32
+ return !sharedKysely || Boolean(args?.isolated);
33
+ }
34
+ async function useTestAutoCleanupKysely(args) {
35
+ const kysely = await acquireKysely(args);
36
+ if (ownsKysely(args)) {
14
37
  (0, bun_test_1.afterAll)(async () => {
15
38
  await kysely.destroy();
16
39
  });
17
- return {
18
- kysely,
19
- };
20
- }
21
- async function useTestAutoCleanupKysely(args) {
22
- if (process.env.VR_TEST_SHARED_KYSELY === '1') {
23
- const existing = globalThis.__vrplatform_testSharedKysely;
24
- if (!existing) {
25
- const created = (0, local_1.useLocalKysely)(args);
26
- globalThis.__vrplatform_testSharedKysely = created;
27
- return created;
28
- }
29
- return await existing;
30
40
  }
31
- const kysely = await (0, local_1.useLocalKysely)(args);
32
- (0, bun_test_1.afterAll)(async () => {
33
- await kysely.destroy();
34
- });
35
41
  return kysely;
36
42
  }
37
43
  async function useLocalKyselyResource(args) {
38
- const kysely = await (0, local_1.useLocalKysely)(args);
44
+ const kysely = await acquireKysely(args);
39
45
  return new Proxy({}, {
40
46
  get(_target, prop) {
41
47
  // somehow not working if using Symbol.dispose
42
48
  if (prop === Symbol.asyncDispose) {
43
49
  return async () => {
50
+ if (!ownsKysely(args))
51
+ return;
44
52
  await kysely.destroy();
45
53
  };
46
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"src/","sources":["test/index.ts"],"names":[],"mappings":";;AAiBA,sCAcC;AAED,4DAkBC;AAMD,wDAyBC;AAlFD,uCAAoC;AAEpC,oCAAsE;AAYtE;;GAEG;AACI,KAAK,UAAU,aAAa,CACjC,eAA2B,EAC3B,IAA4B;IAE5B,MAAM,MAAM,GAAG,MAAM,IAAA,sBAAc,EAAC,IAAI,CAAC,CAAC;IAE1C,IAAI,eAAe,KAAK,UAAU;QAChC,IAAA,mBAAQ,EAAC,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IAEL,OAAO;QACL,MAAM;KACP,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,wBAAwB,CAAC,IAA4B;IACzE,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,GAAG,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,UAAU,CAAC,6BAA6B,CAAC;QAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,IAAA,sBAAc,EAAC,IAAI,CAAC,CAAC;YACrC,UAAU,CAAC,6BAA6B,GAAG,OAAO,CAAC;YACnD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,MAAM,QAAQ,CAAC;IACxB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAA,sBAAc,EAAC,IAAI,CAAC,CAAC;IAE1C,IAAA,mBAAQ,EAAC,KAAK,IAAI,EAAE;QAClB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAMM,KAAK,UAAU,sBAAsB,CAC1C,IAA4B;IAE5B,MAAM,MAAM,GAAG,MAAM,IAAA,sBAAc,EAAC,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 type { Kysely } from 'kysely';\nimport { type UseLocalKyselyOptions, useLocalKysely } from '../local';\nimport type { DB } from '../v1.generated';\n\ndeclare global {\n // Shared Kysely instance for test processes that run multiple files in one Bun process.\n // This must be process-global to allow cross-file reuse.\n var __vrplatform_testSharedKysely:\n | Promise<Kysely<DB>>\n | Kysely<DB>\n | undefined;\n}\n\n/**\n * @deprecated Use `useLocalKyselyResource` instead.\n */\nexport async function useTestKysely(\n cleanupStrategy: 'afterAll',\n args?: UseLocalKyselyOptions\n) {\n const kysely = await useLocalKysely(args);\n\n if (cleanupStrategy === 'afterAll')\n afterAll(async () => {\n await kysely.destroy();\n });\n\n return {\n kysely,\n };\n}\n\nexport async function useTestAutoCleanupKysely(args?: UseLocalKyselyOptions) {\n if (process.env.VR_TEST_SHARED_KYSELY === '1') {\n const existing = globalThis.__vrplatform_testSharedKysely;\n if (!existing) {\n const created = useLocalKysely(args);\n globalThis.__vrplatform_testSharedKysely = created;\n return created;\n }\n return await existing;\n }\n\n const kysely = await useLocalKysely(args);\n\n afterAll(async () => {\n await kysely.destroy();\n });\n\n return kysely;\n}\n\ntype ReturnType = Kysely<DB> & {\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":";;AA+BA,kDAKC;AAcD,4DAUC;AAMD,wDA0BC;AA5FD,uCAAoC;AACpC,oCAIkB;AAelB;;;;;;;;;;GAUG;AACH,SAAgB,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,IAAA,sBAAc,EAAC,IAAI,CAAC,CAAC;IACjE,UAAU,CAAC,wBAAwB,KAAnC,UAAU,CAAC,wBAAwB,GAAK,IAAA,sBAAc,EAAC,IAAI,CAAC,EAAC;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;AAEM,KAAK,UAAU,wBAAwB,CAAC,IAA2B;IACxE,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,IAAA,mBAAQ,EAAC,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAMM,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"]}
@@ -1,7 +1,7 @@
1
- import { type ControlledTransaction, type Kysely, type Transaction } from './isomorphic';
1
+ import { type ControlledTransaction, type DatabaseKysely, type DatabaseTransaction, type Transaction } from './isomorphic';
2
2
  export type ActiveTransaction = Transaction | ControlledTransaction;
3
- export declare function isActiveTransaction(db: Kysely | ActiveTransaction): db is ActiveTransaction;
4
- export declare function startControlledTransaction(db: Kysely): Promise<import("kysely").ControlledTransaction<import("./v1.generated").DB, []>>;
3
+ export declare function isActiveTransaction<Database>(db: DatabaseKysely<Database> | DatabaseTransaction<Database>): db is DatabaseTransaction<Database>;
4
+ export declare function startControlledTransaction<Database>(db: DatabaseKysely<Database>): Promise<import("kysely").ControlledTransaction<Database, []>>;
5
5
  export declare function createTransactionSavepoint(trx: ActiveTransaction, savepointName: string): Promise<ActiveTransaction>;
6
6
  export declare function rollbackTransactionSavepoint(trx: ActiveTransaction, savepointName: string): Promise<ActiveTransaction>;
7
7
  export declare function releaseTransactionSavepoint(trx: ActiveTransaction, savepointName: string): Promise<ActiveTransaction>;
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.js","sourceRoot":"src/","sources":["transaction.ts"],"names":[],"mappings":";;AASA,kDAIC;AAED,gEAEC;AAYD,gEAMC;AAED,oEAMC;AAED,kEAMC;AAnDD,6CAKsB;AAItB,SAAgB,mBAAmB,CACjC,EAA8B;IAE9B,OAAO,EAAE,EAAE,aAAa,KAAK,IAAI,CAAC;AACpC,CAAC;AAEM,KAAK,UAAU,0BAA0B,CAAC,EAAU;IACzD,OAAO,EAAE,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,CAAC;AACzC,CAAC;AAED,uEAAuE;AACvE,kDAAkD;AAClD,SAAS,mBAAmB,CAC1B,GAAgB,EAChB,OAAoE,EACpE,aAAqB;IAErB,OAAO,gBAAG,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7D,CAAC;AAEM,KAAK,UAAU,0BAA0B,CAC9C,GAAsB,EACtB,aAAqB;IAErB,MAAM,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAC3D,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,KAAK,UAAU,4BAA4B,CAChD,GAAsB,EACtB,aAAqB;IAErB,MAAM,mBAAmB,CAAC,GAAG,EAAE,uBAAuB,EAAE,aAAa,CAAC,CAAC;IACvE,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,KAAK,UAAU,2BAA2B,CAC/C,GAAsB,EACtB,aAAqB;IAErB,MAAM,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,EAAE,aAAa,CAAC,CAAC;IACnE,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import {\n type ControlledTransaction,\n type Kysely,\n sql,\n type Transaction,\n} from './isomorphic';\n\nexport type ActiveTransaction = Transaction | ControlledTransaction;\n\nexport function isActiveTransaction(\n db: Kysely | ActiveTransaction\n): db is ActiveTransaction {\n return db?.isTransaction === true;\n}\n\nexport async function startControlledTransaction(db: Kysely) {\n return db.startTransaction().execute();\n}\n\n// Our dialect stack supports controlled transactions, but not Kysely's\n// savepoint commands consistently across drivers.\nfunction runSavepointCommand(\n trx: Transaction,\n command: 'savepoint' | 'rollback to savepoint' | 'release savepoint',\n savepointName: string\n) {\n return sql.raw(`${command} ${savepointName}`).execute(trx);\n}\n\nexport async function createTransactionSavepoint(\n trx: ActiveTransaction,\n savepointName: string\n): Promise<ActiveTransaction> {\n await runSavepointCommand(trx, 'savepoint', savepointName);\n return trx;\n}\n\nexport async function rollbackTransactionSavepoint(\n trx: ActiveTransaction,\n savepointName: string\n): Promise<ActiveTransaction> {\n await runSavepointCommand(trx, 'rollback to savepoint', savepointName);\n return trx;\n}\n\nexport async function releaseTransactionSavepoint(\n trx: ActiveTransaction,\n savepointName: string\n): Promise<ActiveTransaction> {\n await runSavepointCommand(trx, 'release savepoint', savepointName);\n return trx;\n}\n"]}
1
+ {"version":3,"file":"transaction.js","sourceRoot":"src/","sources":["transaction.ts"],"names":[],"mappings":";;AAUA,kDAIC;AAED,gEAIC;AAYD,gEAMC;AAED,oEAMC;AAED,kEAMC;AAtDD,6CAMsB;AAItB,SAAgB,mBAAmB,CACjC,EAA4D;IAE5D,OAAO,EAAE,EAAE,aAAa,KAAK,IAAI,CAAC;AACpC,CAAC;AAEM,KAAK,UAAU,0BAA0B,CAC9C,EAA4B;IAE5B,OAAO,EAAE,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,CAAC;AACzC,CAAC;AAED,uEAAuE;AACvE,kDAAkD;AAClD,SAAS,mBAAmB,CAC1B,GAAgB,EAChB,OAAoE,EACpE,aAAqB;IAErB,OAAO,gBAAG,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7D,CAAC;AAEM,KAAK,UAAU,0BAA0B,CAC9C,GAAsB,EACtB,aAAqB;IAErB,MAAM,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAC3D,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,KAAK,UAAU,4BAA4B,CAChD,GAAsB,EACtB,aAAqB;IAErB,MAAM,mBAAmB,CAAC,GAAG,EAAE,uBAAuB,EAAE,aAAa,CAAC,CAAC;IACvE,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,KAAK,UAAU,2BAA2B,CAC/C,GAAsB,EACtB,aAAqB;IAErB,MAAM,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,EAAE,aAAa,CAAC,CAAC;IACnE,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import {\n type ControlledTransaction,\n type DatabaseKysely,\n type DatabaseTransaction,\n sql,\n type Transaction,\n} from './isomorphic';\n\nexport type ActiveTransaction = Transaction | ControlledTransaction;\n\nexport function isActiveTransaction<Database>(\n db: DatabaseKysely<Database> | DatabaseTransaction<Database>\n): db is DatabaseTransaction<Database> {\n return db?.isTransaction === true;\n}\n\nexport async function startControlledTransaction<Database>(\n db: DatabaseKysely<Database>\n) {\n return db.startTransaction().execute();\n}\n\n// Our dialect stack supports controlled transactions, but not Kysely's\n// savepoint commands consistently across drivers.\nfunction runSavepointCommand(\n trx: Transaction,\n command: 'savepoint' | 'rollback to savepoint' | 'release savepoint',\n savepointName: string\n) {\n return sql.raw(`${command} ${savepointName}`).execute(trx);\n}\n\nexport async function createTransactionSavepoint(\n trx: ActiveTransaction,\n savepointName: string\n): Promise<ActiveTransaction> {\n await runSavepointCommand(trx, 'savepoint', savepointName);\n return trx;\n}\n\nexport async function rollbackTransactionSavepoint(\n trx: ActiveTransaction,\n savepointName: string\n): Promise<ActiveTransaction> {\n await runSavepointCommand(trx, 'rollback to savepoint', savepointName);\n return trx;\n}\n\nexport async function releaseTransactionSavepoint(\n trx: ActiveTransaction,\n savepointName: string\n): Promise<ActiveTransaction> {\n await runSavepointCommand(trx, 'release savepoint', savepointName);\n return trx;\n}\n"]}