@vrplatform/kysely 1.3.45-stage.11 → 1.3.45-stage.1104
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/build/.data.tar +2 -2
- package/build/main/control-plane/index.d.ts +28 -6
- package/build/main/control-plane/index.js.map +1 -1
- package/build/main/index.d.ts +23 -1
- package/build/main/index.js +209 -50
- package/build/main/index.js.map +1 -1
- package/build/main/local/index.js +115 -8
- package/build/main/local/index.js.map +1 -1
- package/build/main/postgres-error.d.ts +3 -3
- package/build/main/postgres-error.js +4 -3
- package/build/main/postgres-error.js.map +1 -1
- package/build/main/query/tenant/status.d.ts +1 -1
- package/build/main/query/tenant/status.js +5 -2
- package/build/main/query/tenant/status.js.map +1 -1
- package/build/main/regional.d.ts +1 -0
- package/build/main/regional.js +1 -0
- package/build/main/regional.js.map +1 -1
- package/build/main/test/index.d.ts +25 -2
- package/build/main/test/index.js +40 -8
- package/build/main/test/index.js.map +1 -1
- package/build/main/v1.generated.d.ts +193 -19
- package/build/main/v1.generated.js.map +1 -1
- package/build/migrations-v2/0000000000031-ui-permission-role-simplification.ts +70 -0
- package/build/migrations-v2/0000000000032-tenant-delete-ownership-cascades.ts +44 -0
- package/build/migrations-v2/0000000000033-plaid-connect-session-telemetry.ts +31 -0
- package/build/migrations-v2/0000000000033-reservation-issue-seed-bucket-index.ts +19 -0
- package/build/migrations-v2/0000000000034-retire-recent-classification-indexes.ts +29 -0
- package/build/migrations-v2/0000000000035-core-change-autovacuum.ts +24 -0
- package/build/migrations-v2/0000000000036-journal-entry-inactive-reason-constraint.ts +33 -0
- package/build/migrations-v2/0000000000037-journal-entry-inactive-reasons.ts +19 -0
- package/build/migrations-v2/0000000000038-journal-entry-group-inactive-reason.ts +14 -0
- package/build/migrations-v2/0000000000039-reservation-guest-breakdown.ts +19 -0
- package/build/migrations-v2/0000000000040-csv-import-source-identity-index.ts +23 -0
- package/build/migrations-v2/0000000000041-payment-returns.ts +38 -0
- package/build/migrations-v2/0000000000042-operation-resource-types.ts +609 -0
- package/build/migrations-v2/0000000000043-reservation-journal-freshness.ts +149 -0
- package/build/migrations-v2/0000000000044-reservation-journal-freshness-backfill.ts +254 -0
- package/build/migrations-v2/0000000000045-reservation-journal-freshness-revision-repair.ts +83 -0
- package/build/migrations-v2/0000000000046-materialized-reservation-journal-operations.ts +709 -0
- package/build/migrations-v2/0000000000047-public-audit-completion.ts +77 -0
- package/build/migrations-v2/0000000000048-reservation-journal-full-refresh-repair.ts +136 -0
- package/build/migrations-v2/0000000000049-queued-journal-operation-failures.ts +60 -0
- package/build/migrations-v2/0000000000050-connection-oauth-state.ts +43 -0
- package/build/migrations-v2/0000000000051-owner-statement-email-delivery.ts +134 -0
- package/build/migrations-v2/0000000000052-fee-journal-lock-skip-operations.ts +59 -0
- package/build/migrations-v2/0000000000053-fee-journal-lock-skip-null-attempt.ts +44 -0
- package/build/migrations-v2/0000000000054-journal-refresh-issue-codes.ts +16 -0
- package/build/migrations-v2/0000000000055-tenant-billing-subscription.ts +8 -0
- package/build/migrations-v2/0000000000056-journal-operation-failure-precedence.ts +306 -0
- package/build/migrations-v2/0000000000057-journal-invalidation-failure-code.ts +28 -0
- package/build/migrations-v2/0000000000058-journal-invalidation-locked-failure.ts +16 -0
- package/build/migrations-v2/0000000000059-billing-active-listing-cross-region-partner.ts +135 -0
- package/build/migrations-v2/0000000000060-accounting-integrity-change-driven.ts +99 -0
- package/build/migrations-v2/0000000000061-tenant-pending-onboarding-status.ts +37 -0
- package/build/migrations-v2/0000000000062-statement-payout-operations.ts +16 -0
- package/build/migrations-v2/0000000000063-missing-account-assignments-issue-code.ts +13 -0
- package/build/module/control-plane/index.d.ts +28 -6
- package/build/module/control-plane/index.js.map +1 -1
- package/build/module/index.d.ts +23 -1
- package/build/module/index.js +206 -50
- package/build/module/index.js.map +1 -1
- package/build/module/local/index.js +115 -8
- package/build/module/local/index.js.map +1 -1
- package/build/module/postgres-error.d.ts +3 -3
- package/build/module/postgres-error.js +4 -3
- package/build/module/postgres-error.js.map +1 -1
- package/build/module/query/tenant/status.d.ts +1 -1
- package/build/module/query/tenant/status.js +5 -2
- package/build/module/query/tenant/status.js.map +1 -1
- package/build/module/regional.d.ts +1 -0
- package/build/module/regional.js +1 -0
- package/build/module/regional.js.map +1 -1
- package/build/module/test/index.d.ts +25 -2
- package/build/module/test/index.js +39 -8
- package/build/module/test/index.js.map +1 -1
- package/build/module/v1.generated.d.ts +193 -19
- package/build/module/v1.generated.js.map +1 -1
- package/package.json +9 -7
|
@@ -10,6 +10,11 @@ export type JsonPrimitive = boolean | number | string | null;
|
|
|
10
10
|
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
|
11
11
|
export type Int8 = ColumnType<string, number | string | bigint, number | string | bigint>;
|
|
12
12
|
export type Timestamp = ColumnType<Date | string, Date | string, Date | string>;
|
|
13
|
+
export type ControlPlaneOperationStatus = 'completed' | 'failed' | 'queued' | 'running';
|
|
14
|
+
export type ControlPlaneOperationType = 'ach-verification' | 'bank-rule-run' | 'calendar-block' | 'calendar-unblock' | 'connection-archive' | 'connection-connect' | 'connection-extract' | 'connection-sync' | 'csv-import' | 'csv-import-preview' | 'export' | 'flow-run' | 'historical-gl-import' | 'historical-statement-import' | 'listing-journal-refresh' | 'plaid-initial-sync' | 'pms-cutover' | 'pms-cutover-preview' | 'provider-payment' | 'provider-payment-recovery' | 'recurring-transaction-run' | 'reservation-journal-refresh' | 'statement-payout' | 'statement-payout-preview' | 'team-delete' | 'team-demo-data' | 'team-duplicate' | 'team-initialize' | 'transaction-journal-refresh' | 'vri-statement-import' | 'vri-team-migration' | 'webhook-test';
|
|
15
|
+
export type ControlPlaneOperationResourceRole = 'result' | 'source' | 'target';
|
|
16
|
+
export type ControlPlaneOperationResourceType = 'bank-rule' | 'connection' | 'contact' | 'file' | 'flow' | 'listing' | 'recurring-fee' | 'recurring-transaction-template' | 'reservation' | 'statement' | 'team' | 'transaction' | 'webhook';
|
|
17
|
+
export type ControlPlaneOperationSourceType = 'destructive-job' | 'regional-operation';
|
|
13
18
|
export interface ControlPlaneApp {
|
|
14
19
|
authentication: Generated<Json>;
|
|
15
20
|
category: string | null;
|
|
@@ -169,8 +174,8 @@ export interface ControlPlaneOperation {
|
|
|
169
174
|
sourceRegion: TenantDataRegion | null;
|
|
170
175
|
sourceVersion: Generated<number>;
|
|
171
176
|
startedAt: Timestamp | null;
|
|
172
|
-
status: Generated<
|
|
173
|
-
type:
|
|
177
|
+
status: Generated<ControlPlaneOperationStatus>;
|
|
178
|
+
type: ControlPlaneOperationType;
|
|
174
179
|
updatedAt: Generated<Timestamp>;
|
|
175
180
|
}
|
|
176
181
|
export interface ControlPlaneOperationResource {
|
|
@@ -178,18 +183,18 @@ export interface ControlPlaneOperationResource {
|
|
|
178
183
|
isPrimary: Generated<boolean>;
|
|
179
184
|
operationId: string;
|
|
180
185
|
resourceId: string;
|
|
181
|
-
resourceType:
|
|
182
|
-
role:
|
|
186
|
+
resourceType: ControlPlaneOperationResourceType;
|
|
187
|
+
role: ControlPlaneOperationResourceRole;
|
|
183
188
|
}
|
|
184
189
|
export interface ControlPlaneOperationSource {
|
|
185
190
|
finishedAt: Timestamp | null;
|
|
186
191
|
operationId: string;
|
|
187
192
|
required: Generated<boolean>;
|
|
188
193
|
sourceId: string;
|
|
189
|
-
sourceType:
|
|
194
|
+
sourceType: ControlPlaneOperationSourceType;
|
|
190
195
|
sourceVersion: Generated<number>;
|
|
191
196
|
startedAt: Timestamp | null;
|
|
192
|
-
status: Generated<
|
|
197
|
+
status: Generated<ControlPlaneOperationStatus>;
|
|
193
198
|
}
|
|
194
199
|
export interface ControlPlaneEvent {
|
|
195
200
|
createdAt: Generated<Timestamp>;
|
|
@@ -370,6 +375,22 @@ export interface ControlPlanePartnerManagedTeamAssignment {
|
|
|
370
375
|
partnerTenantId: string;
|
|
371
376
|
userId: string;
|
|
372
377
|
}
|
|
378
|
+
export interface ControlPlaneOwnerPortal {
|
|
379
|
+
hostname: string;
|
|
380
|
+
tenantId: string;
|
|
381
|
+
status: Generated<'pending' | 'active' | 'disabled'>;
|
|
382
|
+
name: string;
|
|
383
|
+
logo: string | null;
|
|
384
|
+
colorPrimary: string;
|
|
385
|
+
showPlatformBranding: Generated<boolean>;
|
|
386
|
+
linksEnabled: Generated<boolean>;
|
|
387
|
+
sender: {
|
|
388
|
+
from: string;
|
|
389
|
+
replyTo: string;
|
|
390
|
+
} | null;
|
|
391
|
+
revision: Generated<number>;
|
|
392
|
+
updatedAt: Generated<Timestamp>;
|
|
393
|
+
}
|
|
373
394
|
export interface ControlPlaneTenant {
|
|
374
395
|
billingPartnerId: string | null;
|
|
375
396
|
billingPlan: string | null;
|
|
@@ -470,6 +491,7 @@ export interface ControlPlaneDB {
|
|
|
470
491
|
'controlPlane.partnerManagedTeamAssignment': ControlPlanePartnerManagedTeamAssignment;
|
|
471
492
|
'controlPlane.reservationLineDefault': ControlPlaneReservationLineDefault;
|
|
472
493
|
'controlPlane.rolloutMonitorSnapshot': ControlPlaneRolloutMonitorSnapshot;
|
|
494
|
+
'controlPlane.ownerPortal': ControlPlaneOwnerPortal;
|
|
473
495
|
'controlPlane.tenant': ControlPlaneTenant;
|
|
474
496
|
'controlPlane.tenantRegionMigration': ControlPlaneTenantRegionMigration;
|
|
475
497
|
'controlPlane.tenantUser': ControlPlaneTenantUser;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["control-plane/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EAGd,wBAAwB,GAQzB,MAAM,QAAQ,CAAC;AA+hBhB,MAAM,6BAA8B,SAAQ,wBAAwB;IAEvD;IACA;IAFX,YACW,MAAc,EACd,2BAAmC;QAE5C,KAAK,EAAE,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QACd,gCAA2B,GAA3B,2BAA2B,CAAQ;IAG9C,CAAC;IAEkB,4BAA4B,CAC7C,IAA6B,EAC7B,OAAgB;QAEhB,MAAM,WAAW,GAAG,KAAK,CAAC,4BAA4B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtE,IACE,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc;YAC3C,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,eAAe,EAC5C,CAAC;YACD,OAAO,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACxE,CAAC;QACD,IACE,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,kBAAkB;YAC/C,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,oBAAoB,EACjD,CAAC;YACD,OAAO;gBACL,GAAG,WAAW;gBACd,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC;aAChE,CAAC;QACJ,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAEkB,iBAAiB,CAClC,IAAkB,EAClB,OAAgB;QAEhB,MAAM,WAAW,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;YAC1C,CAAC,CAAC;gBACE,GAAG,WAAW;gBACd,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;aACzE;YACH,CAAC,CAAC,WAAW,CAAC;IAClB,CAAC;CACF;AAED,MAAM,wBAAwB;IACnB,YAAY,CAAgC;IAErD,YAAY,MAAc,EAAE,2BAAmC;QAC7D,IAAI,CAAC,YAAY,GAAG,IAAI,6BAA6B,CACnD,MAAM,EACN,2BAA2B,CAC5B,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,IAA8B;QAC3C,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,IAA+B;QAE/B,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CACpC,MAA8B,EAC9B,MAAc,EACd,2BAA2B,GAAG,MAAM;IAEpC,OAAO,MAAM,CAAC,UAAU,CACtB,IAAI,wBAAwB,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAClE,CAAC;AACJ,CAAC","sourcesContent":["import {\n type ColumnType,\n type FunctionNode,\n IdentifierNode,\n type Kysely,\n type KyselyPlugin,\n OperationNodeTransformer,\n type PluginTransformQueryArgs,\n type PluginTransformResultArgs,\n type QueryId,\n type QueryResult,\n type RootOperationNode,\n type SchemableIdentifierNode,\n type UnknownRow,\n} from 'kysely';\nimport type { TenantDataRegion } from '../regional';\n\nexport type Generated<T> =\n T extends ColumnType<infer S, infer I, infer U>\n ? ColumnType<S, I | undefined, U>\n : ColumnType<T, T | undefined, T>;\n\nexport type Json = JsonValue;\n\nexport type JsonArray = JsonValue[];\n\nexport type JsonObject = {\n [x: string]: JsonValue | undefined;\n};\n\nexport type JsonPrimitive = boolean | number | string | null;\n\nexport type JsonValue = JsonArray | JsonObject | JsonPrimitive;\n\nexport type Int8 = ColumnType<\n string,\n number | string | bigint,\n number | string | bigint\n>;\n\nexport type Timestamp = ColumnType<Date | string, Date | string, Date | string>;\n\nexport interface ControlPlaneApp {\n authentication: Generated<Json>;\n category: string | null;\n color: string | null;\n createdAt: Generated<Timestamp>;\n icon: string | null;\n iconRound: string | null;\n id: Generated<string>;\n info: Json | null;\n name: string;\n type: string;\n version: Generated<number>;\n}\n\nexport interface ControlPlaneAccountingIntegrityEvaluation {\n caseCount: Generated<Int8>;\n completedAt: Timestamp | null;\n completedRunCount: Generated<number>;\n createdAt: Generated<Timestamp>;\n environment: string;\n error: Json | null;\n expectedRunCount: number;\n failedRunCount: Generated<number>;\n findingRowCount: Generated<Int8>;\n gitRevision: string;\n id: string;\n results: Generated<Json>;\n rowsScanned: Generated<Int8>;\n skippedRunCount: Generated<number>;\n source: string;\n startedAt: Timestamp;\n status: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneAccountingIntegrityDefinitionDraft {\n artifact: Json;\n artifactHash: string;\n code: string;\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n ownerId: string;\n previewResult: Json | null;\n rationale: string;\n revision: Generated<number>;\n status: string;\n templateId: string;\n templateVersion: number;\n title: string;\n updatedAt: Generated<Timestamp>;\n validationResult: Json | null;\n}\n\nexport interface ControlPlaneAccountingIntegrityDefinitionVersion {\n artifact: Json;\n artifactHash: string;\n code: string;\n draftId: string;\n id: Generated<string>;\n publishedAt: Generated<Timestamp>;\n publishedBy: string;\n rollout: string;\n templateId: string;\n templateVersion: number;\n version: number;\n}\n\nexport interface ControlPlaneBookingChannel {\n channelRef: string | null;\n color: string | null;\n createdAt: Generated<Timestamp>;\n icon: string | null;\n iconProvider: string | null;\n id: Generated<string>;\n lastGenerateRun: Timestamp | null;\n logo: string | null;\n logoProvider: string | null;\n selectedBookingChannelIconCandidateId: string | null;\n selectedBookingChannelLogoCandidateId: string | null;\n uniqueRef: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneBookingChannelIconCandidate {\n bookingChannelId: string;\n cloudflareImageId: string | null;\n color: string | null;\n comment: string | null;\n createdAt: Generated<Timestamp>;\n externalIcon: string | null;\n height: number | null;\n id: Generated<string>;\n provider: Generated<string>;\n source: string | null;\n updatedAt: Generated<Timestamp>;\n width: number | null;\n}\n\nexport interface ControlPlaneCurrency {\n name: string;\n}\n\nexport type DestructiveJobStep =\n | 'completed'\n | 'completion_effects'\n | 'control_plane_deleted'\n | 'control_plane_deleting'\n | 'queued'\n | 'regional_deleted'\n | 'regional_deleting'\n | 'validated';\n\nexport interface ControlPlaneDestructiveJob {\n attempts: Generated<number>;\n authorizedByTenantId: string;\n availableAt: Generated<Timestamp>;\n claimedAt: Timestamp | null;\n claimedBy: string | null;\n completedAt: Timestamp | null;\n completionData: Json | null;\n completionWarningCode: string | null;\n completionWarningDetails: Json | null;\n createdAt: Generated<Timestamp>;\n dataRegion: TenantDataRegion;\n failureCode: string | null;\n failureDetails: Json | null;\n force: Generated<boolean>;\n id: Generated<string>;\n jobType: 'tenant.delete';\n maxAttempts: Generated<number>;\n requestId: string | null;\n requestedByActorType: 'api_key' | 'system' | 'user';\n requestedByTenantId: string;\n requestedByUserId: string | null;\n startedAt: Timestamp | null;\n status: Generated<'canceled' | 'completed' | 'failed' | 'queued' | 'running'>;\n step: Generated<DestructiveJobStep>;\n targetId: string;\n triggerRunId: string | null;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneDestructiveJobAttempt {\n attemptNumber: number;\n failureCode: string | null;\n failureDetails: Json | null;\n finishedAt: Timestamp | null;\n id: Generated<string>;\n jobId: string;\n startedAt: Generated<Timestamp>;\n status: Generated<'completed' | 'failed' | 'running' | 'superseded'>;\n step: DestructiveJobStep;\n triggerRunId: string | null;\n}\n\nexport interface ControlPlaneDestructiveJobOperation {\n action: 'abandon' | 'cancel' | 'retry';\n actor: string;\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n jobId: string;\n previousStatus: string;\n previousStep: string;\n reasonCode: string;\n}\n\nexport interface ControlPlaneOperation {\n createdAt: Generated<Timestamp>;\n failureCode: string | null;\n failureMessage: string | null;\n finishedAt: Timestamp | null;\n id: Generated<string>;\n initiatedByUserId: string | null;\n requesterTenantId: string;\n retainUntil: Timestamp | null;\n sourceRegion: TenantDataRegion | null;\n sourceVersion: Generated<number>;\n startedAt: Timestamp | null;\n status: Generated<'completed' | 'failed' | 'queued' | 'running'>;\n type: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneOperationResource {\n createdAt: Generated<Timestamp>;\n isPrimary: Generated<boolean>;\n operationId: string;\n resourceId: string;\n resourceType: string;\n role: 'result' | 'source' | 'target';\n}\n\nexport interface ControlPlaneOperationSource {\n finishedAt: Timestamp | null;\n operationId: string;\n required: Generated<boolean>;\n sourceId: string;\n sourceType: 'destructive-job' | 'regional-operation';\n sourceVersion: Generated<number>;\n startedAt: Timestamp | null;\n status: Generated<'completed' | 'failed' | 'queued' | 'running'>;\n}\n\nexport interface ControlPlaneEvent {\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n name: string;\n packageName: string;\n props: Json;\n tenantId: string | null;\n timestamp: Generated<Timestamp>;\n trackedAt: Generated<Timestamp | null>;\n userId: string | null;\n}\n\nexport interface ControlPlaneTrackingQueueFailure {\n bodyFingerprint: string | null;\n capturedAt: Generated<Timestamp>;\n dispositionAt: Timestamp | null;\n dispositionHistory: Generated<Json[]>;\n dispositionReasonCode: string | null;\n dispositionActor: string | null;\n environment: 'production' | 'staging';\n event: Json | null;\n eventId: string | null;\n expiresAt: Timestamp;\n failureCode: string;\n id: Generated<string>;\n lastReplayedAt: Timestamp | null;\n queueMessageId: string;\n replayCount: Generated<number>;\n recurrenceCount: Generated<number>;\n status: Generated<'captured' | 'discarded' | 'replayed'>;\n updatedAt: Generated<Timestamp>;\n validationIssues: Json | null;\n}\n\nexport interface ControlPlaneConnectionRoute {\n connectionId: string;\n createdAt: Generated<Timestamp>;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneFeature {\n createdAt: Generated<Timestamp>;\n description: string | null;\n id: Generated<string>;\n issueUrl: string | null;\n requiredApprovals: Generated<Json | null>;\n status: Generated<string | null>;\n tenantId: string | null;\n title: string;\n updatedAt: Generated<Timestamp>;\n url: string | null;\n}\n\nexport interface ControlPlaneFeatureEnabledTeam {\n createdAt: Generated<Timestamp>;\n featureId: string;\n id: Generated<string>;\n status: Generated<string | null>;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneFeatureApproval {\n createdAt: Generated<Timestamp>;\n featureId: string;\n id: Generated<string>;\n status: Generated<string | null>;\n updatedAt: Generated<Timestamp>;\n userId: string;\n}\n\nexport interface ControlPlaneFlow {\n appId: string;\n createdAt: Generated<Timestamp>;\n description: string | null;\n eventListening: Generated<Json>;\n id: Generated<string>;\n isPublic: Generated<boolean>;\n leftType: string | null;\n mappingSchema: Generated<Json>;\n revision: Generated<number>;\n rightType: string | null;\n runSchema: Generated<Json>;\n settingSchema: Generated<Json>;\n title: string;\n type: 'pull' | 'push' | null;\n uniqueRef: string;\n updatedAt: Generated<Timestamp>;\n useGlobalMapping: Generated<boolean>;\n}\n\nexport interface ControlPlaneIssueMessageOverwrite {\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n message: string;\n pattern: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneLineClassification {\n appConflict: Generated<boolean>;\n appId: string | null;\n createdAt: Generated<Timestamp>;\n firstSeenAt: Timestamp;\n id: Generated<string>;\n kind: string;\n lastSeenAt: Timestamp;\n name: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneLineClassificationTeamUsage {\n classificationId: string;\n createdAt: Generated<Timestamp>;\n dataRegion: string;\n firstSeenAt: Timestamp;\n lastSeenAt: Timestamp;\n mappingStatus: string | null;\n revision: number;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneReservationLineDefault {\n accountKey: string | null;\n bookingChannel: string | null;\n bookingChannelKey: Generated<string>;\n classificationId: string;\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n partnerTenantId: string | null;\n revenueRecognition: string | null;\n revision: Generated<number>;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneRolloutMonitorSnapshot {\n monitorName: string;\n result: Json;\n snapshotDate: Timestamp;\n}\n\nexport interface ControlPlaneTransactionLineMapping {\n accountAssignmentType: string | null;\n createdAt: Generated<Timestamp>;\n deletedAt: Timestamp | null;\n id: Generated<string>;\n lineType: string;\n revision: Generated<number>;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneGeneralLedgerDefaultSet {\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n partnerTenantId: string | null;\n publishedVersion: number | null;\n sourceDataRegion: string;\n sourceDigest: string | null;\n sourceTenantId: string;\n templateKey: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneGeneralLedgerDefaultVersion {\n dataJson: Json;\n defaultSetId: string;\n id: Generated<string>;\n publishedAt: Generated<Timestamp>;\n sourceDigest: string;\n sourceTenantId: string;\n version: number;\n}\n\nexport interface ControlPlaneOutbox {\n aggregateId: string;\n aggregateType: string;\n attempts: Generated<number>;\n createdAt: Generated<Timestamp>;\n dataRegion: string | null;\n eventType: string;\n eventVersion: number;\n id: Generated<string>;\n lastError: string | null;\n payload: Generated<Json>;\n publishedAt: Timestamp | null;\n}\n\nexport interface ControlPlanePartnerManagedTeamAssignment {\n createdAt: Generated<Timestamp>;\n managedTeamId: string;\n partnerTenantId: string;\n userId: string;\n}\n\nexport interface ControlPlaneTenant {\n billingPartnerId: string | null;\n billingPlan: string | null;\n createdAt: Generated<Timestamp>;\n dataRegion: Generated<string>;\n id: Generated<string>;\n migrationStatus: Generated<string>;\n name: string;\n partnerId: string | null;\n partnerDeniedPermissions: Generated<string[]>;\n slug: string;\n status: Generated<string | null>;\n storageRealm: Generated<string>;\n type: Generated<string | null>;\n uniqueRef: string | null;\n updatedAt: Generated<Timestamp | null>;\n}\n\nexport interface ControlPlaneTenantRegionMigration {\n actor: string;\n completedAt: Timestamp | null;\n error: Json | null;\n id: string;\n reason: string;\n sourceManifest: Json | null;\n sourceRegion: string;\n startedAt: Generated<Timestamp>;\n status: Generated<string>;\n targetManifest: Json | null;\n targetRegion: string;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneTenantUser {\n createdAt: Generated<Timestamp | null>;\n id: Generated<string>;\n lastInvitedAt: Timestamp | null;\n managedTeamAccess: Generated<'all' | 'assigned'>;\n permissionBundles: Generated<string[]>;\n role: Generated<string | null>;\n status: Generated<string | null>;\n tenantId: string;\n updatedAt: Generated<Timestamp | null>;\n userId: string;\n}\n\nexport interface ControlPlaneToken {\n createdAt: Generated<Timestamp>;\n expiresAt: Timestamp | null;\n id: Generated<string>;\n nanoId: Generated<string>;\n payload: Generated<Json>;\n tenantId: string | null;\n type: string | null;\n userId: string | null;\n}\n\nexport interface ControlPlaneUser {\n clerkId: string | null;\n createdAt: Generated<Timestamp | null>;\n email: string | null;\n firstName: string | null;\n id: Generated<string>;\n internalOperationGrants: Generated<string[]>;\n isAdmin: Generated<boolean>;\n lastName: string | null;\n lastSeen: Timestamp | null;\n name: string | null;\n partnerId: string | null;\n phone: string | null;\n secondaryEmails: Generated<Json>;\n status: Generated<string | null>;\n sub: string | null;\n type: Generated<string | null>;\n updatedAt: Generated<Timestamp | null>;\n}\n\nexport interface ControlPlaneDB {\n 'controlPlane.accountingIntegrityDefinitionDraft': ControlPlaneAccountingIntegrityDefinitionDraft;\n 'controlPlane.accountingIntegrityDefinitionVersion': ControlPlaneAccountingIntegrityDefinitionVersion;\n 'controlPlane.accountingIntegrityEvaluation': ControlPlaneAccountingIntegrityEvaluation;\n 'controlPlane.app': ControlPlaneApp;\n 'controlPlane.bookingChannel': ControlPlaneBookingChannel;\n 'controlPlane.bookingChannelIconCandidate': ControlPlaneBookingChannelIconCandidate;\n 'controlPlane.connectionRoute': ControlPlaneConnectionRoute;\n 'controlPlane.controlPlaneOutbox': ControlPlaneOutbox;\n 'controlPlane.currency': ControlPlaneCurrency;\n 'controlPlane.destructiveJob': ControlPlaneDestructiveJob;\n 'controlPlane.destructiveJobAttempt': ControlPlaneDestructiveJobAttempt;\n 'controlPlane.destructiveJobOperation': ControlPlaneDestructiveJobOperation;\n 'controlPlane.events': ControlPlaneEvent;\n 'controlPlane.feature': ControlPlaneFeature;\n 'controlPlane.featureApproval': ControlPlaneFeatureApproval;\n 'controlPlane.featureEnabledTeam': ControlPlaneFeatureEnabledTeam;\n 'controlPlane.generalLedgerDefaultSet': ControlPlaneGeneralLedgerDefaultSet;\n 'controlPlane.generalLedgerDefaultVersion': ControlPlaneGeneralLedgerDefaultVersion;\n 'controlPlane.lineClassification': ControlPlaneLineClassification;\n 'controlPlane.lineClassificationTeamUsage': ControlPlaneLineClassificationTeamUsage;\n 'controlPlane.operation': ControlPlaneOperation;\n 'controlPlane.operationResource': ControlPlaneOperationResource;\n 'controlPlane.operationSource': ControlPlaneOperationSource;\n 'controlPlane.partnerManagedTeamAssignment': ControlPlanePartnerManagedTeamAssignment;\n 'controlPlane.reservationLineDefault': ControlPlaneReservationLineDefault;\n 'controlPlane.rolloutMonitorSnapshot': ControlPlaneRolloutMonitorSnapshot;\n 'controlPlane.tenant': ControlPlaneTenant;\n 'controlPlane.tenantRegionMigration': ControlPlaneTenantRegionMigration;\n 'controlPlane.tenantUser': ControlPlaneTenantUser;\n 'controlPlane.trackingQueueFailure': ControlPlaneTrackingQueueFailure;\n 'controlPlane.token': ControlPlaneToken;\n 'controlPlane.transactionLineMapping': ControlPlaneTransactionLineMapping;\n 'controlPlane.user': ControlPlaneUser;\n 'controlPlaneCore.flow': ControlPlaneFlow;\n 'controlPlaneCore.issueMessageOverwrite': ControlPlaneIssueMessageOverwrite;\n}\n\nclass ControlPlaneSchemaTransformer extends OperationNodeTransformer {\n constructor(\n readonly schema: string,\n readonly issueMessageOverwriteSchema: string\n ) {\n super();\n }\n\n protected override transformSchemableIdentifier(\n node: SchemableIdentifierNode,\n queryId: QueryId\n ): SchemableIdentifierNode {\n const transformed = super.transformSchemableIdentifier(node, queryId);\n if (\n transformed.schema?.name === 'controlPlane' ||\n transformed.schema?.name === 'control_plane'\n ) {\n return { ...transformed, schema: IdentifierNode.create(this.schema) };\n }\n if (\n transformed.schema?.name === 'controlPlaneCore' ||\n transformed.schema?.name === 'control_plane_core'\n ) {\n return {\n ...transformed,\n schema: IdentifierNode.create(this.issueMessageOverwriteSchema),\n };\n }\n return transformed;\n }\n\n protected override transformFunction(\n node: FunctionNode,\n queryId: QueryId\n ): FunctionNode {\n const transformed = super.transformFunction(node, queryId);\n return node.func.startsWith('controlPlane.')\n ? {\n ...transformed,\n func: `${this.schema}.${transformed.func.slice('controlPlane.'.length)}`,\n }\n : transformed;\n }\n}\n\nclass ControlPlaneSchemaPlugin implements KyselyPlugin {\n readonly #transformer: ControlPlaneSchemaTransformer;\n\n constructor(schema: string, issueMessageOverwriteSchema: string) {\n this.#transformer = new ControlPlaneSchemaTransformer(\n schema,\n issueMessageOverwriteSchema\n );\n }\n\n transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n return this.#transformer.transformNode(args.node, args.queryId);\n }\n\n async transformResult(\n args: PluginTransformResultArgs\n ): Promise<QueryResult<UnknownRow>> {\n return args.result;\n }\n}\n\nexport function withControlPlaneSchema(\n kysely: Kysely<ControlPlaneDB>,\n schema: string,\n issueMessageOverwriteSchema = 'core'\n) {\n return kysely.withPlugin(\n new ControlPlaneSchemaPlugin(schema, issueMessageOverwriteSchema)\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["control-plane/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EAGd,wBAAwB,GAQzB,MAAM,QAAQ,CAAC;AA2mBhB,MAAM,6BAA8B,SAAQ,wBAAwB;IAEvD;IACA;IAFX,YACW,MAAc,EACd,2BAAmC;QAE5C,KAAK,EAAE,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QACd,gCAA2B,GAA3B,2BAA2B,CAAQ;IAG9C,CAAC;IAEkB,4BAA4B,CAC7C,IAA6B,EAC7B,OAAgB;QAEhB,MAAM,WAAW,GAAG,KAAK,CAAC,4BAA4B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtE,IACE,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc;YAC3C,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,eAAe,EAC5C,CAAC;YACD,OAAO,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACxE,CAAC;QACD,IACE,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,kBAAkB;YAC/C,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,oBAAoB,EACjD,CAAC;YACD,OAAO;gBACL,GAAG,WAAW;gBACd,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC;aAChE,CAAC;QACJ,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAEkB,iBAAiB,CAClC,IAAkB,EAClB,OAAgB;QAEhB,MAAM,WAAW,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;YAC1C,CAAC,CAAC;gBACE,GAAG,WAAW;gBACd,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;aACzE;YACH,CAAC,CAAC,WAAW,CAAC;IAClB,CAAC;CACF;AAED,MAAM,wBAAwB;IACnB,YAAY,CAAgC;IAErD,YAAY,MAAc,EAAE,2BAAmC;QAC7D,IAAI,CAAC,YAAY,GAAG,IAAI,6BAA6B,CACnD,MAAM,EACN,2BAA2B,CAC5B,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,IAA8B;QAC3C,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,IAA+B;QAE/B,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CACpC,MAA8B,EAC9B,MAAc,EACd,2BAA2B,GAAG,MAAM;IAEpC,OAAO,MAAM,CAAC,UAAU,CACtB,IAAI,wBAAwB,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAClE,CAAC;AACJ,CAAC","sourcesContent":["import {\n type ColumnType,\n type FunctionNode,\n IdentifierNode,\n type Kysely,\n type KyselyPlugin,\n OperationNodeTransformer,\n type PluginTransformQueryArgs,\n type PluginTransformResultArgs,\n type QueryId,\n type QueryResult,\n type RootOperationNode,\n type SchemableIdentifierNode,\n type UnknownRow,\n} from 'kysely';\nimport type { TenantDataRegion } from '../regional';\n\nexport type Generated<T> =\n T extends ColumnType<infer S, infer I, infer U>\n ? ColumnType<S, I | undefined, U>\n : ColumnType<T, T | undefined, T>;\n\nexport type Json = JsonValue;\n\nexport type JsonArray = JsonValue[];\n\nexport type JsonObject = {\n [x: string]: JsonValue | undefined;\n};\n\nexport type JsonPrimitive = boolean | number | string | null;\n\nexport type JsonValue = JsonArray | JsonObject | JsonPrimitive;\n\nexport type Int8 = ColumnType<\n string,\n number | string | bigint,\n number | string | bigint\n>;\n\nexport type Timestamp = ColumnType<Date | string, Date | string, Date | string>;\n\nexport type ControlPlaneOperationStatus =\n | 'completed'\n | 'failed'\n | 'queued'\n | 'running';\n\nexport type ControlPlaneOperationType =\n | 'ach-verification'\n | 'bank-rule-run'\n | 'calendar-block'\n | 'calendar-unblock'\n | 'connection-archive'\n | 'connection-connect'\n | 'connection-extract'\n | 'connection-sync'\n | 'csv-import'\n | 'csv-import-preview'\n | 'export'\n | 'flow-run'\n | 'historical-gl-import'\n | 'historical-statement-import'\n | 'listing-journal-refresh'\n | 'plaid-initial-sync'\n | 'pms-cutover'\n | 'pms-cutover-preview'\n | 'provider-payment'\n | 'provider-payment-recovery'\n | 'recurring-transaction-run'\n | 'reservation-journal-refresh'\n | 'statement-payout'\n | 'statement-payout-preview'\n | 'team-delete'\n | 'team-demo-data'\n | 'team-duplicate'\n | 'team-initialize'\n | 'transaction-journal-refresh'\n | 'vri-statement-import'\n | 'vri-team-migration'\n | 'webhook-test';\n\nexport type ControlPlaneOperationResourceRole = 'result' | 'source' | 'target';\n\nexport type ControlPlaneOperationResourceType =\n | 'bank-rule'\n | 'connection'\n | 'contact'\n | 'file'\n | 'flow'\n | 'listing'\n | 'recurring-fee'\n | 'recurring-transaction-template'\n | 'reservation'\n | 'statement'\n | 'team'\n | 'transaction'\n | 'webhook';\n\nexport type ControlPlaneOperationSourceType =\n | 'destructive-job'\n | 'regional-operation';\n\nexport interface ControlPlaneApp {\n authentication: Generated<Json>;\n category: string | null;\n color: string | null;\n createdAt: Generated<Timestamp>;\n icon: string | null;\n iconRound: string | null;\n id: Generated<string>;\n info: Json | null;\n name: string;\n type: string;\n version: Generated<number>;\n}\n\nexport interface ControlPlaneAccountingIntegrityEvaluation {\n caseCount: Generated<Int8>;\n completedAt: Timestamp | null;\n completedRunCount: Generated<number>;\n createdAt: Generated<Timestamp>;\n environment: string;\n error: Json | null;\n expectedRunCount: number;\n failedRunCount: Generated<number>;\n findingRowCount: Generated<Int8>;\n gitRevision: string;\n id: string;\n results: Generated<Json>;\n rowsScanned: Generated<Int8>;\n skippedRunCount: Generated<number>;\n source: string;\n startedAt: Timestamp;\n status: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneAccountingIntegrityDefinitionDraft {\n artifact: Json;\n artifactHash: string;\n code: string;\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n ownerId: string;\n previewResult: Json | null;\n rationale: string;\n revision: Generated<number>;\n status: string;\n templateId: string;\n templateVersion: number;\n title: string;\n updatedAt: Generated<Timestamp>;\n validationResult: Json | null;\n}\n\nexport interface ControlPlaneAccountingIntegrityDefinitionVersion {\n artifact: Json;\n artifactHash: string;\n code: string;\n draftId: string;\n id: Generated<string>;\n publishedAt: Generated<Timestamp>;\n publishedBy: string;\n rollout: string;\n templateId: string;\n templateVersion: number;\n version: number;\n}\n\nexport interface ControlPlaneBookingChannel {\n channelRef: string | null;\n color: string | null;\n createdAt: Generated<Timestamp>;\n icon: string | null;\n iconProvider: string | null;\n id: Generated<string>;\n lastGenerateRun: Timestamp | null;\n logo: string | null;\n logoProvider: string | null;\n selectedBookingChannelIconCandidateId: string | null;\n selectedBookingChannelLogoCandidateId: string | null;\n uniqueRef: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneBookingChannelIconCandidate {\n bookingChannelId: string;\n cloudflareImageId: string | null;\n color: string | null;\n comment: string | null;\n createdAt: Generated<Timestamp>;\n externalIcon: string | null;\n height: number | null;\n id: Generated<string>;\n provider: Generated<string>;\n source: string | null;\n updatedAt: Generated<Timestamp>;\n width: number | null;\n}\n\nexport interface ControlPlaneCurrency {\n name: string;\n}\n\nexport type DestructiveJobStep =\n | 'completed'\n | 'completion_effects'\n | 'control_plane_deleted'\n | 'control_plane_deleting'\n | 'queued'\n | 'regional_deleted'\n | 'regional_deleting'\n | 'validated';\n\nexport interface ControlPlaneDestructiveJob {\n attempts: Generated<number>;\n authorizedByTenantId: string;\n availableAt: Generated<Timestamp>;\n claimedAt: Timestamp | null;\n claimedBy: string | null;\n completedAt: Timestamp | null;\n completionData: Json | null;\n completionWarningCode: string | null;\n completionWarningDetails: Json | null;\n createdAt: Generated<Timestamp>;\n dataRegion: TenantDataRegion;\n failureCode: string | null;\n failureDetails: Json | null;\n force: Generated<boolean>;\n id: Generated<string>;\n jobType: 'tenant.delete';\n maxAttempts: Generated<number>;\n requestId: string | null;\n requestedByActorType: 'api_key' | 'system' | 'user';\n requestedByTenantId: string;\n requestedByUserId: string | null;\n startedAt: Timestamp | null;\n status: Generated<'canceled' | 'completed' | 'failed' | 'queued' | 'running'>;\n step: Generated<DestructiveJobStep>;\n targetId: string;\n triggerRunId: string | null;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneDestructiveJobAttempt {\n attemptNumber: number;\n failureCode: string | null;\n failureDetails: Json | null;\n finishedAt: Timestamp | null;\n id: Generated<string>;\n jobId: string;\n startedAt: Generated<Timestamp>;\n status: Generated<'completed' | 'failed' | 'running' | 'superseded'>;\n step: DestructiveJobStep;\n triggerRunId: string | null;\n}\n\nexport interface ControlPlaneDestructiveJobOperation {\n action: 'abandon' | 'cancel' | 'retry';\n actor: string;\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n jobId: string;\n previousStatus: string;\n previousStep: string;\n reasonCode: string;\n}\n\nexport interface ControlPlaneOperation {\n createdAt: Generated<Timestamp>;\n failureCode: string | null;\n failureMessage: string | null;\n finishedAt: Timestamp | null;\n id: Generated<string>;\n initiatedByUserId: string | null;\n requesterTenantId: string;\n retainUntil: Timestamp | null;\n sourceRegion: TenantDataRegion | null;\n sourceVersion: Generated<number>;\n startedAt: Timestamp | null;\n status: Generated<ControlPlaneOperationStatus>;\n type: ControlPlaneOperationType;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneOperationResource {\n createdAt: Generated<Timestamp>;\n isPrimary: Generated<boolean>;\n operationId: string;\n resourceId: string;\n resourceType: ControlPlaneOperationResourceType;\n role: ControlPlaneOperationResourceRole;\n}\n\nexport interface ControlPlaneOperationSource {\n finishedAt: Timestamp | null;\n operationId: string;\n required: Generated<boolean>;\n sourceId: string;\n sourceType: ControlPlaneOperationSourceType;\n sourceVersion: Generated<number>;\n startedAt: Timestamp | null;\n status: Generated<ControlPlaneOperationStatus>;\n}\n\nexport interface ControlPlaneEvent {\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n name: string;\n packageName: string;\n props: Json;\n tenantId: string | null;\n timestamp: Generated<Timestamp>;\n trackedAt: Generated<Timestamp | null>;\n userId: string | null;\n}\n\nexport interface ControlPlaneTrackingQueueFailure {\n bodyFingerprint: string | null;\n capturedAt: Generated<Timestamp>;\n dispositionAt: Timestamp | null;\n dispositionHistory: Generated<Json[]>;\n dispositionReasonCode: string | null;\n dispositionActor: string | null;\n environment: 'production' | 'staging';\n event: Json | null;\n eventId: string | null;\n expiresAt: Timestamp;\n failureCode: string;\n id: Generated<string>;\n lastReplayedAt: Timestamp | null;\n queueMessageId: string;\n replayCount: Generated<number>;\n recurrenceCount: Generated<number>;\n status: Generated<'captured' | 'discarded' | 'replayed'>;\n updatedAt: Generated<Timestamp>;\n validationIssues: Json | null;\n}\n\nexport interface ControlPlaneConnectionRoute {\n connectionId: string;\n createdAt: Generated<Timestamp>;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneFeature {\n createdAt: Generated<Timestamp>;\n description: string | null;\n id: Generated<string>;\n issueUrl: string | null;\n requiredApprovals: Generated<Json | null>;\n status: Generated<string | null>;\n tenantId: string | null;\n title: string;\n updatedAt: Generated<Timestamp>;\n url: string | null;\n}\n\nexport interface ControlPlaneFeatureEnabledTeam {\n createdAt: Generated<Timestamp>;\n featureId: string;\n id: Generated<string>;\n status: Generated<string | null>;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneFeatureApproval {\n createdAt: Generated<Timestamp>;\n featureId: string;\n id: Generated<string>;\n status: Generated<string | null>;\n updatedAt: Generated<Timestamp>;\n userId: string;\n}\n\nexport interface ControlPlaneFlow {\n appId: string;\n createdAt: Generated<Timestamp>;\n description: string | null;\n eventListening: Generated<Json>;\n id: Generated<string>;\n isPublic: Generated<boolean>;\n leftType: string | null;\n mappingSchema: Generated<Json>;\n revision: Generated<number>;\n rightType: string | null;\n runSchema: Generated<Json>;\n settingSchema: Generated<Json>;\n title: string;\n type: 'pull' | 'push' | null;\n uniqueRef: string;\n updatedAt: Generated<Timestamp>;\n useGlobalMapping: Generated<boolean>;\n}\n\nexport interface ControlPlaneIssueMessageOverwrite {\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n message: string;\n pattern: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneLineClassification {\n appConflict: Generated<boolean>;\n appId: string | null;\n createdAt: Generated<Timestamp>;\n firstSeenAt: Timestamp;\n id: Generated<string>;\n kind: string;\n lastSeenAt: Timestamp;\n name: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneLineClassificationTeamUsage {\n classificationId: string;\n createdAt: Generated<Timestamp>;\n dataRegion: string;\n firstSeenAt: Timestamp;\n lastSeenAt: Timestamp;\n mappingStatus: string | null;\n revision: number;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneReservationLineDefault {\n accountKey: string | null;\n bookingChannel: string | null;\n bookingChannelKey: Generated<string>;\n classificationId: string;\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n partnerTenantId: string | null;\n revenueRecognition: string | null;\n revision: Generated<number>;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneRolloutMonitorSnapshot {\n monitorName: string;\n result: Json;\n snapshotDate: Timestamp;\n}\n\nexport interface ControlPlaneTransactionLineMapping {\n accountAssignmentType: string | null;\n createdAt: Generated<Timestamp>;\n deletedAt: Timestamp | null;\n id: Generated<string>;\n lineType: string;\n revision: Generated<number>;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneGeneralLedgerDefaultSet {\n createdAt: Generated<Timestamp>;\n id: Generated<string>;\n partnerTenantId: string | null;\n publishedVersion: number | null;\n sourceDataRegion: string;\n sourceDigest: string | null;\n sourceTenantId: string;\n templateKey: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneGeneralLedgerDefaultVersion {\n dataJson: Json;\n defaultSetId: string;\n id: Generated<string>;\n publishedAt: Generated<Timestamp>;\n sourceDigest: string;\n sourceTenantId: string;\n version: number;\n}\n\nexport interface ControlPlaneOutbox {\n aggregateId: string;\n aggregateType: string;\n attempts: Generated<number>;\n createdAt: Generated<Timestamp>;\n dataRegion: string | null;\n eventType: string;\n eventVersion: number;\n id: Generated<string>;\n lastError: string | null;\n payload: Generated<Json>;\n publishedAt: Timestamp | null;\n}\n\nexport interface ControlPlanePartnerManagedTeamAssignment {\n createdAt: Generated<Timestamp>;\n managedTeamId: string;\n partnerTenantId: string;\n userId: string;\n}\n\nexport interface ControlPlaneOwnerPortal {\n hostname: string;\n tenantId: string;\n status: Generated<'pending' | 'active' | 'disabled'>;\n name: string;\n logo: string | null;\n colorPrimary: string;\n showPlatformBranding: Generated<boolean>;\n linksEnabled: Generated<boolean>;\n sender: { from: string; replyTo: string } | null;\n revision: Generated<number>;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneTenant {\n billingPartnerId: string | null;\n billingPlan: string | null;\n createdAt: Generated<Timestamp>;\n dataRegion: Generated<string>;\n id: Generated<string>;\n migrationStatus: Generated<string>;\n name: string;\n partnerId: string | null;\n partnerDeniedPermissions: Generated<string[]>;\n slug: string;\n status: Generated<string | null>;\n storageRealm: Generated<string>;\n type: Generated<string | null>;\n uniqueRef: string | null;\n updatedAt: Generated<Timestamp | null>;\n}\n\nexport interface ControlPlaneTenantRegionMigration {\n actor: string;\n completedAt: Timestamp | null;\n error: Json | null;\n id: string;\n reason: string;\n sourceManifest: Json | null;\n sourceRegion: string;\n startedAt: Generated<Timestamp>;\n status: Generated<string>;\n targetManifest: Json | null;\n targetRegion: string;\n tenantId: string;\n updatedAt: Generated<Timestamp>;\n}\n\nexport interface ControlPlaneTenantUser {\n createdAt: Generated<Timestamp | null>;\n id: Generated<string>;\n lastInvitedAt: Timestamp | null;\n managedTeamAccess: Generated<'all' | 'assigned'>;\n permissionBundles: Generated<string[]>;\n role: Generated<string | null>;\n status: Generated<string | null>;\n tenantId: string;\n updatedAt: Generated<Timestamp | null>;\n userId: string;\n}\n\nexport interface ControlPlaneToken {\n createdAt: Generated<Timestamp>;\n expiresAt: Timestamp | null;\n id: Generated<string>;\n nanoId: Generated<string>;\n payload: Generated<Json>;\n tenantId: string | null;\n type: string | null;\n userId: string | null;\n}\n\nexport interface ControlPlaneUser {\n clerkId: string | null;\n createdAt: Generated<Timestamp | null>;\n email: string | null;\n firstName: string | null;\n id: Generated<string>;\n internalOperationGrants: Generated<string[]>;\n isAdmin: Generated<boolean>;\n lastName: string | null;\n lastSeen: Timestamp | null;\n name: string | null;\n partnerId: string | null;\n phone: string | null;\n secondaryEmails: Generated<Json>;\n status: Generated<string | null>;\n sub: string | null;\n type: Generated<string | null>;\n updatedAt: Generated<Timestamp | null>;\n}\n\nexport interface ControlPlaneDB {\n 'controlPlane.accountingIntegrityDefinitionDraft': ControlPlaneAccountingIntegrityDefinitionDraft;\n 'controlPlane.accountingIntegrityDefinitionVersion': ControlPlaneAccountingIntegrityDefinitionVersion;\n 'controlPlane.accountingIntegrityEvaluation': ControlPlaneAccountingIntegrityEvaluation;\n 'controlPlane.app': ControlPlaneApp;\n 'controlPlane.bookingChannel': ControlPlaneBookingChannel;\n 'controlPlane.bookingChannelIconCandidate': ControlPlaneBookingChannelIconCandidate;\n 'controlPlane.connectionRoute': ControlPlaneConnectionRoute;\n 'controlPlane.controlPlaneOutbox': ControlPlaneOutbox;\n 'controlPlane.currency': ControlPlaneCurrency;\n 'controlPlane.destructiveJob': ControlPlaneDestructiveJob;\n 'controlPlane.destructiveJobAttempt': ControlPlaneDestructiveJobAttempt;\n 'controlPlane.destructiveJobOperation': ControlPlaneDestructiveJobOperation;\n 'controlPlane.events': ControlPlaneEvent;\n 'controlPlane.feature': ControlPlaneFeature;\n 'controlPlane.featureApproval': ControlPlaneFeatureApproval;\n 'controlPlane.featureEnabledTeam': ControlPlaneFeatureEnabledTeam;\n 'controlPlane.generalLedgerDefaultSet': ControlPlaneGeneralLedgerDefaultSet;\n 'controlPlane.generalLedgerDefaultVersion': ControlPlaneGeneralLedgerDefaultVersion;\n 'controlPlane.lineClassification': ControlPlaneLineClassification;\n 'controlPlane.lineClassificationTeamUsage': ControlPlaneLineClassificationTeamUsage;\n 'controlPlane.operation': ControlPlaneOperation;\n 'controlPlane.operationResource': ControlPlaneOperationResource;\n 'controlPlane.operationSource': ControlPlaneOperationSource;\n 'controlPlane.partnerManagedTeamAssignment': ControlPlanePartnerManagedTeamAssignment;\n 'controlPlane.reservationLineDefault': ControlPlaneReservationLineDefault;\n 'controlPlane.rolloutMonitorSnapshot': ControlPlaneRolloutMonitorSnapshot;\n 'controlPlane.ownerPortal': ControlPlaneOwnerPortal;\n 'controlPlane.tenant': ControlPlaneTenant;\n 'controlPlane.tenantRegionMigration': ControlPlaneTenantRegionMigration;\n 'controlPlane.tenantUser': ControlPlaneTenantUser;\n 'controlPlane.trackingQueueFailure': ControlPlaneTrackingQueueFailure;\n 'controlPlane.token': ControlPlaneToken;\n 'controlPlane.transactionLineMapping': ControlPlaneTransactionLineMapping;\n 'controlPlane.user': ControlPlaneUser;\n 'controlPlaneCore.flow': ControlPlaneFlow;\n 'controlPlaneCore.issueMessageOverwrite': ControlPlaneIssueMessageOverwrite;\n}\n\nclass ControlPlaneSchemaTransformer extends OperationNodeTransformer {\n constructor(\n readonly schema: string,\n readonly issueMessageOverwriteSchema: string\n ) {\n super();\n }\n\n protected override transformSchemableIdentifier(\n node: SchemableIdentifierNode,\n queryId: QueryId\n ): SchemableIdentifierNode {\n const transformed = super.transformSchemableIdentifier(node, queryId);\n if (\n transformed.schema?.name === 'controlPlane' ||\n transformed.schema?.name === 'control_plane'\n ) {\n return { ...transformed, schema: IdentifierNode.create(this.schema) };\n }\n if (\n transformed.schema?.name === 'controlPlaneCore' ||\n transformed.schema?.name === 'control_plane_core'\n ) {\n return {\n ...transformed,\n schema: IdentifierNode.create(this.issueMessageOverwriteSchema),\n };\n }\n return transformed;\n }\n\n protected override transformFunction(\n node: FunctionNode,\n queryId: QueryId\n ): FunctionNode {\n const transformed = super.transformFunction(node, queryId);\n return node.func.startsWith('controlPlane.')\n ? {\n ...transformed,\n func: `${this.schema}.${transformed.func.slice('controlPlane.'.length)}`,\n }\n : transformed;\n }\n}\n\nclass ControlPlaneSchemaPlugin implements KyselyPlugin {\n readonly #transformer: ControlPlaneSchemaTransformer;\n\n constructor(schema: string, issueMessageOverwriteSchema: string) {\n this.#transformer = new ControlPlaneSchemaTransformer(\n schema,\n issueMessageOverwriteSchema\n );\n }\n\n transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n return this.#transformer.transformNode(args.node, args.queryId);\n }\n\n async transformResult(\n args: PluginTransformResultArgs\n ): Promise<QueryResult<UnknownRow>> {\n return args.result;\n }\n}\n\nexport function withControlPlaneSchema(\n kysely: Kysely<ControlPlaneDB>,\n schema: string,\n issueMessageOverwriteSchema = 'core'\n) {\n return kysely.withPlugin(\n new ControlPlaneSchemaPlugin(schema, issueMessageOverwriteSchema)\n );\n}\n"]}
|
package/build/module/index.d.ts
CHANGED
|
@@ -8,22 +8,44 @@ export * from './postgres-error';
|
|
|
8
8
|
export * from './query';
|
|
9
9
|
export * from './regional';
|
|
10
10
|
export * from './transaction';
|
|
11
|
+
import type { TenantDataRegion } from './regional';
|
|
11
12
|
import type { DB } from './v1.generated';
|
|
13
|
+
/** The database a Worker reaches through its Hyperdrive binding. */
|
|
14
|
+
type HyperdriveDatabase = 'controlPlane' | 'regional';
|
|
12
15
|
type KyselyOpts = {
|
|
13
|
-
|
|
16
|
+
dataRegion?: TenantDataRegion;
|
|
17
|
+
hyperdrive?: HyperdriveDatabase;
|
|
18
|
+
onRetryDiagnostic?: (diagnostic: PostgresRetryDiagnostic) => void;
|
|
14
19
|
repositoryName?: string;
|
|
15
20
|
log?: true | LogConfig;
|
|
16
21
|
};
|
|
22
|
+
type PostgresRetryDiagnostic = {
|
|
23
|
+
attemptCount: number;
|
|
24
|
+
dataRegion?: TenantDataRegion;
|
|
25
|
+
operationKind: 'acquisition' | 'mutation' | 'select' | 'transaction';
|
|
26
|
+
outcome: 'exhausted' | 'notRetryable' | 'retrying';
|
|
27
|
+
repositoryName?: string;
|
|
28
|
+
};
|
|
17
29
|
type PgOpt = {
|
|
18
30
|
forceDisableSSL?: boolean;
|
|
19
31
|
probe?: true;
|
|
20
32
|
retries?: false | number;
|
|
21
33
|
} & Pick<KyselyOpts, 'hyperdrive'>;
|
|
34
|
+
/**
|
|
35
|
+
* Replays a complete database operation after a PostgreSQL deadlock (40P01)
|
|
36
|
+
* or lock timeout (55P03), using the same three-attempt jittered budget as
|
|
37
|
+
* connection retries. The operation must own its transaction and must not
|
|
38
|
+
* contain external side effects such as partner API writes.
|
|
39
|
+
*/
|
|
40
|
+
export declare function retryPostgresLockFailure<T>(operation: () => Promise<T>): Promise<T>;
|
|
22
41
|
export type Kysely = K<DB>;
|
|
23
42
|
export type ControlPlaneKysely = K<ControlPlaneDB>;
|
|
24
43
|
export type ControlPlaneTransaction = T<ControlPlaneDB>;
|
|
25
44
|
export declare function useKysely<Database = DB>(postgres: Sql, options?: KyselyOpts): K<Database>;
|
|
45
|
+
export declare function usePostgres(connectionString: string, opt?: Pick<PgOpt, 'forceDisableSSL' | 'hyperdrive'>): postgres.Sql<{}>;
|
|
26
46
|
export declare function useAsyncPostgres(connectionString: string, opt?: PgOpt): Promise<postgres.Sql<{}>>;
|
|
27
47
|
export declare function useAsyncKysely(connectionString: string, opt?: PgOpt & KyselyOpts): Promise<K<DB>>;
|
|
48
|
+
export declare function useAsyncNeonWebSocketKysely(connectionString: string, opt?: Pick<PgOpt, 'probe'> & KyselyOpts): Promise<K<DB>>;
|
|
49
|
+
export declare function useControlPlaneKysely(postgres: Sql, options?: KyselyOpts): K<ControlPlaneDB>;
|
|
28
50
|
export declare function useAsyncControlPlaneKysely(connectionString: string, opt?: PgOpt & KyselyOpts): Promise<K<ControlPlaneDB>>;
|
|
29
51
|
export declare function forceCloseAllPostgres(timeoutMs?: number): Promise<void>;
|
package/build/module/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { backOff } from 'exponential-backoff';
|
|
2
|
+
import { Pool } from '@neondatabase/serverless';
|
|
3
|
+
import { PostgresDialect } from 'kysely';
|
|
2
4
|
import { PostgresJSDialect, PostgresJSDriver, } from 'kysely-postgres-js';
|
|
3
5
|
import postgres from 'postgres';
|
|
4
6
|
import { withControlPlaneSchema } from './control-plane';
|
|
5
7
|
import { KyselyError } from './error';
|
|
6
8
|
import { getKysely } from './plugins';
|
|
9
|
+
import { isPostgresError } from './postgres-error';
|
|
7
10
|
export * from './error';
|
|
8
11
|
export * from './isomorphic';
|
|
9
12
|
export * from './postgres-error';
|
|
@@ -16,25 +19,117 @@ const retryableMessages = [
|
|
|
16
19
|
'CONNECT_TIMEOUT',
|
|
17
20
|
'Idle connection closed by Hyperdrive.',
|
|
18
21
|
'server_login_retry',
|
|
22
|
+
'Timed out while creating a new server connection.',
|
|
19
23
|
];
|
|
20
24
|
const postgresRetryAttempts = 3;
|
|
25
|
+
/**
|
|
26
|
+
* Parameter types PostgreSQL described per statement signature (PRO-18871).
|
|
27
|
+
* Postgres.js describes a statement in a round trip of its own before it can
|
|
28
|
+
* execute it when a parameter type is unknown, and a Worker request always
|
|
29
|
+
* starts on new connections. The patched driver reads and fills this map
|
|
30
|
+
* through its `statement_types` option and then parses, describes, binds and
|
|
31
|
+
* executes a known statement in one round trip. It forgets a statement's
|
|
32
|
+
* types when the statement fails, so a schema change is described again.
|
|
33
|
+
*/
|
|
34
|
+
class StatementTypes extends Map {
|
|
35
|
+
set(signature, types) {
|
|
36
|
+
if (!this.has(signature) && this.size >= 2000) {
|
|
37
|
+
this.delete(this.keys().next().value);
|
|
38
|
+
}
|
|
39
|
+
return super.set(signature, types);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Kept for the isolate's lifetime, one map per Hyperdrive database. */
|
|
43
|
+
const hyperdriveStatementTypes = {
|
|
44
|
+
controlPlane: new StatementTypes(),
|
|
45
|
+
regional: new StatementTypes(),
|
|
46
|
+
};
|
|
21
47
|
function isRetryableConnectionError(error) {
|
|
22
48
|
const message = error instanceof Error ? error.message : String(error);
|
|
23
49
|
return retryableMessages.some((retryable) => message.includes(retryable));
|
|
24
50
|
}
|
|
25
|
-
function
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
51
|
+
function isConnectionReset(error) {
|
|
52
|
+
return (error instanceof Error && 'code' in error && error.code === 'ECONNRESET');
|
|
53
|
+
}
|
|
54
|
+
function isRetryableConnectionAcquisitionError(error) {
|
|
55
|
+
return (isRetryableConnectionError(error) ||
|
|
56
|
+
isConnectionReset(error) ||
|
|
57
|
+
(error instanceof Error &&
|
|
58
|
+
(error.message === 'connection attempt failed' ||
|
|
59
|
+
('code' in error && error.code === 'CONNECTION_DESTROYED'))));
|
|
60
|
+
}
|
|
61
|
+
function isQueryRetryDiagnosticError(error) {
|
|
62
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
63
|
+
return (isRetryableConnectionError(error) ||
|
|
64
|
+
isConnectionReset(error) ||
|
|
65
|
+
message === 'Egress connection severed outside of Hyperdrive' ||
|
|
66
|
+
message === 'Network connection lost.' ||
|
|
67
|
+
message === 'Node shutting down' ||
|
|
68
|
+
message === 'Node shutting down.' ||
|
|
69
|
+
message === 'shutting down');
|
|
70
|
+
}
|
|
71
|
+
async function retryPostgres(operation, retry, diagnostic) {
|
|
72
|
+
let attemptCount = 0;
|
|
73
|
+
let retried = false;
|
|
74
|
+
const emitDiagnostic = (outcome) => {
|
|
75
|
+
if (!diagnostic)
|
|
76
|
+
return;
|
|
77
|
+
diagnostic.emit({
|
|
78
|
+
attemptCount,
|
|
79
|
+
dataRegion: diagnostic.dataRegion,
|
|
80
|
+
operationKind: diagnostic.operationKind,
|
|
81
|
+
outcome,
|
|
82
|
+
repositoryName: diagnostic.repositoryName,
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
try {
|
|
86
|
+
return await backOff(async () => {
|
|
87
|
+
attemptCount++;
|
|
88
|
+
return await operation();
|
|
89
|
+
}, {
|
|
90
|
+
numOfAttempts: postgresRetryAttempts,
|
|
91
|
+
startingDelay: parseDuration('1s'),
|
|
92
|
+
maxDelay: parseDuration('5s'),
|
|
93
|
+
// Scheduled chunk fan-outs open many connections at once; full jitter
|
|
94
|
+
// keeps their retries from reconnecting in lockstep.
|
|
95
|
+
jitter: 'full',
|
|
96
|
+
async retry(error, attemptNumber) {
|
|
97
|
+
const shouldRetry = attemptNumber < postgresRetryAttempts &&
|
|
98
|
+
(await retry(error, attemptNumber));
|
|
99
|
+
if (shouldRetry && diagnostic) {
|
|
100
|
+
retried = true;
|
|
101
|
+
emitDiagnostic('retrying');
|
|
102
|
+
}
|
|
103
|
+
return shouldRetry;
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (diagnostic?.shouldEmit(error)) {
|
|
109
|
+
emitDiagnostic(retried && attemptCount === postgresRetryAttempts
|
|
110
|
+
? 'exhausted'
|
|
111
|
+
: 'notRetryable');
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Replays a complete database operation after a PostgreSQL deadlock (40P01)
|
|
118
|
+
* or lock timeout (55P03), using the same three-attempt jittered budget as
|
|
119
|
+
* connection retries. The operation must own its transaction and must not
|
|
120
|
+
* contain external side effects such as partner API writes.
|
|
121
|
+
*/
|
|
122
|
+
export function retryPostgresLockFailure(operation) {
|
|
123
|
+
return retryPostgres(operation, (error) => isPostgresError(error, { code: '40P01' }) ||
|
|
124
|
+
isPostgresError(error, { code: '55P03' }));
|
|
32
125
|
}
|
|
33
126
|
class RetryingPostgresJSDialect extends PostgresJSDialect {
|
|
34
127
|
config;
|
|
35
|
-
|
|
128
|
+
retryDiagnostic;
|
|
129
|
+
constructor(config, retryDiagnostic) {
|
|
36
130
|
super(config);
|
|
37
131
|
this.config = config;
|
|
132
|
+
this.retryDiagnostic = retryDiagnostic;
|
|
38
133
|
}
|
|
39
134
|
createDriver() {
|
|
40
135
|
const driver = new PostgresJSDriver(this.config);
|
|
@@ -53,21 +148,38 @@ class RetryingPostgresJSDialect extends PostgresJSDialect {
|
|
|
53
148
|
inTransaction: false,
|
|
54
149
|
};
|
|
55
150
|
const connection = {
|
|
56
|
-
executeQuery: (compiledQuery) =>
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
151
|
+
executeQuery: (compiledQuery) => {
|
|
152
|
+
const operationKind = state.inTransaction
|
|
153
|
+
? 'transaction'
|
|
154
|
+
: compiledQuery.query.kind === 'SelectQueryNode'
|
|
155
|
+
? 'select'
|
|
156
|
+
: 'mutation';
|
|
157
|
+
return retryPostgres(() => state.connection.executeQuery(compiledQuery), async (error) => {
|
|
158
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
159
|
+
if (state.inTransaction ||
|
|
160
|
+
(!isRetryableConnectionError(error) &&
|
|
161
|
+
(compiledQuery.query.kind !== 'SelectQueryNode' ||
|
|
162
|
+
(!isConnectionReset(error) &&
|
|
163
|
+
message !==
|
|
164
|
+
'Egress connection severed outside of Hyperdrive' &&
|
|
165
|
+
message !== 'Network connection lost.' &&
|
|
166
|
+
message !== 'Node shutting down' &&
|
|
167
|
+
message !== 'Node shutting down.' &&
|
|
168
|
+
message !== 'shutting down')))) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
// Postgres.js already ejects a severed reserved connection.
|
|
172
|
+
// Acquire a new reservation before replaying the safe read.
|
|
173
|
+
state.connection = await driver.acquireConnection();
|
|
174
|
+
return true;
|
|
175
|
+
}, this.retryDiagnostic
|
|
176
|
+
? {
|
|
177
|
+
...this.retryDiagnostic,
|
|
178
|
+
operationKind,
|
|
179
|
+
shouldEmit: isQueryRetryDiagnosticError,
|
|
180
|
+
}
|
|
181
|
+
: undefined);
|
|
182
|
+
},
|
|
71
183
|
streamQuery: (compiledQuery, chunkSize) => {
|
|
72
184
|
if (chunkSize === undefined) {
|
|
73
185
|
throw new Error('Postgres stream chunk size is required');
|
|
@@ -120,16 +232,35 @@ class RetryingPostgresJSDialect extends PostgresJSDialect {
|
|
|
120
232
|
}
|
|
121
233
|
export function useKysely(postgres, options) {
|
|
122
234
|
console.debug('Creating Kysely instance');
|
|
235
|
+
const emitRetryDiagnostic = options?.onRetryDiagnostic ??
|
|
236
|
+
(options?.repositoryName
|
|
237
|
+
? (diagnostic) => console.warn('Postgres operation retry diagnostic', diagnostic)
|
|
238
|
+
: undefined);
|
|
123
239
|
const reserveConnection = postgres.reserve.bind(postgres);
|
|
124
240
|
postgres.reserve = async () => {
|
|
125
|
-
const connection = await retryPostgres(reserveConnection,
|
|
241
|
+
const connection = await retryPostgres(reserveConnection, isRetryableConnectionAcquisitionError, emitRetryDiagnostic
|
|
242
|
+
? {
|
|
243
|
+
dataRegion: options?.dataRegion,
|
|
244
|
+
emit: emitRetryDiagnostic,
|
|
245
|
+
operationKind: 'acquisition',
|
|
246
|
+
repositoryName: options?.repositoryName,
|
|
247
|
+
shouldEmit: isRetryableConnectionAcquisitionError,
|
|
248
|
+
}
|
|
249
|
+
: undefined);
|
|
126
250
|
if (options?.hyperdrive) {
|
|
127
251
|
const unsafe = connection.unsafe;
|
|
128
252
|
connection.unsafe = (query, parameters, queryOptions) => unsafe(query, parameters, { ...queryOptions, prepare: true });
|
|
129
253
|
}
|
|
130
254
|
return connection;
|
|
131
255
|
};
|
|
132
|
-
const kysely = getKysely(new RetryingPostgresJSDialect({ postgres }
|
|
256
|
+
const kysely = getKysely(new RetryingPostgresJSDialect({ postgres }, emitRetryDiagnostic
|
|
257
|
+
? {
|
|
258
|
+
dataRegion: options?.dataRegion,
|
|
259
|
+
emit: emitRetryDiagnostic,
|
|
260
|
+
repositoryName: options?.repositoryName,
|
|
261
|
+
shouldEmit: isQueryRetryDiagnosticError,
|
|
262
|
+
}
|
|
263
|
+
: undefined), {
|
|
133
264
|
repositoryName: options?.repositoryName,
|
|
134
265
|
log: options?.log,
|
|
135
266
|
});
|
|
@@ -143,43 +274,55 @@ export function useKysely(postgres, options) {
|
|
|
143
274
|
return kysely;
|
|
144
275
|
}
|
|
145
276
|
let _connections = [];
|
|
277
|
+
export function usePostgres(connectionString, opt) {
|
|
278
|
+
const ssl = opt?.forceDisableSSL !== true && !opt?.hyperdrive;
|
|
279
|
+
const sql = postgres(connectionString, {
|
|
280
|
+
ssl: ssl ? 'require' : false,
|
|
281
|
+
target_session_attrs: 'read-write',
|
|
282
|
+
// Named prepared statements: PRO-17965 (Hyperdrive and Crunchy PgBouncer).
|
|
283
|
+
prepare: true,
|
|
284
|
+
...(opt?.hyperdrive
|
|
285
|
+
? {
|
|
286
|
+
max: 5,
|
|
287
|
+
// Retire idle clients before Hyperdrive can close them asynchronously.
|
|
288
|
+
idle_timeout: 10,
|
|
289
|
+
statement_types: hyperdriveStatementTypes[opt.hyperdrive],
|
|
290
|
+
}
|
|
291
|
+
: {
|
|
292
|
+
connect_timeout: 10,
|
|
293
|
+
idle_timeout: 60,
|
|
294
|
+
}),
|
|
295
|
+
});
|
|
296
|
+
// statement_timeout/lock_timeout are role-level settings on the cluster
|
|
297
|
+
// (ALTER ROLE application SET ...) so they cover every pooled
|
|
298
|
+
// connection; per-session SETs here only ever applied to one of them
|
|
299
|
+
_connections.push(sql);
|
|
300
|
+
return sql;
|
|
301
|
+
}
|
|
146
302
|
export async function useAsyncPostgres(connectionString, opt) {
|
|
147
303
|
const delayMs = 2500;
|
|
148
304
|
const probe = opt?.probe === true;
|
|
149
305
|
const retries = probe ? (opt?.retries === false ? 0 : opt?.retries || 3) : 1;
|
|
150
|
-
const ssl = opt?.forceDisableSSL !== true && opt?.hyperdrive !== true;
|
|
151
306
|
const url = new URL(connectionString);
|
|
152
|
-
console.debug(`Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${
|
|
307
|
+
console.debug(`Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${opt?.forceDisableSSL !== true && !opt?.hyperdrive}, and port=${url.port}`);
|
|
153
308
|
if (_connections.length > 0)
|
|
154
309
|
console.warn(`We already have ${_connections.length} Postgres connections`);
|
|
155
310
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
311
|
+
let sql;
|
|
156
312
|
try {
|
|
157
|
-
|
|
158
|
-
ssl: ssl ? 'require' : false,
|
|
159
|
-
target_session_attrs: 'read-write',
|
|
160
|
-
// enable prepare statements, pgbouncer on crunchy allows for prepared statements
|
|
161
|
-
prepare: true,
|
|
162
|
-
...(opt?.hyperdrive
|
|
163
|
-
? {
|
|
164
|
-
max: 5,
|
|
165
|
-
// Retire idle clients before Hyperdrive can close them asynchronously.
|
|
166
|
-
idle_timeout: 10,
|
|
167
|
-
}
|
|
168
|
-
: {
|
|
169
|
-
connect_timeout: 10,
|
|
170
|
-
idle_timeout: 60,
|
|
171
|
-
}),
|
|
172
|
-
});
|
|
313
|
+
sql = usePostgres(connectionString, opt);
|
|
173
314
|
if (probe) {
|
|
174
|
-
|
|
315
|
+
// Opening a connection already checks that the session is writable
|
|
316
|
+
// and loads the array types; a probe query would add a round trip.
|
|
317
|
+
(await sql.reserve()).release();
|
|
175
318
|
}
|
|
176
|
-
// statement_timeout/lock_timeout are role-level settings on the cluster
|
|
177
|
-
// (ALTER ROLE application SET ...) so they cover every pooled
|
|
178
|
-
// connection; per-session SETs here only ever applied to one of them
|
|
179
|
-
_connections.push(sql);
|
|
180
319
|
return sql;
|
|
181
320
|
}
|
|
182
321
|
catch (err) {
|
|
322
|
+
if (sql) {
|
|
323
|
+
await sql.end({ timeout: 0 }).catch(() => undefined);
|
|
324
|
+
_connections.splice(_connections.indexOf(sql), 1);
|
|
325
|
+
}
|
|
183
326
|
if (attempt === retries)
|
|
184
327
|
throw err;
|
|
185
328
|
console.warn(`Postgres connection failed (attempt ${attempt}), retrying...`);
|
|
@@ -193,9 +336,22 @@ export async function useAsyncKysely(connectionString, opt) {
|
|
|
193
336
|
const sql = await useAsyncPostgres(connectionString, opt);
|
|
194
337
|
return useKysely(sql, opt);
|
|
195
338
|
}
|
|
339
|
+
export async function useAsyncNeonWebSocketKysely(connectionString, opt) {
|
|
340
|
+
const pool = new Pool({ connectionString, max: 5 });
|
|
341
|
+
const kysely = getKysely(new PostgresDialect({ pool }), opt ?? {});
|
|
342
|
+
kysely.destroy = async () => {
|
|
343
|
+
console.debug('Closing Neon WebSocket Kysely connection');
|
|
344
|
+
await pool.end();
|
|
345
|
+
};
|
|
346
|
+
if (opt?.probe)
|
|
347
|
+
await pool.query('select 1');
|
|
348
|
+
return kysely;
|
|
349
|
+
}
|
|
350
|
+
export function useControlPlaneKysely(postgres, options) {
|
|
351
|
+
return withControlPlaneSchema(useKysely(postgres, options), 'public');
|
|
352
|
+
}
|
|
196
353
|
export async function useAsyncControlPlaneKysely(connectionString, opt) {
|
|
197
|
-
|
|
198
|
-
return withControlPlaneSchema(useKysely(sql, opt), 'public');
|
|
354
|
+
return useControlPlaneKysely(await useAsyncPostgres(connectionString, opt), opt);
|
|
199
355
|
}
|
|
200
356
|
export async function forceCloseAllPostgres(timeoutMs = 5000) {
|
|
201
357
|
await Promise.race([
|