@pipeline-builder/pipeline-events 4.0.10 → 4.0.12

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/lib/tags.js ADDED
@@ -0,0 +1,125 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { BoundedMap, CACHE_MAX_ENTRIES, log } from './util.js';
4
+ let codepipelineMod;
5
+ async function loadCodePipeline() {
6
+ if (!codepipelineMod)
7
+ codepipelineMod = (await import('@aws-sdk/client-codepipeline'));
8
+ return codepipelineMod;
9
+ }
10
+ // Tag resolution: pb.pipeline-id + pb.deploys.
11
+ // Pipelines are tagged at CDK synth with:
12
+ // pb.pipeline-id = <platform pipelineId>
13
+ // pb.deploys = <stage>:<env> pairs joined by '+', e.g.
14
+ // "Deploy-stg:staging+Deploy-prod:production"
15
+ // We resolve those tags from the live CodePipeline (region-aware). The ARN/account
16
+ // never leave AWS, so there's no masking. Cached per ARN (warm-container) to avoid
17
+ // hammering the ListTags API.
18
+ //
19
+ // Requires the Lambda execution role to allow `codepipeline:ListTagsForResource`.
20
+ // AccessDenied is a config error (alert loudly); a missing pb.pipeline-id tag is
21
+ // treated as "not yet registered" (skip).
22
+ const PIPELINE_ID_TAG = 'pb.pipeline-id';
23
+ const DEPLOYS_TAG = 'pb.deploys';
24
+ // Canonical per-pipeline org tag (applied at synth by pipeline-core). It is the
25
+ // RESOLVED org for every event of this pipeline — used to key the per-org GitHub
26
+ // token and to attribute ingest-health. orgId is a platform id, never an AWS
27
+ // account id, so it is safe to read/forward.
28
+ const ORG_ID_TAG = 'OrgId';
29
+ const clientsByRegion = new Map();
30
+ // `ts` lets BOTH outcomes expire: a negative (resolved-but-untagged) so a
31
+ // pipeline tagged AFTER its first event becomes resolvable, and a positive so a
32
+ // re-synth that changes `pb.deploys` (a stage renamed, an environment added) or
33
+ // `OrgId` is picked up without recycling the warm container — a lifetime cache
34
+ // would keep attributing deploys to stages that no longer exist.
35
+ const resolvedByArn = new BoundedMap(CACHE_MAX_ENTRIES);
36
+ const NEG_CACHE_TTL_MS = 5 * 60 * 1000;
37
+ const POS_CACHE_TTL_MS = 15 * 60 * 1000;
38
+ /** Cap on commit/ref/environment fields — the ingest contract allows max 255. */
39
+ export const MAX_ATTR = 255;
40
+ /**
41
+ * Parse the `pb.deploys` tag value into a stage→environment map. The value is
42
+ * `<stage>:<env>` pairs joined by `+` (CodePipeline-tag-safe; no JSON). A stage
43
+ * present here is a deploy; its mapped environment is what the forwarder stamps on
44
+ * that stage's STAGE/ACTION events (DORA deploy attribution). Malformed pairs are
45
+ * skipped defensively.
46
+ */
47
+ function parseDeploys(value) {
48
+ const map = new Map();
49
+ if (!value)
50
+ return map;
51
+ for (const pair of value.split('+')) {
52
+ const idx = pair.indexOf(':');
53
+ if (idx <= 0)
54
+ continue;
55
+ const stage = pair.slice(0, idx).trim();
56
+ const env = pair.slice(idx + 1).trim();
57
+ if (stage && env)
58
+ map.set(stage, env.slice(0, MAX_ATTR));
59
+ }
60
+ return map;
61
+ }
62
+ async function pipelineClient(region) {
63
+ let client = clientsByRegion.get(region);
64
+ if (!client) {
65
+ const { CodePipelineClient } = await loadCodePipeline();
66
+ client = new CodePipelineClient({ region });
67
+ clientsByRegion.set(region, client);
68
+ }
69
+ return client;
70
+ }
71
+ /**
72
+ * Resolve a CodePipeline's tags → the platform pipelineId (pb.pipeline-id) plus the
73
+ * deploy-stage→environment map (pb.deploys). `pipelineId` is null when the pipeline
74
+ * has no pb.pipeline-id tag (unregistered). Throws on AccessDenied so a missing IAM
75
+ * grant surfaces loudly instead of silently dropping every event.
76
+ */
77
+ export async function resolvePipeline(arn, region) {
78
+ const cached = resolvedByArn.get(arn);
79
+ // Serve a hit until its TTL (short for a negative, longer for a positive),
80
+ // then re-resolve so tag changes land.
81
+ if (cached && Date.now() - cached.ts < (cached.pipelineId !== null ? POS_CACHE_TTL_MS : NEG_CACHE_TTL_MS)) {
82
+ return { pipelineId: cached.pipelineId, orgId: cached.orgId, deploys: cached.deploys };
83
+ }
84
+ try {
85
+ const client = await pipelineClient(region);
86
+ const { ListTagsForResourceCommand } = await loadCodePipeline();
87
+ const out = await client.send(new ListTagsForResourceCommand({ resourceArn: arn }));
88
+ const pipelineId = out.tags?.find(t => t.key === PIPELINE_ID_TAG)?.value ?? null;
89
+ const orgId = out.tags?.find(t => t.key === ORG_ID_TAG)?.value ?? null;
90
+ const deploys = parseDeploys(out.tags?.find(t => t.key === DEPLOYS_TAG)?.value);
91
+ if (!pipelineId)
92
+ log.warn('Pipeline missing pb.pipeline-id tag — skipping (register it?)', { arn });
93
+ resolvedByArn.set(arn, { pipelineId, orgId, deploys, ts: Date.now() });
94
+ return { pipelineId, orgId, deploys };
95
+ }
96
+ catch (err) {
97
+ const name = err?.name;
98
+ if (name === 'AccessDeniedException') {
99
+ // Don't cache — this is a fixable misconfig, not a property of the pipeline.
100
+ log.error('AccessDenied calling codepipeline:ListTagsForResource — grant it to the Lambda role', { arn, error: name });
101
+ throw err;
102
+ }
103
+ // Transient/infra errors (throttling, timeouts, 5xx) MUST propagate so the SQS
104
+ // batch is retried rather than silently dropping the event — an event dropped
105
+ // BEFORE it reaches the ingest is lost permanently (the ingest's partial-unique
106
+ // index only dedupes events that were actually POSTed). Only swallow when the
107
+ // failure is a definitive answer that this ARN has no usable tag.
108
+ const e = err;
109
+ const status = e.$metadata?.httpStatusCode;
110
+ const retryable = e.$retryable != null
111
+ || (typeof status === 'number' && status >= 500)
112
+ || /throttl|timeout|toomanyrequests|serviceunavailable|econnreset|networkingerror/i.test(name ?? '');
113
+ if (retryable) {
114
+ log.error('Transient error resolving pb.pipeline-id tag — will retry the batch', { arn, error: name ?? String(err) });
115
+ throw err;
116
+ }
117
+ log.error('Failed to resolve pb.pipeline-id tag', { arn, error: name ?? String(err) });
118
+ return { pipelineId: null, orgId: null, deploys: new Map() };
119
+ }
120
+ }
121
+ /** @internal Test-only: forget resolved pipelines. */
122
+ export function _resetTagsForTests() {
123
+ resolvedByArn.clear();
124
+ }
125
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFncy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90YWdzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFZL0QsSUFBSSxlQUErQyxDQUFDO0FBQ3BELEtBQUssVUFBVSxnQkFBZ0I7SUFDN0IsSUFBSSxDQUFDLGVBQWU7UUFBRSxlQUFlLEdBQUcsQ0FBQyxNQUFNLE1BQU0sQ0FBQyw4QkFBOEIsQ0FBQyxDQUFrQyxDQUFDO0lBQ3hILE9BQU8sZUFBZSxDQUFDO0FBQ3pCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsMENBQTBDO0FBQzFDLDJDQUEyQztBQUMzQyw2REFBNkQ7QUFDN0QsaUVBQWlFO0FBQ2pFLG1GQUFtRjtBQUNuRixtRkFBbUY7QUFDbkYsOEJBQThCO0FBQzlCLEVBQUU7QUFDRixrRkFBa0Y7QUFDbEYsaUZBQWlGO0FBQ2pGLDBDQUEwQztBQUUxQyxNQUFNLGVBQWUsR0FBRyxnQkFBZ0IsQ0FBQztBQUN6QyxNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUM7QUFDakMsZ0ZBQWdGO0FBQ2hGLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsNkNBQTZDO0FBQzdDLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQztBQUMzQixNQUFNLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFBa0MsQ0FBQztBQUdsRSwwRUFBMEU7QUFDMUUsZ0ZBQWdGO0FBQ2hGLGdGQUFnRjtBQUNoRiwrRUFBK0U7QUFDL0UsaUVBQWlFO0FBQ2pFLE1BQU0sYUFBYSxHQUFHLElBQUksVUFBVSxDQUF3RyxpQkFBaUIsQ0FBQyxDQUFDO0FBQy9KLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDdkMsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElB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LENBQUMsT0FBTyxNQUFNLEtBQUssUUFBUSxJQUFJLE1BQU0sSUFBSSxHQUFHLENBQUM7ZUFDN0MsZ0ZBQWdGLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN2RyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQ2QsR0FBRyxDQUFDLEtBQUssQ0FBQyxxRUFBcUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdEgsTUFBTSxHQUFHLENBQUM7UUFDWixDQUFDO1FBQ0QsR0FBRyxDQUFDLEtBQUssQ0FBQyxzQ0FBc0MsRUFBRSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdkYsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQy9ELENBQUM7QUFDSCxDQUFDO0FBRUQsc0RBQXNEO0FBQ3RELE1BQU0sVUFBVSxrQkFBa0I7SUFDaEMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ3hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgQm91bmRlZE1hcCwgQ0FDSEVfTUFYX0VOVFJJRVMsIGxvZyB9IGZyb20gJy4vdXRpbC5qcyc7XG5cbi8vIEFXUyBMYW1iZGEncyBOb2RlIHJ1bnRpbWUgcHJvdmlkZXMgQGF3cy1zZGsgdjMsIHNvIHRoZSBDb2RlUGlwZWxpbmUgY2xpZW50IGlzXG4vLyBsb2FkZWQgbGF6aWx5IHZpYSBkeW5hbWljIGltcG9ydCgpIOKAlCBhIHN0YXRpYyB3b3Jrc3BhY2UgZGVwZW5kZW5jeSB3b3VsZFxuLy8gcGVydHVyYiB0aGUgc2hhcmVkIEBhd3Mtc2RrIHZlcnNpb24gdHJlZS4gTWluaW1hbCBsb2NhbCB0eXBlcyBrZWVwIHRoZSBjYWxsXG4vLyBzaXRlcyB0eXBlLWNoZWNrZWQuXG5pbnRlcmZhY2UgTGlzdFRhZ3NPdXRwdXQgeyB0YWdzPzogQXJyYXk8eyBrZXk/OiBzdHJpbmc7IHZhbHVlPzogc3RyaW5nIH0+IH1cbmludGVyZmFjZSBDb2RlUGlwZWxpbmVDbGllbnRMaWtlIHsgc2VuZChjb21tYW5kOiB1bmtub3duKTogUHJvbWlzZTxMaXN0VGFnc091dHB1dD4gfVxuaW50ZXJmYWNlIENvZGVQaXBlbGluZU1vZHVsZSB7XG4gIENvZGVQaXBlbGluZUNsaWVudDogbmV3IChjb25maWc6IHsgcmVnaW9uOiBzdHJpbmcgfSkgPT4gQ29kZVBpcGVsaW5lQ2xpZW50TGlrZTtcbiAgTGlzdFRhZ3NGb3JSZXNvdXJjZUNvbW1hbmQ6IG5ldyAoaW5wdXQ6IHsgcmVzb3VyY2VBcm46IHN0cmluZyB9KSA9PiB1bmtub3duO1xufVxubGV0IGNvZGVwaXBlbGluZU1vZDogQ29kZVBpcGVsaW5lTW9kdWxlIHwgdW5kZWZpbmVkO1xuYXN5bmMgZnVuY3Rpb24gbG9hZENvZGVQaXBlbGluZSgpOiBQcm9taXNlPENvZGVQaXBlbGluZU1vZHVsZT4ge1xuICBpZiAoIWNvZGVwaXBlbGluZU1vZCkgY29kZXBpcGVsaW5lTW9kID0gKGF3YWl0IGltcG9ydCgnQGF3cy1zZGsvY2xpZW50LWNvZGVwaXBlbGluZScpKSBhcyB1bmtub3duIGFzIENvZGVQaXBlbGluZU1vZHVsZTtcbiAgcmV0dXJuIGNvZGVwaXBlbGluZU1vZDtcbn1cblxuLy8gVGFnIHJlc29sdXRpb246IHBiLnBpcGVsaW5lLWlkICsgcGIuZGVwbG95cy5cbi8vIFBpcGVsaW5lcyBhcmUgdGFnZ2VkIGF0IENESyBzeW50aCB3aXRoOlxuLy8gICBwYi5waXBlbGluZS1pZCA9IDxwbGF0Zm9ybSBwaXBlbGluZUlkPlxuLy8gICBwYi5kZXBsb3lzICAgICA9IDxzdGFnZT46PGVudj4gcGFpcnMgam9pbmVkIGJ5ICcrJywgZS5nLlxuLy8gICAgICAgICAgICAgICAgICAgIFwiRGVwbG95LXN0ZzpzdGFnaW5nK0RlcGxveS1wcm9kOnByb2R1Y3Rpb25cIlxuLy8gV2UgcmVzb2x2ZSB0aG9zZSB0YWdzIGZyb20gdGhlIGxpdmUgQ29kZVBpcGVsaW5lIChyZWdpb24tYXdhcmUpLiBUaGUgQVJOL2FjY291bnRcbi8vIG5ldmVyIGxlYXZlIEFXUywgc28gdGhlcmUncyBubyBtYXNraW5nLiBDYWNoZWQgcGVyIEFSTiAod2FybS1jb250YWluZXIpIHRvIGF2b2lkXG4vLyBoYW1tZXJpbmcgdGhlIExpc3RUYWdzIEFQSS5cbi8vXG4vLyBSZXF1aXJlcyB0aGUgTGFtYmRhIGV4ZWN1dGlvbiByb2xlIHRvIGFsbG93IGBjb2RlcGlwZWxpbmU6TGlzdFRhZ3NGb3JSZXNvdXJjZWAuXG4vLyBBY2Nlc3NEZW5pZWQgaXMgYSBjb25maWcgZXJyb3IgKGFsZXJ0IGxvdWRseSk7IGEgbWlzc2luZyBwYi5waXBlbGluZS1pZCB0YWcgaXNcbi8vIHRyZWF0ZWQgYXMgXCJub3QgeWV0IHJlZ2lzdGVyZWRcIiAoc2tpcCkuXG5cbmNvbnN0IFBJUEVMSU5FX0lEX1RBRyA9ICdwYi5waXBlbGluZS1pZCc7XG5jb25zdCBERVBMT1lTX1RBRyA9ICdwYi5kZXBsb3lzJztcbi8vIENhbm9uaWNhbCBwZXItcGlwZWxpbmUgb3JnIHRhZyAoYXBwbGllZCBhdCBzeW50aCBieSBwaXBlbGluZS1jb3JlKS4gSXQgaXMgdGhlXG4vLyBSRVNPTFZFRCBvcmcgZm9yIGV2ZXJ5IGV2ZW50IG9mIHRoaXMgcGlwZWxpbmUg4oCUIHVzZWQgdG8ga2V5IHRoZSBwZXItb3JnIEdpdEh1YlxuLy8gdG9rZW4gYW5kIHRvIGF0dHJpYnV0ZSBpbmdlc3QtaGVhbHRoLiBvcmdJZCBpcyBhIHBsYXRmb3JtIGlkLCBuZXZlciBhbiBBV1Ncbi8vIGFjY291bnQgaWQsIHNvIGl0IGlzIHNhZmUgdG8gcmVhZC9mb3J3YXJkLlxuY29uc3QgT1JHX0lEX1RBRyA9ICdPcmdJZCc7XG5jb25zdCBjbGllbnRzQnlSZWdpb24gPSBuZXcgTWFwPHN0cmluZywgQ29kZVBpcGVsaW5lQ2xpZW50TGlrZT4oKTtcblxuXG4vLyBgdHNgIGxldHMgQk9USCBvdXRjb21lcyBleHBpcmU6IGEgbmVnYXRpdmUgKHJlc29sdmVkLWJ1dC11bnRhZ2dlZCkgc28gYVxuLy8gcGlwZWxpbmUgdGFnZ2VkIEFGVEVSIGl0cyBmaXJzdCBldmVudCBiZWNvbWVzIHJlc29sdmFibGUsIGFuZCBhIHBvc2l0aXZlIHNvIGFcbi8vIHJlLXN5bnRoIHRoYXQgY2hhbmdlcyBgcGIuZGVwbG95c2AgKGEgc3RhZ2UgcmVuYW1lZCwgYW4gZW52aXJvbm1lbnQgYWRkZWQpIG9yXG4vLyBgT3JnSWRgIGlzIHBpY2tlZCB1cCB3aXRob3V0IHJlY3ljbGluZyB0aGUgd2FybSBjb250YWluZXIg4oCUIGEgbGlmZXRpbWUgY2FjaGVcbi8vIHdvdWxkIGtlZXAgYXR0cmlidXRpbmcgZGVwbG95cyB0byBzdGFnZXMgdGhhdCBubyBsb25nZXIgZXhpc3QuXG5jb25zdCByZXNvbHZlZEJ5QXJuID0gbmV3IEJvdW5kZWRNYXA8c3RyaW5nLCB7IHBpcGVsaW5lSWQ6IHN0cmluZyB8IG51bGw7IG9yZ0lkOiBzdHJpbmcgfCBudWxsOyBkZXBsb3lzOiBNYXA8c3RyaW5nLCBzdHJpbmc+OyB0czogbnVtYmVyIH0+KENBQ0hFX01BWF9FTlRSSUVTKTtcbmNvbnN0IE5FR19DQUNIRV9UVExfTVMgPSA1ICogNjAgKiAxMDAwO1xuY29uc3QgUE9TX0NBQ0hFX1RUTF9NUyA9IDE1ICogNjAgKiAxMDAwO1xuXG4vKiogUmVzb2x2ZWQgcGlwZWxpbmUgbWV0YWRhdGEgcmVhZCBmcm9tIHRoZSBDb2RlUGlwZWxpbmUgcmVzb3VyY2UgdGFncy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZWRQaXBlbGluZSB7XG4gIC8qKiBQbGF0Zm9ybSBwaXBlbGluZUlkIChwYi5waXBlbGluZS1pZCB0YWcpOyBudWxsIHdoZW4gdW50YWdnZWQvdW5yZWdpc3RlcmVkLiAqL1xuICBwaXBlbGluZUlkOiBzdHJpbmcgfCBudWxsO1xuICAvKiogUGxhdGZvcm0gb3JnSWQgKE9yZ0lkIHRhZyk7IG51bGwgd2hlbiB0aGUgcGlwZWxpbmUgY2FycmllcyBubyBvcmcgdGFnLiAqL1xuICBvcmdJZDogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIE1hcCBvZiBkZXBsb3ktc3RhZ2UgbmFtZSDihpIgZW52aXJvbm1lbnQgKHBhcnNlZCBmcm9tIHBiLmRlcGxveXMpLiBFbXB0eSB3aGVuIG5vbmUuICovXG4gIGRlcGxveXM6IE1hcDxzdHJpbmcsIHN0cmluZz47XG59XG5cbi8qKiBDYXAgb24gY29tbWl0L3JlZi9lbnZpcm9ubWVudCBmaWVsZHMg4oCUIHRoZSBpbmdlc3QgY29udHJhY3QgYWxsb3dzIG1heCAyNTUuICovXG5leHBvcnQgY29uc3QgTUFYX0FUVFIgPSAyNTU7XG5cbi8qKlxuICogUGFyc2UgdGhlIGBwYi5kZXBsb3lzYCB0YWcgdmFsdWUgaW50byBhIHN0YWdl4oaSZW52aXJvbm1lbnQgbWFwLiBUaGUgdmFsdWUgaXNcbiAqIGA8c3RhZ2U+OjxlbnY+YCBwYWlycyBqb2luZWQgYnkgYCtgIChDb2RlUGlwZWxpbmUtdGFnLXNhZmU7IG5vIEpTT04pLiBBIHN0YWdlXG4gKiBwcmVzZW50IGhlcmUgaXMgYSBkZXBsb3k7IGl0cyBtYXBwZWQgZW52aXJvbm1lbnQgaXMgd2hhdCB0aGUgZm9yd2FyZGVyIHN0YW1wcyBvblxuICogdGhhdCBzdGFnZSdzIFNUQUdFL0FDVElPTiBldmVudHMgKERPUkEgZGVwbG95IGF0dHJpYnV0aW9uKS4gTWFsZm9ybWVkIHBhaXJzIGFyZVxuICogc2tpcHBlZCBkZWZlbnNpdmVseS5cbiAqL1xuZnVuY3Rpb24gcGFyc2VEZXBsb3lzKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBNYXA8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgbWFwID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIG1hcDtcbiAgZm9yIChjb25zdCBwYWlyIG9mIHZhbHVlLnNwbGl0KCcrJykpIHtcbiAgICBjb25zdCBpZHggPSBwYWlyLmluZGV4T2YoJzonKTtcbiAgICBpZiAoaWR4IDw9IDApIGNvbnRpbnVlO1xuICAgIGNvbnN0IHN0YWdlID0gcGFpci5zbGljZSgwLCBpZHgpLnRyaW0oKTtcbiAgICBjb25zdCBlbnYgPSBwYWlyLnNsaWNlKGlkeCArIDEpLnRyaW0oKTtcbiAgICBpZiAoc3RhZ2UgJiYgZW52KSBtYXAuc2V0KHN0YWdlLCBlbnYuc2xpY2UoMCwgTUFYX0FUVFIpKTtcbiAgfVxuICByZXR1cm4gbWFwO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwaXBlbGluZUNsaWVudChyZWdpb246IHN0cmluZyk6IFByb21pc2U8Q29kZVBpcGVsaW5lQ2xpZW50TGlrZT4ge1xuICBsZXQgY2xpZW50ID0gY2xpZW50c0J5UmVnaW9uLmdldChyZWdpb24pO1xuICBpZiAoIWNsaWVudCkge1xuICAgIGNvbnN0IHsgQ29kZVBpcGVsaW5lQ2xpZW50IH0gPSBhd2FpdCBsb2FkQ29kZVBpcGVsaW5lKCk7XG4gICAgY2xpZW50ID0gbmV3IENvZGVQaXBlbGluZUNsaWVudCh7IHJlZ2lvbiB9KTtcbiAgICBjbGllbnRzQnlSZWdpb24uc2V0KHJlZ2lvbiwgY2xpZW50KTtcbiAgfVxuICByZXR1cm4gY2xpZW50O1xufVxuXG4vKipcbiAqIFJlc29sdmUgYSBDb2RlUGlwZWxpbmUncyB0YWdzIOKGkiB0aGUgcGxhdGZvcm0gcGlwZWxpbmVJZCAocGIucGlwZWxpbmUtaWQpIHBsdXMgdGhlXG4gKiBkZXBsb3ktc3RhZ2XihpJlbnZpcm9ubWVudCBtYXAgKHBiLmRlcGxveXMpLiBgcGlwZWxpbmVJZGAgaXMgbnVsbCB3aGVuIHRoZSBwaXBlbGluZVxuICogaGFzIG5vIHBiLnBpcGVsaW5lLWlkIHRhZyAodW5yZWdpc3RlcmVkKS4gVGhyb3dzIG9uIEFjY2Vzc0RlbmllZCBzbyBhIG1pc3NpbmcgSUFNXG4gKiBncmFudCBzdXJmYWNlcyBsb3VkbHkgaW5zdGVhZCBvZiBzaWxlbnRseSBkcm9wcGluZyBldmVyeSBldmVudC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVQaXBlbGluZShhcm46IHN0cmluZywgcmVnaW9uOiBzdHJpbmcpOiBQcm9taXNlPFJlc29sdmVkUGlwZWxpbmU+IHtcbiAgY29uc3QgY2FjaGVkID0gcmVzb2x2ZWRCeUFybi5nZXQoYXJuKTtcbiAgLy8gU2VydmUgYSBoaXQgdW50aWwgaXRzIFRUTCAoc2hvcnQgZm9yIGEgbmVnYXRpdmUsIGxvbmdlciBmb3IgYSBwb3NpdGl2ZSksXG4gIC8vIHRoZW4gcmUtcmVzb2x2ZSBzbyB0YWcgY2hhbmdlcyBsYW5kLlxuICBpZiAoY2FjaGVkICYmIERhdGUubm93KCkgLSBjYWNoZWQudHMgPCAoY2FjaGVkLnBpcGVsaW5lSWQgIT09IG51bGwgPyBQT1NfQ0FDSEVfVFRMX01TIDogTkVHX0NBQ0hFX1RUTF9NUykpIHtcbiAgICByZXR1cm4geyBwaXBlbGluZUlkOiBjYWNoZWQucGlwZWxpbmVJZCwgb3JnSWQ6IGNhY2hlZC5vcmdJZCwgZGVwbG95czogY2FjaGVkLmRlcGxveXMgfTtcbiAgfVxuICB0cnkge1xuICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHBpcGVsaW5lQ2xpZW50KHJlZ2lvbik7XG4gICAgY29uc3QgeyBMaXN0VGFnc0ZvclJlc291cmNlQ29tbWFuZCB9ID0gYXdhaXQgbG9hZENvZGVQaXBlbGluZSgpO1xuICAgIGNvbnN0IG91dCA9IGF3YWl0IGNsaWVudC5zZW5kKG5ldyBMaXN0VGFnc0ZvclJlc291cmNlQ29tbWFuZCh7IHJlc291cmNlQXJuOiBhcm4gfSkpO1xuICAgIGNvbnN0IHBpcGVsaW5lSWQgPSBvdXQudGFncz8uZmluZCh0ID0+IHQua2V5ID09PSBQSVBFTElORV9JRF9UQUcpPy52YWx1ZSA/PyBudWxsO1xuICAgIGNvbnN0IG9yZ0lkID0gb3V0LnRhZ3M/LmZpbmQodCA9PiB0LmtleSA9PT0gT1JHX0lEX1RBRyk/LnZhbHVlID8/IG51bGw7XG4gICAgY29uc3QgZGVwbG95cyA9IHBhcnNlRGVwbG95cyhvdXQudGFncz8uZmluZCh0ID0+IHQua2V5ID09PSBERVBMT1lTX1RBRyk/LnZhbHVlKTtcbiAgICBpZiAoIXBpcGVsaW5lSWQpIGxvZy53YXJuKCdQaXBlbGluZSBtaXNzaW5nIHBiLnBpcGVsaW5lLWlkIHRhZyDigJQgc2tpcHBpbmcgKHJlZ2lzdGVyIGl0PyknLCB7IGFybiB9KTtcbiAgICByZXNvbHZlZEJ5QXJuLnNldChhcm4sIHsgcGlwZWxpbmVJZCwgb3JnSWQsIGRlcGxveXMsIHRzOiBEYXRlLm5vdygpIH0pO1xuICAgIHJldHVybiB7IHBpcGVsaW5lSWQsIG9yZ0lkLCBkZXBsb3lzIH07XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGNvbnN0IG5hbWUgPSAoZXJyIGFzIHsgbmFtZT86IHN0cmluZyB9KT8ubmFtZTtcbiAgICBpZiAobmFtZSA9PT0gJ0FjY2Vzc0RlbmllZEV4Y2VwdGlvbicpIHtcbiAgICAgIC8vIERvbid0IGNhY2hlIOKAlCB0aGlzIGlzIGEgZml4YWJsZSBtaXNjb25maWcsIG5vdCBhIHByb3BlcnR5IG9mIHRoZSBwaXBlbGluZS5cbiAgICAgIGxvZy5lcnJvcignQWNjZXNzRGVuaWVkIGNhbGxpbmcgY29kZXBpcGVsaW5lOkxpc3RUYWdzRm9yUmVzb3VyY2Ug4oCUIGdyYW50IGl0IHRvIHRoZSBMYW1iZGEgcm9sZScsIHsgYXJuLCBlcnJvcjogbmFtZSB9KTtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgLy8gVHJhbnNpZW50L2luZnJhIGVycm9ycyAodGhyb3R0bGluZywgdGltZW91dHMsIDV4eCkgTVVTVCBwcm9wYWdhdGUgc28gdGhlIFNRU1xuICAgIC8vIGJhdGNoIGlzIHJldHJpZWQgcmF0aGVyIHRoYW4gc2lsZW50bHkgZHJvcHBpbmcgdGhlIGV2ZW50IOKAlCBhbiBldmVudCBkcm9wcGVkXG4gICAgLy8gQkVGT1JFIGl0IHJlYWNoZXMgdGhlIGluZ2VzdCBpcyBsb3N0IHBlcm1hbmVudGx5ICh0aGUgaW5nZXN0J3MgcGFydGlhbC11bmlxdWVcbiAgICAvLyBpbmRleCBvbmx5IGRlZHVwZXMgZXZlbnRzIHRoYXQgd2VyZSBhY3R1YWxseSBQT1NUZWQpLiBPbmx5IHN3YWxsb3cgd2hlbiB0aGVcbiAgICAvLyBmYWlsdXJlIGlzIGEgZGVmaW5pdGl2ZSBhbnN3ZXIgdGhhdCB0aGlzIEFSTiBoYXMgbm8gdXNhYmxlIHRhZy5cbiAgICBjb25zdCBlID0gZXJyIGFzIHsgbmFtZT86IHN0cmluZzsgJHJldHJ5YWJsZT86IHVua25vd247ICRtZXRhZGF0YT86IHsgaHR0cFN0YXR1c0NvZGU/OiBudW1iZXIgfSB9O1xuICAgIGNvbnN0IHN0YXR1cyA9IGUuJG1ldGFkYXRhPy5odHRwU3RhdHVzQ29kZTtcbiAgICBjb25zdCByZXRyeWFibGUgPSBlLiRyZXRyeWFibGUgIT0gbnVsbFxuICAgICAgfHwgKHR5cGVvZiBzdGF0dXMgPT09ICdudW1iZXInICYmIHN0YXR1cyA+PSA1MDApXG4gICAgICB8fCAvdGhyb3R0bHx0aW1lb3V0fHRvb21hbnlyZXF1ZXN0c3xzZXJ2aWNldW5hdmFpbGFibGV8ZWNvbm5yZXNldHxuZXR3b3JraW5nZXJyb3IvaS50ZXN0KG5hbWUgPz8gJycpO1xuICAgIGlmIChyZXRyeWFibGUpIHtcbiAgICAgIGxvZy5lcnJvcignVHJhbnNpZW50IGVycm9yIHJlc29sdmluZyBwYi5waXBlbGluZS1pZCB0YWcg4oCUIHdpbGwgcmV0cnkgdGhlIGJhdGNoJywgeyBhcm4sIGVycm9yOiBuYW1lID8/IFN0cmluZyhlcnIpIH0pO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgICBsb2cuZXJyb3IoJ0ZhaWxlZCB0byByZXNvbHZlIHBiLnBpcGVsaW5lLWlkIHRhZycsIHsgYXJuLCBlcnJvcjogbmFtZSA/PyBTdHJpbmcoZXJyKSB9KTtcbiAgICByZXR1cm4geyBwaXBlbGluZUlkOiBudWxsLCBvcmdJZDogbnVsbCwgZGVwbG95czogbmV3IE1hcCgpIH07XG4gIH1cbn1cblxuLyoqIEBpbnRlcm5hbCBUZXN0LW9ubHk6IGZvcmdldCByZXNvbHZlZCBwaXBlbGluZXMuICovXG5leHBvcnQgZnVuY3Rpb24gX3Jlc2V0VGFnc0ZvclRlc3RzKCk6IHZvaWQge1xuICByZXNvbHZlZEJ5QXJuLmNsZWFyKCk7XG59XG4iXX0=
@@ -0,0 +1,8 @@
1
+ {
2
+ "package": "@pipeline-builder/pipeline-events",
3
+ "entries": {
4
+ ".": {
5
+ "handler": "function"
6
+ }
7
+ }
8
+ }
package/lib/util.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ /** Shared plumbing for the event-ingestion Lambda modules. */
2
+ export declare const log: {
3
+ info: (msg: string, data?: unknown) => void;
4
+ warn: (msg: string, data?: unknown) => void;
5
+ error: (msg: string, data?: unknown) => void;
6
+ };
7
+ /**
8
+ * A Map that holds at most `max` entries, evicting the least recently SET one.
9
+ * Every per-key cache in this module is keyed by something unbounded (pipeline
10
+ * ARN, pipeline × commit, org), and a fleet forwarder's warm container can live
11
+ * for hours across thousands of pipelines — an unbounded Map is a slow leak that
12
+ * ends in an OOM-killed Lambda and a redelivered batch.
13
+ */
14
+ export declare class BoundedMap<K, V> extends Map<K, V> {
15
+ private readonly max;
16
+ constructor(max: number);
17
+ set(key: K, value: V): this;
18
+ }
19
+ /** Upper bound for every per-key cache below. */
20
+ export declare const CACHE_MAX_ENTRIES = 5000;
21
+ export declare function loadSdk<T>(pkg: string): Promise<T>;
package/lib/util.js ADDED
@@ -0,0 +1,43 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /** Shared plumbing for the event-ingestion Lambda modules. */
4
+ export const log = {
5
+ info: (msg, data) => console.log(JSON.stringify({ level: 'INFO', message: msg, data, ts: new Date().toISOString() })),
6
+ warn: (msg, data) => console.log(JSON.stringify({ level: 'WARN', message: msg, data, ts: new Date().toISOString() })),
7
+ error: (msg, data) => console.error(JSON.stringify({ level: 'ERROR', message: msg, data, ts: new Date().toISOString() })),
8
+ };
9
+ /**
10
+ * A Map that holds at most `max` entries, evicting the least recently SET one.
11
+ * Every per-key cache in this module is keyed by something unbounded (pipeline
12
+ * ARN, pipeline × commit, org), and a fleet forwarder's warm container can live
13
+ * for hours across thousands of pipelines — an unbounded Map is a slow leak that
14
+ * ends in an OOM-killed Lambda and a redelivered batch.
15
+ */
16
+ export class BoundedMap extends Map {
17
+ max;
18
+ constructor(max) {
19
+ super();
20
+ this.max = max;
21
+ }
22
+ set(key, value) {
23
+ if (super.has(key)) {
24
+ super.delete(key); // refresh recency
25
+ }
26
+ else if (this.size >= this.max) {
27
+ const oldest = this.keys().next().value;
28
+ if (oldest !== undefined)
29
+ super.delete(oldest);
30
+ }
31
+ return super.set(key, value);
32
+ }
33
+ }
34
+ /** Upper bound for every per-key cache below. */
35
+ export const CACHE_MAX_ENTRIES = 5000;
36
+ // Variable-specifier loader for SDK clients that are NOT devDependencies of this
37
+ // package (`@aws-sdk/client-codecommit`, `@aws-sdk/client-sqs` — present only in
38
+ // the Lambda runtime / jest mocks). A `string` specifier keeps `tsc` from
39
+ // resolving them at build time, and the bundle leaves `@aws-sdk/*` external.
40
+ export async function loadSdk(pkg) {
41
+ return (await import(pkg));
42
+ }
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsOERBQThEO0FBRTlELE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBRztJQUNqQixJQUFJLEVBQUUsQ0FBQyxHQUFXLEVBQUUsSUFBYyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN2SSxJQUFJLEVBQUUsQ0FBQyxHQUFXLEVBQUUsSUFBYyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN2SSxLQUFLLEVBQUUsQ0FBQyxHQUFXLEVBQUUsSUFBYyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztDQUM1SSxDQUFDO0FBRUY7Ozs7OztHQU1HO0FBQ0gsTUFBTSxPQUFPLFVBQWlCLFNBQVEsR0FBUztJQUNoQixHQUFHO0lBQWhDLFlBQTZCLEdBQVc7UUFBSSxLQUFLLEVBQUUsQ0FBQzttQkFBdkIsR0FBRztJQUFxQixDQUFDO0lBQzdDLEdBQUcsQ0FBQyxHQUFNLEVBQUUsS0FBUTtRQUMzQixJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNuQixLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsa0JBQWtCO1FBQ3ZDLENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDeEMsSUFBSSxNQUFNLEtBQUssU0FBUztnQkFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9CLENBQUM7Q0FDRjtBQUVELGlEQUFpRDtBQUNqRCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUM7QUFFdEMsaUZBQWlGO0FBQ2pGLGlGQUFpRjtBQUNqRiwwRUFBMEU7QUFDMUUsNkVBQTZFO0FBQzdFLE1BQU0sQ0FBQyxLQUFLLFVBQVUsT0FBTyxDQUFJLEdBQVc7SUFDMUMsT0FBTyxDQUFDLE1BQU0sTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFNLENBQUM7QUFDbEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKiogU2hhcmVkIHBsdW1iaW5nIGZvciB0aGUgZXZlbnQtaW5nZXN0aW9uIExhbWJkYSBtb2R1bGVzLiAqL1xuXG5leHBvcnQgY29uc3QgbG9nID0ge1xuICBpbmZvOiAobXNnOiBzdHJpbmcsIGRhdGE/OiB1bmtub3duKSA9PiBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7IGxldmVsOiAnSU5GTycsIG1lc3NhZ2U6IG1zZywgZGF0YSwgdHM6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSB9KSksXG4gIHdhcm46IChtc2c6IHN0cmluZywgZGF0YT86IHVua25vd24pID0+IGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHsgbGV2ZWw6ICdXQVJOJywgbWVzc2FnZTogbXNnLCBkYXRhLCB0czogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH0pKSxcbiAgZXJyb3I6IChtc2c6IHN0cmluZywgZGF0YT86IHVua25vd24pID0+IGNvbnNvbGUuZXJyb3IoSlNPTi5zdHJpbmdpZnkoeyBsZXZlbDogJ0VSUk9SJywgbWVzc2FnZTogbXNnLCBkYXRhLCB0czogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH0pKSxcbn07XG5cbi8qKlxuICogQSBNYXAgdGhhdCBob2xkcyBhdCBtb3N0IGBtYXhgIGVudHJpZXMsIGV2aWN0aW5nIHRoZSBsZWFzdCByZWNlbnRseSBTRVQgb25lLlxuICogRXZlcnkgcGVyLWtleSBjYWNoZSBpbiB0aGlzIG1vZHVsZSBpcyBrZXllZCBieSBzb21ldGhpbmcgdW5ib3VuZGVkIChwaXBlbGluZVxuICogQVJOLCBwaXBlbGluZSDDlyBjb21taXQsIG9yZyksIGFuZCBhIGZsZWV0IGZvcndhcmRlcidzIHdhcm0gY29udGFpbmVyIGNhbiBsaXZlXG4gKiBmb3IgaG91cnMgYWNyb3NzIHRob3VzYW5kcyBvZiBwaXBlbGluZXMg4oCUIGFuIHVuYm91bmRlZCBNYXAgaXMgYSBzbG93IGxlYWsgdGhhdFxuICogZW5kcyBpbiBhbiBPT00ta2lsbGVkIExhbWJkYSBhbmQgYSByZWRlbGl2ZXJlZCBiYXRjaC5cbiAqL1xuZXhwb3J0IGNsYXNzIEJvdW5kZWRNYXA8SywgVj4gZXh0ZW5kcyBNYXA8SywgVj4ge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IG1heDogbnVtYmVyKSB7IHN1cGVyKCk7IH1cbiAgb3ZlcnJpZGUgc2V0KGtleTogSywgdmFsdWU6IFYpOiB0aGlzIHtcbiAgICBpZiAoc3VwZXIuaGFzKGtleSkpIHtcbiAgICAgIHN1cGVyLmRlbGV0ZShrZXkpOyAvLyByZWZyZXNoIHJlY2VuY3lcbiAgICB9IGVsc2UgaWYgKHRoaXMuc2l6ZSA+PSB0aGlzLm1heCkge1xuICAgICAgY29uc3Qgb2xkZXN0ID0gdGhpcy5rZXlzKCkubmV4dCgpLnZhbHVlO1xuICAgICAgaWYgKG9sZGVzdCAhPT0gdW5kZWZpbmVkKSBzdXBlci5kZWxldGUob2xkZXN0KTtcbiAgICB9XG4gICAgcmV0dXJuIHN1cGVyLnNldChrZXksIHZhbHVlKTtcbiAgfVxufVxuXG4vKiogVXBwZXIgYm91bmQgZm9yIGV2ZXJ5IHBlci1rZXkgY2FjaGUgYmVsb3cuICovXG5leHBvcnQgY29uc3QgQ0FDSEVfTUFYX0VOVFJJRVMgPSA1MDAwO1xuXG4vLyBWYXJpYWJsZS1zcGVjaWZpZXIgbG9hZGVyIGZvciBTREsgY2xpZW50cyB0aGF0IGFyZSBOT1QgZGV2RGVwZW5kZW5jaWVzIG9mIHRoaXNcbi8vIHBhY2thZ2UgKGBAYXdzLXNkay9jbGllbnQtY29kZWNvbW1pdGAsIGBAYXdzLXNkay9jbGllbnQtc3FzYCDigJQgcHJlc2VudCBvbmx5IGluXG4vLyB0aGUgTGFtYmRhIHJ1bnRpbWUgLyBqZXN0IG1vY2tzKS4gQSBgc3RyaW5nYCBzcGVjaWZpZXIga2VlcHMgYHRzY2AgZnJvbVxuLy8gcmVzb2x2aW5nIHRoZW0gYXQgYnVpbGQgdGltZSwgYW5kIHRoZSBidW5kbGUgbGVhdmVzIGBAYXdzLXNkay8qYCBleHRlcm5hbC5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkU2RrPFQ+KHBrZzogc3RyaW5nKTogUHJvbWlzZTxUPiB7XG4gIHJldHVybiAoYXdhaXQgaW1wb3J0KHBrZykpIGFzIFQ7XG59XG4iXX0=
package/package.json CHANGED
@@ -11,17 +11,19 @@
11
11
  "@jest/globals": "30.4.1",
12
12
  "@stylistic/eslint-plugin": "^2",
13
13
  "@types/aws-lambda": "8.10.162",
14
- "@types/node": "26.1.2",
14
+ "@types/node": "^24",
15
15
  "@typescript-eslint/eslint-plugin": "^8",
16
16
  "@typescript-eslint/parser": "^8",
17
17
  "@typescript/native": "npm:typescript@^7.0.2",
18
+ "esbuild": "0.28.0",
18
19
  "eslint": "^9",
19
20
  "eslint-import-resolver-typescript": "^4.4.4",
20
21
  "eslint-plugin-import": "^2.32.0",
21
22
  "jest": "30.4.2",
22
23
  "jest-junit": "^17",
23
24
  "ts-jest": "29.4.12",
24
- "typescript": "npm:@typescript/typescript6@^6.0.2"
25
+ "typescript": "npm:@typescript/typescript6@^6.0.2",
26
+ "@pipeline-builder/pipeline-core": "4.1.17"
25
27
  },
26
28
  "keywords": [
27
29
  "ci-cd",
@@ -77,7 +79,7 @@
77
79
  "access": "public",
78
80
  "registry": "https://registry.npmjs.org/"
79
81
  },
80
- "version": "4.0.10",
82
+ "version": "4.0.12",
81
83
  "bugs": {
82
84
  "url": "https://github.com/mwashburn160/pipeline-builder/issues"
83
85
  },
@@ -143,12 +145,17 @@
143
145
  "setupFilesAfterEnv": [
144
146
  "<rootDir>/../../jest-env-guard.js"
145
147
  ],
148
+ "collectCoverageFrom": [
149
+ "src/**/*.ts",
150
+ "!src/**/*.d.ts",
151
+ "!src/testing/**"
152
+ ],
146
153
  "coverageThreshold": {
147
154
  "global": {
148
- "statements": 94,
149
- "branches": 77,
155
+ "statements": 95,
156
+ "branches": 78,
150
157
  "functions": 95,
151
- "lines": 94
158
+ "lines": 95
152
159
  }
153
160
  }
154
161
  },
@@ -160,11 +167,14 @@
160
167
  "compile": "pnpm dlx projen compile",
161
168
  "default": "pnpm dlx projen default",
162
169
  "eslint": "pnpm dlx projen eslint",
170
+ "lint:fix": "pnpm dlx projen lint:fix",
163
171
  "package": "pnpm dlx projen package",
164
172
  "post-compile": "pnpm dlx projen post-compile",
165
173
  "pre-compile": "pnpm dlx projen pre-compile",
166
174
  "test": "pnpm dlx projen test",
175
+ "test:update": "pnpm dlx projen test:update",
167
176
  "test:watch": "pnpm dlx projen test:watch",
177
+ "typecheck:tests": "pnpm dlx projen typecheck:tests",
168
178
  "watch": "pnpm dlx projen watch",
169
179
  "projen": "pnpm dlx projen"
170
180
  }