@pipeline-builder/pipeline-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.
Files changed (84) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +69 -0
  3. package/lib/cdk.d.ts +38 -0
  4. package/lib/cdk.js +44 -0
  5. package/lib/config/app-config.d.ts +109 -0
  6. package/lib/config/app-config.js +197 -0
  7. package/lib/config/aws-config-cdk.d.ts +49 -0
  8. package/lib/config/aws-config-cdk.js +65 -0
  9. package/lib/config/billing-config.d.ts +24 -0
  10. package/lib/config/billing-config.js +497 -0
  11. package/lib/config/config-types.d.ts +346 -0
  12. package/lib/config/config-types.js +4 -0
  13. package/lib/config/entitlements.d.ts +23 -0
  14. package/lib/config/entitlements.js +46 -0
  15. package/lib/config/handler-constants.d.ts +10 -0
  16. package/lib/config/handler-constants.js +39 -0
  17. package/lib/config/infrastructure-config.d.ts +66 -0
  18. package/lib/config/infrastructure-config.js +197 -0
  19. package/lib/config/server-config.d.ts +53 -0
  20. package/lib/config/server-config.js +175 -0
  21. package/lib/config/service-client.d.ts +13 -0
  22. package/lib/config/service-client.js +20 -0
  23. package/lib/core/artifact-manager.d.ts +62 -0
  24. package/lib/core/artifact-manager.js +83 -0
  25. package/lib/core/id-generator.d.ts +50 -0
  26. package/lib/core/id-generator.js +50 -0
  27. package/lib/core/metadata-builder.d.ts +48 -0
  28. package/lib/core/metadata-builder.js +278 -0
  29. package/lib/core/metadata-helpers.d.ts +31 -0
  30. package/lib/core/metadata-helpers.js +55 -0
  31. package/lib/core/network-types.d.ts +200 -0
  32. package/lib/core/network-types.js +4 -0
  33. package/lib/core/network.d.ts +33 -0
  34. package/lib/core/network.js +112 -0
  35. package/lib/core/pipeline-helpers.d.ts +61 -0
  36. package/lib/core/pipeline-helpers.js +563 -0
  37. package/lib/core/pipeline-types.d.ts +118 -0
  38. package/lib/core/pipeline-types.js +131 -0
  39. package/lib/core/role-types.d.ts +254 -0
  40. package/lib/core/role-types.js +4 -0
  41. package/lib/core/role.d.ts +14 -0
  42. package/lib/core/role.js +117 -0
  43. package/lib/core/security-group-types.d.ts +84 -0
  44. package/lib/core/security-group-types.js +4 -0
  45. package/lib/core/security-group.d.ts +14 -0
  46. package/lib/core/security-group.js +33 -0
  47. package/lib/handlers/plugin-lookup-handler.d.ts +32 -0
  48. package/lib/handlers/plugin-lookup-handler.js +292 -0
  49. package/lib/handlers/pnpm-lock.yaml +12 -0
  50. package/lib/index.d.ts +45 -0
  51. package/lib/index.js +53 -0
  52. package/lib/pipeline/pipeline-builder.d.ts +123 -0
  53. package/lib/pipeline/pipeline-builder.js +476 -0
  54. package/lib/pipeline/pipeline-configuration.d.ts +81 -0
  55. package/lib/pipeline/pipeline-configuration.js +214 -0
  56. package/lib/pipeline/plugin-lookup.d.ts +131 -0
  57. package/lib/pipeline/plugin-lookup.js +316 -0
  58. package/lib/pipeline/plugin-spec.d.ts +138 -0
  59. package/lib/pipeline/plugin-spec.js +4 -0
  60. package/lib/pipeline/source-builder.d.ts +62 -0
  61. package/lib/pipeline/source-builder.js +164 -0
  62. package/lib/pipeline/source-types.d.ts +221 -0
  63. package/lib/pipeline/source-types.js +4 -0
  64. package/lib/pipeline/stage-builder.d.ts +78 -0
  65. package/lib/pipeline/stage-builder.js +129 -0
  66. package/lib/pipeline/step-types.d.ts +222 -0
  67. package/lib/pipeline/step-types.js +4 -0
  68. package/lib/template/evaluator.d.ts +42 -0
  69. package/lib/template/evaluator.js +164 -0
  70. package/lib/template/index.d.ts +34 -0
  71. package/lib/template/index.js +118 -0
  72. package/lib/template/metrics.d.ts +10 -0
  73. package/lib/template/metrics.js +43 -0
  74. package/lib/template/plugin-resolver.d.ts +8 -0
  75. package/lib/template/plugin-resolver.js +48 -0
  76. package/lib/template/tokenizer.d.ts +49 -0
  77. package/lib/template/tokenizer.js +233 -0
  78. package/lib/template/topo-sort.d.ts +17 -0
  79. package/lib/template/topo-sort.js +88 -0
  80. package/lib/template/validate.d.ts +45 -0
  81. package/lib/template/validate.js +96 -0
  82. package/lib/template/walker.d.ts +34 -0
  83. package/lib/template/walker.js +83 -0
  84. package/package.json +184 -0
@@ -0,0 +1,197 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { MAX_PAGE_LIMIT as SHARED_MAX_PAGE_LIMIT, DEFAULT_PAGE_LIMIT as SHARED_DEFAULT_PAGE_LIMIT } from '@pipeline-builder/api-core';
4
+ import { loadBillingConfig } from './billing-config.js';
5
+ import * as HandlerConstants from './handler-constants.js';
6
+ import { loadRegistryConfig, loadRedisConfig, loadPluginBuildConfig, loadDockerConfig, loadDatabaseConfig, loadObservabilityConfig, loadComplianceConfig, loadAWSConfig, } from './infrastructure-config.js';
7
+ import { loadServerConfig, loadAuthConfig, loadRateLimitConfig, validateServerConfig, validateAuthConfig, } from './server-config.js';
8
+ /**
9
+ * Core constants — configurable via environment variables with sensible defaults.
10
+ */
11
+ export class CoreConstants {
12
+ static NAME_PATTERN = /^[a-z0-9-]+$/;
13
+ // Supported JWT algorithms
14
+ static ALLOWED_JWT_ALGORITHMS = ['HS256', 'RS256', 'ES256'];
15
+ // Custom Resource Handler configuration (must be less than Lambda timeout of 30s to allow response handling).
16
+ // Sourced from the dependency-free `handler-constants.ts` leaf — the Lambda handler imports that module
17
+ // directly (not this one) so its esbuild bundle never pulls in aws-cdk-lib via infrastructure-config.
18
+ static HANDLER_TIMEOUT_MS = HandlerConstants.HANDLER_TIMEOUT_MS;
19
+ /** Default platform URL fallback when PLATFORM_BASE_URL is not set. */
20
+ static DEFAULT_PLATFORM_URL = HandlerConstants.DEFAULT_PLATFORM_URL;
21
+ static HANDLER_DEFAULT_BASE_URL = HandlerConstants.HANDLER_DEFAULT_BASE_URL;
22
+ static HANDLER_MAX_RETRIES = HandlerConstants.HANDLER_MAX_RETRIES;
23
+ static HANDLER_RETRY_DELAY_MS = HandlerConstants.HANDLER_RETRY_DELAY_MS;
24
+ // Plugin build queue configuration.
25
+ // NOTE: maxAttempts / backoffDelayMs / workerTimeoutMs are NOT duplicated here —
26
+ // `loadPluginBuildConfig` (infrastructure-config.ts) is their single source of
27
+ // truth, read via `Config.get('pluginBuild')`.
28
+ static PLUGIN_BUILD_QUEUE_NAME = process.env.PLUGIN_BUILD_QUEUE_NAME || 'plugin-build';
29
+ static PLUGIN_BUILD_COMPLETED_RETENTION_SECS = parseInt(process.env.PLUGIN_BUILD_COMPLETED_RETENTION_SECS || '3600', 10); // 1 hr
30
+ static PLUGIN_BUILD_FAILED_RETENTION_SECS = parseInt(process.env.PLUGIN_BUILD_FAILED_RETENTION_SECS || '86400', 10); // 24 hr
31
+ // Pagination and limits — single source in api-core (validation/common-schemas)
32
+ // so the validation layer, this config, and pipeline-data's CrudService never drift.
33
+ static MAX_PAGE_LIMIT = SHARED_MAX_PAGE_LIMIT;
34
+ static DEFAULT_PAGE_LIMIT = SHARED_DEFAULT_PAGE_LIMIT;
35
+ static MAX_PROMPT_LENGTH = parseInt(process.env.MAX_PROMPT_LENGTH || '5000', 10);
36
+ static PLUGIN_MAX_UPLOAD_MB = parseInt(process.env.PLUGIN_MAX_UPLOAD_MB || '4096', 10);
37
+ static PIPELINE_NAME_MAX_LENGTH = parseInt(process.env.PIPELINE_NAME_MAX_LENGTH || '100', 10);
38
+ static DEFAULT_PLUGIN_VERSION = process.env.DEFAULT_PLUGIN_VERSION || '1.0.0';
39
+ // SSE stream timeout for AI generation endpoints
40
+ static SSE_STREAM_TIMEOUT_MS = parseInt(process.env.SSE_STREAM_TIMEOUT_MS || '300000', 10); // 5 min
41
+ // Git provider API base URLs (configurable for enterprise instances)
42
+ static GITHUB_API_BASE_URL = process.env.GITHUB_API_BASE_URL || 'https://api.github.com';
43
+ static BITBUCKET_API_BASE_URL = process.env.BITBUCKET_API_BASE_URL || 'https://api.bitbucket.org/2.0';
44
+ // Bulk operations and event ingestion
45
+ static MAX_BULK_ITEMS = parseInt(process.env.MAX_BULK_ITEMS || '100', 10);
46
+ static MAX_EVENTS_PER_BATCH = parseInt(process.env.MAX_EVENTS_PER_BATCH || '100', 10);
47
+ static DEFAULT_REPORT_RANGE_DAYS = parseInt(process.env.DEFAULT_REPORT_RANGE_DAYS || '30', 10);
48
+ // Secrets Manager path prefix for org-scoped secrets
49
+ static SECRETS_PATH_PREFIX = process.env.SECRETS_PATH_PREFIX || 'pipeline-builder';
50
+ /** Build a Secrets Manager path: {prefix}/{orgId}/{name} */
51
+ static secretPath(orgId, name) {
52
+ return `${CoreConstants.SECRETS_PATH_PREFIX}/${orgId}/${name}`;
53
+ }
54
+ // Database connection
55
+ static DB_MAX_RETRIES = parseInt(process.env.DB_MAX_RETRIES || '3', 10);
56
+ static DB_RETRY_DELAY_MS = parseInt(process.env.DB_RETRY_DELAY_MS || '1000', 10); // 1s
57
+ static DB_TRANSACTION_TIMEOUT_MS = parseInt(process.env.DB_TRANSACTION_TIMEOUT_MS || '30000', 10); // 30s
58
+ static DB_CLOSE_TIMEOUT_MS = parseInt(process.env.DB_CLOSE_TIMEOUT_MS || '5000', 10); // 5s
59
+ // Response compression
60
+ static COMPRESSION_THRESHOLD_BYTES = parseInt(process.env.COMPRESSION_THRESHOLD_BYTES || '1024', 10);
61
+ // Idempotency
62
+ static IDEMPOTENCY_TTL_MS = parseInt(process.env.IDEMPOTENCY_TTL_MS || '300000', 10); // 5 min
63
+ static IDEMPOTENCY_MAX_STORE_SIZE = parseInt(process.env.IDEMPOTENCY_MAX_STORE_SIZE || '10000', 10);
64
+ static IDEMPOTENCY_CLEANUP_INTERVAL_MS = parseInt(process.env.IDEMPOTENCY_CLEANUP_INTERVAL_MS || '60000', 10); // 1 min
65
+ // Cache
66
+ static CACHE_CLEANUP_INTERVAL_MS = parseInt(process.env.CACHE_CLEANUP_INTERVAL_MS || '30000', 10); // 30s
67
+ // Server-side cache TTLs (seconds)
68
+ static CACHE_TTL_ENTITY = parseInt(process.env.CACHE_TTL_ENTITY || '60', 10); // plugin/pipeline findById
69
+ static CACHE_TTL_MESSAGE = parseInt(process.env.CACHE_TTL_MESSAGE || '300', 10); // announcements/conversations (5 min)
70
+ static CACHE_TTL_REPORT_INVENTORY = parseInt(process.env.CACHE_TTL_REPORT_INVENTORY || '300', 10); // plugin summary/distribution (5 min)
71
+ static CACHE_TTL_REPORT_TIMESERIES = parseInt(process.env.CACHE_TTL_REPORT_TIMESERIES || '120', 10); // execution/build metrics (2 min)
72
+ static CACHE_TTL_COMPLIANCE_RULES = parseInt(process.env.CACHE_TTL_COMPLIANCE_RULES || '60', 10); // active compliance rules
73
+ static CACHE_TTL_BILLING_PLANS = parseInt(process.env.CACHE_TTL_BILLING_PLANS || '14400', 10); // billing plans (4 hours)
74
+ // SSE backpressure
75
+ static SSE_BACKPRESSURE_THRESHOLD = parseInt(process.env.SSE_BACKPRESSURE_THRESHOLD || '10', 10);
76
+ // HTTP Cache-Control headers
77
+ static CACHE_CONTROL_LIST = process.env.CACHE_CONTROL_LIST || 'private, max-age=30, stale-while-revalidate=60';
78
+ static CACHE_CONTROL_DETAIL = process.env.CACHE_CONTROL_DETAIL || 'private, max-age=60, stale-while-revalidate=120';
79
+ }
80
+ /**
81
+ * Per-section loader map — each section is loaded lazily on first access.
82
+ * This avoids loading all config sections (and their required env vars)
83
+ * when only one section is needed (e.g. CDK synthesis only needs 'aws').
84
+ */
85
+ const sectionLoaders = {
86
+ server: loadServerConfig,
87
+ auth: loadAuthConfig,
88
+ database: loadDatabaseConfig,
89
+ registry: loadRegistryConfig,
90
+ redis: loadRedisConfig,
91
+ pluginBuild: loadPluginBuildConfig,
92
+ dockerConfig: loadDockerConfig,
93
+ observability: loadObservabilityConfig,
94
+ compliance: loadComplianceConfig,
95
+ aws: loadAWSConfig,
96
+ rateLimit: loadRateLimitConfig,
97
+ billing: loadBillingConfig,
98
+ };
99
+ /** Per-section validators — only run for sections that have validation logic. */
100
+ const sectionValidators = {
101
+ server: validateServerConfig,
102
+ };
103
+ /**
104
+ * Configuration facade with lazy per-section loading.
105
+ *
106
+ * Each section is loaded and validated independently on first access,
107
+ * so requesting `Config.get('aws')` does not trigger loading of
108
+ * server, auth, or billing config (and their env var requirements).
109
+ *
110
+ * Usage: `Config.get('server')`, `Config.get('auth')`, etc.
111
+ */
112
+ export class Config {
113
+ static cache = new Map();
114
+ /**
115
+ * Get a specific configuration section (loaded lazily on first access).
116
+ */
117
+ static get(section) {
118
+ if (!this.cache.has(section)) {
119
+ const loader = sectionLoaders[section];
120
+ const value = loader();
121
+ const validator = sectionValidators[section];
122
+ if (validator)
123
+ validator(value);
124
+ this.cache.set(section, value);
125
+ }
126
+ return this.cache.get(section);
127
+ }
128
+ /**
129
+ * Merge a partial override into a config section, taking precedence over the
130
+ * env-loaded values for all subsequent `Config.get(section)` calls.
131
+ *
132
+ * Used at CDK synth start to inject platform-sourced infrastructure config
133
+ * (e.g. the registry pull host derived from the platform's public URL) so the
134
+ * synth does not silently depend on the operator's local `process.env`.
135
+ * `undefined` fields in `partial` are ignored so they never clobber a loaded
136
+ * value. Loads (and validates) the section first so the override merges onto
137
+ * the real defaults.
138
+ */
139
+ static override(section, partial) {
140
+ const current = this.get(section);
141
+ const defined = Object.fromEntries(Object.entries(partial).filter(([, v]) => v !== undefined));
142
+ this.cache.set(section, { ...current, ...defined });
143
+ }
144
+ /**
145
+ * Like {@link override}, but scoped: snapshots the current cache state for
146
+ * `section` and returns a restore function that reverts it. Use around a
147
+ * single unit of work (e.g. one CDK PipelineBuilder's synth) so a per-builder
148
+ * override does NOT leak into the process-wide cache and bleed into sibling
149
+ * builders in a multi-pipeline CDK app. Calling the returned function restores
150
+ * the exact prior state — the previously cached value, or an unloaded section
151
+ * if it had not been cached yet (so the next `get()` re-loads from env).
152
+ */
153
+ static overrideScoped(section, partial) {
154
+ const hadCached = this.cache.has(section);
155
+ const previous = hadCached ? this.cache.get(section) : undefined;
156
+ this.override(section, partial);
157
+ return () => {
158
+ if (hadCached)
159
+ this.cache.set(section, previous);
160
+ else
161
+ this.cache.delete(section);
162
+ };
163
+ }
164
+ /**
165
+ * Clear all cached config sections so the next `Config.get()` re-reads them
166
+ * from the current `process.env` (re-running each section's loader + validator).
167
+ *
168
+ * Use when env has been mutated in-process and the cache is now stale — e.g. a
169
+ * long-running CLI that reconfigures between operations. CDK synth runs in a
170
+ * fresh subprocess that already reads env on first access, so it does not need
171
+ * this. Note: this also drops any values set via {@link override}.
172
+ */
173
+ static reload() {
174
+ this.cache.clear();
175
+ }
176
+ /**
177
+ * @internal Reset configuration (for testing only). Alias for {@link reload}.
178
+ */
179
+ static _resetForTesting() {
180
+ this.reload();
181
+ }
182
+ /**
183
+ * Validate auth configuration (JWT secrets, algorithms, expiration).
184
+ * Call this at server startup, not during CDK synthesis.
185
+ */
186
+ static validateAuth() {
187
+ validateAuthConfig(this.get('auth'));
188
+ }
189
+ /**
190
+ * Untyped config access — use when the published package types don't include a new section yet.
191
+ * Avoids the `(Config as unknown as ...).get(...)` cast pattern in consumers.
192
+ */
193
+ static getAny(section) {
194
+ return this.get(section);
195
+ }
196
+ }
197
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLWNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvYXBwLWNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxjQUFjLElBQUkscUJBQXFCLEVBQUUsa0JBQWtCLElBQUkseUJBQXlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUV0SSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUV4RCxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sd0JBQXdCLENBQUM7QUFDM0QsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixlQUFlLEVBQ2YscUJBQXFCLEVBQ3JCLGdCQUFnQixFQUNoQixrQkFBa0IsRUFDbEIsdUJBQXVCLEVBQ3ZCLG9CQUFvQixFQUNwQixhQUFhLEdBQ2QsTUFBTSw0QkFBNEIsQ0FBQztBQUNwQyxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLGNBQWMsRUFDZCxtQkFBbUIsRUFDbkIsb0JBQW9CLEVBQ3BCLGtCQUFrQixHQUNuQixNQUFNLG9CQUFvQixDQUFDO0FBRTVCOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFDeEIsTUFBTSxDQUFVLFlBQVksR0FBRyxjQUFjLENBQUM7SUFFOUMsMkJBQTJCO0lBQzNCLE1BQU0sQ0FBVSxzQkFBc0IsR0FBZ0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRWxGLDhHQUE4RztJQUM5Ryx3R0FBd0c7SUFDeEcsc0dBQXNHO0lBQ3RHLE1BQU0sQ0FBVSxrQkFBa0IsR0FBRyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FBQztJQUN6RSx1RUFBdUU7SUFDdkUsTUFBTSxDQUFVLG9CQUFvQixHQUFHLGdCQUFnQixDQUFDLG9CQUFvQixDQUFDO0lBRTdFLE1BQU0sQ0FBVSx3QkFBd0IsR0FBRyxnQkFBZ0IsQ0FBQyx3QkFBd0IsQ0FBQztJQUNyRixN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QjtRQUNyQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxZQUFZO1FBQ2pCLGtCQUFrQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFlO1FBQzNCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUEwQixDQUFDLENBQUM7SUFDOUMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IE1BWF9QQUdFX0xJTUlUIGFzIFNIQVJFRF9NQVhfUEFHRV9MSU1JVCwgREVGQVVMVF9QQUdFX0xJTUlUIGFzIFNIQVJFRF9ERUZBVUxUX1BBR0VfTElNSVQgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgdHlwZSB7IEFsZ29yaXRobSB9IGZyb20gJ2pzb253ZWJ0b2tlbic7XG5pbXBvcnQgeyBsb2FkQmlsbGluZ0NvbmZpZyB9IGZyb20gJy4vYmlsbGluZy1jb25maWcuanMnO1xuaW1wb3J0IHR5cGUgeyBBcHBDb25maWcgfSBmcm9tICcuL2NvbmZpZy10eXBlcy5qcyc7XG5pbXBvcnQgKiBhcyBIYW5kbGVyQ29uc3RhbnRzIGZyb20gJy4vaGFuZGxlci1jb25zdGFudHMuanMnO1xuaW1wb3J0IHtcbiAgbG9hZFJlZ2lzdHJ5Q29uZmlnLFxuICBsb2FkUmVkaXNDb25maWcsXG4gIGxvYWRQbHVnaW5CdWlsZENvbmZpZyxcbiAgbG9hZERvY2tlckNvbmZpZyxcbiAgbG9hZERhdGFiYXNlQ29uZmlnLFxuICBsb2FkT2JzZXJ2YWJpbGl0eUNvbmZpZyxcbiAgbG9hZENvbXBsaWFuY2VDb25maWcsXG4gIGxvYWRBV1NDb25maWcsXG59IGZyb20gJy4vaW5mcmFzdHJ1Y3R1cmUtY29uZmlnLmpzJztcbmltcG9ydCB7XG4gIGxvYWRTZXJ2ZXJDb25maWcsXG4gIGxvYWRBdXRoQ29uZmlnLFxuICBsb2FkUmF0ZUxpbWl0Q29uZmlnLFxuICB2YWxpZGF0ZVNlcnZlckNvbmZpZyxcbiAgdmFsaWRhdGVBdXRoQ29uZmlnLFxufSBmcm9tICcuL3NlcnZlci1jb25maWcuanMnO1xuXG4vKipcbiAqIENvcmUgY29uc3RhbnRzIOKAlCBjb25maWd1cmFibGUgdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyB3aXRoIHNlbnNpYmxlIGRlZmF1bHRzLlxuICovXG5leHBvcnQgY2xhc3MgQ29yZUNvbnN0YW50cyB7XG4gIHN0YXRpYyByZWFkb25seSBOQU1FX1BBVFRFUk4gPSAvXlthLXowLTktXSskLztcblxuICAvLyBTdXBwb3J0ZWQgSldUIGFsZ29yaXRobXNcbiAgc3RhdGljIHJlYWRvbmx5IEFMTE9XRURfSldUX0FMR09SSVRITVM6IEFsZ29yaXRobVtdID0gWydIUzI1NicsICdSUzI1NicsICdFUzI1NiddO1xuXG4gIC8vIEN1c3RvbSBSZXNvdXJjZSBIYW5kbGVyIGNvbmZpZ3VyYXRpb24gKG11c3QgYmUgbGVzcyB0aGFuIExhbWJkYSB0aW1lb3V0IG9mIDMwcyB0byBhbGxvdyByZXNwb25zZSBoYW5kbGluZykuXG4gIC8vIFNvdXJjZWQgZnJvbSB0aGUgZGVwZW5kZW5jeS1mcmVlIGBoYW5kbGVyLWNvbnN0YW50cy50c2AgbGVhZiDigJQgdGhlIExhbWJkYSBoYW5kbGVyIGltcG9ydHMgdGhhdCBtb2R1bGVcbiAgLy8gZGlyZWN0bHkgKG5vdCB0aGlzIG9uZSkgc28gaXRzIGVzYnVpbGQgYnVuZGxlIG5ldmVyIHB1bGxzIGluIGF3cy1jZGstbGliIHZpYSBpbmZyYXN0cnVjdHVyZS1jb25maWcuXG4gIHN0YXRpYyByZWFkb25seSBIQU5ETEVSX1RJTUVPVVRfTVMgPSBIYW5kbGVyQ29uc3RhbnRzLkhBTkRMRVJfVElNRU9VVF9NUztcbiAgLyoqIERlZmF1bHQgcGxhdGZvcm0gVVJMIGZhbGxiYWNrIHdoZW4gUExBVEZPUk1fQkFTRV9VUkwgaXMgbm90IHNldC4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfUExBVEZPUk1fVVJMID0gSGFuZGxlckNvbnN0YW50cy5ERUZBVUxUX1BMQVRGT1JNX1VSTDtcblxuICBzdGF0aWMgcmVhZG9ubHkgSEFORExFUl9ERUZBVUxUX0JBU0VfVVJMID0gSGFuZGxlckNvbnN0YW50cy5IQU5ETEVSX0RFRkFVTFRfQkFTRV9VUkw7XG4gIHN0YXRpYyByZWFkb25seSBIQU5ETEVSX01BWF9SRVRSSUVTID0gSGFuZGxlckNvbnN0YW50cy5IQU5ETEVSX01BWF9SRVRSSUVTO1xuICBzdGF0aWMgcmVhZG9ubHkgSEFORExFUl9SRVRSWV9ERUxBWV9NUyA9IEhhbmRsZXJDb25zdGFudHMuSEFORExFUl9SRVRSWV9ERUxBWV9NUztcblxuICAvLyBQbHVnaW4gYnVpbGQgcXVldWUgY29uZmlndXJhdGlvbi5cbiAgLy8gTk9URTogbWF4QXR0ZW1wdHMgLyBiYWNrb2ZmRGVsYXlNcyAvIHdvcmtlclRpbWVvdXRNcyBhcmUgTk9UIGR1cGxpY2F0ZWQgaGVyZSDigJRcbiAgLy8gYGxvYWRQbHVnaW5CdWlsZENvbmZpZ2AgKGluZnJhc3RydWN0dXJlLWNvbmZpZy50cykgaXMgdGhlaXIgc2luZ2xlIHNvdXJjZSBvZlxuICAvLyB0cnV0aCwgcmVhZCB2aWEgYENvbmZpZy5nZXQoJ3BsdWdpbkJ1aWxkJylgLlxuICBzdGF0aWMgcmVhZG9ubHkgUExVR0lOX0JVSUxEX1FVRVVFX05BTUUgPSBwcm9jZXNzLmVudi5QTFVHSU5fQlVJTERfUVVFVUVfTkFNRSB8fCAncGx1Z2luLWJ1aWxkJztcbiAgc3RhdGljIHJlYWRvbmx5IFBMVUdJTl9CVUlMRF9DT01QTEVURURfUkVURU5USU9OX1NFQ1MgPSBwYXJzZUludChwcm9jZXNzLmVudi5QTFVHSU5fQlVJTERfQ09NUExFVEVEX1JFVEVOVElPTl9TRUNTIHx8ICczNjAwJywgMTApOyAvLyAxIGhyXG4gIHN0YXRpYyByZWFkb25seSBQTFVHSU5fQlVJTERfRkFJTEVEX1JFVEVOVElPTl9TRUNTID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuUExVR0lOX0JVSUxEX0ZBSUxFRF9SRVRFTlRJT05fU0VDUyB8fCAnODY0MDAnLCAxMCk7IC8vIDI0IGhyXG5cbiAgLy8gUGFnaW5hdGlvbiBhbmQgbGltaXRzIOKAlCBzaW5nbGUgc291cmNlIGluIGFwaS1jb3JlICh2YWxpZGF0aW9uL2NvbW1vbi1zY2hlbWFzKVxuICAvLyBzbyB0aGUgdmFsaWRhdGlvbiBsYXllciwgdGhpcyBjb25maWcsIGFuZCBwaXBlbGluZS1kYXRhJ3MgQ3J1ZFNlcnZpY2UgbmV2ZXIgZHJpZnQuXG4gIHN0YXRpYyByZWFkb25seSBNQVhfUEFHRV9MSU1JVCA9IFNIQVJFRF9NQVhfUEFHRV9MSU1JVDtcbiAgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfUEFHRV9MSU1JVCA9IFNIQVJFRF9ERUZBVUxUX1BBR0VfTElNSVQ7XG4gIHN0YXRpYyByZWFkb25seSBNQVhfUFJPTVBUX0xFTkdUSCA9IHBhcnNlSW50KHByb2Nlc3MuZW52Lk1BWF9QUk9NUFRfTEVOR1RIIHx8ICc1MDAwJywgMTApO1xuICBzdGF0aWMgcmVhZG9ubHkgUExVR0lOX01BWF9VUExPQURfTUIgPSBwYXJzZUludChwcm9jZXNzLmVudi5QTFVHSU5fTUFYX1VQTE9BRF9NQiB8fCAnNDA5NicsIDEwKTtcbiAgc3RhdGljIHJlYWRvbmx5IFBJUEVMSU5FX05BTUVfTUFYX0xFTkdUSCA9IHBhcnNlSW50KHByb2Nlc3MuZW52LlBJUEVMSU5FX05BTUVfTUFYX0xFTkdUSCB8fCAnMTAwJywgMTApO1xuICBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9QTFVHSU5fVkVSU0lPTiA9IHByb2Nlc3MuZW52LkRFRkFVTFRfUExVR0lOX1ZFUlNJT04gfHwgJzEuMC4wJztcblxuICAvLyBTU0Ugc3RyZWFtIHRpbWVvdXQgZm9yIEFJIGdlbmVyYXRpb24gZW5kcG9pbnRzXG4gIHN0YXRpYyByZWFkb25seSBTU0VfU1RSRUFNX1RJTUVPVVRfTVMgPSBwYXJzZUludChwcm9jZXNzLmVudi5TU0VfU1RSRUFNX1RJTUVPVVRfTVMgfHwgJzMwMDAwMCcsIDEwKTsgLy8gNSBtaW5cblxuICAvLyBHaXQgcHJvdmlkZXIgQVBJIGJhc2UgVVJMcyAoY29uZmlndXJhYmxlIGZvciBlbnRlcnByaXNlIGluc3RhbmNlcylcbiAgc3RhdGljIHJlYWRvbmx5IEdJVEhVQl9BUElfQkFTRV9VUkwgPSBwcm9jZXNzLmVudi5HSVRIVUJfQVBJX0JBU0VfVVJMIHx8ICdodHRwczovL2FwaS5naXRodWIuY29tJztcbiAgc3RhdGljIHJlYWRvbmx5IEJJVEJVQ0tFVF9BUElfQkFTRV9VUkwgPSBwcm9jZXNzLmVudi5CSVRCVUNLRVRfQVBJX0JBU0VfVVJMIHx8ICdodHRwczovL2FwaS5iaXRidWNrZXQub3JnLzIuMCc7XG5cbiAgLy8gQnVsayBvcGVyYXRpb25zIGFuZCBldmVudCBpbmdlc3Rpb25cbiAgc3RhdGljIHJlYWRvbmx5IE1BWF9CVUxLX0lURU1TID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuTUFYX0JVTEtfSVRFTVMgfHwgJzEwMCcsIDEwKTtcbiAgc3RhdGljIHJlYWRvbmx5IE1BWF9FVkVOVFNfUEVSX0JBVENIID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuTUFYX0VWRU5UU19QRVJfQkFUQ0ggfHwgJzEwMCcsIDEwKTtcbiAgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfUkVQT1JUX1JBTkdFX0RBWVMgPSBwYXJzZUludChwcm9jZXNzLmVudi5ERUZBVUxUX1JFUE9SVF9SQU5HRV9EQVlTIHx8ICczMCcsIDEwKTtcblxuICAvLyBTZWNyZXRzIE1hbmFnZXIgcGF0aCBwcmVmaXggZm9yIG9yZy1zY29wZWQgc2VjcmV0c1xuICBzdGF0aWMgcmVhZG9ubHkgU0VDUkVUU19QQVRIX1BSRUZJWCA9IHByb2Nlc3MuZW52LlNFQ1JFVFNfUEFUSF9QUkVGSVggfHwgJ3BpcGVsaW5lLWJ1aWxkZXInO1xuXG4gIC8qKiBCdWlsZCBhIFNlY3JldHMgTWFuYWdlciBwYXRoOiB7cHJlZml4fS97b3JnSWR9L3tuYW1lfSAqL1xuICBzdGF0aWMgc2VjcmV0UGF0aChvcmdJZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHtDb3JlQ29uc3RhbnRzLlNFQ1JFVFNfUEFUSF9QUkVGSVh9LyR7b3JnSWR9LyR7bmFtZX1gO1xuICB9XG5cbiAgLy8gRGF0YWJhc2UgY29ubmVjdGlvblxuICBzdGF0aWMgcmVhZG9ubHkgREJfTUFYX1JFVFJJRVMgPSBwYXJzZUludChwcm9jZXNzLmVudi5EQl9NQVhfUkVUUklFUyB8fCAnMycsIDEwKTtcbiAgc3RhdGljIHJlYWRvbmx5IERCX1JFVFJZX0RFTEFZX01TID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuREJfUkVUUllfREVMQVlfTVMgfHwgJzEwMDAnLCAxMCk7IC8vIDFzXG4gIHN0YXRpYyByZWFkb25seSBEQl9UUkFOU0FDVElPTl9USU1FT1VUX01TID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuREJfVFJBTlNBQ1RJT05fVElNRU9VVF9NUyB8fCAnMzAwMDAnLCAxMCk7IC8vIDMwc1xuICBzdGF0aWMgcmVhZG9ubHkgREJfQ0xPU0VfVElNRU9VVF9NUyA9IHBhcnNlSW50KHByb2Nlc3MuZW52LkRCX0NMT1NFX1RJTUVPVVRfTVMgfHwgJzUwMDAnLCAxMCk7IC8vIDVzXG5cbiAgLy8gUmVzcG9uc2UgY29tcHJlc3Npb25cbiAgc3RhdGljIHJlYWRvbmx5IENPTVBSRVNTSU9OX1RIUkVTSE9MRF9CWVRFUyA9IHBhcnNlSW50KHByb2Nlc3MuZW52LkNPTVBSRVNTSU9OX1RIUkVTSE9MRF9CWVRFUyB8fCAnMTAyNCcsIDEwKTtcblxuICAvLyBJZGVtcG90ZW5jeVxuICBzdGF0aWMgcmVhZG9ubHkgSURFTVBPVEVOQ1lfVFRMX01TID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuSURFTVBPVEVOQ1lfVFRMX01TIHx8ICczMDAwMDAnLCAxMCk7IC8vIDUgbWluXG4gIHN0YXRpYyByZWFkb25seSBJREVNUE9URU5DWV9NQVhfU1RPUkVfU0laRSA9IHBhcnNlSW50KHByb2Nlc3MuZW52LklERU1QT1RFTkNZX01BWF9TVE9SRV9TSVpFIHx8ICcxMDAwMCcsIDEwKTtcbiAgc3RhdGljIHJlYWRvbmx5IElERU1QT1RFTkNZX0NMRUFOVVBfSU5URVJWQUxfTVMgPSBwYXJzZUludChwcm9jZXNzLmVudi5JREVNUE9URU5DWV9DTEVBTlVQX0lOVEVSVkFMX01TIHx8ICc2MDAwMCcsIDEwKTsgLy8gMSBtaW5cblxuICAvLyBDYWNoZVxuICBzdGF0aWMgcmVhZG9ubHkgQ0FDSEVfQ0xFQU5VUF9JTlRFUlZBTF9NUyA9IHBhcnNlSW50KHByb2Nlc3MuZW52LkNBQ0hFX0NMRUFOVVBfSU5URVJWQUxfTVMgfHwgJzMwMDAwJywgMTApOyAvLyAzMHNcblxuICAvLyBTZXJ2ZXItc2lkZSBjYWNoZSBUVExzIChzZWNvbmRzKVxuICBzdGF0aWMgcmVhZG9ubHkgQ0FDSEVfVFRMX0VOVElUWSA9IHBhcnNlSW50KHByb2Nlc3MuZW52LkNBQ0hFX1RUTF9FTlRJVFkgfHwgJzYwJywgMTApOyAvLyBwbHVnaW4vcGlwZWxpbmUgZmluZEJ5SWRcbiAgc3RhdGljIHJlYWRvbmx5IENBQ0hFX1RUTF9NRVNTQUdFID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuQ0FDSEVfVFRMX01FU1NBR0UgfHwgJzMwMCcsIDEwKTsgLy8gYW5ub3VuY2VtZW50cy9jb252ZXJzYXRpb25zICg1IG1pbilcbiAgc3RhdGljIHJlYWRvbmx5IENBQ0hFX1RUTF9SRVBPUlRfSU5WRU5UT1JZID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuQ0FDSEVfVFRMX1JFUE9SVF9JTlZFTlRPUlkgfHwgJzMwMCcsIDEwKTsgLy8gcGx1Z2luIHN1bW1hcnkvZGlzdHJpYnV0aW9uICg1IG1pbilcbiAgc3RhdGljIHJlYWRvbmx5IENBQ0hFX1RUTF9SRVBPUlRfVElNRVNFUklFUyA9IHBhcnNlSW50KHByb2Nlc3MuZW52LkNBQ0hFX1RUTF9SRVBPUlRfVElNRVNFUklFUyB8fCAnMTIwJywgMTApOyAvLyBleGVjdXRpb24vYnVpbGQgbWV0cmljcyAoMiBtaW4pXG4gIHN0YXRpYyByZWFkb25seSBDQUNIRV9UVExfQ09NUExJQU5DRV9SVUxFUyA9IHBhcnNlSW50KHByb2Nlc3MuZW52LkNBQ0hFX1RUTF9DT01QTElBTkNFX1JVTEVTIHx8ICc2MCcsIDEwKTsgLy8gYWN0aXZlIGNvbXBsaWFuY2UgcnVsZXNcbiAgc3RhdGljIHJlYWRvbmx5IENBQ0hFX1RUTF9CSUxMSU5HX1BMQU5TID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuQ0FDSEVfVFRMX0JJTExJTkdfUExBTlMgfHwgJzE0NDAwJywgMTApOyAvLyBiaWxsaW5nIHBsYW5zICg0IGhvdXJzKVxuXG4gIC8vIFNTRSBiYWNrcHJlc3N1cmVcbiAgc3RhdGljIHJlYWRvbmx5IFNTRV9CQUNLUFJFU1NVUkVfVEhSRVNIT0xEID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuU1NFX0JBQ0tQUkVTU1VSRV9USFJFU0hPTEQgfHwgJzEwJywgMTApO1xuXG4gIC8vIEhUVFAgQ2FjaGUtQ29udHJvbCBoZWFkZXJzXG4gIHN0YXRpYyByZWFkb25seSBDQUNIRV9DT05UUk9MX0xJU1QgPSBwcm9jZXNzLmVudi5DQUNIRV9DT05UUk9MX0xJU1QgfHwgJ3ByaXZhdGUsIG1heC1hZ2U9MzAsIHN0YWxlLXdoaWxlLXJldmFsaWRhdGU9NjAnO1xuICBzdGF0aWMgcmVhZG9ubHkgQ0FDSEVfQ09OVFJPTF9ERVRBSUwgPSBwcm9jZXNzLmVudi5DQUNIRV9DT05UUk9MX0RFVEFJTCB8fCAncHJpdmF0ZSwgbWF4LWFnZT02MCwgc3RhbGUtd2hpbGUtcmV2YWxpZGF0ZT0xMjAnO1xufVxuXG4vKipcbiAqIFBlci1zZWN0aW9uIGxvYWRlciBtYXAg4oCUIGVhY2ggc2VjdGlvbiBpcyBsb2FkZWQgbGF6aWx5IG9uIGZpcnN0IGFjY2Vzcy5cbiAqIFRoaXMgYXZvaWRzIGxvYWRpbmcgYWxsIGNvbmZpZyBzZWN0aW9ucyAoYW5kIHRoZWlyIHJlcXVpcmVkIGVudiB2YXJzKVxuICogd2hlbiBvbmx5IG9uZSBzZWN0aW9uIGlzIG5lZWRlZCAoZS5nLiBDREsgc3ludGhlc2lzIG9ubHkgbmVlZHMgJ2F3cycpLlxuICovXG5jb25zdCBzZWN0aW9uTG9hZGVyczogeyBbSyBpbiBrZXlvZiBBcHBDb25maWddOiAoKSA9PiBBcHBDb25maWdbS10gfSA9IHtcbiAgc2VydmVyOiBsb2FkU2VydmVyQ29uZmlnLFxuICBhdXRoOiBsb2FkQXV0aENvbmZpZyxcbiAgZGF0YWJhc2U6IGxvYWREYXRhYmFzZUNvbmZpZyxcbiAgcmVnaXN0cnk6IGxvYWRSZWdpc3RyeUNvbmZpZyxcbiAgcmVkaXM6IGxvYWRSZWRpc0NvbmZpZyxcbiAgcGx1Z2luQnVpbGQ6IGxvYWRQbHVnaW5CdWlsZENvbmZpZyxcbiAgZG9ja2VyQ29uZmlnOiBsb2FkRG9ja2VyQ29uZmlnLFxuICBvYnNlcnZhYmlsaXR5OiBsb2FkT2JzZXJ2YWJpbGl0eUNvbmZpZyxcbiAgY29tcGxpYW5jZTogbG9hZENvbXBsaWFuY2VDb25maWcsXG4gIGF3czogbG9hZEFXU0NvbmZpZyxcbiAgcmF0ZUxpbWl0OiBsb2FkUmF0ZUxpbWl0Q29uZmlnLFxuICBiaWxsaW5nOiBsb2FkQmlsbGluZ0NvbmZpZyxcbn07XG5cbi8qKiBQZXItc2VjdGlvbiB2YWxpZGF0b3JzIOKAlCBvbmx5IHJ1biBmb3Igc2VjdGlvbnMgdGhhdCBoYXZlIHZhbGlkYXRpb24gbG9naWMuICovXG5jb25zdCBzZWN0aW9uVmFsaWRhdG9yczogUGFydGlhbDx7IFtLIGluIGtleW9mIEFwcENvbmZpZ106IChjb25maWc6IEFwcENvbmZpZ1tLXSkgPT4gdm9pZCB9PiA9IHtcbiAgc2VydmVyOiB2YWxpZGF0ZVNlcnZlckNvbmZpZyxcbn07XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmYWNhZGUgd2l0aCBsYXp5IHBlci1zZWN0aW9uIGxvYWRpbmcuXG4gKlxuICogRWFjaCBzZWN0aW9uIGlzIGxvYWRlZCBhbmQgdmFsaWRhdGVkIGluZGVwZW5kZW50bHkgb24gZmlyc3QgYWNjZXNzLFxuICogc28gcmVxdWVzdGluZyBgQ29uZmlnLmdldCgnYXdzJylgIGRvZXMgbm90IHRyaWdnZXIgbG9hZGluZyBvZlxuICogc2VydmVyLCBhdXRoLCBvciBiaWxsaW5nIGNvbmZpZyAoYW5kIHRoZWlyIGVudiB2YXIgcmVxdWlyZW1lbnRzKS5cbiAqXG4gKiBVc2FnZTogYENvbmZpZy5nZXQoJ3NlcnZlcicpYCwgYENvbmZpZy5nZXQoJ2F1dGgnKWAsIGV0Yy5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbmZpZyB7XG4gIHByaXZhdGUgc3RhdGljIGNhY2hlID0gbmV3IE1hcDxrZXlvZiBBcHBDb25maWcsIHVua25vd24+KCk7XG5cbiAgLyoqXG4gICAqIEdldCBhIHNwZWNpZmljIGNvbmZpZ3VyYXRpb24gc2VjdGlvbiAobG9hZGVkIGxhemlseSBvbiBmaXJzdCBhY2Nlc3MpLlxuICAgKi9cbiAgc3RhdGljIGdldDxLIGV4dGVuZHMga2V5b2YgQXBwQ29uZmlnPihzZWN0aW9uOiBLKTogQXBwQ29uZmlnW0tdIHtcbiAgICBpZiAoIXRoaXMuY2FjaGUuaGFzKHNlY3Rpb24pKSB7XG4gICAgICBjb25zdCBsb2FkZXIgPSBzZWN0aW9uTG9hZGVyc1tzZWN0aW9uXTtcbiAgICAgIGNvbnN0IHZhbHVlID0gbG9hZGVyKCk7XG4gICAgICBjb25zdCB2YWxpZGF0b3IgPSBzZWN0aW9uVmFsaWRhdG9yc1tzZWN0aW9uXTtcbiAgICAgIGlmICh2YWxpZGF0b3IpICh2YWxpZGF0b3IgYXMgKHY6IEFwcENvbmZpZ1tLXSkgPT4gdm9pZCkodmFsdWUpO1xuICAgICAgdGhpcy5jYWNoZS5zZXQoc2VjdGlvbiwgdmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoc2VjdGlvbikgYXMgQXBwQ29uZmlnW0tdO1xuICB9XG5cbiAgLyoqXG4gICAqIE1lcmdlIGEgcGFydGlhbCBvdmVycmlkZSBpbnRvIGEgY29uZmlnIHNlY3Rpb24sIHRha2luZyBwcmVjZWRlbmNlIG92ZXIgdGhlXG4gICAqIGVudi1sb2FkZWQgdmFsdWVzIGZvciBhbGwgc3Vic2VxdWVudCBgQ29uZmlnLmdldChzZWN0aW9uKWAgY2FsbHMuXG4gICAqXG4gICAqIFVzZWQgYXQgQ0RLIHN5bnRoIHN0YXJ0IHRvIGluamVjdCBwbGF0Zm9ybS1zb3VyY2VkIGluZnJhc3RydWN0dXJlIGNvbmZpZ1xuICAgKiAoZS5nLiB0aGUgcmVnaXN0cnkgcHVsbCBob3N0IGRlcml2ZWQgZnJvbSB0aGUgcGxhdGZvcm0ncyBwdWJsaWMgVVJMKSBzbyB0aGVcbiAgICogc3ludGggZG9lcyBub3Qgc2lsZW50bHkgZGVwZW5kIG9uIHRoZSBvcGVyYXRvcidzIGxvY2FsIGBwcm9jZXNzLmVudmAuXG4gICAqIGB1bmRlZmluZWRgIGZpZWxkcyBpbiBgcGFydGlhbGAgYXJlIGlnbm9yZWQgc28gdGhleSBuZXZlciBjbG9iYmVyIGEgbG9hZGVkXG4gICAqIHZhbHVlLiBMb2FkcyAoYW5kIHZhbGlkYXRlcykgdGhlIHNlY3Rpb24gZmlyc3Qgc28gdGhlIG92ZXJyaWRlIG1lcmdlcyBvbnRvXG4gICAqIHRoZSByZWFsIGRlZmF1bHRzLlxuICAgKi9cbiAgc3RhdGljIG92ZXJyaWRlPEsgZXh0ZW5kcyBrZXlvZiBBcHBDb25maWc+KHNlY3Rpb246IEssIHBhcnRpYWw6IFBhcnRpYWw8QXBwQ29uZmlnW0tdPik6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmdldChzZWN0aW9uKTtcbiAgICBjb25zdCBkZWZpbmVkID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXMocGFydGlhbCkuZmlsdGVyKChbLCB2XSkgPT4gdiAhPT0gdW5kZWZpbmVkKSxcbiAgICApIGFzIFBhcnRpYWw8QXBwQ29uZmlnW0tdPjtcbiAgICB0aGlzLmNhY2hlLnNldChzZWN0aW9uLCB7IC4uLmN1cnJlbnQsIC4uLmRlZmluZWQgfSk7XG4gIH1cblxuICAvKipcbiAgICogTGlrZSB7QGxpbmsgb3ZlcnJpZGV9LCBidXQgc2NvcGVkOiBzbmFwc2hvdHMgdGhlIGN1cnJlbnQgY2FjaGUgc3RhdGUgZm9yXG4gICAqIGBzZWN0aW9uYCBhbmQgcmV0dXJucyBhIHJlc3RvcmUgZnVuY3Rpb24gdGhhdCByZXZlcnRzIGl0LiBVc2UgYXJvdW5kIGFcbiAgICogc2luZ2xlIHVuaXQgb2Ygd29yayAoZS5nLiBvbmUgQ0RLIFBpcGVsaW5lQnVpbGRlcidzIHN5bnRoKSBzbyBhIHBlci1idWlsZGVyXG4gICAqIG92ZXJyaWRlIGRvZXMgTk9UIGxlYWsgaW50byB0aGUgcHJvY2Vzcy13aWRlIGNhY2hlIGFuZCBibGVlZCBpbnRvIHNpYmxpbmdcbiAgICogYnVpbGRlcnMgaW4gYSBtdWx0aS1waXBlbGluZSBDREsgYXBwLiBDYWxsaW5nIHRoZSByZXR1cm5lZCBmdW5jdGlvbiByZXN0b3Jlc1xuICAgKiB0aGUgZXhhY3QgcHJpb3Igc3RhdGUg4oCUIHRoZSBwcmV2aW91c2x5IGNhY2hlZCB2YWx1ZSwgb3IgYW4gdW5sb2FkZWQgc2VjdGlvblxuICAgKiBpZiBpdCBoYWQgbm90IGJlZW4gY2FjaGVkIHlldCAoc28gdGhlIG5leHQgYGdldCgpYCByZS1sb2FkcyBmcm9tIGVudikuXG4gICAqL1xuICBzdGF0aWMgb3ZlcnJpZGVTY29wZWQ8SyBleHRlbmRzIGtleW9mIEFwcENvbmZpZz4oXG4gICAgc2VjdGlvbjogSyxcbiAgICBwYXJ0aWFsOiBQYXJ0aWFsPEFwcENvbmZpZ1tLXT4sXG4gICk6ICgpID0+IHZvaWQge1xuICAgIGNvbnN0IGhhZENhY2hlZCA9IHRoaXMuY2FjaGUuaGFzKHNlY3Rpb24pO1xuICAgIGNvbnN0IHByZXZpb3VzID0gaGFkQ2FjaGVkID8gdGhpcy5jYWNoZS5nZXQoc2VjdGlvbikgOiB1bmRlZmluZWQ7XG4gICAgdGhpcy5vdmVycmlkZShzZWN0aW9uLCBwYXJ0aWFsKTtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKGhhZENhY2hlZCkgdGhpcy5jYWNoZS5zZXQoc2VjdGlvbiwgcHJldmlvdXMpO1xuICAgICAgZWxzZSB0aGlzLmNhY2hlLmRlbGV0ZShzZWN0aW9uKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFyIGFsbCBjYWNoZWQgY29uZmlnIHNlY3Rpb25zIHNvIHRoZSBuZXh0IGBDb25maWcuZ2V0KClgIHJlLXJlYWRzIHRoZW1cbiAgICogZnJvbSB0aGUgY3VycmVudCBgcHJvY2Vzcy5lbnZgIChyZS1ydW5uaW5nIGVhY2ggc2VjdGlvbidzIGxvYWRlciArIHZhbGlkYXRvcikuXG4gICAqXG4gICAqIFVzZSB3aGVuIGVudiBoYXMgYmVlbiBtdXRhdGVkIGluLXByb2Nlc3MgYW5kIHRoZSBjYWNoZSBpcyBub3cgc3RhbGUg4oCUIGUuZy4gYVxuICAgKiBsb25nLXJ1bm5pbmcgQ0xJIHRoYXQgcmVjb25maWd1cmVzIGJldHdlZW4gb3BlcmF0aW9ucy4gQ0RLIHN5bnRoIHJ1bnMgaW4gYVxuICAgKiBmcmVzaCBzdWJwcm9jZXNzIHRoYXQgYWxyZWFkeSByZWFkcyBlbnYgb24gZmlyc3QgYWNjZXNzLCBzbyBpdCBkb2VzIG5vdCBuZWVkXG4gICAqIHRoaXMuIE5vdGU6IHRoaXMgYWxzbyBkcm9wcyBhbnkgdmFsdWVzIHNldCB2aWEge0BsaW5rIG92ZXJyaWRlfS5cbiAgICovXG4gIHN0YXRpYyByZWxvYWQoKTogdm9pZCB7XG4gICAgdGhpcy5jYWNoZS5jbGVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBSZXNldCBjb25maWd1cmF0aW9uIChmb3IgdGVzdGluZyBvbmx5KS4gQWxpYXMgZm9yIHtAbGluayByZWxvYWR9LlxuICAgKi9cbiAgc3RhdGljIF9yZXNldEZvclRlc3RpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5yZWxvYWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBhdXRoIGNvbmZpZ3VyYXRpb24gKEpXVCBzZWNyZXRzLCBhbGdvcml0aG1zLCBleHBpcmF0aW9uKS5cbiAgICogQ2FsbCB0aGlzIGF0IHNlcnZlciBzdGFydHVwLCBub3QgZHVyaW5nIENESyBzeW50aGVzaXMuXG4gICAqL1xuICBzdGF0aWMgdmFsaWRhdGVBdXRoKCk6IHZvaWQge1xuICAgIHZhbGlkYXRlQXV0aENvbmZpZyh0aGlzLmdldCgnYXV0aCcpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnR5cGVkIGNvbmZpZyBhY2Nlc3Mg4oCUIHVzZSB3aGVuIHRoZSBwdWJsaXNoZWQgcGFja2FnZSB0eXBlcyBkb24ndCBpbmNsdWRlIGEgbmV3IHNlY3Rpb24geWV0LlxuICAgKiBBdm9pZHMgdGhlIGAoQ29uZmlnIGFzIHVua25vd24gYXMgLi4uKS5nZXQoLi4uKWAgY2FzdCBwYXR0ZXJuIGluIGNvbnN1bWVycy5cbiAgICovXG4gIHN0YXRpYyBnZXRBbnkoc2VjdGlvbjogc3RyaW5nKTogdW5rbm93biB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KHNlY3Rpb24gYXMga2V5b2YgQXBwQ29uZmlnKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,49 @@
1
+ /**
2
+ * CDK adapters for {@link AWSConfig}.
3
+ *
4
+ * `AWSConfig` is deliberately plain data (see its doc comment): env-loaded
5
+ * numbers and strings, no `aws-cdk-lib` on the import graph. That keeps `Config`
6
+ * — which every API service reads — free of CDK. These functions are the single
7
+ * conversion point from that plain data into CDK value objects, and they live
8
+ * behind the `@pipeline-builder/pipeline-core/cdk` entry point, so only code that
9
+ * actually synthesizes stacks pays for `aws-cdk-lib`.
10
+ */
11
+ import { Duration, RemovalPolicy } from 'aws-cdk-lib';
12
+ import { Architecture, Runtime } from 'aws-cdk-lib/aws-lambda';
13
+ import { RetentionDays } from 'aws-cdk-lib/aws-logs';
14
+ import type { AWSConfig } from './config-types.js';
15
+ /**
16
+ * Resolve a Lambda runtime identifier (e.g. `'nodejs24.x'`) to a CDK `Runtime`.
17
+ *
18
+ * @param runtime - runtime identifier from `Config.get('aws').lambda.runtime`
19
+ * @returns the CDK enum member; falls back to Node.js 24 for unknown values
20
+ */
21
+ export declare function lambdaRuntime(runtime: AWSConfig['lambda']['runtime']): Runtime;
22
+ /**
23
+ * Convert a Lambda timeout in seconds to a CDK `Duration`.
24
+ *
25
+ * @param seconds - timeout from `Config.get('aws').lambda.timeoutSeconds`
26
+ */
27
+ export declare function lambdaTimeout(seconds: AWSConfig['lambda']['timeoutSeconds']): Duration;
28
+ /**
29
+ * Resolve a Lambda architecture name to a CDK `Architecture`.
30
+ *
31
+ * @param architecture - value from `Config.get('aws').lambda.architecture`
32
+ */
33
+ export declare function lambdaArchitecture(architecture: AWSConfig['lambda']['architecture']): Architecture;
34
+ /**
35
+ * Convert a retention day count to CDK's `RetentionDays`.
36
+ *
37
+ * `RetentionDays` members are the day counts themselves, so the cast is exact —
38
+ * `infrastructure-config.ts` has already validated the value against the same
39
+ * set of allowed periods.
40
+ *
41
+ * @param days - value from `Config.get('aws').logging.retentionDays`
42
+ */
43
+ export declare function logRetention(days: AWSConfig['logging']['retentionDays']): RetentionDays;
44
+ /**
45
+ * Resolve a log-group removal policy name to a CDK `RemovalPolicy`.
46
+ *
47
+ * @param policy - value from `Config.get('aws').logging.removalPolicy`
48
+ */
49
+ export declare function logRemovalPolicy(policy: AWSConfig['logging']['removalPolicy']): RemovalPolicy;
@@ -0,0 +1,65 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * CDK adapters for {@link AWSConfig}.
5
+ *
6
+ * `AWSConfig` is deliberately plain data (see its doc comment): env-loaded
7
+ * numbers and strings, no `aws-cdk-lib` on the import graph. That keeps `Config`
8
+ * — which every API service reads — free of CDK. These functions are the single
9
+ * conversion point from that plain data into CDK value objects, and they live
10
+ * behind the `@pipeline-builder/pipeline-core/cdk` entry point, so only code that
11
+ * actually synthesizes stacks pays for `aws-cdk-lib`.
12
+ */
13
+ import { Duration, RemovalPolicy } from 'aws-cdk-lib';
14
+ import { Architecture, Runtime } from 'aws-cdk-lib/aws-lambda';
15
+ import { RetentionDays } from 'aws-cdk-lib/aws-logs';
16
+ /** Runtime identifiers this platform supports, mapped to their CDK enum member. */
17
+ const RUNTIMES = {
18
+ 'nodejs24.x': Runtime.NODEJS_24_X,
19
+ };
20
+ /**
21
+ * Resolve a Lambda runtime identifier (e.g. `'nodejs24.x'`) to a CDK `Runtime`.
22
+ *
23
+ * @param runtime - runtime identifier from `Config.get('aws').lambda.runtime`
24
+ * @returns the CDK enum member; falls back to Node.js 24 for unknown values
25
+ */
26
+ export function lambdaRuntime(runtime) {
27
+ return RUNTIMES[runtime] || Runtime.NODEJS_24_X;
28
+ }
29
+ /**
30
+ * Convert a Lambda timeout in seconds to a CDK `Duration`.
31
+ *
32
+ * @param seconds - timeout from `Config.get('aws').lambda.timeoutSeconds`
33
+ */
34
+ export function lambdaTimeout(seconds) {
35
+ return Duration.seconds(seconds);
36
+ }
37
+ /**
38
+ * Resolve a Lambda architecture name to a CDK `Architecture`.
39
+ *
40
+ * @param architecture - value from `Config.get('aws').lambda.architecture`
41
+ */
42
+ export function lambdaArchitecture(architecture) {
43
+ return architecture === 'x86_64' ? Architecture.X86_64 : Architecture.ARM_64;
44
+ }
45
+ /**
46
+ * Convert a retention day count to CDK's `RetentionDays`.
47
+ *
48
+ * `RetentionDays` members are the day counts themselves, so the cast is exact —
49
+ * `infrastructure-config.ts` has already validated the value against the same
50
+ * set of allowed periods.
51
+ *
52
+ * @param days - value from `Config.get('aws').logging.retentionDays`
53
+ */
54
+ export function logRetention(days) {
55
+ return days;
56
+ }
57
+ /**
58
+ * Resolve a log-group removal policy name to a CDK `RemovalPolicy`.
59
+ *
60
+ * @param policy - value from `Config.get('aws').logging.removalPolicy`
61
+ */
62
+ export function logRemovalPolicy(policy) {
63
+ return policy === 'retain' ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY;
64
+ }
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWNvbmZpZy1jZGsuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29uZmlnL2F3cy1jb25maWctY2RrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7OztHQVNHO0FBRUgsT0FBTyxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFHckQsbUZBQW1GO0FBQ25GLE1BQU0sUUFBUSxHQUE0QjtJQUN4QyxZQUFZLEVBQUUsT0FBTyxDQUFDLFdBQVc7Q0FDbEMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxPQUF1QztJQUNuRSxPQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxPQUFPLENBQUMsV0FBVyxDQUFDO0FBQ2xELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxPQUE4QztJQUMxRSxPQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDbkMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsWUFBaUQ7SUFDbEYsT0FBTyxZQUFZLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDO0FBQy9FLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsSUFBMkM7SUFDdEUsT0FBTyxJQUFxQixDQUFDO0FBQy9CLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLE1BQTZDO0lBQzVFLE9BQU8sTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQztBQUM1RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogQ0RLIGFkYXB0ZXJzIGZvciB7QGxpbmsgQVdTQ29uZmlnfS5cbiAqXG4gKiBgQVdTQ29uZmlnYCBpcyBkZWxpYmVyYXRlbHkgcGxhaW4gZGF0YSAoc2VlIGl0cyBkb2MgY29tbWVudCk6IGVudi1sb2FkZWRcbiAqIG51bWJlcnMgYW5kIHN0cmluZ3MsIG5vIGBhd3MtY2RrLWxpYmAgb24gdGhlIGltcG9ydCBncmFwaC4gVGhhdCBrZWVwcyBgQ29uZmlnYFxuICog4oCUIHdoaWNoIGV2ZXJ5IEFQSSBzZXJ2aWNlIHJlYWRzIOKAlCBmcmVlIG9mIENESy4gVGhlc2UgZnVuY3Rpb25zIGFyZSB0aGUgc2luZ2xlXG4gKiBjb252ZXJzaW9uIHBvaW50IGZyb20gdGhhdCBwbGFpbiBkYXRhIGludG8gQ0RLIHZhbHVlIG9iamVjdHMsIGFuZCB0aGV5IGxpdmVcbiAqIGJlaGluZCB0aGUgYEBwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUvY2RrYCBlbnRyeSBwb2ludCwgc28gb25seSBjb2RlIHRoYXRcbiAqIGFjdHVhbGx5IHN5bnRoZXNpemVzIHN0YWNrcyBwYXlzIGZvciBgYXdzLWNkay1saWJgLlxuICovXG5cbmltcG9ydCB7IER1cmF0aW9uLCBSZW1vdmFsUG9saWN5IH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQXJjaGl0ZWN0dXJlLCBSdW50aW1lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBSZXRlbnRpb25EYXlzIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0IHR5cGUgeyBBV1NDb25maWcgfSBmcm9tICcuL2NvbmZpZy10eXBlcy5qcyc7XG5cbi8qKiBSdW50aW1lIGlkZW50aWZpZXJzIHRoaXMgcGxhdGZvcm0gc3VwcG9ydHMsIG1hcHBlZCB0byB0aGVpciBDREsgZW51bSBtZW1iZXIuICovXG5jb25zdCBSVU5USU1FUzogUmVjb3JkPHN0cmluZywgUnVudGltZT4gPSB7XG4gICdub2RlanMyNC54JzogUnVudGltZS5OT0RFSlNfMjRfWCxcbn07XG5cbi8qKlxuICogUmVzb2x2ZSBhIExhbWJkYSBydW50aW1lIGlkZW50aWZpZXIgKGUuZy4gYCdub2RlanMyNC54J2ApIHRvIGEgQ0RLIGBSdW50aW1lYC5cbiAqXG4gKiBAcGFyYW0gcnVudGltZSAtIHJ1bnRpbWUgaWRlbnRpZmllciBmcm9tIGBDb25maWcuZ2V0KCdhd3MnKS5sYW1iZGEucnVudGltZWBcbiAqIEByZXR1cm5zIHRoZSBDREsgZW51bSBtZW1iZXI7IGZhbGxzIGJhY2sgdG8gTm9kZS5qcyAyNCBmb3IgdW5rbm93biB2YWx1ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhbWJkYVJ1bnRpbWUocnVudGltZTogQVdTQ29uZmlnWydsYW1iZGEnXVsncnVudGltZSddKTogUnVudGltZSB7XG4gIHJldHVybiBSVU5USU1FU1tydW50aW1lXSB8fCBSdW50aW1lLk5PREVKU18yNF9YO1xufVxuXG4vKipcbiAqIENvbnZlcnQgYSBMYW1iZGEgdGltZW91dCBpbiBzZWNvbmRzIHRvIGEgQ0RLIGBEdXJhdGlvbmAuXG4gKlxuICogQHBhcmFtIHNlY29uZHMgLSB0aW1lb3V0IGZyb20gYENvbmZpZy5nZXQoJ2F3cycpLmxhbWJkYS50aW1lb3V0U2Vjb25kc2BcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhbWJkYVRpbWVvdXQoc2Vjb25kczogQVdTQ29uZmlnWydsYW1iZGEnXVsndGltZW91dFNlY29uZHMnXSk6IER1cmF0aW9uIHtcbiAgcmV0dXJuIER1cmF0aW9uLnNlY29uZHMoc2Vjb25kcyk7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIExhbWJkYSBhcmNoaXRlY3R1cmUgbmFtZSB0byBhIENESyBgQXJjaGl0ZWN0dXJlYC5cbiAqXG4gKiBAcGFyYW0gYXJjaGl0ZWN0dXJlIC0gdmFsdWUgZnJvbSBgQ29uZmlnLmdldCgnYXdzJykubGFtYmRhLmFyY2hpdGVjdHVyZWBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhbWJkYUFyY2hpdGVjdHVyZShhcmNoaXRlY3R1cmU6IEFXU0NvbmZpZ1snbGFtYmRhJ11bJ2FyY2hpdGVjdHVyZSddKTogQXJjaGl0ZWN0dXJlIHtcbiAgcmV0dXJuIGFyY2hpdGVjdHVyZSA9PT0gJ3g4Nl82NCcgPyBBcmNoaXRlY3R1cmUuWDg2XzY0IDogQXJjaGl0ZWN0dXJlLkFSTV82NDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgcmV0ZW50aW9uIGRheSBjb3VudCB0byBDREsncyBgUmV0ZW50aW9uRGF5c2AuXG4gKlxuICogYFJldGVudGlvbkRheXNgIG1lbWJlcnMgYXJlIHRoZSBkYXkgY291bnRzIHRoZW1zZWx2ZXMsIHNvIHRoZSBjYXN0IGlzIGV4YWN0IOKAlFxuICogYGluZnJhc3RydWN0dXJlLWNvbmZpZy50c2AgaGFzIGFscmVhZHkgdmFsaWRhdGVkIHRoZSB2YWx1ZSBhZ2FpbnN0IHRoZSBzYW1lXG4gKiBzZXQgb2YgYWxsb3dlZCBwZXJpb2RzLlxuICpcbiAqIEBwYXJhbSBkYXlzIC0gdmFsdWUgZnJvbSBgQ29uZmlnLmdldCgnYXdzJykubG9nZ2luZy5yZXRlbnRpb25EYXlzYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9nUmV0ZW50aW9uKGRheXM6IEFXU0NvbmZpZ1snbG9nZ2luZyddWydyZXRlbnRpb25EYXlzJ10pOiBSZXRlbnRpb25EYXlzIHtcbiAgcmV0dXJuIGRheXMgYXMgUmV0ZW50aW9uRGF5cztcbn1cblxuLyoqXG4gKiBSZXNvbHZlIGEgbG9nLWdyb3VwIHJlbW92YWwgcG9saWN5IG5hbWUgdG8gYSBDREsgYFJlbW92YWxQb2xpY3lgLlxuICpcbiAqIEBwYXJhbSBwb2xpY3kgLSB2YWx1ZSBmcm9tIGBDb25maWcuZ2V0KCdhd3MnKS5sb2dnaW5nLnJlbW92YWxQb2xpY3lgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2dSZW1vdmFsUG9saWN5KHBvbGljeTogQVdTQ29uZmlnWydsb2dnaW5nJ11bJ3JlbW92YWxQb2xpY3knXSk6IFJlbW92YWxQb2xpY3kge1xuICByZXR1cm4gcG9saWN5ID09PSAncmV0YWluJyA/IFJlbW92YWxQb2xpY3kuUkVUQUlOIDogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZO1xufVxuIl19
@@ -0,0 +1,24 @@
1
+ import type { BillingConfig, BundleConfig, ComboDiscountConfig } from './config-types.js';
2
+ /**
3
+ * Load billing plan configuration from environment variables.
4
+ */
5
+ export declare function loadBillingConfig(): BillingConfig;
6
+ /**
7
+ * Config-load guardrail for combos: every `bundleId` must resolve to an ACTIVE
8
+ * bundle and every `minQuantities` key must be one of the combo's `bundleIds`.
9
+ * A typo'd member or stray minQuantity key otherwise ships a permanently-inert
10
+ * combo (missing bundle treated as unit price 0, or a min never satisfiable),
11
+ * silently never applying. Throws so misconfig fails fast at boot.
12
+ */
13
+ export declare function assertCombosValid(combos: ComboDiscountConfig[], bundles: BundleConfig[]): void;
14
+ /**
15
+ * Config-load guardrail for the `requires` prerequisite graph. A `requires` entry
16
+ * that doesn't resolve to an ACTIVE bundle — or that participates in a cycle —
17
+ * silently makes the referencing bundle unpurchasable (the addon route rejects
18
+ * with 400 forever because the prerequisite can never be satisfied). Catch it at
19
+ * load with a clear error rather than shipping a dead SKU.
20
+ *
21
+ * - Every id in a bundle's `requires` MUST name an active bundle in the catalog.
22
+ * - The `requires` graph MUST be acyclic (a → b → a can never be satisfied).
23
+ */
24
+ export declare function assertBundleRequiresValid(bundles: BundleConfig[]): void;