@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.
- package/LICENSE +202 -0
- package/README.md +69 -0
- package/lib/cdk.d.ts +38 -0
- package/lib/cdk.js +44 -0
- package/lib/config/app-config.d.ts +109 -0
- package/lib/config/app-config.js +197 -0
- package/lib/config/aws-config-cdk.d.ts +49 -0
- package/lib/config/aws-config-cdk.js +65 -0
- package/lib/config/billing-config.d.ts +24 -0
- package/lib/config/billing-config.js +497 -0
- package/lib/config/config-types.d.ts +346 -0
- package/lib/config/config-types.js +4 -0
- package/lib/config/entitlements.d.ts +23 -0
- package/lib/config/entitlements.js +46 -0
- package/lib/config/handler-constants.d.ts +10 -0
- package/lib/config/handler-constants.js +39 -0
- package/lib/config/infrastructure-config.d.ts +66 -0
- package/lib/config/infrastructure-config.js +197 -0
- package/lib/config/server-config.d.ts +53 -0
- package/lib/config/server-config.js +175 -0
- package/lib/config/service-client.d.ts +13 -0
- package/lib/config/service-client.js +20 -0
- package/lib/core/artifact-manager.d.ts +62 -0
- package/lib/core/artifact-manager.js +83 -0
- package/lib/core/id-generator.d.ts +50 -0
- package/lib/core/id-generator.js +50 -0
- package/lib/core/metadata-builder.d.ts +48 -0
- package/lib/core/metadata-builder.js +278 -0
- package/lib/core/metadata-helpers.d.ts +31 -0
- package/lib/core/metadata-helpers.js +55 -0
- package/lib/core/network-types.d.ts +200 -0
- package/lib/core/network-types.js +4 -0
- package/lib/core/network.d.ts +33 -0
- package/lib/core/network.js +112 -0
- package/lib/core/pipeline-helpers.d.ts +61 -0
- package/lib/core/pipeline-helpers.js +563 -0
- package/lib/core/pipeline-types.d.ts +118 -0
- package/lib/core/pipeline-types.js +131 -0
- package/lib/core/role-types.d.ts +254 -0
- package/lib/core/role-types.js +4 -0
- package/lib/core/role.d.ts +14 -0
- package/lib/core/role.js +117 -0
- package/lib/core/security-group-types.d.ts +84 -0
- package/lib/core/security-group-types.js +4 -0
- package/lib/core/security-group.d.ts +14 -0
- package/lib/core/security-group.js +33 -0
- package/lib/handlers/plugin-lookup-handler.d.ts +32 -0
- package/lib/handlers/plugin-lookup-handler.js +292 -0
- package/lib/handlers/pnpm-lock.yaml +12 -0
- package/lib/index.d.ts +45 -0
- package/lib/index.js +53 -0
- package/lib/pipeline/pipeline-builder.d.ts +123 -0
- package/lib/pipeline/pipeline-builder.js +476 -0
- package/lib/pipeline/pipeline-configuration.d.ts +81 -0
- package/lib/pipeline/pipeline-configuration.js +214 -0
- package/lib/pipeline/plugin-lookup.d.ts +131 -0
- package/lib/pipeline/plugin-lookup.js +316 -0
- package/lib/pipeline/plugin-spec.d.ts +138 -0
- package/lib/pipeline/plugin-spec.js +4 -0
- package/lib/pipeline/source-builder.d.ts +62 -0
- package/lib/pipeline/source-builder.js +164 -0
- package/lib/pipeline/source-types.d.ts +221 -0
- package/lib/pipeline/source-types.js +4 -0
- package/lib/pipeline/stage-builder.d.ts +78 -0
- package/lib/pipeline/stage-builder.js +129 -0
- package/lib/pipeline/step-types.d.ts +222 -0
- package/lib/pipeline/step-types.js +4 -0
- package/lib/template/evaluator.d.ts +42 -0
- package/lib/template/evaluator.js +164 -0
- package/lib/template/index.d.ts +34 -0
- package/lib/template/index.js +118 -0
- package/lib/template/metrics.d.ts +10 -0
- package/lib/template/metrics.js +43 -0
- package/lib/template/plugin-resolver.d.ts +8 -0
- package/lib/template/plugin-resolver.js +48 -0
- package/lib/template/tokenizer.d.ts +49 -0
- package/lib/template/tokenizer.js +233 -0
- package/lib/template/topo-sort.d.ts +17 -0
- package/lib/template/topo-sort.js +88 -0
- package/lib/template/validate.d.ts +45 -0
- package/lib/template/validate.js +96 -0
- package/lib/template/walker.d.ts +34 -0
- package/lib/template/walker.js +83 -0
- 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;
|