@voyant-travel/db 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +60 -0
- package/dist/aggregate-snapshots.d.ts +66 -0
- package/dist/aggregate-snapshots.d.ts.map +1 -0
- package/dist/aggregate-snapshots.js +110 -0
- package/dist/aggregate-snapshots.js.map +1 -0
- package/dist/columns/collection.d.ts +37 -0
- package/dist/columns/collection.d.ts.map +1 -0
- package/dist/columns/collection.js +44 -0
- package/dist/columns/collection.js.map +1 -0
- package/dist/columns/cruise.d.ts +26 -0
- package/dist/columns/cruise.d.ts.map +1 -0
- package/dist/columns/cruise.js +31 -0
- package/dist/columns/cruise.js.map +1 -0
- package/dist/columns/departure-sub-tables.d.ts +179 -0
- package/dist/columns/departure-sub-tables.d.ts.map +1 -0
- package/dist/columns/departure-sub-tables.js +214 -0
- package/dist/columns/departure-sub-tables.js.map +1 -0
- package/dist/columns/departure.d.ts +20 -0
- package/dist/columns/departure.d.ts.map +1 -0
- package/dist/columns/departure.js +23 -0
- package/dist/columns/departure.js.map +1 -0
- package/dist/columns/destinations.d.ts +21 -0
- package/dist/columns/destinations.d.ts.map +1 -0
- package/dist/columns/destinations.js +24 -0
- package/dist/columns/destinations.js.map +1 -0
- package/dist/columns/index.d.ts +31 -0
- package/dist/columns/index.d.ts.map +1 -0
- package/dist/columns/index.js +57 -0
- package/dist/columns/index.js.map +1 -0
- package/dist/columns/itinerary-sub-tables.d.ts +177 -0
- package/dist/columns/itinerary-sub-tables.d.ts.map +1 -0
- package/dist/columns/itinerary-sub-tables.js +122 -0
- package/dist/columns/itinerary-sub-tables.js.map +1 -0
- package/dist/columns/itinerary.d.ts +17 -0
- package/dist/columns/itinerary.d.ts.map +1 -0
- package/dist/columns/itinerary.js +20 -0
- package/dist/columns/itinerary.js.map +1 -0
- package/dist/columns/lodging.d.ts +143 -0
- package/dist/columns/lodging.d.ts.map +1 -0
- package/dist/columns/lodging.js +164 -0
- package/dist/columns/lodging.js.map +1 -0
- package/dist/columns/offers.d.ts +31 -0
- package/dist/columns/offers.d.ts.map +1 -0
- package/dist/columns/offers.js +43 -0
- package/dist/columns/offers.js.map +1 -0
- package/dist/columns/pricing.d.ts +60 -0
- package/dist/columns/pricing.d.ts.map +1 -0
- package/dist/columns/pricing.js +71 -0
- package/dist/columns/pricing.js.map +1 -0
- package/dist/columns/product-accommodation.d.ts +99 -0
- package/dist/columns/product-accommodation.d.ts.map +1 -0
- package/dist/columns/product-accommodation.js +65 -0
- package/dist/columns/product-accommodation.js.map +1 -0
- package/dist/columns/product-addons.d.ts +18 -0
- package/dist/columns/product-addons.d.ts.map +1 -0
- package/dist/columns/product-addons.js +21 -0
- package/dist/columns/product-addons.js.map +1 -0
- package/dist/columns/product-availability-states.d.ts +65 -0
- package/dist/columns/product-availability-states.d.ts.map +1 -0
- package/dist/columns/product-availability-states.js +81 -0
- package/dist/columns/product-availability-states.js.map +1 -0
- package/dist/columns/product-availability.d.ts +21 -0
- package/dist/columns/product-availability.d.ts.map +1 -0
- package/dist/columns/product-availability.js +24 -0
- package/dist/columns/product-availability.js.map +1 -0
- package/dist/columns/product-booking-rules.d.ts +45 -0
- package/dist/columns/product-booking-rules.d.ts.map +1 -0
- package/dist/columns/product-booking-rules.js +55 -0
- package/dist/columns/product-booking-rules.js.map +1 -0
- package/dist/columns/product-category-assignments.d.ts +17 -0
- package/dist/columns/product-category-assignments.d.ts.map +1 -0
- package/dist/columns/product-category-assignments.js +20 -0
- package/dist/columns/product-category-assignments.js.map +1 -0
- package/dist/columns/product-extensions.d.ts +24 -0
- package/dist/columns/product-extensions.d.ts.map +1 -0
- package/dist/columns/product-extensions.js +27 -0
- package/dist/columns/product-extensions.js.map +1 -0
- package/dist/columns/product-media.d.ts +19 -0
- package/dist/columns/product-media.d.ts.map +1 -0
- package/dist/columns/product-media.js +22 -0
- package/dist/columns/product-media.js.map +1 -0
- package/dist/columns/product-overrides.d.ts +19 -0
- package/dist/columns/product-overrides.d.ts.map +1 -0
- package/dist/columns/product-overrides.js +22 -0
- package/dist/columns/product-overrides.js.map +1 -0
- package/dist/columns/product-preferences.d.ts +51 -0
- package/dist/columns/product-preferences.d.ts.map +1 -0
- package/dist/columns/product-preferences.js +59 -0
- package/dist/columns/product-preferences.js.map +1 -0
- package/dist/columns/product-publish-settings.d.ts +18 -0
- package/dist/columns/product-publish-settings.d.ts.map +1 -0
- package/dist/columns/product-publish-settings.js +21 -0
- package/dist/columns/product-publish-settings.js.map +1 -0
- package/dist/columns/product-rate-plans.d.ts +28 -0
- package/dist/columns/product-rate-plans.d.ts.map +1 -0
- package/dist/columns/product-rate-plans.js +33 -0
- package/dist/columns/product-rate-plans.js.map +1 -0
- package/dist/columns/product-translations.d.ts +24 -0
- package/dist/columns/product-translations.d.ts.map +1 -0
- package/dist/columns/product-translations.js +27 -0
- package/dist/columns/product-translations.js.map +1 -0
- package/dist/columns/product-versions.d.ts +19 -0
- package/dist/columns/product-versions.d.ts.map +1 -0
- package/dist/columns/product-versions.js +22 -0
- package/dist/columns/product-versions.js.map +1 -0
- package/dist/columns/product-visibility.d.ts +16 -0
- package/dist/columns/product-visibility.d.ts.map +1 -0
- package/dist/columns/product-visibility.js +19 -0
- package/dist/columns/product-visibility.js.map +1 -0
- package/dist/columns/product.d.ts +56 -0
- package/dist/columns/product.d.ts.map +1 -0
- package/dist/columns/product.js +44 -0
- package/dist/columns/product.js.map +1 -0
- package/dist/columns/room.d.ts +117 -0
- package/dist/columns/room.d.ts.map +1 -0
- package/dist/columns/room.js +86 -0
- package/dist/columns/room.js.map +1 -0
- package/dist/columns/ship.d.ts +22 -0
- package/dist/columns/ship.d.ts.map +1 -0
- package/dist/columns/ship.js +25 -0
- package/dist/columns/ship.js.map +1 -0
- package/dist/columns/tags.d.ts +33 -0
- package/dist/columns/tags.d.ts.map +1 -0
- package/dist/columns/tags.js +38 -0
- package/dist/columns/tags.js.map +1 -0
- package/dist/columns/transport.d.ts +53 -0
- package/dist/columns/transport.d.ts.map +1 -0
- package/dist/columns/transport.js +62 -0
- package/dist/columns/transport.js.map +1 -0
- package/dist/connection-config.d.ts +101 -0
- package/dist/connection-config.d.ts.map +1 -0
- package/dist/connection-config.js +106 -0
- package/dist/connection-config.js.map +1 -0
- package/dist/crud.d.ts +87 -0
- package/dist/crud.d.ts.map +1 -0
- package/dist/crud.js +190 -0
- package/dist/crud.js.map +1 -0
- package/dist/helpers.d.ts +33 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +49 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +5 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/typeid-column.d.ts +75 -0
- package/dist/lib/typeid-column.d.ts.map +1 -0
- package/dist/lib/typeid-column.js +92 -0
- package/dist/lib/typeid-column.js.map +1 -0
- package/dist/lib/typeid-core.d.ts +36 -0
- package/dist/lib/typeid-core.d.ts.map +1 -0
- package/dist/lib/typeid-core.js +67 -0
- package/dist/lib/typeid-core.js.map +1 -0
- package/dist/lib/typeid-prefixes.d.ts +342 -0
- package/dist/lib/typeid-prefixes.d.ts.map +1 -0
- package/dist/lib/typeid-prefixes.js +379 -0
- package/dist/lib/typeid-prefixes.js.map +1 -0
- package/dist/lib/typeid-schemas.d.ts +206 -0
- package/dist/lib/typeid-schemas.d.ts.map +1 -0
- package/dist/lib/typeid-schemas.js +207 -0
- package/dist/lib/typeid-schemas.js.map +1 -0
- package/dist/lib/typeid-zod.d.ts +16 -0
- package/dist/lib/typeid-zod.d.ts.map +1 -0
- package/dist/lib/typeid-zod.js +29 -0
- package/dist/lib/typeid-zod.js.map +1 -0
- package/dist/lib/typeid.d.ts +2 -0
- package/dist/lib/typeid.d.ts.map +1 -0
- package/dist/lib/typeid.js +6 -0
- package/dist/lib/typeid.js.map +1 -0
- package/dist/lifecycle.d.ts +24 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +30 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/links.d.ts +22 -0
- package/dist/links.d.ts.map +1 -0
- package/dist/links.js +281 -0
- package/dist/links.js.map +1 -0
- package/dist/operators.d.ts +9 -0
- package/dist/operators.d.ts.map +1 -0
- package/dist/operators.js +9 -0
- package/dist/operators.js.map +1 -0
- package/dist/outbox.d.ts +87 -0
- package/dist/outbox.d.ts.map +1 -0
- package/dist/outbox.js +245 -0
- package/dist/outbox.js.map +1 -0
- package/dist/primitives/catalog-schemas.d.ts +101 -0
- package/dist/primitives/catalog-schemas.d.ts.map +1 -0
- package/dist/primitives/catalog-schemas.js +69 -0
- package/dist/primitives/catalog-schemas.js.map +1 -0
- package/dist/primitives/catalog.d.ts +47 -0
- package/dist/primitives/catalog.d.ts.map +1 -0
- package/dist/primitives/catalog.js +94 -0
- package/dist/primitives/catalog.js.map +1 -0
- package/dist/primitives/index.d.ts +4 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +4 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/primitives/offers.d.ts +224 -0
- package/dist/primitives/offers.d.ts.map +1 -0
- package/dist/primitives/offers.js +132 -0
- package/dist/primitives/offers.js.map +1 -0
- package/dist/queries/index.d.ts +18 -0
- package/dist/queries/index.d.ts.map +1 -0
- package/dist/queries/index.js +30 -0
- package/dist/queries/index.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +5 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/locks.d.ts +5 -0
- package/dist/runtime/locks.d.ts.map +1 -0
- package/dist/runtime/locks.js +36 -0
- package/dist/runtime/locks.js.map +1 -0
- package/dist/schema/00_ensure_schemas.d.ts +5 -0
- package/dist/schema/00_ensure_schemas.d.ts.map +1 -0
- package/dist/schema/00_ensure_schemas.js +6 -0
- package/dist/schema/00_ensure_schemas.js.map +1 -0
- package/dist/schema/aggregate-snapshots.d.ts +97 -0
- package/dist/schema/aggregate-snapshots.d.ts.map +1 -0
- package/dist/schema/aggregate-snapshots.js +27 -0
- package/dist/schema/aggregate-snapshots.js.map +1 -0
- package/dist/schema/iam/apikey.d.ts +396 -0
- package/dist/schema/iam/apikey.d.ts.map +1 -0
- package/dist/schema/iam/apikey.js +41 -0
- package/dist/schema/iam/apikey.js.map +1 -0
- package/dist/schema/iam/auth.d.ts +1026 -0
- package/dist/schema/iam/auth.d.ts.map +1 -0
- package/dist/schema/iam/auth.js +138 -0
- package/dist/schema/iam/auth.js.map +1 -0
- package/dist/schema/iam/cloud_auth.d.ts +446 -0
- package/dist/schema/iam/cloud_auth.d.ts.map +1 -0
- package/dist/schema/iam/cloud_auth.js +46 -0
- package/dist/schema/iam/cloud_auth.js.map +1 -0
- package/dist/schema/iam/index.d.ts +8 -0
- package/dist/schema/iam/index.d.ts.map +1 -0
- package/dist/schema/iam/index.js +8 -0
- package/dist/schema/iam/index.js.map +1 -0
- package/dist/schema/iam/invitations.d.ts +173 -0
- package/dist/schema/iam/invitations.d.ts.map +1 -0
- package/dist/schema/iam/invitations.js +27 -0
- package/dist/schema/iam/invitations.js.map +1 -0
- package/dist/schema/iam/kms.d.ts +53 -0
- package/dist/schema/iam/kms.d.ts.map +1 -0
- package/dist/schema/iam/kms.js +40 -0
- package/dist/schema/iam/kms.js.map +1 -0
- package/dist/schema/iam/roles.d.ts +12 -0
- package/dist/schema/iam/roles.d.ts.map +1 -0
- package/dist/schema/iam/roles.js +12 -0
- package/dist/schema/iam/roles.js.map +1 -0
- package/dist/schema/iam/user_profiles.d.ts +442 -0
- package/dist/schema/iam/user_profiles.d.ts.map +1 -0
- package/dist/schema/iam/user_profiles.js +125 -0
- package/dist/schema/iam/user_profiles.js.map +1 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/infra/domains.d.ts +609 -0
- package/dist/schema/infra/domains.d.ts.map +1 -0
- package/dist/schema/infra/domains.js +108 -0
- package/dist/schema/infra/domains.js.map +1 -0
- package/dist/schema/infra/email_domain_records.d.ts +255 -0
- package/dist/schema/infra/email_domain_records.d.ts.map +1 -0
- package/dist/schema/infra/email_domain_records.js +65 -0
- package/dist/schema/infra/email_domain_records.js.map +1 -0
- package/dist/schema/infra/event_outbox.d.ts +232 -0
- package/dist/schema/infra/event_outbox.d.ts.map +1 -0
- package/dist/schema/infra/event_outbox.js +59 -0
- package/dist/schema/infra/event_outbox.js.map +1 -0
- package/dist/schema/infra/idempotency_keys.d.ts +186 -0
- package/dist/schema/infra/idempotency_keys.d.ts.map +1 -0
- package/dist/schema/infra/idempotency_keys.js +40 -0
- package/dist/schema/infra/idempotency_keys.js.map +1 -0
- package/dist/schema/infra/index.d.ts +9 -0
- package/dist/schema/infra/index.d.ts.map +1 -0
- package/dist/schema/infra/index.js +10 -0
- package/dist/schema/infra/index.js.map +1 -0
- package/dist/schema/infra/public_document_delivery_grants.d.ts +356 -0
- package/dist/schema/infra/public_document_delivery_grants.d.ts.map +1 -0
- package/dist/schema/infra/public_document_delivery_grants.js +36 -0
- package/dist/schema/infra/public_document_delivery_grants.js.map +1 -0
- package/dist/schema/infra/rate_limit_buckets.d.ts +138 -0
- package/dist/schema/infra/rate_limit_buckets.d.ts.map +1 -0
- package/dist/schema/infra/rate_limit_buckets.js +52 -0
- package/dist/schema/infra/rate_limit_buckets.js.map +1 -0
- package/dist/schema/infra/webhook_deliveries.d.ts +572 -0
- package/dist/schema/infra/webhook_deliveries.d.ts.map +1 -0
- package/dist/schema/infra/webhook_deliveries.js +136 -0
- package/dist/schema/infra/webhook_deliveries.js.map +1 -0
- package/dist/schema/infra/webhook_subscriptions.d.ts +284 -0
- package/dist/schema/infra/webhook_subscriptions.d.ts.map +1 -0
- package/dist/schema/infra/webhook_subscriptions.js +64 -0
- package/dist/schema/infra/webhook_subscriptions.js.map +1 -0
- package/dist/schema/infra/write_intents.d.ts +185 -0
- package/dist/schema/infra/write_intents.d.ts.map +1 -0
- package/dist/schema/infra/write_intents.js +50 -0
- package/dist/schema/infra/write_intents.js.map +1 -0
- package/dist/schema/voyant/bookings.d.ts +2 -0
- package/dist/schema/voyant/bookings.d.ts.map +1 -0
- package/dist/schema/voyant/bookings.js +2 -0
- package/dist/schema/voyant/bookings.js.map +1 -0
- package/dist/schema/voyant/finance.d.ts +2 -0
- package/dist/schema/voyant/finance.d.ts.map +1 -0
- package/dist/schema/voyant/finance.js +2 -0
- package/dist/schema/voyant/finance.js.map +1 -0
- package/dist/test-utils.d.ts +17 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +56 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/transaction-capability.d.ts +11 -0
- package/dist/transaction-capability.d.ts.map +1 -0
- package/dist/transaction-capability.js +17 -0
- package/dist/transaction-capability.js.map +1 -0
- package/dist/transaction.d.ts +31 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +72 -0
- package/dist/transaction.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +19 -0
- package/dist/utils.js.map +1 -0
- package/dist/write-intents.d.ts +51 -0
- package/dist/write-intents.d.ts.map +1 -0
- package/dist/write-intents.js +95 -0
- package/dist/write-intents.js.map +1 -0
- package/package.json +306 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async write intents (RFC voyant#1687 Phase 3.2 — the queued write
|
|
3
|
+
* pipeline's result mailbox).
|
|
4
|
+
*
|
|
5
|
+
* An intent is "a write the caller asked for but didn't wait for": the
|
|
6
|
+
* route validates the payload, stores it here, durably emits a
|
|
7
|
+
* `<kind>.requested` event (transactional outbox), and answers
|
|
8
|
+
* **202 + a status URL**. The outbox delivers the event to the intent's
|
|
9
|
+
* handler — with the outbox's at-least-once retries, backoff, and
|
|
10
|
+
* dead-lettering — and the handler writes the outcome back onto the
|
|
11
|
+
* row. Under a payday spike, callers get instant 202s and the work
|
|
12
|
+
* drains at the outbox's controlled pace instead of thundering-herding
|
|
13
|
+
* the booking transaction.
|
|
14
|
+
*
|
|
15
|
+
* Dedup: `idempotency_key` is unique — a retried POST with the same key
|
|
16
|
+
* returns the SAME intent rather than enqueueing twice.
|
|
17
|
+
*
|
|
18
|
+
* Status semantics: `pending` until a handler settles it. Handlers
|
|
19
|
+
* distinguish FINAL business outcomes (capacity conflict → `failed`
|
|
20
|
+
* with a result payload, never retried) from infra errors (thrown →
|
|
21
|
+
* the outbox retries). A stale sweep fails intents whose event
|
|
22
|
+
* dead-lettered.
|
|
23
|
+
*/
|
|
24
|
+
export declare const writeIntentsTable: Omit<import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
25
|
+
name: "write_intents";
|
|
26
|
+
schema: undefined;
|
|
27
|
+
columns: {
|
|
28
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
29
|
+
name: string;
|
|
30
|
+
tableName: "write_intents";
|
|
31
|
+
dataType: "string";
|
|
32
|
+
columnType: "PgText";
|
|
33
|
+
data: string;
|
|
34
|
+
driverParam: string;
|
|
35
|
+
notNull: true;
|
|
36
|
+
hasDefault: true;
|
|
37
|
+
isPrimaryKey: true;
|
|
38
|
+
isAutoincrement: false;
|
|
39
|
+
hasRuntimeDefault: true;
|
|
40
|
+
enumValues: [string, ...string[]];
|
|
41
|
+
baseColumn: never;
|
|
42
|
+
identity: undefined;
|
|
43
|
+
generated: undefined;
|
|
44
|
+
}, {}, {}>;
|
|
45
|
+
kind: import("drizzle-orm/pg-core").PgColumn<{
|
|
46
|
+
name: "kind";
|
|
47
|
+
tableName: "write_intents";
|
|
48
|
+
dataType: "string";
|
|
49
|
+
columnType: "PgText";
|
|
50
|
+
data: string;
|
|
51
|
+
driverParam: string;
|
|
52
|
+
notNull: true;
|
|
53
|
+
hasDefault: false;
|
|
54
|
+
isPrimaryKey: false;
|
|
55
|
+
isAutoincrement: false;
|
|
56
|
+
hasRuntimeDefault: false;
|
|
57
|
+
enumValues: [string, ...string[]];
|
|
58
|
+
baseColumn: never;
|
|
59
|
+
identity: undefined;
|
|
60
|
+
generated: undefined;
|
|
61
|
+
}, {}, {}>;
|
|
62
|
+
payload: import("drizzle-orm/pg-core").PgColumn<{
|
|
63
|
+
name: "payload";
|
|
64
|
+
tableName: "write_intents";
|
|
65
|
+
dataType: "json";
|
|
66
|
+
columnType: "PgJsonb";
|
|
67
|
+
data: unknown;
|
|
68
|
+
driverParam: unknown;
|
|
69
|
+
notNull: true;
|
|
70
|
+
hasDefault: false;
|
|
71
|
+
isPrimaryKey: false;
|
|
72
|
+
isAutoincrement: false;
|
|
73
|
+
hasRuntimeDefault: false;
|
|
74
|
+
enumValues: undefined;
|
|
75
|
+
baseColumn: never;
|
|
76
|
+
identity: undefined;
|
|
77
|
+
generated: undefined;
|
|
78
|
+
}, {}, {}>;
|
|
79
|
+
idempotencyKey: import("drizzle-orm/pg-core").PgColumn<{
|
|
80
|
+
name: "idempotency_key";
|
|
81
|
+
tableName: "write_intents";
|
|
82
|
+
dataType: "string";
|
|
83
|
+
columnType: "PgText";
|
|
84
|
+
data: string;
|
|
85
|
+
driverParam: string;
|
|
86
|
+
notNull: true;
|
|
87
|
+
hasDefault: false;
|
|
88
|
+
isPrimaryKey: false;
|
|
89
|
+
isAutoincrement: false;
|
|
90
|
+
hasRuntimeDefault: false;
|
|
91
|
+
enumValues: [string, ...string[]];
|
|
92
|
+
baseColumn: never;
|
|
93
|
+
identity: undefined;
|
|
94
|
+
generated: undefined;
|
|
95
|
+
}, {}, {}>;
|
|
96
|
+
status: import("drizzle-orm/pg-core").PgColumn<{
|
|
97
|
+
name: "status";
|
|
98
|
+
tableName: "write_intents";
|
|
99
|
+
dataType: "string";
|
|
100
|
+
columnType: "PgText";
|
|
101
|
+
data: "failed" | "pending" | "succeeded";
|
|
102
|
+
driverParam: string;
|
|
103
|
+
notNull: true;
|
|
104
|
+
hasDefault: true;
|
|
105
|
+
isPrimaryKey: false;
|
|
106
|
+
isAutoincrement: false;
|
|
107
|
+
hasRuntimeDefault: false;
|
|
108
|
+
enumValues: ["pending", "succeeded", "failed"];
|
|
109
|
+
baseColumn: never;
|
|
110
|
+
identity: undefined;
|
|
111
|
+
generated: undefined;
|
|
112
|
+
}, {}, {}>;
|
|
113
|
+
result: import("drizzle-orm/pg-core").PgColumn<{
|
|
114
|
+
name: "result";
|
|
115
|
+
tableName: "write_intents";
|
|
116
|
+
dataType: "json";
|
|
117
|
+
columnType: "PgJsonb";
|
|
118
|
+
data: unknown;
|
|
119
|
+
driverParam: unknown;
|
|
120
|
+
notNull: false;
|
|
121
|
+
hasDefault: false;
|
|
122
|
+
isPrimaryKey: false;
|
|
123
|
+
isAutoincrement: false;
|
|
124
|
+
hasRuntimeDefault: false;
|
|
125
|
+
enumValues: undefined;
|
|
126
|
+
baseColumn: never;
|
|
127
|
+
identity: undefined;
|
|
128
|
+
generated: undefined;
|
|
129
|
+
}, {}, {}>;
|
|
130
|
+
error: import("drizzle-orm/pg-core").PgColumn<{
|
|
131
|
+
name: "error";
|
|
132
|
+
tableName: "write_intents";
|
|
133
|
+
dataType: "string";
|
|
134
|
+
columnType: "PgText";
|
|
135
|
+
data: string;
|
|
136
|
+
driverParam: string;
|
|
137
|
+
notNull: false;
|
|
138
|
+
hasDefault: false;
|
|
139
|
+
isPrimaryKey: false;
|
|
140
|
+
isAutoincrement: false;
|
|
141
|
+
hasRuntimeDefault: false;
|
|
142
|
+
enumValues: [string, ...string[]];
|
|
143
|
+
baseColumn: never;
|
|
144
|
+
identity: undefined;
|
|
145
|
+
generated: undefined;
|
|
146
|
+
}, {}, {}>;
|
|
147
|
+
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
148
|
+
name: "created_at";
|
|
149
|
+
tableName: "write_intents";
|
|
150
|
+
dataType: "date";
|
|
151
|
+
columnType: "PgTimestamp";
|
|
152
|
+
data: Date;
|
|
153
|
+
driverParam: string;
|
|
154
|
+
notNull: true;
|
|
155
|
+
hasDefault: true;
|
|
156
|
+
isPrimaryKey: false;
|
|
157
|
+
isAutoincrement: false;
|
|
158
|
+
hasRuntimeDefault: false;
|
|
159
|
+
enumValues: undefined;
|
|
160
|
+
baseColumn: never;
|
|
161
|
+
identity: undefined;
|
|
162
|
+
generated: undefined;
|
|
163
|
+
}, {}, {}>;
|
|
164
|
+
completedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
165
|
+
name: "completed_at";
|
|
166
|
+
tableName: "write_intents";
|
|
167
|
+
dataType: "date";
|
|
168
|
+
columnType: "PgTimestamp";
|
|
169
|
+
data: Date;
|
|
170
|
+
driverParam: string;
|
|
171
|
+
notNull: false;
|
|
172
|
+
hasDefault: false;
|
|
173
|
+
isPrimaryKey: false;
|
|
174
|
+
isAutoincrement: false;
|
|
175
|
+
hasRuntimeDefault: false;
|
|
176
|
+
enumValues: undefined;
|
|
177
|
+
baseColumn: never;
|
|
178
|
+
identity: undefined;
|
|
179
|
+
generated: undefined;
|
|
180
|
+
}, {}, {}>;
|
|
181
|
+
};
|
|
182
|
+
dialect: "pg";
|
|
183
|
+
}>, "enableRLS">;
|
|
184
|
+
export type WriteIntentRow = typeof writeIntentsTable.$inferSelect;
|
|
185
|
+
//# sourceMappingURL=write_intents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write_intents.d.ts","sourceRoot":"","sources":["../../../src/schema/infra/write_intents.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA0BjB,CAAA;AAEb,MAAM,MAAM,cAAc,GAAG,OAAO,iBAAiB,CAAC,YAAY,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
import { index, jsonb, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
|
|
3
|
+
import { typeId } from "../../lib/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Async write intents (RFC voyant#1687 Phase 3.2 — the queued write
|
|
6
|
+
* pipeline's result mailbox).
|
|
7
|
+
*
|
|
8
|
+
* An intent is "a write the caller asked for but didn't wait for": the
|
|
9
|
+
* route validates the payload, stores it here, durably emits a
|
|
10
|
+
* `<kind>.requested` event (transactional outbox), and answers
|
|
11
|
+
* **202 + a status URL**. The outbox delivers the event to the intent's
|
|
12
|
+
* handler — with the outbox's at-least-once retries, backoff, and
|
|
13
|
+
* dead-lettering — and the handler writes the outcome back onto the
|
|
14
|
+
* row. Under a payday spike, callers get instant 202s and the work
|
|
15
|
+
* drains at the outbox's controlled pace instead of thundering-herding
|
|
16
|
+
* the booking transaction.
|
|
17
|
+
*
|
|
18
|
+
* Dedup: `idempotency_key` is unique — a retried POST with the same key
|
|
19
|
+
* returns the SAME intent rather than enqueueing twice.
|
|
20
|
+
*
|
|
21
|
+
* Status semantics: `pending` until a handler settles it. Handlers
|
|
22
|
+
* distinguish FINAL business outcomes (capacity conflict → `failed`
|
|
23
|
+
* with a result payload, never retried) from infra errors (thrown →
|
|
24
|
+
* the outbox retries). A stale sweep fails intents whose event
|
|
25
|
+
* dead-lettered.
|
|
26
|
+
*/
|
|
27
|
+
export const writeIntentsTable = pgTable("write_intents", {
|
|
28
|
+
id: typeId("write_intents"),
|
|
29
|
+
/** Handler routing key, e.g. "storefront.booking.bootstrap". */
|
|
30
|
+
kind: text("kind").notNull(),
|
|
31
|
+
/** The validated request payload the handler will execute. */
|
|
32
|
+
payload: jsonb("payload").notNull(),
|
|
33
|
+
/** Client-supplied (Idempotency-Key) or generated. Unique. */
|
|
34
|
+
idempotencyKey: text("idempotency_key").notNull(),
|
|
35
|
+
status: text("status", { enum: ["pending", "succeeded", "failed"] })
|
|
36
|
+
.notNull()
|
|
37
|
+
.default("pending"),
|
|
38
|
+
/** Handler outcome payload (success result OR final-failure detail). */
|
|
39
|
+
result: jsonb("result"),
|
|
40
|
+
/** Infra/dead-letter error detail for failed intents. */
|
|
41
|
+
error: text("error"),
|
|
42
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
43
|
+
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
44
|
+
}, (table) => [
|
|
45
|
+
uniqueIndex("write_intents_idempotency_key_uniq").on(table.idempotencyKey),
|
|
46
|
+
// Stale-sweep working set; partial keeps it tiny.
|
|
47
|
+
// agent-quality: raw-sql reviewed -- owner: db; dynamic SQL interpolation uses Drizzle parameter binding or vetted SQL identifiers.
|
|
48
|
+
index("write_intents_pending_idx").on(table.createdAt).where(sql `${table.status} = 'pending'`),
|
|
49
|
+
]).enableRLS();
|
|
50
|
+
//# sourceMappingURL=write_intents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write_intents.js","sourceRoot":"","sources":["../../../src/schema/infra/write_intents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEzF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAE3C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CACtC,eAAe,EACf;IACE,EAAE,EAAE,MAAM,CAAC,eAAe,CAAC;IAC3B,gEAAgE;IAChE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,8DAA8D;IAC9D,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACnC,8DAA8D;IAC9D,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC;SACjE,OAAO,EAAE;SACT,OAAO,CAAC,SAAS,CAAC;IACrB,wEAAwE;IACxE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;IACvB,yDAAyD;IACzD,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;IACjF,WAAW,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;CAC/D,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,WAAW,CAAC,oCAAoC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;IAC1E,kDAAkD;IAClD,oIAAoI;IACpI,KAAK,CAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAA,GAAG,KAAK,CAAC,MAAM,cAAc,CAAC;CAC/F,CACF,CAAC,SAAS,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bookings.d.ts","sourceRoot":"","sources":["../../../src/schema/voyant/bookings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bookings.js","sourceRoot":"","sources":["../../../src/schema/voyant/bookings.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finance.d.ts","sourceRoot":"","sources":["../../../src/schema/voyant/finance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finance.js","sourceRoot":"","sources":["../../../src/schema/voyant/finance.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a database client connected to the test database.
|
|
4
|
+
* Requires the test Postgres instance from `docker-compose.test.yml`.
|
|
5
|
+
*
|
|
6
|
+
* Always uses the Node.js adapter (postgres.js) since tests run in Node.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createTestDb(): PostgresJsDatabase;
|
|
9
|
+
/**
|
|
10
|
+
* Closes the shared test database client for the current process.
|
|
11
|
+
*/
|
|
12
|
+
export declare function closeTestDb(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Truncates all non-system tables in the test database.
|
|
15
|
+
*/
|
|
16
|
+
export declare function cleanupTestDb(db: PostgresJsDatabase): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AA4BjE;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,kBAAkB,CAcjD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAKjD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
import { createDbClient } from "./index.js";
|
|
3
|
+
const TEST_DB_PORT = process.env.TEST_DATABASE_PORT ?? "5436";
|
|
4
|
+
const TEST_DB_NAME = "voyant_test";
|
|
5
|
+
const TEST_DB_USER = "test";
|
|
6
|
+
const TEST_DB_PASSWORD = "test";
|
|
7
|
+
function buildDefaultTestDbUrl(port) {
|
|
8
|
+
const url = new URL("postgres://localhost");
|
|
9
|
+
url.port = port;
|
|
10
|
+
url.pathname = `/${TEST_DB_NAME}`;
|
|
11
|
+
url.username = TEST_DB_USER;
|
|
12
|
+
url.password = TEST_DB_PASSWORD;
|
|
13
|
+
return url.toString();
|
|
14
|
+
}
|
|
15
|
+
const TEST_DB_URL = process.env.TEST_DATABASE_URL ?? buildDefaultTestDbUrl(TEST_DB_PORT);
|
|
16
|
+
let testDbSingleton = null;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a database client connected to the test database.
|
|
19
|
+
* Requires the test Postgres instance from `docker-compose.test.yml`.
|
|
20
|
+
*
|
|
21
|
+
* Always uses the Node.js adapter (postgres.js) since tests run in Node.
|
|
22
|
+
*/
|
|
23
|
+
export function createTestDb() {
|
|
24
|
+
if (!testDbSingleton) {
|
|
25
|
+
testDbSingleton = createDbClient(TEST_DB_URL, {
|
|
26
|
+
adapter: "node",
|
|
27
|
+
nodeMaxConnections: 1,
|
|
28
|
+
// Production timeout defaults don't apply to test infrastructure:
|
|
29
|
+
// cleanupTestDb's TRUNCATE over the full ~350-table schema can
|
|
30
|
+
// exceed the 10s statement_timeout on a cold Postgres, killing
|
|
31
|
+
// every integration suite's setup.
|
|
32
|
+
timeouts: { statementMs: false, queryMs: false, connectMs: false },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return testDbSingleton;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Closes the shared test database client for the current process.
|
|
39
|
+
*/
|
|
40
|
+
export async function closeTestDb() {
|
|
41
|
+
const db = testDbSingleton;
|
|
42
|
+
testDbSingleton = null;
|
|
43
|
+
await db?.$client?.end?.({ timeout: 0 });
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Truncates all non-system tables in the test database.
|
|
47
|
+
*/
|
|
48
|
+
export async function cleanupTestDb(db) {
|
|
49
|
+
const result = await db.execute(sql `SELECT tablename FROM pg_tables WHERE schemaname = 'public'`);
|
|
50
|
+
const tables = result;
|
|
51
|
+
if (tables.length > 0) {
|
|
52
|
+
const names = tables.map((r) => `"${r.tablename}"`).join(", ");
|
|
53
|
+
await db.execute(sql.raw(`TRUNCATE ${names} CASCADE`));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=test-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAA;AAC7D,MAAM,YAAY,GAAG,aAAa,CAAA;AAClC,MAAM,YAAY,GAAG,MAAM,CAAA;AAC3B,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAE/B,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,CAAA;IAC3C,GAAG,CAAC,IAAI,GAAG,IAAI,CAAA;IACf,GAAG,CAAC,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAA;IACjC,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAA;IAC3B,GAAG,CAAC,QAAQ,GAAG,gBAAgB,CAAA;IAC/B,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC;AAED,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,qBAAqB,CAAC,YAAY,CAAC,CAAA;AAQxF,IAAI,eAAe,GAAwC,IAAI,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,cAAc,CAAC,WAAW,EAAE;YAC5C,OAAO,EAAE,MAAM;YACf,kBAAkB,EAAE,CAAC;YACrB,kEAAkE;YAClE,+DAA+D;YAC/D,+DAA+D;YAC/D,mCAAmC;YACnC,QAAQ,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE;SACnE,CAAiC,CAAA;IACpC,CAAC;IAED,OAAO,eAAe,CAAA;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,EAAE,GAAG,eAAe,CAAA;IAC1B,eAAe,GAAG,IAAI,CAAA;IAEtB,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAsB;IACxD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAC7B,GAAG,CAAA,6DAA6D,CACjE,CAAA;IAED,MAAM,MAAM,GAAG,MAAiC,CAAA;IAChD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9D,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,CAAA;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const VOYANT_DB_SUPPORTS_TRANSACTIONS: unique symbol;
|
|
2
|
+
export declare const VOYANT_DB_DISPOSE: unique symbol;
|
|
3
|
+
export type DbTransactionCapability = {
|
|
4
|
+
[VOYANT_DB_SUPPORTS_TRANSACTIONS]?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export type DbDisposeCapability = {
|
|
7
|
+
[VOYANT_DB_DISPOSE]?: () => Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare function dbSupportsTransactions(db: unknown): boolean | undefined;
|
|
10
|
+
export declare function dbClientDispose(db: unknown): (() => Promise<void>) | undefined;
|
|
11
|
+
//# sourceMappingURL=transaction-capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-capability.d.ts","sourceRoot":"","sources":["../src/transaction-capability.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,eAA+C,CAAA;AAC3F,eAAO,MAAM,iBAAiB,eAAkC,CAAA;AAEhE,MAAM,MAAM,uBAAuB,GAAG;IACpC,CAAC,+BAA+B,CAAC,CAAC,EAAE,OAAO,CAAA;CAC5C,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1C,CAAA;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAOvE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAO9E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const VOYANT_DB_SUPPORTS_TRANSACTIONS = Symbol.for("voyant.db.supportsTransactions");
|
|
2
|
+
export const VOYANT_DB_DISPOSE = Symbol.for("voyant.db.dispose");
|
|
3
|
+
export function dbSupportsTransactions(db) {
|
|
4
|
+
if (!db || (typeof db !== "object" && typeof db !== "function")) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
const capability = db[VOYANT_DB_SUPPORTS_TRANSACTIONS];
|
|
8
|
+
return typeof capability === "boolean" ? capability : undefined;
|
|
9
|
+
}
|
|
10
|
+
export function dbClientDispose(db) {
|
|
11
|
+
if (!db || (typeof db !== "object" && typeof db !== "function")) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const dispose = db[VOYANT_DB_DISPOSE];
|
|
15
|
+
return typeof dispose === "function" ? dispose : undefined;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=transaction-capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-capability.js","sourceRoot":"","sources":["../src/transaction-capability.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;AAUhE,MAAM,UAAU,sBAAsB,CAAC,EAAW;IAChD,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC;QAChE,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,UAAU,GAAI,EAA8B,CAAC,+BAA+B,CAAC,CAAA;IACnF,OAAO,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;AACjE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAW;IACzC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC;QAChE,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,OAAO,GAAI,EAA0B,CAAC,iBAAiB,CAAC,CAAA;IAC9D,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5D,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run `callback` inside a database transaction when the driver supports one,
|
|
3
|
+
* or invoke it directly against the same `db` handle when it doesn't.
|
|
4
|
+
*
|
|
5
|
+
* Designed for Voyant services that share code paths between drivers with
|
|
6
|
+
* different transaction semantics:
|
|
7
|
+
*
|
|
8
|
+
* - `postgres-js` (node) and `neon-serverless` (WebSocket): real transactions.
|
|
9
|
+
* The driver's `transaction(...)` method is used.
|
|
10
|
+
* - `neon-http` (edge): the HTTP driver tagged with
|
|
11
|
+
* `VOYANT_DB_SUPPORTS_TRANSACTIONS = false` by `createDbClient`. The
|
|
12
|
+
* callback runs directly against `db`. Writes execute as independent
|
|
13
|
+
* statements — atomicity is lost on this driver. Callers that need true
|
|
14
|
+
* atomicity must select a transaction-capable adapter at startup.
|
|
15
|
+
*
|
|
16
|
+
* Nested calls are detected via a `WeakSet`: when invoked with a `tx` handle
|
|
17
|
+
* that the helper already opened, the callback runs in-place against that
|
|
18
|
+
* same handle (no second `BEGIN`).
|
|
19
|
+
*
|
|
20
|
+
* As a defense-in-depth, if a driver's `transaction()` throws with
|
|
21
|
+
* "No transactions support …" *before* the callback executes (i.e. the
|
|
22
|
+
* capability tag is missing on an HTTP-like driver), the helper retries by
|
|
23
|
+
* invoking the callback directly. Errors raised *after* the callback starts
|
|
24
|
+
* are not retried — they propagate.
|
|
25
|
+
*/
|
|
26
|
+
export declare function withOptionalTransaction<TDb, T>(db: TDb, callback: (tx: TDb) => Promise<T>): Promise<T>;
|
|
27
|
+
/** @internal — exposed for tests so they can assert WeakSet behavior */
|
|
28
|
+
export declare const __test__: {
|
|
29
|
+
activeTransactionDbs: WeakSet<object>;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,CAAC,EAClD,EAAE,EAAE,GAAG,EACP,QAAQ,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAChC,OAAO,CAAC,CAAC,CAAC,CAqCZ;AAED,wEAAwE;AACxE,eAAO,MAAM,QAAQ;;CAEpB,CAAA"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { dbSupportsTransactions } from "./transaction-capability.js";
|
|
2
|
+
const activeTransactionDbs = new WeakSet();
|
|
3
|
+
function isUnsupportedTransactionError(error) {
|
|
4
|
+
return error instanceof Error && /No transactions support/i.test(error.message);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Run `callback` inside a database transaction when the driver supports one,
|
|
8
|
+
* or invoke it directly against the same `db` handle when it doesn't.
|
|
9
|
+
*
|
|
10
|
+
* Designed for Voyant services that share code paths between drivers with
|
|
11
|
+
* different transaction semantics:
|
|
12
|
+
*
|
|
13
|
+
* - `postgres-js` (node) and `neon-serverless` (WebSocket): real transactions.
|
|
14
|
+
* The driver's `transaction(...)` method is used.
|
|
15
|
+
* - `neon-http` (edge): the HTTP driver tagged with
|
|
16
|
+
* `VOYANT_DB_SUPPORTS_TRANSACTIONS = false` by `createDbClient`. The
|
|
17
|
+
* callback runs directly against `db`. Writes execute as independent
|
|
18
|
+
* statements — atomicity is lost on this driver. Callers that need true
|
|
19
|
+
* atomicity must select a transaction-capable adapter at startup.
|
|
20
|
+
*
|
|
21
|
+
* Nested calls are detected via a `WeakSet`: when invoked with a `tx` handle
|
|
22
|
+
* that the helper already opened, the callback runs in-place against that
|
|
23
|
+
* same handle (no second `BEGIN`).
|
|
24
|
+
*
|
|
25
|
+
* As a defense-in-depth, if a driver's `transaction()` throws with
|
|
26
|
+
* "No transactions support …" *before* the callback executes (i.e. the
|
|
27
|
+
* capability tag is missing on an HTTP-like driver), the helper retries by
|
|
28
|
+
* invoking the callback directly. Errors raised *after* the callback starts
|
|
29
|
+
* are not retried — they propagate.
|
|
30
|
+
*/
|
|
31
|
+
export async function withOptionalTransaction(db, callback) {
|
|
32
|
+
if (db && typeof db === "object" && activeTransactionDbs.has(db)) {
|
|
33
|
+
return callback(db);
|
|
34
|
+
}
|
|
35
|
+
if (dbSupportsTransactions(db) === false) {
|
|
36
|
+
return callback(db);
|
|
37
|
+
}
|
|
38
|
+
const maybeTransactional = db;
|
|
39
|
+
if (typeof maybeTransactional.transaction !== "function") {
|
|
40
|
+
return callback(db);
|
|
41
|
+
}
|
|
42
|
+
let callbackStarted = false;
|
|
43
|
+
try {
|
|
44
|
+
return await maybeTransactional.transaction(async (tx) => {
|
|
45
|
+
callbackStarted = true;
|
|
46
|
+
const txKey = tx;
|
|
47
|
+
const trackable = txKey && typeof txKey === "object";
|
|
48
|
+
if (trackable) {
|
|
49
|
+
activeTransactionDbs.add(txKey);
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return await callback(tx);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
if (trackable) {
|
|
56
|
+
activeTransactionDbs.delete(txKey);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (!callbackStarted && isUnsupportedTransactionError(error)) {
|
|
63
|
+
return callback(db);
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** @internal — exposed for tests so they can assert WeakSet behavior */
|
|
69
|
+
export const __test__ = {
|
|
70
|
+
activeTransactionDbs,
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAEpE,MAAM,oBAAoB,GAAG,IAAI,OAAO,EAAU,CAAA;AAElD,SAAS,6BAA6B,CAAC,KAAc;IACnD,OAAO,KAAK,YAAY,KAAK,IAAI,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AACjF,CAAC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,EAAO,EACP,QAAiC;IAEjC,IAAI,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,oBAAoB,CAAC,GAAG,CAAC,EAAY,CAAC,EAAE,CAAC;QAC3E,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC;IAED,IAAI,sBAAsB,CAAC,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;QACzC,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC;IAED,MAAM,kBAAkB,GAAG,EAA+B,CAAA;IAC1D,IAAI,OAAO,kBAAkB,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACzD,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC;IAED,IAAI,eAAe,GAAG,KAAK,CAAA;IAC3B,IAAI,CAAC;QACH,OAAO,MAAM,kBAAkB,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACvD,eAAe,GAAG,IAAI,CAAA;YACtB,MAAM,KAAK,GAAG,EAAa,CAAA;YAC3B,MAAM,SAAS,GAAG,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAA;YACpD,IAAI,SAAS,EAAE,CAAC;gBACd,oBAAoB,CAAC,GAAG,CAAC,KAAe,CAAC,CAAA;YAC3C,CAAC;YACD,IAAI,CAAC;gBACH,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC,CAAA;YAC3B,CAAC;oBAAS,CAAC;gBACT,IAAI,SAAS,EAAE,CAAC;oBACd,oBAAoB,CAAC,MAAM,CAAC,KAAe,CAAC,CAAA;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,eAAe,IAAI,6BAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;QACrB,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,oBAAoB;CACrB,CAAA"}
|