@pipeline-builder/api-core 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 +98 -0
- package/lib/constants/ai-providers.d.ts +52 -0
- package/lib/constants/ai-providers.js +129 -0
- package/lib/constants/http-status.d.ts +20 -0
- package/lib/constants/http-status.js +26 -0
- package/lib/constants/index.d.ts +3 -0
- package/lib/constants/index.js +6 -0
- package/lib/constants/time.d.ts +10 -0
- package/lib/constants/time.js +13 -0
- package/lib/errors/app-errors.d.ts +30 -0
- package/lib/errors/app-errors.js +53 -0
- package/lib/errors/index.d.ts +1 -0
- package/lib/errors/index.js +4 -0
- package/lib/helpers/access-helpers.d.ts +63 -0
- package/lib/helpers/access-helpers.js +82 -0
- package/lib/helpers/crud-helpers.d.ts +9 -0
- package/lib/helpers/crud-helpers.js +23 -0
- package/lib/helpers/index.d.ts +6 -0
- package/lib/helpers/index.js +9 -0
- package/lib/helpers/org-hierarchy-http.d.ts +74 -0
- package/lib/helpers/org-hierarchy-http.js +144 -0
- package/lib/helpers/org-hierarchy.d.ts +57 -0
- package/lib/helpers/org-hierarchy.js +110 -0
- package/lib/helpers/restore-helpers.d.ts +49 -0
- package/lib/helpers/restore-helpers.js +78 -0
- package/lib/helpers/sse-helpers.d.ts +20 -0
- package/lib/helpers/sse-helpers.js +45 -0
- package/lib/index.d.ts +58 -0
- package/lib/index.js +71 -0
- package/lib/middleware/auth.d.ts +208 -0
- package/lib/middleware/auth.js +588 -0
- package/lib/middleware/index.d.ts +3 -0
- package/lib/middleware/index.js +6 -0
- package/lib/middleware/mongo-sanitize.d.ts +32 -0
- package/lib/middleware/mongo-sanitize.js +100 -0
- package/lib/middleware/step-up.d.ts +45 -0
- package/lib/middleware/step-up.js +138 -0
- package/lib/openapi/extend-zod.d.ts +1 -0
- package/lib/openapi/extend-zod.js +6 -0
- package/lib/openapi/index.d.ts +2 -0
- package/lib/openapi/index.js +5 -0
- package/lib/openapi/registry.d.ts +17 -0
- package/lib/openapi/registry.js +38 -0
- package/lib/openapi/routes/ask-routes.d.ts +7 -0
- package/lib/openapi/routes/ask-routes.js +62 -0
- package/lib/openapi/routes/billing-routes.d.ts +1 -0
- package/lib/openapi/routes/billing-routes.js +66 -0
- package/lib/openapi/routes/image-registry-routes.d.ts +7 -0
- package/lib/openapi/routes/image-registry-routes.js +98 -0
- package/lib/openapi/routes/index.d.ts +5 -0
- package/lib/openapi/routes/index.js +28 -0
- package/lib/openapi/routes/message-routes.d.ts +1 -0
- package/lib/openapi/routes/message-routes.js +105 -0
- package/lib/openapi/routes/pipeline-routes.d.ts +1 -0
- package/lib/openapi/routes/pipeline-routes.js +105 -0
- package/lib/openapi/routes/pipeline-template-routes.d.ts +1 -0
- package/lib/openapi/routes/pipeline-template-routes.js +61 -0
- package/lib/openapi/routes/plugin-routes.d.ts +1 -0
- package/lib/openapi/routes/plugin-routes.js +96 -0
- package/lib/openapi/routes/quota-routes.d.ts +1 -0
- package/lib/openapi/routes/quota-routes.js +62 -0
- package/lib/openapi/schema-registry.d.ts +25 -0
- package/lib/openapi/schema-registry.js +91 -0
- package/lib/routes/health.d.ts +41 -0
- package/lib/routes/health.js +82 -0
- package/lib/routes/index.d.ts +1 -0
- package/lib/routes/index.js +4 -0
- package/lib/services/audit-spool.d.ts +80 -0
- package/lib/services/audit-spool.js +172 -0
- package/lib/services/cache-service.d.ts +124 -0
- package/lib/services/cache-service.js +276 -0
- package/lib/services/circuit-breaker.d.ts +45 -0
- package/lib/services/circuit-breaker.js +138 -0
- package/lib/services/compliance-client.d.ts +46 -0
- package/lib/services/compliance-client.js +128 -0
- package/lib/services/compliance-event-subscriber.d.ts +16 -0
- package/lib/services/compliance-event-subscriber.js +72 -0
- package/lib/services/durable-event-bus.d.ts +96 -0
- package/lib/services/durable-event-bus.js +204 -0
- package/lib/services/entity-events.d.ts +48 -0
- package/lib/services/entity-events.js +79 -0
- package/lib/services/env-redis.d.ts +44 -0
- package/lib/services/env-redis.js +94 -0
- package/lib/services/http-client.d.ts +143 -0
- package/lib/services/http-client.js +335 -0
- package/lib/services/index.d.ts +18 -0
- package/lib/services/index.js +20 -0
- package/lib/services/leader-lock.d.ts +45 -0
- package/lib/services/leader-lock.js +85 -0
- package/lib/services/quota.d.ts +130 -0
- package/lib/services/quota.js +264 -0
- package/lib/services/remote-audit-client.d.ts +160 -0
- package/lib/services/remote-audit-client.js +390 -0
- package/lib/services/retry-strategy.d.ts +74 -0
- package/lib/services/retry-strategy.js +118 -0
- package/lib/services/scheduler.d.ts +41 -0
- package/lib/services/scheduler.js +86 -0
- package/lib/services/service-boot.d.ts +20 -0
- package/lib/services/service-boot.js +28 -0
- package/lib/services/sse-ticket-store.d.ts +51 -0
- package/lib/services/sse-ticket-store.js +130 -0
- package/lib/services/token-revocation.d.ts +52 -0
- package/lib/services/token-revocation.js +120 -0
- package/lib/testing/tier-mock.d.ts +44 -0
- package/lib/testing/tier-mock.js +65 -0
- package/lib/types/audit-events.d.ts +69 -0
- package/lib/types/audit-events.js +4 -0
- package/lib/types/catalog-metadata.d.ts +36 -0
- package/lib/types/catalog-metadata.js +21 -0
- package/lib/types/common.d.ts +255 -0
- package/lib/types/common.js +41 -0
- package/lib/types/error-codes.d.ts +54 -0
- package/lib/types/error-codes.js +107 -0
- package/lib/types/feature-flags.d.ts +36 -0
- package/lib/types/feature-flags.js +128 -0
- package/lib/types/http.d.ts +27 -0
- package/lib/types/http.js +4 -0
- package/lib/types/index.d.ts +11 -0
- package/lib/types/index.js +14 -0
- package/lib/types/permissions.d.ts +65 -0
- package/lib/types/permissions.js +131 -0
- package/lib/types/pipeline-template.d.ts +30 -0
- package/lib/types/pipeline-template.js +13 -0
- package/lib/types/pipeline.d.ts +59 -0
- package/lib/types/pipeline.js +31 -0
- package/lib/types/quota-tiers.d.ts +79 -0
- package/lib/types/quota-tiers.js +221 -0
- package/lib/types/visibility.d.ts +20 -0
- package/lib/types/visibility.js +22 -0
- package/lib/utils/alias-resolver.d.ts +37 -0
- package/lib/utils/alias-resolver.js +68 -0
- package/lib/utils/audit.d.ts +15 -0
- package/lib/utils/audit.js +39 -0
- package/lib/utils/aws-scrub.d.ts +11 -0
- package/lib/utils/aws-scrub.js +67 -0
- package/lib/utils/compliance-attributes.d.ts +6 -0
- package/lib/utils/compliance-attributes.js +69 -0
- package/lib/utils/concurrency.d.ts +9 -0
- package/lib/utils/concurrency.js +29 -0
- package/lib/utils/crash-handlers.d.ts +18 -0
- package/lib/utils/crash-handlers.js +36 -0
- package/lib/utils/env.d.ts +28 -0
- package/lib/utils/env.js +54 -0
- package/lib/utils/headers.d.ts +18 -0
- package/lib/utils/headers.js +21 -0
- package/lib/utils/identity.d.ts +40 -0
- package/lib/utils/identity.js +51 -0
- package/lib/utils/index.d.ts +17 -0
- package/lib/utils/index.js +20 -0
- package/lib/utils/logger.d.ts +38 -0
- package/lib/utils/logger.js +174 -0
- package/lib/utils/metric-emitter.d.ts +36 -0
- package/lib/utils/metric-emitter.js +32 -0
- package/lib/utils/object.d.ts +13 -0
- package/lib/utils/object.js +18 -0
- package/lib/utils/params.d.ts +150 -0
- package/lib/utils/params.js +206 -0
- package/lib/utils/response.d.ts +117 -0
- package/lib/utils/response.js +223 -0
- package/lib/utils/safe-require.d.ts +13 -0
- package/lib/utils/safe-require.js +19 -0
- package/lib/utils/secret-encryption.d.ts +176 -0
- package/lib/utils/secret-encryption.js +374 -0
- package/lib/utils/ssrf.d.ts +30 -0
- package/lib/utils/ssrf.js +106 -0
- package/lib/validation/ai-schemas.d.ts +56 -0
- package/lib/validation/ai-schemas.js +78 -0
- package/lib/validation/common-schemas.d.ts +133 -0
- package/lib/validation/common-schemas.js +94 -0
- package/lib/validation/index.d.ts +7 -0
- package/lib/validation/index.js +10 -0
- package/lib/validation/message-schemas.d.ts +160 -0
- package/lib/validation/message-schemas.js +156 -0
- package/lib/validation/middleware.d.ts +72 -0
- package/lib/validation/middleware.js +65 -0
- package/lib/validation/pipeline-schemas.d.ts +181 -0
- package/lib/validation/pipeline-schemas.js +101 -0
- package/lib/validation/pipeline-template-schemas.d.ts +155 -0
- package/lib/validation/pipeline-template-schemas.js +66 -0
- package/lib/validation/plugin-schemas.d.ts +171 -0
- package/lib/validation/plugin-schemas.js +81 -0
- package/openapi.yaml +292 -0
- package/package.json +167 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { registry } from '../registry.js';
|
|
4
|
+
const tags = ['Quotas'];
|
|
5
|
+
const auth = [{ bearerAuth: [] }];
|
|
6
|
+
export function registerQuotaRoutes() {
|
|
7
|
+
registry.registerPath({
|
|
8
|
+
method: 'get',
|
|
9
|
+
path: '/quotas',
|
|
10
|
+
summary: 'Get own quotas',
|
|
11
|
+
description: 'Get quota usage and limits for the current organization (from JWT).',
|
|
12
|
+
tags,
|
|
13
|
+
security: auth,
|
|
14
|
+
responses: { 200: { description: 'Organization quota details' } },
|
|
15
|
+
});
|
|
16
|
+
registry.registerPath({
|
|
17
|
+
method: 'get',
|
|
18
|
+
path: '/quotas/all',
|
|
19
|
+
summary: 'Get all org quotas',
|
|
20
|
+
description: 'Get quotas for all organizations. System admin only.',
|
|
21
|
+
tags,
|
|
22
|
+
security: auth,
|
|
23
|
+
responses: { 200: { description: 'All organization quotas' }, 403: { description: 'Admin required' } },
|
|
24
|
+
});
|
|
25
|
+
registry.registerPath({
|
|
26
|
+
method: 'get',
|
|
27
|
+
path: '/quotas/{orgId}',
|
|
28
|
+
summary: 'Get org quotas',
|
|
29
|
+
description: 'Get quota usage and limits for a specific organization.',
|
|
30
|
+
tags,
|
|
31
|
+
security: auth,
|
|
32
|
+
responses: { 200: { description: 'Organization quota details' }, 404: { description: 'Organization not found' } },
|
|
33
|
+
});
|
|
34
|
+
registry.registerPath({
|
|
35
|
+
method: 'get',
|
|
36
|
+
path: '/quotas/{orgId}/{quotaType}',
|
|
37
|
+
summary: 'Get specific quota',
|
|
38
|
+
description: 'Get a specific quota type for an organization.',
|
|
39
|
+
tags,
|
|
40
|
+
security: auth,
|
|
41
|
+
responses: { 200: { description: 'Quota type details' } },
|
|
42
|
+
});
|
|
43
|
+
registry.registerPath({
|
|
44
|
+
method: 'put',
|
|
45
|
+
path: '/quotas/{orgId}',
|
|
46
|
+
summary: 'Update org quotas',
|
|
47
|
+
description: 'Update quota limits for an organization. System admin only.',
|
|
48
|
+
tags,
|
|
49
|
+
security: auth,
|
|
50
|
+
responses: { 200: { description: 'Quotas updated' }, 403: { description: 'Admin required' } },
|
|
51
|
+
});
|
|
52
|
+
registry.registerPath({
|
|
53
|
+
method: 'post',
|
|
54
|
+
path: '/quotas/{orgId}/reset',
|
|
55
|
+
summary: 'Reset quota usage',
|
|
56
|
+
description: 'Reset usage counters for an organization. Admin only.',
|
|
57
|
+
tags,
|
|
58
|
+
security: auth,
|
|
59
|
+
responses: { 200: { description: 'Quota usage reset' }, 403: { description: 'Admin required' } },
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEtcm91dGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL29wZW5hcGkvcm91dGVzL3F1b3RhLXJvdXRlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUxQyxNQUFNLElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3hCLE1BQU0sSUFBSSxHQUFHLENBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUVsQyxNQUFNLFVBQVUsbUJBQW1CO0lBQ2pDLFFBQVEsQ0FBQyxZQUFZLENBQUM7UUFDcEIsTUFBTSxFQUFFLEtBQUs7UUFDYixJQUFJLEVBQUUsU0FBUztRQUNmLE9BQU8sRUFBRSxnQkFBZ0I7UUFDekIsV0FBVyxFQUFFLHFFQUFxRTtRQUNsRixJQUFJO1FBQ0osUUFBUSxFQUFFLElBQUk7UUFDZCxTQUFTLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsNEJBQTRCLEVBQUUsRUFBRTtLQUNsRSxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsWUFBWSxDQUFDO1FBQ3BCLE1BQU0sRUFBRSxLQUFLO1FBQ2IsSUFBSSxFQUFFLGFBQWE7UUFDbkIsT0FBTyxFQUFFLG9CQUFvQjtRQUM3QixXQUFXLEVBQUUsc0RBQXNEO1FBQ25FLElBQUk7UUFDSixRQUFRLEVBQUUsSUFBSTtRQUNkLFNBQVMsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLFdBQVcsRUFBRSx5QkFBeUIsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFO0tBQ3ZHLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxZQUFZLENBQUM7UUFDcEIsTUFBTSxFQUFFLEtBQUs7UUFDYixJQUFJLEVBQUUsaUJBQWlCO1FBQ3ZCLE9BQU8sRUFBRSxnQkFBZ0I7UUFDekIsV0FBVyxFQUFFLHlEQUF5RDtRQUN0RSxJQUFJO1FBQ0osUUFBUSxFQUFFLElBQUk7UUFDZCxTQUFTLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsNEJBQTRCLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsd0JBQXdCLEVBQUUsRUFBRTtLQUNsSCxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsWUFBWSxDQUFDO1FBQ3BCLE1BQU0sRUFBRSxLQUFLO1FBQ2IsSUFBSSxFQUFFLDZCQUE2QjtRQUNuQyxPQUFPLEVBQUUsb0JBQW9CO1FBQzdCLFdBQVcsRUFBRSxnREFBZ0Q7UUFDN0QsSUFBSTtRQUNKLFFBQVEsRUFBRSxJQUFJO1FBQ2QsU0FBUyxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsV0FBVyxFQUFFLG9CQUFvQixFQUFFLEVBQUU7S0FDMUQsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFlBQVksQ0FBQztRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLElBQUksRUFBRSxpQkFBaUI7UUFDdkIsT0FBTyxFQUFFLG1CQUFtQjtRQUM1QixXQUFXLEVBQUUsNkRBQTZEO1FBQzFFLElBQUk7UUFDSixRQUFRLEVBQUUsSUFBSTtRQUNkLFNBQVMsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFO0tBQzlGLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxZQUFZLENBQUM7UUFDcEIsTUFBTSxFQUFFLE1BQU07UUFDZCxJQUFJLEVBQUUsdUJBQXVCO1FBQzdCLE9BQU8sRUFBRSxtQkFBbUI7UUFDNUIsV0FBVyxFQUFFLHVEQUF1RDtRQUNwRSxJQUFJO1FBQ0osUUFBUSxFQUFFLElBQUk7UUFDZCxTQUFTLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRTtLQUNqRyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IHJlZ2lzdHJ5IH0gZnJvbSAnLi4vcmVnaXN0cnkuanMnO1xuXG5jb25zdCB0YWdzID0gWydRdW90YXMnXTtcbmNvbnN0IGF1dGggPSBbeyBiZWFyZXJBdXRoOiBbXSB9XTtcblxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyUXVvdGFSb3V0ZXMoKTogdm9pZCB7XG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyUGF0aCh7XG4gICAgbWV0aG9kOiAnZ2V0JyxcbiAgICBwYXRoOiAnL3F1b3RhcycsXG4gICAgc3VtbWFyeTogJ0dldCBvd24gcXVvdGFzJyxcbiAgICBkZXNjcmlwdGlvbjogJ0dldCBxdW90YSB1c2FnZSBhbmQgbGltaXRzIGZvciB0aGUgY3VycmVudCBvcmdhbml6YXRpb24gKGZyb20gSldUKS4nLFxuICAgIHRhZ3MsXG4gICAgc2VjdXJpdHk6IGF1dGgsXG4gICAgcmVzcG9uc2VzOiB7IDIwMDogeyBkZXNjcmlwdGlvbjogJ09yZ2FuaXphdGlvbiBxdW90YSBkZXRhaWxzJyB9IH0sXG4gIH0pO1xuXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyUGF0aCh7XG4gICAgbWV0aG9kOiAnZ2V0JyxcbiAgICBwYXRoOiAnL3F1b3Rhcy9hbGwnLFxuICAgIHN1bW1hcnk6ICdHZXQgYWxsIG9yZyBxdW90YXMnLFxuICAgIGRlc2NyaXB0aW9uOiAnR2V0IHF1b3RhcyBmb3IgYWxsIG9yZ2FuaXphdGlvbnMuIFN5c3RlbSBhZG1pbiBvbmx5LicsXG4gICAgdGFncyxcbiAgICBzZWN1cml0eTogYXV0aCxcbiAgICByZXNwb25zZXM6IHsgMjAwOiB7IGRlc2NyaXB0aW9uOiAnQWxsIG9yZ2FuaXphdGlvbiBxdW90YXMnIH0sIDQwMzogeyBkZXNjcmlwdGlvbjogJ0FkbWluIHJlcXVpcmVkJyB9IH0sXG4gIH0pO1xuXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyUGF0aCh7XG4gICAgbWV0aG9kOiAnZ2V0JyxcbiAgICBwYXRoOiAnL3F1b3Rhcy97b3JnSWR9JyxcbiAgICBzdW1tYXJ5OiAnR2V0IG9yZyBxdW90YXMnLFxuICAgIGRlc2NyaXB0aW9uOiAnR2V0IHF1b3RhIHVzYWdlIGFuZCBsaW1pdHMgZm9yIGEgc3BlY2lmaWMgb3JnYW5pemF0aW9uLicsXG4gICAgdGFncyxcbiAgICBzZWN1cml0eTogYXV0aCxcbiAgICByZXNwb25zZXM6IHsgMjAwOiB7IGRlc2NyaXB0aW9uOiAnT3JnYW5pemF0aW9uIHF1b3RhIGRldGFpbHMnIH0sIDQwNDogeyBkZXNjcmlwdGlvbjogJ09yZ2FuaXphdGlvbiBub3QgZm91bmQnIH0gfSxcbiAgfSk7XG5cbiAgcmVnaXN0cnkucmVnaXN0ZXJQYXRoKHtcbiAgICBtZXRob2Q6ICdnZXQnLFxuICAgIHBhdGg6ICcvcXVvdGFzL3tvcmdJZH0ve3F1b3RhVHlwZX0nLFxuICAgIHN1bW1hcnk6ICdHZXQgc3BlY2lmaWMgcXVvdGEnLFxuICAgIGRlc2NyaXB0aW9uOiAnR2V0IGEgc3BlY2lmaWMgcXVvdGEgdHlwZSBmb3IgYW4gb3JnYW5pemF0aW9uLicsXG4gICAgdGFncyxcbiAgICBzZWN1cml0eTogYXV0aCxcbiAgICByZXNwb25zZXM6IHsgMjAwOiB7IGRlc2NyaXB0aW9uOiAnUXVvdGEgdHlwZSBkZXRhaWxzJyB9IH0sXG4gIH0pO1xuXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyUGF0aCh7XG4gICAgbWV0aG9kOiAncHV0JyxcbiAgICBwYXRoOiAnL3F1b3Rhcy97b3JnSWR9JyxcbiAgICBzdW1tYXJ5OiAnVXBkYXRlIG9yZyBxdW90YXMnLFxuICAgIGRlc2NyaXB0aW9uOiAnVXBkYXRlIHF1b3RhIGxpbWl0cyBmb3IgYW4gb3JnYW5pemF0aW9uLiBTeXN0ZW0gYWRtaW4gb25seS4nLFxuICAgIHRhZ3MsXG4gICAgc2VjdXJpdHk6IGF1dGgsXG4gICAgcmVzcG9uc2VzOiB7IDIwMDogeyBkZXNjcmlwdGlvbjogJ1F1b3RhcyB1cGRhdGVkJyB9LCA0MDM6IHsgZGVzY3JpcHRpb246ICdBZG1pbiByZXF1aXJlZCcgfSB9LFxuICB9KTtcblxuICByZWdpc3RyeS5yZWdpc3RlclBhdGgoe1xuICAgIG1ldGhvZDogJ3Bvc3QnLFxuICAgIHBhdGg6ICcvcXVvdGFzL3tvcmdJZH0vcmVzZXQnLFxuICAgIHN1bW1hcnk6ICdSZXNldCBxdW90YSB1c2FnZScsXG4gICAgZGVzY3JpcHRpb246ICdSZXNldCB1c2FnZSBjb3VudGVycyBmb3IgYW4gb3JnYW5pemF0aW9uLiBBZG1pbiBvbmx5LicsXG4gICAgdGFncyxcbiAgICBzZWN1cml0eTogYXV0aCxcbiAgICByZXNwb25zZXM6IHsgMjAwOiB7IGRlc2NyaXB0aW9uOiAnUXVvdGEgdXNhZ2UgcmVzZXQnIH0sIDQwMzogeyBkZXNjcmlwdGlvbjogJ0FkbWluIHJlcXVpcmVkJyB9IH0sXG4gIH0pO1xufVxuIl19
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const SuccessResponseSchema: z.ZodObject<{
|
|
3
|
+
success: z.ZodLiteral<true>;
|
|
4
|
+
statusCode: z.ZodNumber;
|
|
5
|
+
data: z.ZodOptional<z.ZodUnknown>;
|
|
6
|
+
message: z.ZodOptional<z.ZodString>;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
export declare const ErrorResponseSchema: z.ZodObject<{
|
|
9
|
+
success: z.ZodLiteral<false>;
|
|
10
|
+
statusCode: z.ZodNumber;
|
|
11
|
+
message: z.ZodString;
|
|
12
|
+
code: z.ZodOptional<z.ZodString>;
|
|
13
|
+
details: z.ZodOptional<z.ZodUnknown>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export declare const PaginatedResponseSchema: z.ZodObject<{
|
|
16
|
+
success: z.ZodLiteral<true>;
|
|
17
|
+
statusCode: z.ZodNumber;
|
|
18
|
+
data: z.ZodArray<z.ZodUnknown>;
|
|
19
|
+
count: z.ZodNumber;
|
|
20
|
+
limit: z.ZodNumber;
|
|
21
|
+
offset: z.ZodNumber;
|
|
22
|
+
total: z.ZodOptional<z.ZodNumber>;
|
|
23
|
+
message: z.ZodOptional<z.ZodString>;
|
|
24
|
+
}, z.core.$strip>;
|
|
25
|
+
export declare function registerSchemas(): void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { registry } from './registry.js';
|
|
5
|
+
import { AIGenerateBodySchema, PluginDeployGeneratedSchema, } from '../validation/ai-schemas.js';
|
|
6
|
+
import { VisibilitySchema, PaginationSchema, BaseFilterSchema, } from '../validation/common-schemas.js';
|
|
7
|
+
import { MessageFilterSchema, MessageCreateSchema, MessageReplySchema, } from '../validation/message-schemas.js';
|
|
8
|
+
import { PipelineFilterSchema, PipelineCreateSchema, PipelineUpdateSchema, } from '../validation/pipeline-schemas.js';
|
|
9
|
+
import { PluginFilterSchema, PluginCreateSchema, PluginUpdateSchema, PluginUploadBodySchema, } from '../validation/plugin-schemas.js';
|
|
10
|
+
// Response schemas (exported for type usage)
|
|
11
|
+
export const SuccessResponseSchema = z.object({
|
|
12
|
+
success: z.literal(true),
|
|
13
|
+
statusCode: z.number(),
|
|
14
|
+
data: z.unknown().optional(),
|
|
15
|
+
message: z.string().optional(),
|
|
16
|
+
});
|
|
17
|
+
export const ErrorResponseSchema = z.object({
|
|
18
|
+
success: z.literal(false),
|
|
19
|
+
statusCode: z.number(),
|
|
20
|
+
message: z.string(),
|
|
21
|
+
code: z.string().optional(),
|
|
22
|
+
details: z.unknown().optional(),
|
|
23
|
+
});
|
|
24
|
+
export const PaginatedResponseSchema = z.object({
|
|
25
|
+
success: z.literal(true),
|
|
26
|
+
statusCode: z.number(),
|
|
27
|
+
data: z.array(z.unknown()),
|
|
28
|
+
count: z.number(),
|
|
29
|
+
limit: z.number(),
|
|
30
|
+
offset: z.number(),
|
|
31
|
+
total: z.number().optional(),
|
|
32
|
+
message: z.string().optional(),
|
|
33
|
+
});
|
|
34
|
+
export function registerSchemas() {
|
|
35
|
+
// Common schemas
|
|
36
|
+
registry.register('Visibility', VisibilitySchema.openapi({
|
|
37
|
+
description: 'Sharing rung: "private" (author only), "org" (everyone in the owning organization), or "public" (the org, its teams, and — from the system org — every org)',
|
|
38
|
+
example: 'private',
|
|
39
|
+
}));
|
|
40
|
+
registry.register('PaginationParams', PaginationSchema.openapi({
|
|
41
|
+
description: 'Standard pagination and sorting parameters',
|
|
42
|
+
}));
|
|
43
|
+
registry.register('BaseFilter', BaseFilterSchema.openapi({
|
|
44
|
+
description: 'Common filter fields shared by all entity queries',
|
|
45
|
+
}));
|
|
46
|
+
// Pipeline schemas
|
|
47
|
+
registry.register('PipelineFilter', PipelineFilterSchema.openapi({
|
|
48
|
+
description: 'Query filters for listing pipelines',
|
|
49
|
+
}));
|
|
50
|
+
registry.register('PipelineCreate', PipelineCreateSchema.openapi({
|
|
51
|
+
description: 'Request body for creating a new pipeline',
|
|
52
|
+
}));
|
|
53
|
+
registry.register('PipelineUpdate', PipelineUpdateSchema.openapi({
|
|
54
|
+
description: 'Request body for updating an existing pipeline',
|
|
55
|
+
}));
|
|
56
|
+
// Plugin schemas
|
|
57
|
+
registry.register('PluginFilter', PluginFilterSchema.openapi({
|
|
58
|
+
description: 'Query filters for listing plugins',
|
|
59
|
+
}));
|
|
60
|
+
registry.register('PluginCreate', PluginCreateSchema.openapi({
|
|
61
|
+
description: 'Request body for creating a new plugin',
|
|
62
|
+
}));
|
|
63
|
+
registry.register('PluginUpdate', PluginUpdateSchema.openapi({
|
|
64
|
+
description: 'Request body for updating an existing plugin',
|
|
65
|
+
}));
|
|
66
|
+
registry.register('PluginUploadBody', PluginUploadBodySchema.openapi({
|
|
67
|
+
description: 'Metadata for plugin ZIP upload (multipart form-data)',
|
|
68
|
+
}));
|
|
69
|
+
// Message schemas
|
|
70
|
+
registry.register('MessageFilter', MessageFilterSchema.openapi({
|
|
71
|
+
description: 'Query filters for listing messages',
|
|
72
|
+
}));
|
|
73
|
+
registry.register('MessageCreate', MessageCreateSchema.openapi({
|
|
74
|
+
description: 'Request body for creating a new message or announcement',
|
|
75
|
+
}));
|
|
76
|
+
registry.register('MessageReply', MessageReplySchema.openapi({
|
|
77
|
+
description: 'Request body for replying to a message thread',
|
|
78
|
+
}));
|
|
79
|
+
// AI schemas
|
|
80
|
+
registry.register('AIGenerateBody', AIGenerateBodySchema.openapi({
|
|
81
|
+
description: 'Request body for AI-powered generation (pipeline or plugin)',
|
|
82
|
+
}));
|
|
83
|
+
registry.register('PluginDeployGenerated', PluginDeployGeneratedSchema.openapi({
|
|
84
|
+
description: 'Request body for deploying an AI-generated plugin',
|
|
85
|
+
}));
|
|
86
|
+
// Response schemas
|
|
87
|
+
registry.register('SuccessResponse', SuccessResponseSchema.openapi('SuccessResponse'));
|
|
88
|
+
registry.register('ErrorResponse', ErrorResponseSchema.openapi('ErrorResponse'));
|
|
89
|
+
registry.register('PaginatedResponse', PaginatedResponseSchema.openapi('PaginatedResponse'));
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLXJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29wZW5hcGkvc2NoZW1hLXJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsMkJBQTJCLEdBQzVCLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsZ0JBQWdCLEdBQ2pCLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixtQkFBbUIsRUFDbkIsa0JBQWtCLEdBQ25CLE1BQU0sa0NBQWtDLENBQUM7QUFDMUMsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixvQkFBb0IsRUFDcEIsb0JBQW9CLEdBQ3JCLE1BQU0sbUNBQW1DLENBQUM7QUFDM0MsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixrQkFBa0IsRUFDbEIsa0JBQWtCLEVBQ2xCLHNCQUFzQixHQUN2QixNQUFNLGlDQUFpQyxDQUFDO0FBRXpDLDZDQUE2QztBQUM3QyxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQzVDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztJQUN4QixVQUFVLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRTtJQUN0QixJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUM1QixPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtDQUMvQixDQUFDLENBQUM7QUFFSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxDQUFD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QyxRQUFRLENBQUMsZUFBZSxFQUFFLG1CQUFtQixDQUFDLE9BQU8sQ0FBQztRQUM3RCxXQUFXLEVBQUUsb0NBQW9DO0tBQ2xELENBQUMsQ0FBQyxDQUFDO0lBRUosUUFBUSxDQUFDLFFBQVEsQ0FBQyxlQUFlLEVBQUUsbUJBQW1CLENBQUMsT0FBTyxDQUFDO1FBQzdELFdBQVcsRUFBRSx5REFBeUQ7S0FDdkUsQ0FBQyxDQUFDLENBQUM7SUFFSixRQUFRLENBQUMsUUFBUSxDQUFDLGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxPQUFPLENBQUM7UUFDM0QsV0FBVyxFQUFFLCtDQUErQztLQUM3RCxDQUFDLENBQUMsQ0FBQztJQUVKLGFBQWE7SUFDYixRQUFRLENBQUMsUUFBUSxDQUFDLGdCQUFnQixFQUFFLG9CQUFvQixDQUFDLE9BQU8sQ0FBQztRQUMvRCxXQUFXLEVBQUUsNkRBQTZEO0tBQzNFLENBQUMsQ0FBQyxDQUFDO0lBRUosUUFBUSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSwyQkFBMkIsQ0FBQyxPQUFPLENBQUM7UUFDN0UsV0FBVyxFQUFFLG1EQUFtRDtLQUNqRSxDQUFDLENBQUMsQ0FBQztJQUVKLG1CQUFtQjtJQUNuQixRQUFRLENBQUMsUUFBUSxDQUFDLGlCQUFpQixFQUFFLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7SUFDdkYsUUFBUSxDQUFDLFFBQVEsQ0FBQyxlQUFlLEVBQUUsbUJBQW1CLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7SUFDakYsUUFBUSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSx1QkFBdUIsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO0FBQy9GLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5cbmltcG9ydCB7IHJlZ2lzdHJ5IH0gZnJvbSAnLi9yZWdpc3RyeS5qcyc7XG5pbXBvcnQge1xuICBBSUdlbmVyYXRlQm9keVNjaGVtYSxcbiAgUGx1Z2luRGVwbG95R2VuZXJhdGVkU2NoZW1hLFxufSBmcm9tICcuLi92YWxpZGF0aW9uL2FpLXNjaGVtYXMuanMnO1xuaW1wb3J0IHtcbiAgVmlzaWJpbGl0eVNjaGVtYSxcbiAgUGFnaW5hdGlvblNjaGVtYSxcbiAgQmFzZUZpbHRlclNjaGVtYSxcbn0gZnJvbSAnLi4vdmFsaWRhdGlvbi9jb21tb24tc2NoZW1hcy5qcyc7XG5pbXBvcnQge1xuICBNZXNzYWdlRmlsdGVyU2NoZW1hLFxuICBNZXNzYWdlQ3JlYXRlU2NoZW1hLFxuICBNZXNzYWdlUmVwbHlTY2hlbWEsXG59IGZyb20gJy4uL3ZhbGlkYXRpb24vbWVzc2FnZS1zY2hlbWFzLmpzJztcbmltcG9ydCB7XG4gIFBpcGVsaW5lRmlsdGVyU2NoZW1hLFxuICBQaXBlbGluZUNyZWF0ZVNjaGVtYSxcbiAgUGlwZWxpbmVVcGRhdGVTY2hlbWEsXG59IGZyb20gJy4uL3ZhbGlkYXRpb24vcGlwZWxpbmUtc2NoZW1hcy5qcyc7XG5pbXBvcnQge1xuICBQbHVnaW5GaWx0ZXJTY2hlbWEsXG4gIFBsdWdpbkNyZWF0ZVNjaGVtYSxcbiAgUGx1Z2luVXBkYXRlU2NoZW1hLFxuICBQbHVnaW5VcGxvYWRCb2R5U2NoZW1hLFxufSBmcm9tICcuLi92YWxpZGF0aW9uL3BsdWdpbi1zY2hlbWFzLmpzJztcblxuLy8gUmVzcG9uc2Ugc2NoZW1hcyAoZXhwb3J0ZWQgZm9yIHR5cGUgdXNhZ2UpXG5leHBvcnQgY29uc3QgU3VjY2Vzc1Jlc3BvbnNlU2NoZW1hID0gei5vYmplY3Qoe1xuICBzdWNjZXNzOiB6LmxpdGVyYWwodHJ1ZSksXG4gIHN0YXR1c0NvZGU6IHoubnVtYmVyKCksXG4gIGRhdGE6IHoudW5rbm93bigpLm9wdGlvbmFsKCksXG4gIG1lc3NhZ2U6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgRXJyb3JSZXNwb25zZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgc3VjY2Vzczogei5saXRlcmFsKGZhbHNlKSxcbiAgc3RhdHVzQ29kZTogei5udW1iZXIoKSxcbiAgbWVzc2FnZTogei5zdHJpbmcoKSxcbiAgY29kZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICBkZXRhaWxzOiB6LnVua25vd24oKS5vcHRpb25hbCgpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBQYWdpbmF0ZWRSZXNwb25zZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgc3VjY2Vzczogei5saXRlcmFsKHRydWUpLFxuICBzdGF0dXNDb2RlOiB6Lm51bWJlcigpLFxuICBkYXRhOiB6LmFycmF5KHoudW5rbm93bigpKSxcbiAgY291bnQ6IHoubnVtYmVyKCksXG4gIGxpbWl0OiB6Lm51bWJlcigpLFxuICBvZmZzZXQ6IHoubnVtYmVyKCksXG4gIHRvdGFsOiB6Lm51bWJlcigpLm9wdGlvbmFsKCksXG4gIG1lc3NhZ2U6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbn0pO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJTY2hlbWFzKCk6IHZvaWQge1xuICAvLyBDb21tb24gc2NoZW1hc1xuICByZWdpc3RyeS5yZWdpc3RlcignVmlzaWJpbGl0eScsIFZpc2liaWxpdHlTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdTaGFyaW5nIHJ1bmc6IFwicHJpdmF0ZVwiIChhdXRob3Igb25seSksIFwib3JnXCIgKGV2ZXJ5b25lIGluIHRoZSBvd25pbmcgb3JnYW5pemF0aW9uKSwgb3IgXCJwdWJsaWNcIiAodGhlIG9yZywgaXRzIHRlYW1zLCBhbmQg4oCUIGZyb20gdGhlIHN5c3RlbSBvcmcg4oCUIGV2ZXJ5IG9yZyknLFxuICAgIGV4YW1wbGU6ICdwcml2YXRlJyxcbiAgfSkpO1xuXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdQYWdpbmF0aW9uUGFyYW1zJywgUGFnaW5hdGlvblNjaGVtYS5vcGVuYXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ1N0YW5kYXJkIHBhZ2luYXRpb24gYW5kIHNvcnRpbmcgcGFyYW1ldGVycycsXG4gIH0pKTtcblxuICByZWdpc3RyeS5yZWdpc3RlcignQmFzZUZpbHRlcicsIEJhc2VGaWx0ZXJTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdDb21tb24gZmlsdGVyIGZpZWxkcyBzaGFyZWQgYnkgYWxsIGVudGl0eSBxdWVyaWVzJyxcbiAgfSkpO1xuXG4gIC8vIFBpcGVsaW5lIHNjaGVtYXNcbiAgcmVnaXN0cnkucmVnaXN0ZXIoJ1BpcGVsaW5lRmlsdGVyJywgUGlwZWxpbmVGaWx0ZXJTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdRdWVyeSBmaWx0ZXJzIGZvciBsaXN0aW5nIHBpcGVsaW5lcycsXG4gIH0pKTtcblxuICByZWdpc3RyeS5yZWdpc3RlcignUGlwZWxpbmVDcmVhdGUnLCBQaXBlbGluZUNyZWF0ZVNjaGVtYS5vcGVuYXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ1JlcXVlc3QgYm9keSBmb3IgY3JlYXRpbmcgYSBuZXcgcGlwZWxpbmUnLFxuICB9KSk7XG5cbiAgcmVnaXN0cnkucmVnaXN0ZXIoJ1BpcGVsaW5lVXBkYXRlJywgUGlwZWxpbmVVcGRhdGVTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdSZXF1ZXN0IGJvZHkgZm9yIHVwZGF0aW5nIGFuIGV4aXN0aW5nIHBpcGVsaW5lJyxcbiAgfSkpO1xuXG4gIC8vIFBsdWdpbiBzY2hlbWFzXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdQbHVnaW5GaWx0ZXInLCBQbHVnaW5GaWx0ZXJTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdRdWVyeSBmaWx0ZXJzIGZvciBsaXN0aW5nIHBsdWdpbnMnLFxuICB9KSk7XG5cbiAgcmVnaXN0cnkucmVnaXN0ZXIoJ1BsdWdpbkNyZWF0ZScsIFBsdWdpbkNyZWF0ZVNjaGVtYS5vcGVuYXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ1JlcXVlc3QgYm9keSBmb3IgY3JlYXRpbmcgYSBuZXcgcGx1Z2luJyxcbiAgfSkpO1xuXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdQbHVnaW5VcGRhdGUnLCBQbHVnaW5VcGRhdGVTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdSZXF1ZXN0IGJvZHkgZm9yIHVwZGF0aW5nIGFuIGV4aXN0aW5nIHBsdWdpbicsXG4gIH0pKTtcblxuICByZWdpc3RyeS5yZWdpc3RlcignUGx1Z2luVXBsb2FkQm9keScsIFBsdWdpblVwbG9hZEJvZHlTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdNZXRhZGF0YSBmb3IgcGx1Z2luIFpJUCB1cGxvYWQgKG11bHRpcGFydCBmb3JtLWRhdGEpJyxcbiAgfSkpO1xuXG4gIC8vIE1lc3NhZ2Ugc2NoZW1hc1xuICByZWdpc3RyeS5yZWdpc3RlcignTWVzc2FnZUZpbHRlcicsIE1lc3NhZ2VGaWx0ZXJTY2hlbWEub3BlbmFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdRdWVyeSBmaWx0ZXJzIGZvciBsaXN0aW5nIG1lc3NhZ2VzJyxcbiAgfSkpO1xuXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdNZXNzYWdlQ3JlYXRlJywgTWVzc2FnZUNyZWF0ZVNjaGVtYS5vcGVuYXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ1JlcXVlc3QgYm9keSBmb3IgY3JlYXRpbmcgYSBuZXcgbWVzc2FnZSBvciBhbm5vdW5jZW1lbnQnLFxuICB9KSk7XG5cbiAgcmVnaXN0cnkucmVnaXN0ZXIoJ01lc3NhZ2VSZXBseScsIE1lc3NhZ2VSZXBseVNjaGVtYS5vcGVuYXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ1JlcXVlc3QgYm9keSBmb3IgcmVwbHlpbmcgdG8gYSBtZXNzYWdlIHRocmVhZCcsXG4gIH0pKTtcblxuICAvLyBBSSBzY2hlbWFzXG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdBSUdlbmVyYXRlQm9keScsIEFJR2VuZXJhdGVCb2R5U2NoZW1hLm9wZW5hcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnUmVxdWVzdCBib2R5IGZvciBBSS1wb3dlcmVkIGdlbmVyYXRpb24gKHBpcGVsaW5lIG9yIHBsdWdpbiknLFxuICB9KSk7XG5cbiAgcmVnaXN0cnkucmVnaXN0ZXIoJ1BsdWdpbkRlcGxveUdlbmVyYXRlZCcsIFBsdWdpbkRlcGxveUdlbmVyYXRlZFNjaGVtYS5vcGVuYXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ1JlcXVlc3QgYm9keSBmb3IgZGVwbG95aW5nIGFuIEFJLWdlbmVyYXRlZCBwbHVnaW4nLFxuICB9KSk7XG5cbiAgLy8gUmVzcG9uc2Ugc2NoZW1hc1xuICByZWdpc3RyeS5yZWdpc3RlcignU3VjY2Vzc1Jlc3BvbnNlJywgU3VjY2Vzc1Jlc3BvbnNlU2NoZW1hLm9wZW5hcGkoJ1N1Y2Nlc3NSZXNwb25zZScpKTtcbiAgcmVnaXN0cnkucmVnaXN0ZXIoJ0Vycm9yUmVzcG9uc2UnLCBFcnJvclJlc3BvbnNlU2NoZW1hLm9wZW5hcGkoJ0Vycm9yUmVzcG9uc2UnKSk7XG4gIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdQYWdpbmF0ZWRSZXNwb25zZScsIFBhZ2luYXRlZFJlc3BvbnNlU2NoZW1hLm9wZW5hcGkoJ1BhZ2luYXRlZFJlc3BvbnNlJykpO1xufVxuIl19
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Router, type Request, type Response } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Options for health check endpoint.
|
|
4
|
+
*/
|
|
5
|
+
export interface HealthCheckOptions {
|
|
6
|
+
/** Service name */
|
|
7
|
+
serviceName: string;
|
|
8
|
+
/** Service version (optional) */
|
|
9
|
+
version?: string;
|
|
10
|
+
/** Custom health check function for dependencies */
|
|
11
|
+
checkDependencies?: () => Promise<Record<string, 'connected' | 'disconnected' | 'unknown'>>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Liveness handler — returns 200 as long as the process is alive enough to
|
|
15
|
+
* respond. Dependency status is reported in the body as informational, but a
|
|
16
|
+
* disconnected dependency does NOT fail the probe (use /ready for that).
|
|
17
|
+
*
|
|
18
|
+
* Use as the Kubernetes / ECS LIVENESS probe — it should only fail when the
|
|
19
|
+
* process is genuinely stuck and needs to be restarted.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createHealthCheck(options: HealthCheckOptions): (_req: Request, res: Response) => Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Readiness handler — returns 503 if any dependency is `disconnected` (or
|
|
24
|
+
* the dependency check itself threw). Returns 200 only when the service is
|
|
25
|
+
* fully ready to serve traffic.
|
|
26
|
+
*
|
|
27
|
+
* Use as the Kubernetes / ECS READINESS probe — when this fails, the
|
|
28
|
+
* orchestrator stops routing traffic to this pod but does NOT restart it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createReadinessCheck(options: HealthCheckOptions): (_req: Request, res: Response) => Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Create a health/readiness router exposing:
|
|
33
|
+
* - GET /health — liveness (always 200 unless process is dead)
|
|
34
|
+
* - GET /ready — readiness (503 if dependencies are disconnected)
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* app.use(createHealthRouter({ serviceName: 'plugin' }));
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function createHealthRouter(options: HealthCheckOptions): Router;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Router } from 'express';
|
|
4
|
+
import { sendSuccess, sendError } from '../utils/response.js';
|
|
5
|
+
const startTime = Date.now();
|
|
6
|
+
/**
|
|
7
|
+
* Build a HealthCheckResponse + collect dependency status.
|
|
8
|
+
* Shared between /health (liveness) and /ready (readiness).
|
|
9
|
+
*/
|
|
10
|
+
async function buildHealthResponse(options) {
|
|
11
|
+
const { serviceName, version, checkDependencies } = options;
|
|
12
|
+
const response = {
|
|
13
|
+
status: 'healthy',
|
|
14
|
+
service: serviceName,
|
|
15
|
+
timestamp: new Date().toISOString(),
|
|
16
|
+
uptime: Math.floor((Date.now() - startTime) / 1000),
|
|
17
|
+
};
|
|
18
|
+
if (version)
|
|
19
|
+
response.version = version;
|
|
20
|
+
if (!checkDependencies) {
|
|
21
|
+
return { response, hasDisconnected: false, checkFailed: false };
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
response.dependencies = await checkDependencies();
|
|
25
|
+
const hasDisconnected = Object.values(response.dependencies).some((status) => status === 'disconnected');
|
|
26
|
+
return { response, hasDisconnected, checkFailed: false };
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
response.dependencies = { check: 'disconnected' };
|
|
30
|
+
return { response, hasDisconnected: true, checkFailed: true };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Liveness handler — returns 200 as long as the process is alive enough to
|
|
35
|
+
* respond. Dependency status is reported in the body as informational, but a
|
|
36
|
+
* disconnected dependency does NOT fail the probe (use /ready for that).
|
|
37
|
+
*
|
|
38
|
+
* Use as the Kubernetes / ECS LIVENESS probe — it should only fail when the
|
|
39
|
+
* process is genuinely stuck and needs to be restarted.
|
|
40
|
+
*/
|
|
41
|
+
export function createHealthCheck(options) {
|
|
42
|
+
return async (_req, res) => {
|
|
43
|
+
const { response } = await buildHealthResponse(options);
|
|
44
|
+
sendSuccess(res, 200, response);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Readiness handler — returns 503 if any dependency is `disconnected` (or
|
|
49
|
+
* the dependency check itself threw). Returns 200 only when the service is
|
|
50
|
+
* fully ready to serve traffic.
|
|
51
|
+
*
|
|
52
|
+
* Use as the Kubernetes / ECS READINESS probe — when this fails, the
|
|
53
|
+
* orchestrator stops routing traffic to this pod but does NOT restart it.
|
|
54
|
+
*/
|
|
55
|
+
export function createReadinessCheck(options) {
|
|
56
|
+
return async (_req, res) => {
|
|
57
|
+
const { response, hasDisconnected } = await buildHealthResponse(options);
|
|
58
|
+
if (hasDisconnected) {
|
|
59
|
+
response.status = 'unhealthy';
|
|
60
|
+
sendError(res, 503, 'Service not ready', undefined, response);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
sendSuccess(res, 200, response);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create a health/readiness router exposing:
|
|
68
|
+
* - GET /health — liveness (always 200 unless process is dead)
|
|
69
|
+
* - GET /ready — readiness (503 if dependencies are disconnected)
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* app.use(createHealthRouter({ serviceName: 'plugin' }));
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function createHealthRouter(options) {
|
|
77
|
+
const router = Router();
|
|
78
|
+
router.get('/health', createHealthCheck(options));
|
|
79
|
+
router.get('/ready', createReadinessCheck(options));
|
|
80
|
+
return router;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhbHRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JvdXRlcy9oZWFsdGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsTUFBTSxFQUErQixNQUFNLFNBQVMsQ0FBQztBQUU5RCxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRTlELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQWM3Qjs7O0dBR0c7QUFDSCxLQUFLLFVBQVUsbUJBQW1CLENBQUMsT0FBMkI7SUFLNUQsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxPQUFPLENBQUM7SUFDNUQsTUFBTSxRQUFRLEdBQXdCO1FBQ3BDLE1BQU0sRUFBRSxTQUFTO1FBQ2pCLE9BQU8sRUFBRSxXQUFXO1FBQ3BCLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtRQUNuQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7S0FDcEQsQ0FBQztJQUNGLElBQUksT0FBTztRQUFFLFFBQVEsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBRXhDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDbEUsQ0FBQztJQUVELElBQUksQ0FBQztRQUNILFFBQVEsQ0FBQyxZQUFZLEdBQUcsTUFBTSxpQkFBaUIsRUFBRSxDQUFDO1FBQ2xELE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FDL0QsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sS0FBSyxjQUFjLENBQ3RDLENBQUM7UUFDRixPQUFPLEVBQUUsUUFBUSxFQUFFLGVBQWUsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDM0QsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLFFBQVEsQ0FBQyxZQUFZLEdBQUcsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLENBQUM7UUFDbEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNoRSxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQUMsT0FBMkI7SUFDM0QsT0FBTyxLQUFLLEVBQUUsSUFBYSxFQUFFLEdBQWEsRUFBaUIsRUFBRTtRQUMzRCxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN4RCxXQUFXLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNsQyxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxPQUEyQjtJQUM5RCxPQUFPLEtBQUssRUFBRSxJQUFhLEVBQUUsR0FBYSxFQUFpQixFQUFFO1FBQzNELE1BQU0sRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN6RSxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3BCLFFBQVEsQ0FBQyxNQUFNLEdBQUcsV0FBVyxDQUFDO1lBQzlCLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLG1CQUFtQixFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUM5RCxPQUFPO1FBQ1QsQ0FBQztRQUNELFdBQVcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2xDLENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsT0FBMkI7SUFDNUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxFQUFFLENBQUM7SUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNsRCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgUm91dGVyLCB0eXBlIFJlcXVlc3QsIHR5cGUgUmVzcG9uc2UgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB0eXBlIHsgSGVhbHRoQ2hlY2tSZXNwb25zZSB9IGZyb20gJy4uL3R5cGVzL2NvbW1vbi5qcyc7XG5pbXBvcnQgeyBzZW5kU3VjY2Vzcywgc2VuZEVycm9yIH0gZnJvbSAnLi4vdXRpbHMvcmVzcG9uc2UuanMnO1xuXG5jb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGhlYWx0aCBjaGVjayBlbmRwb2ludC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIZWFsdGhDaGVja09wdGlvbnMge1xuICAvKiogU2VydmljZSBuYW1lICovXG4gIHNlcnZpY2VOYW1lOiBzdHJpbmc7XG4gIC8qKiBTZXJ2aWNlIHZlcnNpb24gKG9wdGlvbmFsKSAqL1xuICB2ZXJzaW9uPzogc3RyaW5nO1xuICAvKiogQ3VzdG9tIGhlYWx0aCBjaGVjayBmdW5jdGlvbiBmb3IgZGVwZW5kZW5jaWVzICovXG4gIGNoZWNrRGVwZW5kZW5jaWVzPzogKCkgPT4gUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCAnY29ubmVjdGVkJyB8ICdkaXNjb25uZWN0ZWQnIHwgJ3Vua25vd24nPj47XG59XG5cbi8qKlxuICogQnVpbGQgYSBIZWFsdGhDaGVja1Jlc3BvbnNlICsgY29sbGVjdCBkZXBlbmRlbmN5IHN0YXR1cy5cbiAqIFNoYXJlZCBiZXR3ZWVuIC9oZWFsdGggKGxpdmVuZXNzKSBhbmQgL3JlYWR5IChyZWFkaW5lc3MpLlxuICovXG5hc3luYyBmdW5jdGlvbiBidWlsZEhlYWx0aFJlc3BvbnNlKG9wdGlvbnM6IEhlYWx0aENoZWNrT3B0aW9ucyk6IFByb21pc2U8e1xuICByZXNwb25zZTogSGVhbHRoQ2hlY2tSZXNwb25zZTtcbiAgaGFzRGlzY29ubmVjdGVkOiBib29sZWFuO1xuICBjaGVja0ZhaWxlZDogYm9vbGVhbjtcbn0+IHtcbiAgY29uc3QgeyBzZXJ2aWNlTmFtZSwgdmVyc2lvbiwgY2hlY2tEZXBlbmRlbmNpZXMgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IHJlc3BvbnNlOiBIZWFsdGhDaGVja1Jlc3BvbnNlID0ge1xuICAgIHN0YXR1czogJ2hlYWx0aHknLFxuICAgIHNlcnZpY2U6IHNlcnZpY2VOYW1lLFxuICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgIHVwdGltZTogTWF0aC5mbG9vcigoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgLyAxMDAwKSxcbiAgfTtcbiAgaWYgKHZlcnNpb24pIHJlc3BvbnNlLnZlcnNpb24gPSB2ZXJzaW9uO1xuXG4gIGlmICghY2hlY2tEZXBlbmRlbmNpZXMpIHtcbiAgICByZXR1cm4geyByZXNwb25zZSwgaGFzRGlzY29ubmVjdGVkOiBmYWxzZSwgY2hlY2tGYWlsZWQ6IGZhbHNlIH07XG4gIH1cblxuICB0cnkge1xuICAgIHJlc3BvbnNlLmRlcGVuZGVuY2llcyA9IGF3YWl0IGNoZWNrRGVwZW5kZW5jaWVzKCk7XG4gICAgY29uc3QgaGFzRGlzY29ubmVjdGVkID0gT2JqZWN0LnZhbHVlcyhyZXNwb25zZS5kZXBlbmRlbmNpZXMpLnNvbWUoXG4gICAgICAoc3RhdHVzKSA9PiBzdGF0dXMgPT09ICdkaXNjb25uZWN0ZWQnLFxuICAgICk7XG4gICAgcmV0dXJuIHsgcmVzcG9uc2UsIGhhc0Rpc2Nvbm5lY3RlZCwgY2hlY2tGYWlsZWQ6IGZhbHNlIH07XG4gIH0gY2F0Y2gge1xuICAgIHJlc3BvbnNlLmRlcGVuZGVuY2llcyA9IHsgY2hlY2s6ICdkaXNjb25uZWN0ZWQnIH07XG4gICAgcmV0dXJuIHsgcmVzcG9uc2UsIGhhc0Rpc2Nvbm5lY3RlZDogdHJ1ZSwgY2hlY2tGYWlsZWQ6IHRydWUgfTtcbiAgfVxufVxuXG4vKipcbiAqIExpdmVuZXNzIGhhbmRsZXIg4oCUIHJldHVybnMgMjAwIGFzIGxvbmcgYXMgdGhlIHByb2Nlc3MgaXMgYWxpdmUgZW5vdWdoIHRvXG4gKiByZXNwb25kLiBEZXBlbmRlbmN5IHN0YXR1cyBpcyByZXBvcnRlZCBpbiB0aGUgYm9keSBhcyBpbmZvcm1hdGlvbmFsLCBidXQgYVxuICogZGlzY29ubmVjdGVkIGRlcGVuZGVuY3kgZG9lcyBOT1QgZmFpbCB0aGUgcHJvYmUgKHVzZSAvcmVhZHkgZm9yIHRoYXQpLlxuICpcbiAqIFVzZSBhcyB0aGUgS3ViZXJuZXRlcyAvIEVDUyBMSVZFTkVTUyBwcm9iZSDigJQgaXQgc2hvdWxkIG9ubHkgZmFpbCB3aGVuIHRoZVxuICogcHJvY2VzcyBpcyBnZW51aW5lbHkgc3R1Y2sgYW5kIG5lZWRzIHRvIGJlIHJlc3RhcnRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUhlYWx0aENoZWNrKG9wdGlvbnM6IEhlYWx0aENoZWNrT3B0aW9ucykge1xuICByZXR1cm4gYXN5bmMgKF9yZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBjb25zdCB7IHJlc3BvbnNlIH0gPSBhd2FpdCBidWlsZEhlYWx0aFJlc3BvbnNlKG9wdGlvbnMpO1xuICAgIHNlbmRTdWNjZXNzKHJlcywgMjAwLCByZXNwb25zZSk7XG4gIH07XG59XG5cbi8qKlxuICogUmVhZGluZXNzIGhhbmRsZXIg4oCUIHJldHVybnMgNTAzIGlmIGFueSBkZXBlbmRlbmN5IGlzIGBkaXNjb25uZWN0ZWRgIChvclxuICogdGhlIGRlcGVuZGVuY3kgY2hlY2sgaXRzZWxmIHRocmV3KS4gUmV0dXJucyAyMDAgb25seSB3aGVuIHRoZSBzZXJ2aWNlIGlzXG4gKiBmdWxseSByZWFkeSB0byBzZXJ2ZSB0cmFmZmljLlxuICpcbiAqIFVzZSBhcyB0aGUgS3ViZXJuZXRlcyAvIEVDUyBSRUFESU5FU1MgcHJvYmUg4oCUIHdoZW4gdGhpcyBmYWlscywgdGhlXG4gKiBvcmNoZXN0cmF0b3Igc3RvcHMgcm91dGluZyB0cmFmZmljIHRvIHRoaXMgcG9kIGJ1dCBkb2VzIE5PVCByZXN0YXJ0IGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVhZGluZXNzQ2hlY2sob3B0aW9uczogSGVhbHRoQ2hlY2tPcHRpb25zKSB7XG4gIHJldHVybiBhc3luYyAoX3JlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGNvbnN0IHsgcmVzcG9uc2UsIGhhc0Rpc2Nvbm5lY3RlZCB9ID0gYXdhaXQgYnVpbGRIZWFsdGhSZXNwb25zZShvcHRpb25zKTtcbiAgICBpZiAoaGFzRGlzY29ubmVjdGVkKSB7XG4gICAgICByZXNwb25zZS5zdGF0dXMgPSAndW5oZWFsdGh5JztcbiAgICAgIHNlbmRFcnJvcihyZXMsIDUwMywgJ1NlcnZpY2Ugbm90IHJlYWR5JywgdW5kZWZpbmVkLCByZXNwb25zZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHNlbmRTdWNjZXNzKHJlcywgMjAwLCByZXNwb25zZSk7XG4gIH07XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgaGVhbHRoL3JlYWRpbmVzcyByb3V0ZXIgZXhwb3Npbmc6XG4gKiAtIEdFVCAvaGVhbHRoIOKAlCBsaXZlbmVzcyAoYWx3YXlzIDIwMCB1bmxlc3MgcHJvY2VzcyBpcyBkZWFkKVxuICogLSBHRVQgL3JlYWR5ICDigJQgcmVhZGluZXNzICg1MDMgaWYgZGVwZW5kZW5jaWVzIGFyZSBkaXNjb25uZWN0ZWQpXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGFwcC51c2UoY3JlYXRlSGVhbHRoUm91dGVyKHsgc2VydmljZU5hbWU6ICdwbHVnaW4nIH0pKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSGVhbHRoUm91dGVyKG9wdGlvbnM6IEhlYWx0aENoZWNrT3B0aW9ucyk6IFJvdXRlciB7XG4gIGNvbnN0IHJvdXRlciA9IFJvdXRlcigpO1xuICByb3V0ZXIuZ2V0KCcvaGVhbHRoJywgY3JlYXRlSGVhbHRoQ2hlY2sob3B0aW9ucykpO1xuICByb3V0ZXIuZ2V0KCcvcmVhZHknLCBjcmVhdGVSZWFkaW5lc3NDaGVjayhvcHRpb25zKSk7XG4gIHJldHVybiByb3V0ZXI7XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './health.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
export * from './health.js';
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcm91dGVzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsY0FBYyxhQUFhLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuZXhwb3J0ICogZnJvbSAnLi9oZWFsdGguanMnO1xuIl19
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { RemoteAuditEvent } from './remote-audit-client.js';
|
|
2
|
+
/** A buffered emission: the event plus which service must re-deliver it. */
|
|
3
|
+
export interface AuditSpoolEntry {
|
|
4
|
+
event: RemoteAuditEvent;
|
|
5
|
+
serviceName: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Durable buffer for audit events that failed LIVE delivery to the platform
|
|
9
|
+
* (retries exhausted during a sustained outage). Without this, the audit trail —
|
|
10
|
+
* a security log — is silently lost the moment the platform is down for longer
|
|
11
|
+
* than the client's small retry budget.
|
|
12
|
+
*
|
|
13
|
+
* Contract:
|
|
14
|
+
* - BOUNDED. A security log must degrade to "dropped the oldest, loudly" (a
|
|
15
|
+
* metric) rather than grow without limit and OOM the emitter.
|
|
16
|
+
* - FAIL-SAFE. Every method swallows its own errors — a broken/unreachable spool
|
|
17
|
+
* must never break or block the audit emission path (which is itself
|
|
18
|
+
* fire-and-forget). A spool problem degrades to the pre-spool behavior.
|
|
19
|
+
* - Ordering is best-effort. Re-delivered events chain at re-delivery time
|
|
20
|
+
* (that's when the platform inserts them), so each event also carries an
|
|
21
|
+
* `occurredAt` stamped at emission for reviewers — see RemoteAuditEvent.
|
|
22
|
+
*/
|
|
23
|
+
export interface AuditSpool {
|
|
24
|
+
/** Buffer an event that failed live delivery. */
|
|
25
|
+
enqueue(entry: AuditSpoolEntry): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Atomically MOVE up to `max` buffered entries onto an in-progress list and
|
|
28
|
+
* return them. Because the entries are moved (not popped-and-dropped), a crash
|
|
29
|
+
* mid-drain leaves them recoverable on the in-progress list — see `recover`.
|
|
30
|
+
* Each taken entry MUST be resolved with exactly one of `ack` (delivered) or
|
|
31
|
+
* `requeue` (still failing), or it lingers on the in-progress list until the
|
|
32
|
+
* next `recover`.
|
|
33
|
+
*/
|
|
34
|
+
take(max: number): Promise<AuditSpoolEntry[]>;
|
|
35
|
+
/** Acknowledge successfully re-delivered entries — removes them from the
|
|
36
|
+
* in-progress list so they are not recovered again. */
|
|
37
|
+
ack(entries: AuditSpoolEntry[]): Promise<void>;
|
|
38
|
+
/** Return entries whose re-delivery failed to the HEAD of the buffer (retried
|
|
39
|
+
* first) and clear them from the in-progress list. Best-effort. */
|
|
40
|
+
requeue(entries: AuditSpoolEntry[]): Promise<void>;
|
|
41
|
+
/** Reclaim any entries stranded on the in-progress list by a prior crash,
|
|
42
|
+
* moving them back to the head of the main buffer. Call once at startup.
|
|
43
|
+
* Returns the number reclaimed. */
|
|
44
|
+
recover(): Promise<number>;
|
|
45
|
+
/** Approximate current depth (for metrics / drain decisions). */
|
|
46
|
+
depth(): Promise<number>;
|
|
47
|
+
}
|
|
48
|
+
/** Minimal Redis LIST surface the spool needs (a subset of ioredis). */
|
|
49
|
+
interface RedisListClient {
|
|
50
|
+
rpush(key: string, ...values: string[]): Promise<number>;
|
|
51
|
+
lpush(key: string, ...values: string[]): Promise<number>;
|
|
52
|
+
lpop(key: string, count: number): Promise<string[] | null>;
|
|
53
|
+
ltrim(key: string, start: number, stop: number): Promise<unknown>;
|
|
54
|
+
llen(key: string): Promise<number>;
|
|
55
|
+
/** Atomically pop from one list end and push to another (Redis ≥ 6.2). */
|
|
56
|
+
lmove(source: string, destination: string, from: 'LEFT' | 'RIGHT', to: 'LEFT' | 'RIGHT'): Promise<string | null>;
|
|
57
|
+
/** Remove `count` occurrences of `value` from a list. */
|
|
58
|
+
lrem(key: string, count: number, value: string): Promise<number>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Redis-LIST-backed spool. Durable across process restarts (unlike an in-memory
|
|
62
|
+
* or per-pod-disk buffer), shared by all replicas of a service, and bounded via
|
|
63
|
+
* a trim-to-tail on overflow (drops the OLDEST, emitting `audit_spool_dropped_total`).
|
|
64
|
+
*/
|
|
65
|
+
export declare function createRedisAuditSpool(redis: RedisListClient, opts?: {
|
|
66
|
+
maxDepth?: number;
|
|
67
|
+
key?: string;
|
|
68
|
+
}): AuditSpool;
|
|
69
|
+
/**
|
|
70
|
+
* Build a Redis-backed audit spool from the ambient `REDIS_URL` / `REDIS_HOST`
|
|
71
|
+
* env via the shared `createEnvRedisClient`. Returns `null` when Redis is not
|
|
72
|
+
* configured or the client can't be constructed — the caller then runs without a
|
|
73
|
+
* spool (pre-spool best-effort behavior), never crashing. The shared helper loads
|
|
74
|
+
* ioredis via `createRequire`, so this stays importable where Redis isn't present.
|
|
75
|
+
*/
|
|
76
|
+
export declare function createEnvRedisAuditSpool(opts?: {
|
|
77
|
+
maxDepth?: number;
|
|
78
|
+
key?: string;
|
|
79
|
+
}): AuditSpool | null;
|
|
80
|
+
export {};
|