@pipeline-builder/pipeline-data 0.0.1
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 +202 -0
- package/README.md +61 -0
- package/drizzle.config.ts +17 -0
- package/lib/api/access-control-builder.d.ts +148 -0
- package/lib/api/access-control-builder.js +199 -0
- package/lib/api/crud-service.d.ts +343 -0
- package/lib/api/crud-service.js +849 -0
- package/lib/api/query-builders.d.ts +82 -0
- package/lib/api/query-builders.js +460 -0
- package/lib/api/reporting-service.d.ts +685 -0
- package/lib/api/reporting-service.js +1564 -0
- package/lib/api/soft-delete-sweep.d.ts +65 -0
- package/lib/api/soft-delete-sweep.js +124 -0
- package/lib/api/viewer-context.d.ts +29 -0
- package/lib/api/viewer-context.js +63 -0
- package/lib/core/query-filters.d.ts +263 -0
- package/lib/core/query-filters.js +4 -0
- package/lib/database/drizzle-schema.d.ts +7357 -0
- package/lib/database/drizzle-schema.js +66 -0
- package/lib/database/index.d.ts +5 -0
- package/lib/database/index.js +8 -0
- package/lib/database/migrator.d.ts +20 -0
- package/lib/database/migrator.js +80 -0
- package/lib/database/postgres-connection.d.ts +201 -0
- package/lib/database/postgres-connection.js +413 -0
- package/lib/database/retry-strategy.d.ts +68 -0
- package/lib/database/retry-strategy.js +122 -0
- package/lib/database/schema/alert.d.ts +588 -0
- package/lib/database/schema/alert.js +130 -0
- package/lib/database/schema/compliance.d.ts +3319 -0
- package/lib/database/schema/compliance.js +377 -0
- package/lib/database/schema/dashboard.d.ts +474 -0
- package/lib/database/schema/dashboard.js +129 -0
- package/lib/database/schema/message-attachment.d.ts +183 -0
- package/lib/database/schema/message-attachment.js +40 -0
- package/lib/database/schema/message.d.ts +411 -0
- package/lib/database/schema/message.js +114 -0
- package/lib/database/schema/pipeline-template.d.ts +466 -0
- package/lib/database/schema/pipeline-template.js +80 -0
- package/lib/database/schema/pipeline.d.ts +1613 -0
- package/lib/database/schema/pipeline.js +332 -0
- package/lib/database/schema/plugin.d.ts +749 -0
- package/lib/database/schema/plugin.js +166 -0
- package/lib/database/tenancy.d.ts +103 -0
- package/lib/database/tenancy.js +167 -0
- package/lib/index.d.ts +32 -0
- package/lib/index.js +38 -0
- package/package.json +161 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// Barrel for the Drizzle schema. The table/type definitions live in per-domain
|
|
5
|
+
// files under `./schema/*`; this module re-exports every one of them so the
|
|
6
|
+
// public API is byte-identical to the previous single-file schema. Existing
|
|
7
|
+
// `import { ... } from '.../drizzle-schema'` sites and the aggregate `schema`
|
|
8
|
+
// object below both continue to resolve exactly as before.
|
|
9
|
+
//
|
|
10
|
+
export * from './schema/plugin.js';
|
|
11
|
+
export * from './schema/pipeline.js';
|
|
12
|
+
export * from './schema/pipeline-template.js';
|
|
13
|
+
export * from './schema/message.js';
|
|
14
|
+
export * from './schema/message-attachment.js';
|
|
15
|
+
export * from './schema/compliance.js';
|
|
16
|
+
export * from './schema/dashboard.js';
|
|
17
|
+
export * from './schema/alert.js';
|
|
18
|
+
import { orgAlertDestination, orgAlertRule } from './schema/alert.js';
|
|
19
|
+
import { compliancePolicy, complianceRule, complianceRuleHistory, complianceAuditLog, complianceExemption, complianceRuleSubscription, complianceScan, complianceScanSchedule, complianceNotificationPreference, complianceNotificationLog, complianceRole, complianceReport, complianceReportSchedule, } from './schema/compliance.js';
|
|
20
|
+
import { dashboard, dashboardPanel } from './schema/dashboard.js';
|
|
21
|
+
import { messageAttachment } from './schema/message-attachment.js';
|
|
22
|
+
import { message } from './schema/message.js';
|
|
23
|
+
import { pipelineTemplate } from './schema/pipeline-template.js';
|
|
24
|
+
import { pipeline, pipelineRegistry, pipelineEvent, deploymentOutcome, ingestHealth, incident, doraSettings } from './schema/pipeline.js';
|
|
25
|
+
import { plugin } from './schema/plugin.js';
|
|
26
|
+
/**
|
|
27
|
+
* Complete Drizzle schema export
|
|
28
|
+
*/
|
|
29
|
+
export const schema = {
|
|
30
|
+
plugin,
|
|
31
|
+
pipeline,
|
|
32
|
+
pipelineTemplate,
|
|
33
|
+
message,
|
|
34
|
+
messageAttachment,
|
|
35
|
+
pipelineRegistry,
|
|
36
|
+
pipelineEvent,
|
|
37
|
+
// DORA post-deploy outcome markers + per-org ingestion health
|
|
38
|
+
deploymentOutcome,
|
|
39
|
+
ingestHealth,
|
|
40
|
+
// Production incidents (webhook-ingested) → automated post-deploy CFR + MTTR
|
|
41
|
+
incident,
|
|
42
|
+
// Per-org DORA overrides (incident correlation window)
|
|
43
|
+
doraSettings,
|
|
44
|
+
// Observability dashboards (user-editable replacement for code-defined dashboards)
|
|
45
|
+
dashboard,
|
|
46
|
+
dashboardPanel,
|
|
47
|
+
// Per-org alert notification destinations (multi-tenant alerting)
|
|
48
|
+
orgAlertDestination,
|
|
49
|
+
// per-org operator-authored alert rules materialized into Prom YAML.
|
|
50
|
+
orgAlertRule,
|
|
51
|
+
// Compliance tables
|
|
52
|
+
compliancePolicy,
|
|
53
|
+
complianceRule,
|
|
54
|
+
complianceRuleHistory,
|
|
55
|
+
complianceAuditLog,
|
|
56
|
+
complianceExemption,
|
|
57
|
+
complianceRuleSubscription,
|
|
58
|
+
complianceScan,
|
|
59
|
+
complianceScanSchedule,
|
|
60
|
+
complianceNotificationPreference,
|
|
61
|
+
complianceNotificationLog,
|
|
62
|
+
complianceRole,
|
|
63
|
+
complianceReport,
|
|
64
|
+
complianceReportSchedule,
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJpenpsZS1zY2hlbWEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0YWJhc2UvZHJpenpsZS1zY2hlbWEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLDJEQUEyRDtBQUMzRCxFQUFFO0FBRUYsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLG1CQUFtQixDQUFDO0FBRWxDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN0RSxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLGNBQWMsRUFDZCxxQkFBcUIsRUFDckIsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQiwwQkFBMEIsRUFDMUIsY0FBYyxFQUNkLHNCQUFzQixFQUN0QixnQ0FBZ0MsRUFDaEMseUJBQXlCLEVBQ3pCLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsd0JBQXdCLEdBQ3pCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDakUsT0FBTyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsaUJBQWlCLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMxSSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFNUM7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxNQUFNLEdBQUc7SUFDcEIsTUFBTTtJQUNOLFFBQVE7SUFDUixnQkFBZ0I7SUFDaEIsT0FBTztJQUNQLGlCQUFpQjtJQUNqQixnQkFBZ0I7SUFDaEIsYUFBYTtJQUNiLDhEQUE4RDtJQUM5RCxpQkFBaUI7SUFDakIsWUFBWTtJQUNaLDZFQUE2RTtJQUM3RSxRQUFRO0lBQ1IsdURBQXVEO0lBQ3ZELFlBQVk7SUFDWixtRkFBbUY7SUFDbkYsU0FBUztJQUNULGNBQWM7SUFDZCxrRUFBa0U7SUFDbEUsbUJBQW1CO0lBQ25CLHNFQUFzRTtJQUN0RSxZQUFZO0lBQ1osb0JBQW9CO0lBQ3BCLGdCQUFnQjtJQUNoQixjQUFjO0lBQ2QscUJBQXFCO0lBQ3JCLGtCQUFrQjtJQUNsQixtQkFBbUI7SUFDbkIsMEJBQTBCO0lBQzFCLGNBQWM7SUFDZCxzQkFBc0I7SUFDdEIsZ0NBQWdDO0lBQ2hDLHlCQUF5QjtJQUN6QixjQUFjO0lBQ2QsZ0JBQWdCO0lBQ2hCLHdCQUF3QjtDQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8vXG4vLyBCYXJyZWwgZm9yIHRoZSBEcml6emxlIHNjaGVtYS4gVGhlIHRhYmxlL3R5cGUgZGVmaW5pdGlvbnMgbGl2ZSBpbiBwZXItZG9tYWluXG4vLyBmaWxlcyB1bmRlciBgLi9zY2hlbWEvKmA7IHRoaXMgbW9kdWxlIHJlLWV4cG9ydHMgZXZlcnkgb25lIG9mIHRoZW0gc28gdGhlXG4vLyBwdWJsaWMgQVBJIGlzIGJ5dGUtaWRlbnRpY2FsIHRvIHRoZSBwcmV2aW91cyBzaW5nbGUtZmlsZSBzY2hlbWEuIEV4aXN0aW5nXG4vLyBgaW1wb3J0IHsgLi4uIH0gZnJvbSAnLi4uL2RyaXp6bGUtc2NoZW1hJ2Agc2l0ZXMgYW5kIHRoZSBhZ2dyZWdhdGUgYHNjaGVtYWBcbi8vIG9iamVjdCBiZWxvdyBib3RoIGNvbnRpbnVlIHRvIHJlc29sdmUgZXhhY3RseSBhcyBiZWZvcmUuXG4vL1xuXG5leHBvcnQgKiBmcm9tICcuL3NjaGVtYS9wbHVnaW4uanMnO1xuZXhwb3J0ICogZnJvbSAnLi9zY2hlbWEvcGlwZWxpbmUuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9zY2hlbWEvcGlwZWxpbmUtdGVtcGxhdGUuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9zY2hlbWEvbWVzc2FnZS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3NjaGVtYS9tZXNzYWdlLWF0dGFjaG1lbnQuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9zY2hlbWEvY29tcGxpYW5jZS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3NjaGVtYS9kYXNoYm9hcmQuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9zY2hlbWEvYWxlcnQuanMnO1xuXG5pbXBvcnQgeyBvcmdBbGVydERlc3RpbmF0aW9uLCBvcmdBbGVydFJ1bGUgfSBmcm9tICcuL3NjaGVtYS9hbGVydC5qcyc7XG5pbXBvcnQge1xuICBjb21wbGlhbmNlUG9saWN5LFxuICBjb21wbGlhbmNlUnVsZSxcbiAgY29tcGxpYW5jZVJ1bGVIaXN0b3J5LFxuICBjb21wbGlhbmNlQXVkaXRMb2csXG4gIGNvbXBsaWFuY2VFeGVtcHRpb24sXG4gIGNvbXBsaWFuY2VSdWxlU3Vic2NyaXB0aW9uLFxuICBjb21wbGlhbmNlU2NhbixcbiAgY29tcGxpYW5jZVNjYW5TY2hlZHVsZSxcbiAgY29tcGxpYW5jZU5vdGlmaWNhdGlvblByZWZlcmVuY2UsXG4gIGNvbXBsaWFuY2VOb3RpZmljYXRpb25Mb2csXG4gIGNvbXBsaWFuY2VSb2xlLFxuICBjb21wbGlhbmNlUmVwb3J0LFxuICBjb21wbGlhbmNlUmVwb3J0U2NoZWR1bGUsXG59IGZyb20gJy4vc2NoZW1hL2NvbXBsaWFuY2UuanMnO1xuaW1wb3J0IHsgZGFzaGJvYXJkLCBkYXNoYm9hcmRQYW5lbCB9IGZyb20gJy4vc2NoZW1hL2Rhc2hib2FyZC5qcyc7XG5pbXBvcnQgeyBtZXNzYWdlQXR0YWNobWVudCB9IGZyb20gJy4vc2NoZW1hL21lc3NhZ2UtYXR0YWNobWVudC5qcyc7XG5pbXBvcnQgeyBtZXNzYWdlIH0gZnJvbSAnLi9zY2hlbWEvbWVzc2FnZS5qcyc7XG5pbXBvcnQgeyBwaXBlbGluZVRlbXBsYXRlIH0gZnJvbSAnLi9zY2hlbWEvcGlwZWxpbmUtdGVtcGxhdGUuanMnO1xuaW1wb3J0IHsgcGlwZWxpbmUsIHBpcGVsaW5lUmVnaXN0cnksIHBpcGVsaW5lRXZlbnQsIGRlcGxveW1lbnRPdXRjb21lLCBpbmdlc3RIZWFsdGgsIGluY2lkZW50LCBkb3JhU2V0dGluZ3MgfSBmcm9tICcuL3NjaGVtYS9waXBlbGluZS5qcyc7XG5pbXBvcnQgeyBwbHVnaW4gfSBmcm9tICcuL3NjaGVtYS9wbHVnaW4uanMnO1xuXG4vKipcbiAqIENvbXBsZXRlIERyaXp6bGUgc2NoZW1hIGV4cG9ydFxuICovXG5leHBvcnQgY29uc3Qgc2NoZW1hID0ge1xuICBwbHVnaW4sXG4gIHBpcGVsaW5lLFxuICBwaXBlbGluZVRlbXBsYXRlLFxuICBtZXNzYWdlLFxuICBtZXNzYWdlQXR0YWNobWVudCxcbiAgcGlwZWxpbmVSZWdpc3RyeSxcbiAgcGlwZWxpbmVFdmVudCxcbiAgLy8gRE9SQSBwb3N0LWRlcGxveSBvdXRjb21lIG1hcmtlcnMgKyBwZXItb3JnIGluZ2VzdGlvbiBoZWFsdGhcbiAgZGVwbG95bWVudE91dGNvbWUsXG4gIGluZ2VzdEhlYWx0aCxcbiAgLy8gUHJvZHVjdGlvbiBpbmNpZGVudHMgKHdlYmhvb2staW5nZXN0ZWQpIOKGkiBhdXRvbWF0ZWQgcG9zdC1kZXBsb3kgQ0ZSICsgTVRUUlxuICBpbmNpZGVudCxcbiAgLy8gUGVyLW9yZyBET1JBIG92ZXJyaWRlcyAoaW5jaWRlbnQgY29ycmVsYXRpb24gd2luZG93KVxuICBkb3JhU2V0dGluZ3MsXG4gIC8vIE9ic2VydmFiaWxpdHkgZGFzaGJvYXJkcyAodXNlci1lZGl0YWJsZSByZXBsYWNlbWVudCBmb3IgY29kZS1kZWZpbmVkIGRhc2hib2FyZHMpXG4gIGRhc2hib2FyZCxcbiAgZGFzaGJvYXJkUGFuZWwsXG4gIC8vIFBlci1vcmcgYWxlcnQgbm90aWZpY2F0aW9uIGRlc3RpbmF0aW9ucyAobXVsdGktdGVuYW50IGFsZXJ0aW5nKVxuICBvcmdBbGVydERlc3RpbmF0aW9uLFxuICAvLyBwZXItb3JnIG9wZXJhdG9yLWF1dGhvcmVkIGFsZXJ0IHJ1bGVzICBtYXRlcmlhbGl6ZWQgaW50byBQcm9tIFlBTUwuXG4gIG9yZ0FsZXJ0UnVsZSxcbiAgLy8gQ29tcGxpYW5jZSB0YWJsZXNcbiAgY29tcGxpYW5jZVBvbGljeSxcbiAgY29tcGxpYW5jZVJ1bGUsXG4gIGNvbXBsaWFuY2VSdWxlSGlzdG9yeSxcbiAgY29tcGxpYW5jZUF1ZGl0TG9nLFxuICBjb21wbGlhbmNlRXhlbXB0aW9uLFxuICBjb21wbGlhbmNlUnVsZVN1YnNjcmlwdGlvbixcbiAgY29tcGxpYW5jZVNjYW4sXG4gIGNvbXBsaWFuY2VTY2FuU2NoZWR1bGUsXG4gIGNvbXBsaWFuY2VOb3RpZmljYXRpb25QcmVmZXJlbmNlLFxuICBjb21wbGlhbmNlTm90aWZpY2F0aW9uTG9nLFxuICBjb21wbGlhbmNlUm9sZSxcbiAgY29tcGxpYW5jZVJlcG9ydCxcbiAgY29tcGxpYW5jZVJlcG9ydFNjaGVkdWxlLFxufSBhcyBjb25zdDtcbiJdfQ==
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
export * from './drizzle-schema.js';
|
|
4
|
+
export * from './postgres-connection.js';
|
|
5
|
+
export * from './retry-strategy.js';
|
|
6
|
+
export * from './tenancy.js';
|
|
7
|
+
export { runMigrations } from './migrator.js';
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0YWJhc2UvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixPQUFPLEVBQUUsYUFBYSxFQUF1QixNQUFNLGVBQWUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5leHBvcnQgKiBmcm9tICcuL2RyaXp6bGUtc2NoZW1hLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vcG9zdGdyZXMtY29ubmVjdGlvbi5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3JldHJ5LXN0cmF0ZWd5LmpzJztcbmV4cG9ydCAqIGZyb20gJy4vdGVuYW5jeS5qcyc7XG5leHBvcnQgeyBydW5NaWdyYXRpb25zLCB0eXBlIE1pZ3JhdGVPcHRpb25zIH0gZnJvbSAnLi9taWdyYXRvci5qcyc7XG4iXX0=
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface MigrateOptions {
|
|
2
|
+
/** Absolute path to the migrations folder. Defaults to `<package>/drizzle`. */
|
|
3
|
+
migrationsFolder?: string;
|
|
4
|
+
/** Schema-qualified migrations table name. Defaults to `__drizzle_migrations`. */
|
|
5
|
+
migrationsTable?: string;
|
|
6
|
+
/** Skip the runner entirely (for tests or when a deploy uses an external migration tool). */
|
|
7
|
+
skip?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Run any pending Drizzle migrations against the configured Postgres.
|
|
11
|
+
*
|
|
12
|
+
* No-ops gracefully when:
|
|
13
|
+
* - `options.skip` is true
|
|
14
|
+
* - `RUN_DB_MIGRATIONS` env var is set to a falsy value (`0`/`false`)
|
|
15
|
+
* - the migrations folder doesn't exist (fresh repo, nothing generated yet)
|
|
16
|
+
*
|
|
17
|
+
* Throws on any actual migration failure so the service refuses to start
|
|
18
|
+
* with a half-applied schema.
|
|
19
|
+
*/
|
|
20
|
+
export declare function runMigrations(options?: MigrateOptions): Promise<void>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Drizzle migration runner.
|
|
5
|
+
*
|
|
6
|
+
* Idempotent: safe to call on every service start. drizzle tracks applied
|
|
7
|
+
* migrations in the `__drizzle_migrations` table and skips ones already run.
|
|
8
|
+
*
|
|
9
|
+
* The migration files live at `packages/pipeline-data/drizzle/` and are
|
|
10
|
+
* generated from the `drizzle-schema.ts` source via `pnpm db:generate`
|
|
11
|
+
* (which invokes `drizzle-kit generate`).
|
|
12
|
+
*
|
|
13
|
+
* For brand-new deploys, `postgres-init.sql` still creates the baseline
|
|
14
|
+
* tables — the migration runner will skip its initial baseline migration
|
|
15
|
+
* because the tables already exist (drizzle uses CREATE TABLE IF NOT EXISTS
|
|
16
|
+
* by default for the snapshot-based generator). Future schema changes ship
|
|
17
|
+
* as additive migrations.
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'fs';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
import { createLogger } from '@pipeline-builder/api-core';
|
|
23
|
+
import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
|
24
|
+
import { getConnection } from './postgres-connection.js';
|
|
25
|
+
const logger = createLogger('migrator');
|
|
26
|
+
// ESM has no __dirname; derive it from this module's URL. Without this the
|
|
27
|
+
// migration runner threw `ReferenceError: __dirname is not defined` at startup
|
|
28
|
+
// (onBeforeStart → runMigrations), crash-looping every service that migrates.
|
|
29
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
/** Resolve the default migrations folder relative to this package. */
|
|
31
|
+
function defaultMigrationsFolder() {
|
|
32
|
+
// src/database/migrator.ts → up two levels → package root, then ./drizzle
|
|
33
|
+
return path.resolve(__dirname, '..', '..', 'drizzle');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Run any pending Drizzle migrations against the configured Postgres.
|
|
37
|
+
*
|
|
38
|
+
* No-ops gracefully when:
|
|
39
|
+
* - `options.skip` is true
|
|
40
|
+
* - `RUN_DB_MIGRATIONS` env var is set to a falsy value (`0`/`false`)
|
|
41
|
+
* - the migrations folder doesn't exist (fresh repo, nothing generated yet)
|
|
42
|
+
*
|
|
43
|
+
* Throws on any actual migration failure so the service refuses to start
|
|
44
|
+
* with a half-applied schema.
|
|
45
|
+
*/
|
|
46
|
+
export async function runMigrations(options = {}) {
|
|
47
|
+
if (options.skip) {
|
|
48
|
+
logger.info('Migration runner skipped via options.skip');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const envFlag = process.env.RUN_DB_MIGRATIONS;
|
|
52
|
+
if (envFlag !== undefined && (envFlag === '0' || envFlag.toLowerCase() === 'false')) {
|
|
53
|
+
logger.info('Migration runner skipped via RUN_DB_MIGRATIONS env');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const migrationsFolder = options.migrationsFolder ?? defaultMigrationsFolder();
|
|
57
|
+
if (!fs.existsSync(migrationsFolder)) {
|
|
58
|
+
logger.info('No migrations folder found, nothing to run', { migrationsFolder });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const journalPath = path.join(migrationsFolder, 'meta', '_journal.json');
|
|
62
|
+
if (!fs.existsSync(journalPath)) {
|
|
63
|
+
logger.info('No drizzle journal found, nothing to run', { journalPath });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const conn = getConnection();
|
|
67
|
+
const migrationsTable = options.migrationsTable ?? '__drizzle_migrations';
|
|
68
|
+
logger.info('Running pending Drizzle migrations', { migrationsFolder, migrationsTable });
|
|
69
|
+
try {
|
|
70
|
+
await migrate(conn.db, { migrationsFolder, migrationsTable });
|
|
71
|
+
logger.info('Drizzle migrations complete');
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
logger.error('Drizzle migration failed — refusing to start', {
|
|
75
|
+
error: err instanceof Error ? err.message : String(err),
|
|
76
|
+
});
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0YWJhc2UvbWlncmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDN0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXpELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUV4QywyRUFBMkU7QUFDM0UsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBVy9ELHNFQUFzRTtBQUN0RSxTQUFTLHVCQUF1QjtJQUM5QiwwRUFBMEU7SUFDMUUsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ3hELENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxhQUFhLENBQUMsT0FBTyxHQUFtQixFQUFFO0lBQzlELElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkNBQTJDLENBQUMsQ0FBQztRQUN6RCxPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUM7SUFDOUMsSUFBSSxPQUFPLEtBQUssU0FBUyxJQUFJLENBQUMsT0FBTyxLQUFLLEdBQUcsSUFBSSxPQUFPLENBQUMsV0FBVyxFQUFFLEtBQUssT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNwRixNQUFNLENBQUMsSUFBSSxDQUFDLG9EQUFvRCxDQUFDLENBQUM7UUFDbEUsT0FBTztJQUNULENBQUM7SUFFRCxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSx1QkFBdUIsRUFBRSxDQUFDO0lBQy9FLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztRQUNyQyxNQUFNLENBQUMsSUFBSSxDQUFDLDRDQUE0QyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO1FBQ2hGLE9BQU87SUFDVCxDQUFDO0lBRUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFDekUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztRQUNoQyxNQUFNLENBQUMsSUFBSSxDQUFDLDBDQUEwQyxFQUFFLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUN6RSxPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sSUFBSSxHQUFHLGFBQWEsRUFBRSxDQUFDO0lBQzdCLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxlQUFlLElBQUksc0JBQXNCLENBQUM7SUFFMUUsTUFBTSxDQUFDLElBQUksQ0FBQyxvQ0FBb0MsRUFBRSxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUM7SUFDekYsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUM7UUFDOUQsTUFBTSxDQUFDLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQyw4Q0FBOEMsRUFBRTtZQUMzRCxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztTQUN4RCxDQUFDLENBQUM7UUFDSCxNQUFNLEdBQUcsQ0FBQztJQUNaLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogRHJpenpsZSBtaWdyYXRpb24gcnVubmVyLlxuICpcbiAqIElkZW1wb3RlbnQ6IHNhZmUgdG8gY2FsbCBvbiBldmVyeSBzZXJ2aWNlIHN0YXJ0LiBkcml6emxlIHRyYWNrcyBhcHBsaWVkXG4gKiBtaWdyYXRpb25zIGluIHRoZSBgX19kcml6emxlX21pZ3JhdGlvbnNgIHRhYmxlIGFuZCBza2lwcyBvbmVzIGFscmVhZHkgcnVuLlxuICpcbiAqIFRoZSBtaWdyYXRpb24gZmlsZXMgbGl2ZSBhdCBgcGFja2FnZXMvcGlwZWxpbmUtZGF0YS9kcml6emxlL2AgYW5kIGFyZVxuICogZ2VuZXJhdGVkIGZyb20gdGhlIGBkcml6emxlLXNjaGVtYS50c2Agc291cmNlIHZpYSBgcG5wbSBkYjpnZW5lcmF0ZWBcbiAqICh3aGljaCBpbnZva2VzIGBkcml6emxlLWtpdCBnZW5lcmF0ZWApLlxuICpcbiAqIEZvciBicmFuZC1uZXcgZGVwbG95cywgYHBvc3RncmVzLWluaXQuc3FsYCBzdGlsbCBjcmVhdGVzIHRoZSBiYXNlbGluZVxuICogdGFibGVzIOKAlCB0aGUgbWlncmF0aW9uIHJ1bm5lciB3aWxsIHNraXAgaXRzIGluaXRpYWwgYmFzZWxpbmUgbWlncmF0aW9uXG4gKiBiZWNhdXNlIHRoZSB0YWJsZXMgYWxyZWFkeSBleGlzdCAoZHJpenpsZSB1c2VzIENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTXG4gKiBieSBkZWZhdWx0IGZvciB0aGUgc25hcHNob3QtYmFzZWQgZ2VuZXJhdG9yKS4gRnV0dXJlIHNjaGVtYSBjaGFuZ2VzIHNoaXBcbiAqIGFzIGFkZGl0aXZlIG1pZ3JhdGlvbnMuXG4gKi9cblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICd1cmwnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHsgbWlncmF0ZSB9IGZyb20gJ2RyaXp6bGUtb3JtL25vZGUtcG9zdGdyZXMvbWlncmF0b3InO1xuaW1wb3J0IHsgZ2V0Q29ubmVjdGlvbiB9IGZyb20gJy4vcG9zdGdyZXMtY29ubmVjdGlvbi5qcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcignbWlncmF0b3InKTtcblxuLy8gRVNNIGhhcyBubyBfX2Rpcm5hbWU7IGRlcml2ZSBpdCBmcm9tIHRoaXMgbW9kdWxlJ3MgVVJMLiBXaXRob3V0IHRoaXMgdGhlXG4vLyBtaWdyYXRpb24gcnVubmVyIHRocmV3IGBSZWZlcmVuY2VFcnJvcjogX19kaXJuYW1lIGlzIG5vdCBkZWZpbmVkYCBhdCBzdGFydHVwXG4vLyAob25CZWZvcmVTdGFydCDihpIgcnVuTWlncmF0aW9ucyksIGNyYXNoLWxvb3BpbmcgZXZlcnkgc2VydmljZSB0aGF0IG1pZ3JhdGVzLlxuY29uc3QgX19kaXJuYW1lID0gcGF0aC5kaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWlncmF0ZU9wdGlvbnMge1xuICAvKiogQWJzb2x1dGUgcGF0aCB0byB0aGUgbWlncmF0aW9ucyBmb2xkZXIuIERlZmF1bHRzIHRvIGA8cGFja2FnZT4vZHJpenpsZWAuICovXG4gIG1pZ3JhdGlvbnNGb2xkZXI/OiBzdHJpbmc7XG4gIC8qKiBTY2hlbWEtcXVhbGlmaWVkIG1pZ3JhdGlvbnMgdGFibGUgbmFtZS4gRGVmYXVsdHMgdG8gYF9fZHJpenpsZV9taWdyYXRpb25zYC4gKi9cbiAgbWlncmF0aW9uc1RhYmxlPzogc3RyaW5nO1xuICAvKiogU2tpcCB0aGUgcnVubmVyIGVudGlyZWx5IChmb3IgdGVzdHMgb3Igd2hlbiBhIGRlcGxveSB1c2VzIGFuIGV4dGVybmFsIG1pZ3JhdGlvbiB0b29sKS4gKi9cbiAgc2tpcD86IGJvb2xlYW47XG59XG5cbi8qKiBSZXNvbHZlIHRoZSBkZWZhdWx0IG1pZ3JhdGlvbnMgZm9sZGVyIHJlbGF0aXZlIHRvIHRoaXMgcGFja2FnZS4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRNaWdyYXRpb25zRm9sZGVyKCk6IHN0cmluZyB7XG4gIC8vIHNyYy9kYXRhYmFzZS9taWdyYXRvci50cyDihpIgdXAgdHdvIGxldmVscyDihpIgcGFja2FnZSByb290LCB0aGVuIC4vZHJpenpsZVxuICByZXR1cm4gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uJywgJy4uJywgJ2RyaXp6bGUnKTtcbn1cblxuLyoqXG4gKiBSdW4gYW55IHBlbmRpbmcgRHJpenpsZSBtaWdyYXRpb25zIGFnYWluc3QgdGhlIGNvbmZpZ3VyZWQgUG9zdGdyZXMuXG4gKlxuICogTm8tb3BzIGdyYWNlZnVsbHkgd2hlbjpcbiAqICAgLSBgb3B0aW9ucy5za2lwYCBpcyB0cnVlXG4gKiAgIC0gYFJVTl9EQl9NSUdSQVRJT05TYCBlbnYgdmFyIGlzIHNldCB0byBhIGZhbHN5IHZhbHVlIChgMGAvYGZhbHNlYClcbiAqICAgLSB0aGUgbWlncmF0aW9ucyBmb2xkZXIgZG9lc24ndCBleGlzdCAoZnJlc2ggcmVwbywgbm90aGluZyBnZW5lcmF0ZWQgeWV0KVxuICpcbiAqIFRocm93cyBvbiBhbnkgYWN0dWFsIG1pZ3JhdGlvbiBmYWlsdXJlIHNvIHRoZSBzZXJ2aWNlIHJlZnVzZXMgdG8gc3RhcnRcbiAqIHdpdGggYSBoYWxmLWFwcGxpZWQgc2NoZW1hLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuTWlncmF0aW9ucyhvcHRpb25zOiBNaWdyYXRlT3B0aW9ucyA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChvcHRpb25zLnNraXApIHtcbiAgICBsb2dnZXIuaW5mbygnTWlncmF0aW9uIHJ1bm5lciBza2lwcGVkIHZpYSBvcHRpb25zLnNraXAnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBlbnZGbGFnID0gcHJvY2Vzcy5lbnYuUlVOX0RCX01JR1JBVElPTlM7XG4gIGlmIChlbnZGbGFnICE9PSB1bmRlZmluZWQgJiYgKGVudkZsYWcgPT09ICcwJyB8fCBlbnZGbGFnLnRvTG93ZXJDYXNlKCkgPT09ICdmYWxzZScpKSB7XG4gICAgbG9nZ2VyLmluZm8oJ01pZ3JhdGlvbiBydW5uZXIgc2tpcHBlZCB2aWEgUlVOX0RCX01JR1JBVElPTlMgZW52Jyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgbWlncmF0aW9uc0ZvbGRlciA9IG9wdGlvbnMubWlncmF0aW9uc0ZvbGRlciA/PyBkZWZhdWx0TWlncmF0aW9uc0ZvbGRlcigpO1xuICBpZiAoIWZzLmV4aXN0c1N5bmMobWlncmF0aW9uc0ZvbGRlcikpIHtcbiAgICBsb2dnZXIuaW5mbygnTm8gbWlncmF0aW9ucyBmb2xkZXIgZm91bmQsIG5vdGhpbmcgdG8gcnVuJywgeyBtaWdyYXRpb25zRm9sZGVyIH0pO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGpvdXJuYWxQYXRoID0gcGF0aC5qb2luKG1pZ3JhdGlvbnNGb2xkZXIsICdtZXRhJywgJ19qb3VybmFsLmpzb24nKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGpvdXJuYWxQYXRoKSkge1xuICAgIGxvZ2dlci5pbmZvKCdObyBkcml6emxlIGpvdXJuYWwgZm91bmQsIG5vdGhpbmcgdG8gcnVuJywgeyBqb3VybmFsUGF0aCB9KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBjb25uID0gZ2V0Q29ubmVjdGlvbigpO1xuICBjb25zdCBtaWdyYXRpb25zVGFibGUgPSBvcHRpb25zLm1pZ3JhdGlvbnNUYWJsZSA/PyAnX19kcml6emxlX21pZ3JhdGlvbnMnO1xuXG4gIGxvZ2dlci5pbmZvKCdSdW5uaW5nIHBlbmRpbmcgRHJpenpsZSBtaWdyYXRpb25zJywgeyBtaWdyYXRpb25zRm9sZGVyLCBtaWdyYXRpb25zVGFibGUgfSk7XG4gIHRyeSB7XG4gICAgYXdhaXQgbWlncmF0ZShjb25uLmRiLCB7IG1pZ3JhdGlvbnNGb2xkZXIsIG1pZ3JhdGlvbnNUYWJsZSB9KTtcbiAgICBsb2dnZXIuaW5mbygnRHJpenpsZSBtaWdyYXRpb25zIGNvbXBsZXRlJyk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGxvZ2dlci5lcnJvcignRHJpenpsZSBtaWdyYXRpb24gZmFpbGVkIOKAlCByZWZ1c2luZyB0byBzdGFydCcsIHtcbiAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgfSk7XG4gICAgdGhyb3cgZXJyO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
2
|
+
import { Pool } from 'pg';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the pg TLS/SSL config from an explicit option or the environment,
|
|
5
|
+
* following the same env-tunable pattern as the pool sizing above.
|
|
6
|
+
*
|
|
7
|
+
* Precedence:
|
|
8
|
+
* 1. An explicit `options.ssl` (constructor arg) always wins — including an
|
|
9
|
+
* explicit `false` to force plaintext.
|
|
10
|
+
* 2. `DB_SSL` (`true`/`1` on, `false`/`0` off) or Postgres' standard
|
|
11
|
+
* `PGSSLMODE` (`disable` = off, any other mode = on).
|
|
12
|
+
* 3. Default: ON in production (RDS connections must be encrypted in transit),
|
|
13
|
+
* OFF everywhere else so a local Postgres without TLS keeps working.
|
|
14
|
+
*
|
|
15
|
+
* When enabled, `rejectUnauthorized` follows `DB_SSL_REJECT_UNAUTHORIZED`
|
|
16
|
+
* (default `false`): AWS RDS presents a cert signed by the RDS CA, which is not
|
|
17
|
+
* in Node's default trust store unless the CA bundle is mounted, so certificate
|
|
18
|
+
* VERIFICATION is opt-in to avoid breaking a stock RDS deploy — the channel is
|
|
19
|
+
* still ENCRYPTED. Set `DB_SSL_REJECT_UNAUTHORIZED=true` once the RDS CA bundle
|
|
20
|
+
* is wired to get full verification.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getSslConfig(explicit?: ConnectionOptions['ssl']): boolean | {
|
|
23
|
+
rejectUnauthorized: boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Database connection statistics for monitoring
|
|
27
|
+
*/
|
|
28
|
+
export interface ConnectionStats {
|
|
29
|
+
totalCount: number;
|
|
30
|
+
idleCount: number;
|
|
31
|
+
waitingCount: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Options for configuring the database connection
|
|
35
|
+
*/
|
|
36
|
+
export interface ConnectionOptions {
|
|
37
|
+
/** Whether to enable connection logging */
|
|
38
|
+
enableLogging?: boolean;
|
|
39
|
+
/** Whether to automatically retry failed connections */
|
|
40
|
+
enableAutoRetry?: boolean;
|
|
41
|
+
/** Maximum number of connection retry attempts */
|
|
42
|
+
maxRetries?: number;
|
|
43
|
+
/** Delay between retry attempts in milliseconds */
|
|
44
|
+
retryDelay?: number;
|
|
45
|
+
/** SSL configuration */
|
|
46
|
+
ssl?: boolean | {
|
|
47
|
+
rejectUnauthorized: boolean;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Singleton database connection class.
|
|
52
|
+
* Manages PostgreSQL connection pooling and Drizzle ORM instance.
|
|
53
|
+
*
|
|
54
|
+
* Features:
|
|
55
|
+
* - Singleton pattern for single connection pool
|
|
56
|
+
* - Automatic connection retry with backoff
|
|
57
|
+
* - Connection health monitoring
|
|
58
|
+
* - Graceful shutdown handling
|
|
59
|
+
* - Comprehensive error handling
|
|
60
|
+
* - Connection statistics tracking
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { Connection } from './connection';
|
|
65
|
+
*
|
|
66
|
+
* const connection = Connection.getInstance();
|
|
67
|
+
* const plugins = await connection.db.select().from(schema.plugin);
|
|
68
|
+
*
|
|
69
|
+
* // During shutdown
|
|
70
|
+
* await connection.close();
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare class Connection {
|
|
74
|
+
private static instance;
|
|
75
|
+
/**
|
|
76
|
+
* Drizzle ORM database instance with schema
|
|
77
|
+
*/
|
|
78
|
+
readonly db: ReturnType<typeof drizzle>;
|
|
79
|
+
private readonly pool;
|
|
80
|
+
private readonly options;
|
|
81
|
+
private readonly retryStrategy;
|
|
82
|
+
private isShuttingDown;
|
|
83
|
+
/**
|
|
84
|
+
* Private constructor to enforce singleton pattern.
|
|
85
|
+
* Initializes PostgreSQL connection pool and Drizzle ORM instance.
|
|
86
|
+
*
|
|
87
|
+
* @param options - Optional configuration for the connection
|
|
88
|
+
* @throws {Error} If database initialization fails after all retries
|
|
89
|
+
*/
|
|
90
|
+
private constructor();
|
|
91
|
+
/**
|
|
92
|
+
* Gets the singleton instance of the Connection class.
|
|
93
|
+
* Creates a new instance if one doesn't exist.
|
|
94
|
+
*
|
|
95
|
+
* @param options - Optional configuration (only used on first call)
|
|
96
|
+
* @returns The singleton Connection instance
|
|
97
|
+
*/
|
|
98
|
+
static getInstance(options?: ConnectionOptions): Connection;
|
|
99
|
+
/**
|
|
100
|
+
* Resets the singleton instance.
|
|
101
|
+
* Useful for testing or reconfiguring the connection.
|
|
102
|
+
*
|
|
103
|
+
* @param closeExisting - Whether to close existing connection before reset
|
|
104
|
+
*/
|
|
105
|
+
static reset(closeExisting?: boolean): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Tests the database connection
|
|
108
|
+
*
|
|
109
|
+
* @returns Promise that resolves to true if connection is healthy
|
|
110
|
+
*/
|
|
111
|
+
testConnection(): Promise<boolean>;
|
|
112
|
+
/**
|
|
113
|
+
* Gets connection pool statistics
|
|
114
|
+
*
|
|
115
|
+
* @returns Current connection pool statistics
|
|
116
|
+
*/
|
|
117
|
+
getStats(): ConnectionStats;
|
|
118
|
+
/**
|
|
119
|
+
* Closes the database connection pool gracefully.
|
|
120
|
+
* Should be called during application shutdown.
|
|
121
|
+
*
|
|
122
|
+
* @param timeout - Maximum time to wait for connections to close (ms)
|
|
123
|
+
* @returns Promise that resolves when pool is closed
|
|
124
|
+
*/
|
|
125
|
+
close(timeout?: number): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Checks if the connection is shutting down
|
|
128
|
+
*
|
|
129
|
+
* @returns true if connection is in shutdown state
|
|
130
|
+
*/
|
|
131
|
+
isClosing(): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Sets up event handlers for the connection pool
|
|
134
|
+
*/
|
|
135
|
+
private setupEventHandlers;
|
|
136
|
+
/**
|
|
137
|
+
* Logs connection configuration (sanitized)
|
|
138
|
+
*/
|
|
139
|
+
private logConnectionConfig;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Proxy-based lazy database instance
|
|
143
|
+
* The actual connection is only created when first accessed
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* import { db } from './connection';
|
|
148
|
+
*
|
|
149
|
+
* // Connection is created here on first use, not on import
|
|
150
|
+
* const plugins = await db.select().from(schema.plugin);
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export declare const db: import("drizzle-orm/node-postgres").NodePgDatabase<Record<string, unknown>> & {
|
|
154
|
+
$client: Pool;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Gets the Connection instance for advanced operations
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```typescript
|
|
161
|
+
* import { getConnection } from './connection';
|
|
162
|
+
*
|
|
163
|
+
* const connection = getConnection();
|
|
164
|
+
* const stats = connection.getStats();
|
|
165
|
+
* console.log(`Active connections: ${stats.totalCount}`);
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
export declare function getConnection(): Connection;
|
|
169
|
+
/**
|
|
170
|
+
* Closes the database connection
|
|
171
|
+
* Should be called during application shutdown
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* import { closeConnection } from './connection';
|
|
176
|
+
*
|
|
177
|
+
* process.on('SIGTERM', async () => {
|
|
178
|
+
* await closeConnection();
|
|
179
|
+
* process.exit(0);
|
|
180
|
+
* });
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export declare function closeConnection(): Promise<void>;
|
|
184
|
+
/**
|
|
185
|
+
* Tests the database connection
|
|
186
|
+
*
|
|
187
|
+
* @returns Promise that resolves to true if connection is healthy
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* import { testConnection } from './connection';
|
|
192
|
+
*
|
|
193
|
+
* if (await testConnection()) {
|
|
194
|
+
* console.log('Database is ready');
|
|
195
|
+
* } else {
|
|
196
|
+
* console.error('Database connection failed');
|
|
197
|
+
* process.exit(1);
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
export declare function testConnection(): Promise<boolean>;
|