@pipeline-builder/pipeline-core 4.1.14 → 4.1.16
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/cdk.d.ts +1 -0
- package/lib/cdk.js +2 -1
- package/lib/config/app-config.d.ts +5 -8
- package/lib/config/app-config.js +36 -38
- package/lib/config/config-types.d.ts +9 -112
- package/lib/config/config-types.js +1 -1
- package/lib/config/handler-constants.d.ts +12 -3
- package/lib/config/handler-constants.js +9 -26
- package/lib/config/infrastructure-config.js +44 -43
- package/lib/config/server-config.d.ts +1 -1
- package/lib/config/server-config.js +33 -32
- package/lib/config/service-client.d.ts +3 -7
- package/lib/config/service-client.js +5 -11
- package/lib/core/artifact-manager.d.ts +0 -17
- package/lib/core/artifact-manager.js +1 -17
- package/lib/core/metadata-helpers.d.ts +16 -0
- package/lib/core/metadata-helpers.js +41 -1
- package/lib/core/pipeline-helpers.js +23 -58
- package/lib/core/plugin-contract.d.ts +126 -0
- package/lib/core/plugin-contract.js +217 -0
- package/lib/core/plugin-lookup-envelope.d.ts +14 -0
- package/lib/core/plugin-lookup-envelope.js +29 -0
- package/lib/core/step-manifest.d.ts +50 -0
- package/lib/core/step-manifest.js +47 -0
- package/lib/handlers/platform-credential.d.ts +47 -0
- package/lib/handlers/platform-credential.js +87 -0
- package/lib/handlers/plugin-lookup-handler.d.ts +1 -1
- package/lib/handlers/plugin-lookup-handler.js +48 -42
- package/lib/index.d.ts +8 -8
- package/lib/index.js +10 -9
- package/lib/pipeline/pipeline-builder.d.ts +7 -0
- package/lib/pipeline/pipeline-builder.js +25 -9
- package/lib/pipeline/pipeline-configuration.js +6 -5
- package/lib/pipeline/plugin-lookup.d.ts +0 -1
- package/lib/pipeline/plugin-lookup.js +55 -23
- package/lib/pipeline/plugin-spec.d.ts +41 -0
- package/lib/pipeline/plugin-spec.js +1 -1
- package/lib/pipeline/stage-builder.d.ts +11 -0
- package/lib/pipeline/stage-builder.js +31 -12
- package/lib/pipeline/step-manifest-recorder.d.ts +22 -0
- package/lib/pipeline/step-manifest-recorder.js +57 -0
- package/lib/pipeline/step-types.d.ts +16 -4
- package/lib/pipeline/step-types.js +1 -1
- package/lib/template/index.d.ts +4 -4
- package/lib/template/index.js +5 -5
- package/lib/template/plugin-resolver.js +5 -5
- package/lib/template/tokenizer.d.ts +4 -0
- package/lib/template/tokenizer.js +11 -7
- package/lib/testing/exports.json +72 -0
- package/package.json +36 -8
- package/lib/config/billing-config.d.ts +0 -27
- package/lib/config/billing-config.js +0 -534
- package/lib/config/entitlements.d.ts +0 -23
- package/lib/config/entitlements.js +0 -46
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { MetaDataType } from './pipeline-types.js';
|
|
2
|
+
/** Declared coercion type of a contract key. */
|
|
3
|
+
export type ContractValueType = 'string' | 'number' | 'bool' | 'json';
|
|
4
|
+
/** The contract fields of a plugin record (as `plugins` stores them). */
|
|
5
|
+
export interface PluginContract {
|
|
6
|
+
readonly requiredMetadata?: readonly string[] | null;
|
|
7
|
+
readonly requiredVars?: readonly string[] | null;
|
|
8
|
+
readonly metadataTypes?: Readonly<Record<string, ContractValueType>> | null;
|
|
9
|
+
readonly varsTypes?: Readonly<Record<string, ContractValueType>> | null;
|
|
10
|
+
}
|
|
11
|
+
/** What `{{ pipeline.metadata.* }}` and `{{ pipeline.vars.* }}` resolve against. */
|
|
12
|
+
export interface ContractScope {
|
|
13
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
14
|
+
readonly vars: Readonly<Record<string, unknown>>;
|
|
15
|
+
}
|
|
16
|
+
/** One unmet contract key. */
|
|
17
|
+
export interface ContractIssue {
|
|
18
|
+
readonly kind: 'metadata' | 'vars';
|
|
19
|
+
readonly key: string;
|
|
20
|
+
readonly problem: 'missing' | 'type';
|
|
21
|
+
/** The declared type, for a `type` problem. */
|
|
22
|
+
readonly expected?: ContractValueType;
|
|
23
|
+
readonly message: string;
|
|
24
|
+
}
|
|
25
|
+
/** The pipeline-props fields the contract scope is built from (BuilderProps subset). */
|
|
26
|
+
export interface ContractScopeProps {
|
|
27
|
+
readonly global?: unknown;
|
|
28
|
+
readonly defaults?: unknown;
|
|
29
|
+
readonly synth?: unknown;
|
|
30
|
+
readonly vars?: unknown;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `pipeline.metadata` as synth builds it: `global` ← `defaults.metadata` ←
|
|
34
|
+
* `synth.metadata` (last wins). The single definition — `PipelineConfiguration`
|
|
35
|
+
* uses it too, so the API check and the synth scope cannot drift.
|
|
36
|
+
*/
|
|
37
|
+
export declare function pipelineScopeMetadata(props: ContractScopeProps): MetaDataType;
|
|
38
|
+
/** The contract scope of a pipeline's props (see {@link pipelineScopeMetadata}). */
|
|
39
|
+
export declare function pipelineContractScope(props: ContractScopeProps): ContractScope;
|
|
40
|
+
/**
|
|
41
|
+
* The contract scope inside a synth template scope (`{ pipeline: { metadata,
|
|
42
|
+
* vars, … } }`, see `PipelineConfiguration.getPipelineScope`).
|
|
43
|
+
*/
|
|
44
|
+
export declare function contractScopeFromTemplateScope(templateScope: Readonly<Record<string, unknown>>): ContractScope;
|
|
45
|
+
/**
|
|
46
|
+
* Does `value` satisfy the declared `type` once interpolated? Mirrors the
|
|
47
|
+
* evaluator's `resolveOne` (objects never interpolate) and `applyCoercion`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function isContractValueOfType(value: unknown, type: ContractValueType): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Check one plugin's contract against the pipeline's scope. Returns every
|
|
52
|
+
* issue (missing keys first, then ill-typed ones, metadata before vars);
|
|
53
|
+
* empty when the contract is met. Declared types are checked for every
|
|
54
|
+
* SUPPLIED key, required or not (an optional key with a `| default:` is still
|
|
55
|
+
* coerced when it is supplied).
|
|
56
|
+
*/
|
|
57
|
+
export declare function checkPluginContract(contract: PluginContract, scope: ContractScope): ContractIssue[];
|
|
58
|
+
/**
|
|
59
|
+
* Synth-time guard: throw when `plugin` (resolved for `step`) has unmet
|
|
60
|
+
* contract keys. The API refuses such a pipeline at create/update; this
|
|
61
|
+
* catches one that reached synth another way.
|
|
62
|
+
*/
|
|
63
|
+
export declare function assertPluginContract(plugin: PluginContract & {
|
|
64
|
+
readonly name: string;
|
|
65
|
+
readonly version?: string;
|
|
66
|
+
}, scope: ContractScope, step: string): void;
|
|
67
|
+
/** A plugin reference in pipeline props, with where it sits. */
|
|
68
|
+
export interface PluginStepRef {
|
|
69
|
+
/** JSON path of the step: `synth` or `stages[i].steps[j]`. */
|
|
70
|
+
readonly path: string;
|
|
71
|
+
/** Human label: `synth` or `<stageName>/<alias ?? name>`. */
|
|
72
|
+
readonly label: string;
|
|
73
|
+
readonly name: string;
|
|
74
|
+
/** Publisher handle of an installed listing. */
|
|
75
|
+
readonly publisher?: string;
|
|
76
|
+
readonly alias?: string;
|
|
77
|
+
readonly filter?: Readonly<Record<string, unknown>>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Every plugin reference in a pipeline's props: `synth.plugin`, then each
|
|
81
|
+
* `stages[].steps[].plugin` in order. One entry per STEP (not de-duplicated) —
|
|
82
|
+
* the contract result is reported per step.
|
|
83
|
+
*/
|
|
84
|
+
export declare function collectPluginSteps(props: unknown): PluginStepRef[];
|
|
85
|
+
/**
|
|
86
|
+
* The lookup filter synth sends for a reference (pipeline-manager
|
|
87
|
+
* `resolvePluginsForProps`, the deploy-time custom resource, the pipeline
|
|
88
|
+
* service's contract check): the ref's name — and its `publisher`, which
|
|
89
|
+
* routes the lookup to that publisher's installed listing — overlaid by
|
|
90
|
+
* an explicit `filter` (whose `name` wins), else the default active+default
|
|
91
|
+
* version.
|
|
92
|
+
*/
|
|
93
|
+
export declare function pluginLookupFilter(ref: Pick<PluginStepRef, 'name' | 'filter' | 'publisher'>): Record<string, unknown>;
|
|
94
|
+
/**
|
|
95
|
+
* The plugin-alias SEGMENT of an artifact key — and the resolver's cache key:
|
|
96
|
+
* the explicit alias, or `${name}-alias` when there is none
|
|
97
|
+
* (`${publisher}-${name}-alias` for a qualified reference). THE rule — the frontend's artifact picker
|
|
98
|
+
* (`frontend/src/lib/artifact-keys.ts`), the CLI's pre-resolver and
|
|
99
|
+
* `PluginLookup.normalize` all build keys this way.
|
|
100
|
+
*
|
|
101
|
+
* The places that REGISTER keys must use it too: a stage step registering the
|
|
102
|
+
* bare name (`nodejs-build`) or a synth step suffixing an explicit alias
|
|
103
|
+
* (`my-synth-alias`) would fail any UI-picked input artifact with "No artifact
|
|
104
|
+
* registered", because the key it asks for is never the key that was stored.
|
|
105
|
+
*/
|
|
106
|
+
export declare function pluginArtifactAlias(plugin: PluginRefIdentity): string;
|
|
107
|
+
/** The fields of a plugin REFERENCE that identify it. */
|
|
108
|
+
export interface PluginRefIdentity {
|
|
109
|
+
readonly name: string;
|
|
110
|
+
readonly alias?: string;
|
|
111
|
+
/** Publisher handle of an installed listing; absent for an unqualified reference. */
|
|
112
|
+
readonly publisher?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* A publisher handle as it may appear in a construct id or a key: only
|
|
116
|
+
* `[A-Za-z0-9_-]` (handles already are; this is the guarantee).
|
|
117
|
+
*/
|
|
118
|
+
export declare function sanitizePublisher(publisher: string): string;
|
|
119
|
+
/**
|
|
120
|
+
* The construct-id segment of a plugin step: the explicit alias, else
|
|
121
|
+
* `<publisher>-<name>` for a qualified reference, else the bare name — so a
|
|
122
|
+
* step using `acme`'s `lint` and one using the org's own `lint` never collide,
|
|
123
|
+
* while an unqualified step keeps the id it always had (renaming it would make
|
|
124
|
+
* CloudFormation replace its CodeBuild project).
|
|
125
|
+
*/
|
|
126
|
+
export declare function pluginStepIdAlias(plugin: PluginRefIdentity): string;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Plugin contract enforcement. A plugin spec declares
|
|
5
|
+
* the `{{ pipeline.metadata.X }}` / `{{ pipeline.vars.X }}` keys a pipeline
|
|
6
|
+
* must supply (`requiredMetadata` / `requiredVars`) and the coercion type of
|
|
7
|
+
* each (`metadataTypes` / `varsTypes`). The upload validates the spec against
|
|
8
|
+
* its own templates; this module checks a PIPELINE against the contracts of
|
|
9
|
+
* the plugins it references.
|
|
10
|
+
*
|
|
11
|
+
* CDK-free: shared by the pipeline service (create / update → 400 listing
|
|
12
|
+
* every problem per step) and the synth (fail fast for a pipeline that never
|
|
13
|
+
* went through the API, e.g. a CLI-authored props file).
|
|
14
|
+
*
|
|
15
|
+
* The checks mirror the template evaluator (`template/evaluator.ts`) exactly,
|
|
16
|
+
* so "passes here" means "resolves at synth":
|
|
17
|
+
* - a key is MISSING when absent, null or the empty string (the evaluator
|
|
18
|
+
* falls to `| default:` or fails for all three);
|
|
19
|
+
* - an object/array value never interpolates;
|
|
20
|
+
* - `number` / `bool` / `json` accept what the `| number` / `| bool` /
|
|
21
|
+
* `| json` filters accept after stringification.
|
|
22
|
+
*/
|
|
23
|
+
import { merge } from './metadata-helpers.js';
|
|
24
|
+
function asRecord(v) {
|
|
25
|
+
return v && typeof v === 'object' && !Array.isArray(v) ? v : {};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* `pipeline.metadata` as synth builds it: `global` ← `defaults.metadata` ←
|
|
29
|
+
* `synth.metadata` (last wins). The single definition — `PipelineConfiguration`
|
|
30
|
+
* uses it too, so the API check and the synth scope cannot drift.
|
|
31
|
+
*/
|
|
32
|
+
export function pipelineScopeMetadata(props) {
|
|
33
|
+
return merge(asRecord(props.global), asRecord(asRecord(props.defaults).metadata), asRecord(asRecord(props.synth).metadata));
|
|
34
|
+
}
|
|
35
|
+
/** The contract scope of a pipeline's props (see {@link pipelineScopeMetadata}). */
|
|
36
|
+
export function pipelineContractScope(props) {
|
|
37
|
+
return { metadata: pipelineScopeMetadata(props), vars: asRecord(props.vars) };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The contract scope inside a synth template scope (`{ pipeline: { metadata,
|
|
41
|
+
* vars, … } }`, see `PipelineConfiguration.getPipelineScope`).
|
|
42
|
+
*/
|
|
43
|
+
export function contractScopeFromTemplateScope(templateScope) {
|
|
44
|
+
const pipeline = asRecord(templateScope.pipeline);
|
|
45
|
+
return { metadata: asRecord(pipeline.metadata), vars: asRecord(pipeline.vars) };
|
|
46
|
+
}
|
|
47
|
+
/** Would the evaluator treat `value` as absent (missing / null / empty string)? */
|
|
48
|
+
function isMissing(value) {
|
|
49
|
+
return value === undefined || value === null || value === '';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Does `value` satisfy the declared `type` once interpolated? Mirrors the
|
|
53
|
+
* evaluator's `resolveOne` (objects never interpolate) and `applyCoercion`.
|
|
54
|
+
*/
|
|
55
|
+
export function isContractValueOfType(value, type) {
|
|
56
|
+
if (typeof value === 'object' && value !== null)
|
|
57
|
+
return false;
|
|
58
|
+
const raw = String(value);
|
|
59
|
+
switch (type) {
|
|
60
|
+
case 'string':
|
|
61
|
+
return true;
|
|
62
|
+
case 'number':
|
|
63
|
+
return Number.isFinite(Number(raw));
|
|
64
|
+
case 'bool':
|
|
65
|
+
return ['true', '1', 'yes', 'false', '0', 'no', ''].includes(raw.trim().toLowerCase());
|
|
66
|
+
case 'json':
|
|
67
|
+
try {
|
|
68
|
+
JSON.parse(raw);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** A value still carrying `{{ … }}` is resolved later (pipeline pass 1), so its type can't be judged yet. */
|
|
77
|
+
function isUnresolvedTemplate(value) {
|
|
78
|
+
return typeof value === 'string' && value.includes('{{');
|
|
79
|
+
}
|
|
80
|
+
function checkKind(kind, required, types, supplied) {
|
|
81
|
+
const issues = [];
|
|
82
|
+
const where = kind === 'metadata' ? 'metadata (global / defaults.metadata / synth.metadata)' : 'vars';
|
|
83
|
+
for (const key of new Set(required ?? [])) {
|
|
84
|
+
if (isMissing(supplied[key])) {
|
|
85
|
+
issues.push({ kind, key, problem: 'missing', message: `pipeline ${where} must supply '${key}'` });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const [key, expected] of Object.entries(types ?? {})) {
|
|
89
|
+
const value = supplied[key];
|
|
90
|
+
if (isMissing(value) || isUnresolvedTemplate(value))
|
|
91
|
+
continue;
|
|
92
|
+
if (!isContractValueOfType(value, expected)) {
|
|
93
|
+
const got = typeof value === 'object' ? (Array.isArray(value) ? 'an array' : 'an object') : JSON.stringify(value);
|
|
94
|
+
issues.push({ kind, key, problem: 'type', expected, message: `pipeline ${kind}.${key} must be a ${expected}, got ${got}` });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return issues;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check one plugin's contract against the pipeline's scope. Returns every
|
|
101
|
+
* issue (missing keys first, then ill-typed ones, metadata before vars);
|
|
102
|
+
* empty when the contract is met. Declared types are checked for every
|
|
103
|
+
* SUPPLIED key, required or not (an optional key with a `| default:` is still
|
|
104
|
+
* coerced when it is supplied).
|
|
105
|
+
*/
|
|
106
|
+
export function checkPluginContract(contract, scope) {
|
|
107
|
+
return [
|
|
108
|
+
...checkKind('metadata', contract.requiredMetadata, contract.metadataTypes, scope.metadata),
|
|
109
|
+
...checkKind('vars', contract.requiredVars, contract.varsTypes, scope.vars),
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Synth-time guard: throw when `plugin` (resolved for `step`) has unmet
|
|
114
|
+
* contract keys. The API refuses such a pipeline at create/update; this
|
|
115
|
+
* catches one that reached synth another way.
|
|
116
|
+
*/
|
|
117
|
+
export function assertPluginContract(plugin, scope, step) {
|
|
118
|
+
const issues = checkPluginContract(plugin, scope);
|
|
119
|
+
if (issues.length === 0)
|
|
120
|
+
return;
|
|
121
|
+
throw new Error(`Step "${step}" uses plugin "${plugin.name}${plugin.version ? `@${plugin.version}` : ''}" whose contract is not met:\n`
|
|
122
|
+
+ issues.map((i) => ` • ${i.message}`).join('\n'));
|
|
123
|
+
}
|
|
124
|
+
function toRef(raw, path, label) {
|
|
125
|
+
const r = asRecord(raw);
|
|
126
|
+
if (typeof r.name !== 'string' || r.name.length === 0)
|
|
127
|
+
return null;
|
|
128
|
+
const alias = typeof r.alias === 'string' ? r.alias : undefined;
|
|
129
|
+
const publisher = typeof r.publisher === 'string' && r.publisher.length > 0 ? r.publisher : undefined;
|
|
130
|
+
const filter = r.filter && typeof r.filter === 'object' ? r.filter : undefined;
|
|
131
|
+
return {
|
|
132
|
+
path,
|
|
133
|
+
label: label(r.name, alias, publisher),
|
|
134
|
+
name: r.name,
|
|
135
|
+
...(publisher ? { publisher } : {}),
|
|
136
|
+
...(alias ? { alias } : {}),
|
|
137
|
+
...(filter ? { filter } : {}),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Every plugin reference in a pipeline's props: `synth.plugin`, then each
|
|
142
|
+
* `stages[].steps[].plugin` in order. One entry per STEP (not de-duplicated) —
|
|
143
|
+
* the contract result is reported per step.
|
|
144
|
+
*/
|
|
145
|
+
export function collectPluginSteps(props) {
|
|
146
|
+
const p = asRecord(props);
|
|
147
|
+
const out = [];
|
|
148
|
+
const synth = toRef(asRecord(p.synth).plugin, 'synth', () => 'synth');
|
|
149
|
+
if (synth)
|
|
150
|
+
out.push(synth);
|
|
151
|
+
const stages = Array.isArray(p.stages) ? p.stages : [];
|
|
152
|
+
stages.forEach((stage, i) => {
|
|
153
|
+
const s = asRecord(stage);
|
|
154
|
+
const stageName = typeof s.stageName === 'string' ? s.stageName : `stage ${i + 1}`;
|
|
155
|
+
const steps = Array.isArray(s.steps) ? s.steps : [];
|
|
156
|
+
steps.forEach((step, j) => {
|
|
157
|
+
const ref = toRef(asRecord(step).plugin, `stages[${i}].steps[${j}]`, (name, alias, publisher) => `${stageName}/${alias ?? (publisher ? `${publisher}/${name}` : name)}`);
|
|
158
|
+
if (ref)
|
|
159
|
+
out.push(ref);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The lookup filter synth sends for a reference (pipeline-manager
|
|
166
|
+
* `resolvePluginsForProps`, the deploy-time custom resource, the pipeline
|
|
167
|
+
* service's contract check): the ref's name — and its `publisher`, which
|
|
168
|
+
* routes the lookup to that publisher's installed listing — overlaid by
|
|
169
|
+
* an explicit `filter` (whose `name` wins), else the default active+default
|
|
170
|
+
* version.
|
|
171
|
+
*/
|
|
172
|
+
export function pluginLookupFilter(ref) {
|
|
173
|
+
return {
|
|
174
|
+
name: ref.name,
|
|
175
|
+
...(ref.publisher ? { publisher: ref.publisher } : {}),
|
|
176
|
+
...(ref.filter ?? { isActive: true, isDefault: true }),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// -----------------------------------------------------------------------------
|
|
180
|
+
// Reference identity (CDK-free: the CLI, the pipeline service and synth share it)
|
|
181
|
+
// -----------------------------------------------------------------------------
|
|
182
|
+
/**
|
|
183
|
+
* The plugin-alias SEGMENT of an artifact key — and the resolver's cache key:
|
|
184
|
+
* the explicit alias, or `${name}-alias` when there is none
|
|
185
|
+
* (`${publisher}-${name}-alias` for a qualified reference). THE rule — the frontend's artifact picker
|
|
186
|
+
* (`frontend/src/lib/artifact-keys.ts`), the CLI's pre-resolver and
|
|
187
|
+
* `PluginLookup.normalize` all build keys this way.
|
|
188
|
+
*
|
|
189
|
+
* The places that REGISTER keys must use it too: a stage step registering the
|
|
190
|
+
* bare name (`nodejs-build`) or a synth step suffixing an explicit alias
|
|
191
|
+
* (`my-synth-alias`) would fail any UI-picked input artifact with "No artifact
|
|
192
|
+
* registered", because the key it asks for is never the key that was stored.
|
|
193
|
+
*/
|
|
194
|
+
export function pluginArtifactAlias(plugin) {
|
|
195
|
+
if (plugin.alias)
|
|
196
|
+
return plugin.alias;
|
|
197
|
+
return plugin.publisher ? `${sanitizePublisher(plugin.publisher)}-${plugin.name}-alias` : `${plugin.name}-alias`;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* A publisher handle as it may appear in a construct id or a key: only
|
|
201
|
+
* `[A-Za-z0-9_-]` (handles already are; this is the guarantee).
|
|
202
|
+
*/
|
|
203
|
+
export function sanitizePublisher(publisher) {
|
|
204
|
+
return publisher.replace(/[^A-Za-z0-9_-]/g, '-');
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The construct-id segment of a plugin step: the explicit alias, else
|
|
208
|
+
* `<publisher>-<name>` for a qualified reference, else the bare name — so a
|
|
209
|
+
* step using `acme`'s `lint` and one using the org's own `lint` never collide,
|
|
210
|
+
* while an unqualified step keeps the id it always had (renaming it would make
|
|
211
|
+
* CloudFormation replace its CodeBuild project).
|
|
212
|
+
*/
|
|
213
|
+
export function pluginStepIdAlias(plugin) {
|
|
214
|
+
// `??`, not `||`: an explicit (even empty) alias keeps the id it always had.
|
|
215
|
+
return plugin.alias ?? (plugin.publisher ? `${sanitizePublisher(plugin.publisher)}-${plugin.name}` : plugin.name);
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWNvbnRyYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvcmUvcGx1Z2luLWNvbnRyYWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFzQzlDLFNBQVMsUUFBUSxDQUFDLENBQVU7SUFDMUIsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBNEIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQzdGLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQixDQUFDLEtBQXlCO0lBQzdELE9BQU8sS0FBSyxDQUNWLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFpQixFQUN0QyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQWlCLEVBQzNELFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBaUIsQ0FDekQsQ0FBQztBQUNKLENBQUM7QUFFRCxvRkFBb0Y7QUFDcEYsTUFBTSxVQUFVLHFCQUFxQixDQUFDLEtBQXlCO0lBQzdELE9BQU8sRUFBRSxRQUFRLEVBQUUscUJBQXFCLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztBQUNoRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLDhCQUE4QixDQUFDLGFBQWdEO0lBQzdGLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEQs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QUFDO0lBQ3RDLE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLFFBQVEsQ0FBQztBQUNuSCxDQUFDO0FBVUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLFNBQWlCO0lBQ2pELE9BQU8sU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLE1BQXlCO0lBQ3pELDZFQUE2RTtJQUM3RSxPQUFPLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUNwSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogUGx1Z2luIGNvbnRyYWN0IGVuZm9yY2VtZW50LiBBIHBsdWdpbiBzcGVjIGRlY2xhcmVzXG4gKiB0aGUgYHt7IHBpcGVsaW5lLm1ldGFkYXRhLlggfX1gIC8gYHt7IHBpcGVsaW5lLnZhcnMuWCB9fWAga2V5cyBhIHBpcGVsaW5lXG4gKiBtdXN0IHN1cHBseSAoYHJlcXVpcmVkTWV0YWRhdGFgIC8gYHJlcXVpcmVkVmFyc2ApIGFuZCB0aGUgY29lcmNpb24gdHlwZSBvZlxuICogZWFjaCAoYG1ldGFkYXRhVHlwZXNgIC8gYHZhcnNUeXBlc2ApLiBUaGUgdXBsb2FkIHZhbGlkYXRlcyB0aGUgc3BlYyBhZ2FpbnN0XG4gKiBpdHMgb3duIHRlbXBsYXRlczsgdGhpcyBtb2R1bGUgY2hlY2tzIGEgUElQRUxJTkUgYWdhaW5zdCB0aGUgY29udHJhY3RzIG9mXG4gKiB0aGUgcGx1Z2lucyBpdCByZWZlcmVuY2VzLlxuICpcbiAqIENESy1mcmVlOiBzaGFyZWQgYnkgdGhlIHBpcGVsaW5lIHNlcnZpY2UgKGNyZWF0ZSAvIHVwZGF0ZSDihpIgNDAwIGxpc3RpbmdcbiAqIGV2ZXJ5IHByb2JsZW0gcGVyIHN0ZXApIGFuZCB0aGUgc3ludGggKGZhaWwgZmFzdCBmb3IgYSBwaXBlbGluZSB0aGF0IG5ldmVyXG4gKiB3ZW50IHRocm91Z2ggdGhlIEFQSSwgZS5nLiBhIENMSS1hdXRob3JlZCBwcm9wcyBmaWxlKS5cbiAqXG4gKiBUaGUgY2hlY2tzIG1pcnJvciB0aGUgdGVtcGxhdGUgZXZhbHVhdG9yIChgdGVtcGxhdGUvZXZhbHVhdG9yLnRzYCkgZXhhY3RseSxcbiAqIHNvIFwicGFzc2VzIGhlcmVcIiBtZWFucyBcInJlc29sdmVzIGF0IHN5bnRoXCI6XG4gKiAgIC0gYSBrZXkgaXMgTUlTU0lORyB3aGVuIGFic2VudCwgbnVsbCBvciB0aGUgZW1wdHkgc3RyaW5nICh0aGUgZXZhbHVhdG9yXG4gKiAgICAgZmFsbHMgdG8gYHwgZGVmYXVsdDpgIG9yIGZhaWxzIGZvciBhbGwgdGhyZWUpO1xuICogICAtIGFuIG9iamVjdC9hcnJheSB2YWx1ZSBuZXZlciBpbnRlcnBvbGF0ZXM7XG4gKiAgIC0gYG51bWJlcmAgLyBgYm9vbGAgLyBganNvbmAgYWNjZXB0IHdoYXQgdGhlIGB8IG51bWJlcmAgLyBgfCBib29sYCAvXG4gKiAgICAgYHwganNvbmAgZmlsdGVycyBhY2NlcHQgYWZ0ZXIgc3RyaW5naWZpY2F0aW9uLlxuICovXG5cbmltcG9ydCB7IG1lcmdlIH0gZnJvbSAnLi9tZXRhZGF0YS1oZWxwZXJzLmpzJztcbmltcG9ydCB0eXBlIHsgTWV0YURhdGFUeXBlIH0gZnJvbSAnLi9waXBlbGluZS10eXBlcy5qcyc7XG5cbi8qKiBEZWNsYXJlZCBjb2VyY2lvbiB0eXBlIG9mIGEgY29udHJhY3Qga2V5LiAqL1xuZXhwb3J0IHR5cGUgQ29udHJhY3RWYWx1ZVR5cGUgPSAnc3RyaW5nJyB8ICdudW1iZXInIHwgJ2Jvb2wnIHwgJ2pzb24nO1xuXG4vKiogVGhlIGNvbnRyYWN0IGZpZWxkcyBvZiBhIHBsdWdpbiByZWNvcmQgKGFzIGBwbHVnaW5zYCBzdG9yZXMgdGhlbSkuICovXG5leHBvcnQgaW50ZXJmYWNlIFBsdWdpbkNvbnRyYWN0IHtcbiAgcmVhZG9ubHkgcmVxdWlyZWRNZXRhZGF0YT86IHJlYWRvbmx5IHN0cmluZ1tdIHwgbnVsbDtcbiAgcmVhZG9ubHkgcmVxdWlyZWRWYXJzPzogcmVhZG9ubHkgc3RyaW5nW10gfCBudWxsO1xuICByZWFkb25seSBtZXRhZGF0YVR5cGVzPzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgQ29udHJhY3RWYWx1ZVR5cGU+PiB8IG51bGw7XG4gIHJlYWRvbmx5IHZhcnNUeXBlcz86IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIENvbnRyYWN0VmFsdWVUeXBlPj4gfCBudWxsO1xufVxuXG4vKiogV2hhdCBge3sgcGlwZWxpbmUubWV0YWRhdGEuKiB9fWAgYW5kIGB7eyBwaXBlbGluZS52YXJzLiogfX1gIHJlc29sdmUgYWdhaW5zdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29udHJhY3RTY29wZSB7XG4gIHJlYWRvbmx5IG1ldGFkYXRhOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG4gIHJlYWRvbmx5IHZhcnM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcbn1cblxuLyoqIE9uZSB1bm1ldCBjb250cmFjdCBrZXkuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyYWN0SXNzdWUge1xuICByZWFkb25seSBraW5kOiAnbWV0YWRhdGEnIHwgJ3ZhcnMnO1xuICByZWFkb25seSBrZXk6IHN0cmluZztcbiAgcmVhZG9ubHkgcHJvYmxlbTogJ21pc3NpbmcnIHwgJ3R5cGUnO1xuICAvKiogVGhlIGRlY2xhcmVkIHR5cGUsIGZvciBhIGB0eXBlYCBwcm9ibGVtLiAqL1xuICByZWFkb25seSBleHBlY3RlZD86IENvbnRyYWN0VmFsdWVUeXBlO1xuICByZWFkb25seSBtZXNzYWdlOiBzdHJpbmc7XG59XG5cbi8qKiBUaGUgcGlwZWxpbmUtcHJvcHMgZmllbGRzIHRoZSBjb250cmFjdCBzY29wZSBpcyBidWlsdCBmcm9tIChCdWlsZGVyUHJvcHMgc3Vic2V0KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29udHJhY3RTY29wZVByb3BzIHtcbiAgcmVhZG9ubHkgZ2xvYmFsPzogdW5rbm93bjtcbiAgcmVhZG9ubHkgZGVmYXVsdHM/OiB1bmtub3duO1xuICByZWFkb25seSBzeW50aD86IHVua25vd247XG4gIHJlYWRvbmx5IHZhcnM/OiB1bmtub3duO1xufVxuXG5mdW5jdGlvbiBhc1JlY29yZCh2OiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICByZXR1cm4gdiAmJiB0eXBlb2YgdiA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkodikgPyB2IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IDoge307XG59XG5cbi8qKlxuICogYHBpcGVsaW5lLm1ldGFkYXRhYCBhcyBzeW50aCBidWlsZHMgaXQ6IGBnbG9iYWxgIOKGkCBgZGVmYXVsdHMubWV0YWRhdGFgIOKGkFxuICogYHN5bnRoLm1ldGFkYXRhYCAobGFzdCB3aW5zKS4gVGhlIHNpbmdsZSBkZWZpbml0aW9uIOKAlCBgUGlwZWxpbmVDb25maWd1cmF0aW9uYFxuICogdXNlcyBpdCB0b28sIHNvIHRoZSBBUEkgY2hlY2sgYW5kIHRoZSBzeW50aCBzY29wZSBjYW5ub3QgZHJpZnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwaXBlbGluZVNjb3BlTWV0YWRhdGEocHJvcHM6IENvbnRyYWN0U2NvcGVQcm9wcyk6IE1ldGFEYXRhVHlwZSB7XG4gIHJldHVybiBtZXJnZShcbiAgICBhc1JlY29yZChwcm9wcy5nbG9iYWwpIGFzIE1ldGFEYXRhVHlwZSxcbiAgICBhc1JlY29yZChhc1JlY29yZChwcm9wcy5kZWZhdWx0cykubWV0YWRhdGEpIGFzIE1ldGFEYXRhVHlwZSxcbiAgICBhc1JlY29yZChhc1JlY29yZChwcm9wcy5zeW50aCkubWV0YWRhdGEpIGFzIE1ldGFEYXRhVHlwZSxcbiAgKTtcbn1cblxuLyoqIFRoZSBjb250cmFjdCBzY29wZSBvZiBhIHBpcGVsaW5lJ3MgcHJvcHMgKHNlZSB7QGxpbmsgcGlwZWxpbmVTY29wZU1ldGFkYXRhfSkuICovXG5leHBvcnQgZnVuY3Rpb24gcGlwZWxpbmVDb250cmFjdFNjb3BlKHByb3BzOiBDb250cmFjdFNjb3BlUHJvcHMpOiBDb250cmFjdFNjb3BlIHtcbiAgcmV0dXJuIHsgbWV0YWRhdGE6IHBpcGVsaW5lU2NvcGVNZXRhZGF0YShwcm9wcyksIHZhcnM6IGFzUmVjb3JkKHByb3BzLnZhcnMpIH07XG59XG5cbi8qKlxuICogVGhlIGNvbnRyYWN0IHNjb3BlIGluc2lkZSBhIHN5bnRoIHRlbXBsYXRlIHNjb3BlIChgeyBwaXBlbGluZTogeyBtZXRhZGF0YSxcbiAqIHZhcnMsIOKApiB9IH1gLCBzZWUgYFBpcGVsaW5lQ29uZmlndXJhdGlvbi5nZXRQaXBlbGluZVNjb3BlYCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb250cmFjdFNjb3BlRnJvbVRlbXBsYXRlU2NvcGUodGVtcGxhdGVTY29wZTogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KTogQ29udHJhY3RTY29wZSB7XG4gIGNvbnN0IHBpcGVsaW5lID0gYXNSZWNvcmQodGVtcGxhdGVTY29wZS5waXBlbGluZSk7XG4gIHJldHVybiB7IG1ldGFkYXRhOiBhc1JlY29yZChwaXBlbGluZS5tZXRhZGF0YSksIHZhcnM6IGFzUmVjb3JkKHBpcGVsaW5lLnZhcnMpIH07XG59XG5cbi8qKiBXb3VsZCB0aGUgZXZhbHVhdG9yIHRyZWF0IGB2YWx1ZWAgYXMgYWJzZW50IChtaXNzaW5nIC8gbnVsbCAvIGVtcHR5IHN0cmluZyk/ICovXG5mdW5jdGlvbiBpc01pc3NpbmcodmFsdWU6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnO1xufVxuXG4vKipcbiAqIERvZXMgYHZhbHVlYCBzYXRpc2Z5IHRoZSBkZWNsYXJlZCBgdHlwZWAgb25jZSBpbnRlcnBvbGF0ZWQ/IE1pcnJvcnMgdGhlXG4gKiBldmFsdWF0b3IncyBgcmVzb2x2ZU9uZWAgKG9iamVjdHMgbmV2ZXIgaW50ZXJwb2xhdGUpIGFuZCBgYXBwbHlDb2VyY2lvbmAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbnRyYWN0VmFsdWVPZlR5cGUodmFsdWU6IHVua25vd24sIHR5cGU6IENvbnRyYWN0VmFsdWVUeXBlKTogYm9vbGVhbiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHJhdyA9IFN0cmluZyh2YWx1ZSk7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShOdW1iZXIocmF3KSk7XG4gICAgY2FzZSAnYm9vbCc6XG4gICAgICByZXR1cm4gWyd0cnVlJywgJzEnLCAneWVzJywgJ2ZhbHNlJywgJzAnLCAnbm8nLCAnJ10uaW5jbHVkZXMocmF3LnRyaW0oKS50b0xvd2VyQ2FzZSgpKTtcbiAgICBjYXNlICdqc29uJzpcbiAgICAgIHRyeSB7XG4gICAgICAgIEpTT04ucGFyc2UocmF3KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICB9XG59XG5cbi8qKiBBIHZhbHVlIHN0aWxsIGNhcnJ5aW5nIGB7eyDigKYgfX1gIGlzIHJlc29sdmVkIGxhdGVyIChwaXBlbGluZSBwYXNzIDEpLCBzbyBpdHMgdHlwZSBjYW4ndCBiZSBqdWRnZWQgeWV0LiAqL1xuZnVuY3Rpb24gaXNVbnJlc29sdmVkVGVtcGxhdGUodmFsdWU6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUuaW5jbHVkZXMoJ3t7Jyk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrS2luZChcbiAga2luZDogJ21ldGFkYXRhJyB8ICd2YXJzJyxcbiAgcmVxdWlyZWQ6IHJlYWRvbmx5IHN0cmluZ1tdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgdHlwZXM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIENvbnRyYWN0VmFsdWVUeXBlPj4gfCBudWxsIHwgdW5kZWZpbmVkLFxuICBzdXBwbGllZDogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+LFxuKTogQ29udHJhY3RJc3N1ZVtdIHtcbiAgY29uc3QgaXNzdWVzOiBDb250cmFjdElzc3VlW10gPSBbXTtcbiAgY29uc3Qgd2hlcmUgPSBraW5kID09PSAnbWV0YWRhdGEnID8gJ21ldGFkYXRhIChnbG9iYWwgLyBkZWZhdWx0cy5tZXRhZGF0YSAvIHN5bnRoLm1ldGFkYXRhKScgOiAndmFycyc7XG4gIGZvciAoY29uc3Qga2V5IG9mIG5ldyBTZXQocmVxdWlyZWQgPz8gW10pKSB7XG4gICAgaWYgKGlzTWlzc2luZyhzdXBwbGllZFtrZXldKSkge1xuICAgICAgaXNzdWVzLnB1c2goeyBraW5kLCBrZXksIHByb2JsZW06ICdtaXNzaW5nJywgbWVzc2FnZTogYHBpcGVsaW5lICR7d2hlcmV9IG11c3Qgc3VwcGx5ICcke2tleX0nYCB9KTtcbiAgICB9XG4gIH1cbiAgZm9yIChjb25zdCBba2V5LCBleHBlY3RlZF0gb2YgT2JqZWN0LmVudHJpZXModHlwZXMgPz8ge30pKSB7XG4gICAgY29uc3QgdmFsdWUgPSBzdXBwbGllZFtrZXldO1xuICAgIGlmIChpc01pc3NpbmcodmFsdWUpIHx8IGlzVW5yZXNvbHZlZFRlbXBsYXRlKHZhbHVlKSkgY29udGludWU7XG4gICAgaWYgKCFpc0NvbnRyYWN0VmFsdWVPZlR5cGUodmFsdWUsIGV4cGVjdGVkKSkge1xuICAgICAgY29uc3QgZ290ID0gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyA/IChBcnJheS5pc0FycmF5KHZhbHVlKSA/ICdhbiBhcnJheScgOiAnYW4gb2JqZWN0JykgOiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgICBpc3N1ZXMucHVzaCh7IGtpbmQsIGtleSwgcHJvYmxlbTogJ3R5cGUnLCBleHBlY3RlZCwgbWVzc2FnZTogYHBpcGVsaW5lICR7a2luZH0uJHtrZXl9IG11c3QgYmUgYSAke2V4cGVjdGVkfSwgZ290ICR7Z290fWAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBpc3N1ZXM7XG59XG5cbi8qKlxuICogQ2hlY2sgb25lIHBsdWdpbidzIGNvbnRyYWN0IGFnYWluc3QgdGhlIHBpcGVsaW5lJ3Mgc2NvcGUuIFJldHVybnMgZXZlcnlcbiAqIGlzc3VlIChtaXNzaW5nIGtleXMgZmlyc3QsIHRoZW4gaWxsLXR5cGVkIG9uZXMsIG1ldGFkYXRhIGJlZm9yZSB2YXJzKTtcbiAqIGVtcHR5IHdoZW4gdGhlIGNvbnRyYWN0IGlzIG1ldC4gRGVjbGFyZWQgdHlwZXMgYXJlIGNoZWNrZWQgZm9yIGV2ZXJ5XG4gKiBTVVBQTElFRCBrZXksIHJlcXVpcmVkIG9yIG5vdCAoYW4gb3B0aW9uYWwga2V5IHdpdGggYSBgfCBkZWZhdWx0OmAgaXMgc3RpbGxcbiAqIGNvZXJjZWQgd2hlbiBpdCBpcyBzdXBwbGllZCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja1BsdWdpbkNvbnRyYWN0KGNvbnRyYWN0OiBQbHVnaW5Db250cmFjdCwgc2NvcGU6IENvbnRyYWN0U2NvcGUpOiBDb250cmFjdElzc3VlW10ge1xuICByZXR1cm4gW1xuICAgIC4uLmNoZWNrS2luZCgnbWV0YWRhdGEnLCBjb250cmFjdC5yZXF1aXJlZE1ldGFkYXRhLCBjb250cmFjdC5tZXRhZGF0YVR5cGVzLCBzY29wZS5tZXRhZGF0YSksXG4gICAgLi4uY2hlY2tLaW5kKCd2YXJzJywgY29udHJhY3QucmVxdWlyZWRWYXJzLCBjb250cmFjdC52YXJzVHlwZXMsIHNjb3BlLnZhcnMpLFxuICBdO1xufVxuXG4vKipcbiAqIFN5bnRoLXRpbWUgZ3VhcmQ6IHRocm93IHdoZW4gYHBsdWdpbmAgKHJlc29sdmVkIGZvciBgc3RlcGApIGhhcyB1bm1ldFxuICogY29udHJhY3Qga2V5cy4gVGhlIEFQSSByZWZ1c2VzIHN1Y2ggYSBwaXBlbGluZSBhdCBjcmVhdGUvdXBkYXRlOyB0aGlzXG4gKiBjYXRjaGVzIG9uZSB0aGF0IHJlYWNoZWQgc3ludGggYW5vdGhlciB3YXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRQbHVnaW5Db250cmFjdChcbiAgcGx1Z2luOiBQbHVnaW5Db250cmFjdCAmIHsgcmVhZG9ubHkgbmFtZTogc3RyaW5nOyByZWFkb25seSB2ZXJzaW9uPzogc3RyaW5nIH0sXG4gIHNjb3BlOiBDb250cmFjdFNjb3BlLFxuICBzdGVwOiBzdHJpbmcsXG4pOiB2b2lkIHtcbiAgY29uc3QgaXNzdWVzID0gY2hlY2tQbHVnaW5Db250cmFjdChwbHVnaW4sIHNjb3BlKTtcbiAgaWYgKGlzc3Vlcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgdGhyb3cgbmV3IEVycm9yKFxuICAgIGBTdGVwIFwiJHtzdGVwfVwiIHVzZXMgcGx1Z2luIFwiJHtwbHVnaW4ubmFtZX0ke3BsdWdpbi52ZXJzaW9uID8gYEAke3BsdWdpbi52ZXJzaW9ufWAgOiAnJ31cIiB3aG9zZSBjb250cmFjdCBpcyBub3QgbWV0OlxcbmBcbiAgICArIGlzc3Vlcy5tYXAoKGkpID0+IGAgIOKAoiAke2kubWVzc2FnZX1gKS5qb2luKCdcXG4nKSxcbiAgKTtcbn1cblxuLyoqIEEgcGx1Z2luIHJlZmVyZW5jZSBpbiBwaXBlbGluZSBwcm9wcywgd2l0aCB3aGVyZSBpdCBzaXRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5TdGVwUmVmIHtcbiAgLyoqIEpTT04gcGF0aCBvZiB0aGUgc3RlcDogYHN5bnRoYCBvciBgc3RhZ2VzW2ldLnN0ZXBzW2pdYC4gKi9cbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xuICAvKiogSHVtYW4gbGFiZWw6IGBzeW50aGAgb3IgYDxzdGFnZU5hbWU+LzxhbGlhcyA/PyBuYW1lPmAuICovXG4gIHJlYWRvbmx5IGxhYmVsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgLyoqIFB1Ymxpc2hlciBoYW5kbGUgb2YgYW4gaW5zdGFsbGVkIGxpc3RpbmcuICovXG4gIHJlYWRvbmx5IHB1Ymxpc2hlcj86IHN0cmluZztcbiAgcmVhZG9ubHkgYWxpYXM/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZpbHRlcj86IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcbn1cblxuZnVuY3Rpb24gdG9SZWYocmF3OiB1bmtub3duLCBwYXRoOiBzdHJpbmcsIGxhYmVsOiAobmFtZTogc3RyaW5nLCBhbGlhcz86IHN0cmluZywgcHVibGlzaGVyPzogc3RyaW5nKSA9PiBzdHJpbmcpOiBQbHVnaW5TdGVwUmVmIHwgbnVsbCB7XG4gIGNvbnN0IHIgPSBhc1JlY29yZChyYXcpO1xuICBpZiAodHlwZW9mIHIubmFtZSAhPT0gJ3N0cmluZycgfHwgci5uYW1lLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IGFsaWFzID0gdHlwZW9mIHIuYWxpYXMgPT09ICdzdHJpbmcnID8gci5hbGlhcyA6IHVuZGVmaW5lZDtcbiAgY29uc3QgcHVibGlzaGVyID0gdHlwZW9mIHIucHVibGlzaGVyID09PSAnc3RyaW5nJyAmJiByLnB1Ymxpc2hlci5sZW5ndGggPiAwID8gci5wdWJsaXNoZXIgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IGZpbHRlciA9IHIuZmlsdGVyICYmIHR5cGVvZiByLmZpbHRlciA9PT0gJ29iamVjdCcgPyByLmZpbHRlciBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA6IHVuZGVmaW5lZDtcbiAgcmV0dXJuIHtcbiAgICBwYXRoLFxuICAgIGxhYmVsOiBsYWJlbChyLm5hbWUsIGFsaWFzLCBwdWJsaXNoZXIpLFxuICAgIG5hbWU6IHIubmFtZSxcbiAgICAuLi4ocHVibGlzaGVyID8geyBwdWJsaXNoZXIgfSA6IHt9KSxcbiAgICAuLi4oYWxpYXMgPyB7IGFsaWFzIH0gOiB7fSksXG4gICAgLi4uKGZpbHRlciA/IHsgZmlsdGVyIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICogRXZlcnkgcGx1Z2luIHJlZmVyZW5jZSBpbiBhIHBpcGVsaW5lJ3MgcHJvcHM6IGBzeW50aC5wbHVnaW5gLCB0aGVuIGVhY2hcbiAqIGBzdGFnZXNbXS5zdGVwc1tdLnBsdWdpbmAgaW4gb3JkZXIuIE9uZSBlbnRyeSBwZXIgU1RFUCAobm90IGRlLWR1cGxpY2F0ZWQpIOKAlFxuICogdGhlIGNvbnRyYWN0IHJlc3VsdCBpcyByZXBvcnRlZCBwZXIgc3RlcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbGxlY3RQbHVnaW5TdGVwcyhwcm9wczogdW5rbm93bik6IFBsdWdpblN0ZXBSZWZbXSB7XG4gIGNvbnN0IHAgPSBhc1JlY29yZChwcm9wcyk7XG4gIGNvbnN0IG91dDogUGx1Z2luU3RlcFJlZltdID0gW107XG4gIGNvbnN0IHN5bnRoID0gdG9SZWYoYXNSZWNvcmQocC5zeW50aCkucGx1Z2luLCAnc3ludGgnLCAoKSA9PiAnc3ludGgnKTtcbiAgaWYgKHN5bnRoKSBvdXQucHVzaChzeW50aCk7XG4gIGNvbnN0IHN0YWdlcyA9IEFycmF5LmlzQXJyYXkocC5zdGFnZXMpID8gcC5zdGFnZXMgOiBbXTtcbiAgc3RhZ2VzLmZvckVhY2goKHN0YWdlLCBpKSA9PiB7XG4gICAgY29uc3QgcyA9IGFzUmVjb3JkKHN0YWdlKTtcbiAgICBjb25zdCBzdGFnZU5hbWUgPSB0eXBlb2Ygcy5zdGFnZU5hbWUgPT09ICdzdHJpbmcnID8gcy5zdGFnZU5hbWUgOiBgc3RhZ2UgJHtpICsgMX1gO1xuICAgIGNvbnN0IHN0ZXBzID0gQXJyYXkuaXNBcnJheShzLnN0ZXBzKSA/IHMuc3RlcHMgOiBbXTtcbiAgICBzdGVwcy5mb3JFYWNoKChzdGVwLCBqKSA9PiB7XG4gICAgICBjb25zdCByZWYgPSB0b1JlZihhc1JlY29yZChzdGVwKS5wbHVnaW4sIGBzdGFnZXNbJHtpfV0uc3RlcHNbJHtqfV1gLFxuICAgICAgICAobmFtZSwgYWxpYXMsIHB1Ymxpc2hlcikgPT4gYCR7c3RhZ2VOYW1lfS8ke2FsaWFzID8/IChwdWJsaXNoZXIgPyBgJHtwdWJsaXNoZXJ9LyR7bmFtZX1gIDogbmFtZSl9YCk7XG4gICAgICBpZiAocmVmKSBvdXQucHVzaChyZWYpO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBUaGUgbG9va3VwIGZpbHRlciBzeW50aCBzZW5kcyBmb3IgYSByZWZlcmVuY2UgKHBpcGVsaW5lLW1hbmFnZXJcbiAqIGByZXNvbHZlUGx1Z2luc0ZvclByb3BzYCwgdGhlIGRlcGxveS10aW1lIGN1c3RvbSByZXNvdXJjZSwgdGhlIHBpcGVsaW5lXG4gKiBzZXJ2aWNlJ3MgY29udHJhY3QgY2hlY2spOiB0aGUgcmVmJ3MgbmFtZSDigJQgYW5kIGl0cyBgcHVibGlzaGVyYCwgd2hpY2hcbiAqIHJvdXRlcyB0aGUgbG9va3VwIHRvIHRoYXQgcHVibGlzaGVyJ3MgaW5zdGFsbGVkIGxpc3Rpbmcg4oCUIG92ZXJsYWlkIGJ5XG4gKiBhbiBleHBsaWNpdCBgZmlsdGVyYCAod2hvc2UgYG5hbWVgIHdpbnMpLCBlbHNlIHRoZSBkZWZhdWx0IGFjdGl2ZStkZWZhdWx0XG4gKiB2ZXJzaW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGx1Z2luTG9va3VwRmlsdGVyKHJlZjogUGljazxQbHVnaW5TdGVwUmVmLCAnbmFtZScgfCAnZmlsdGVyJyB8ICdwdWJsaXNoZXInPik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiByZWYubmFtZSxcbiAgICAuLi4ocmVmLnB1Ymxpc2hlciA/IHsgcHVibGlzaGVyOiByZWYucHVibGlzaGVyIH0gOiB7fSksXG4gICAgLi4uKHJlZi5maWx0ZXIgPz8geyBpc0FjdGl2ZTogdHJ1ZSwgaXNEZWZhdWx0OiB0cnVlIH0pLFxuICB9O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUmVmZXJlbmNlIGlkZW50aXR5IChDREstZnJlZTogdGhlIENMSSwgdGhlIHBpcGVsaW5lIHNlcnZpY2UgYW5kIHN5bnRoIHNoYXJlIGl0KVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBUaGUgcGx1Z2luLWFsaWFzIFNFR01FTlQgb2YgYW4gYXJ0aWZhY3Qga2V5IOKAlCBhbmQgdGhlIHJlc29sdmVyJ3MgY2FjaGUga2V5OlxuICogdGhlIGV4cGxpY2l0IGFsaWFzLCBvciBgJHtuYW1lfS1hbGlhc2Agd2hlbiB0aGVyZSBpcyBub25lXG4gKiAoYCR7cHVibGlzaGVyfS0ke25hbWV9LWFsaWFzYCBmb3IgYSBxdWFsaWZpZWQgcmVmZXJlbmNlKS4gVEhFIHJ1bGUg4oCUIHRoZSBmcm9udGVuZCdzIGFydGlmYWN0IHBpY2tlclxuICogKGBmcm9udGVuZC9zcmMvbGliL2FydGlmYWN0LWtleXMudHNgKSwgdGhlIENMSSdzIHByZS1yZXNvbHZlciBhbmRcbiAqIGBQbHVnaW5Mb29rdXAubm9ybWFsaXplYCBhbGwgYnVpbGQga2V5cyB0aGlzIHdheS5cbiAqXG4gKiBUaGUgcGxhY2VzIHRoYXQgUkVHSVNURVIga2V5cyBtdXN0IHVzZSBpdCB0b286IGEgc3RhZ2Ugc3RlcCByZWdpc3RlcmluZyB0aGVcbiAqIGJhcmUgbmFtZSAoYG5vZGVqcy1idWlsZGApIG9yIGEgc3ludGggc3RlcCBzdWZmaXhpbmcgYW4gZXhwbGljaXQgYWxpYXNcbiAqIChgbXktc3ludGgtYWxpYXNgKSB3b3VsZCBmYWlsIGFueSBVSS1waWNrZWQgaW5wdXQgYXJ0aWZhY3Qgd2l0aCBcIk5vIGFydGlmYWN0XG4gKiByZWdpc3RlcmVkXCIsIGJlY2F1c2UgdGhlIGtleSBpdCBhc2tzIGZvciBpcyBuZXZlciB0aGUga2V5IHRoYXQgd2FzIHN0b3JlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsdWdpbkFydGlmYWN0QWxpYXMocGx1Z2luOiBQbHVnaW5SZWZJZGVudGl0eSk6IHN0cmluZyB7XG4gIGlmIChwbHVnaW4uYWxpYXMpIHJldHVybiBwbHVnaW4uYWxpYXM7XG4gIHJldHVybiBwbHVnaW4ucHVibGlzaGVyID8gYCR7c2FuaXRpemVQdWJsaXNoZXIocGx1Z2luLnB1Ymxpc2hlcil9LSR7cGx1Z2luLm5hbWV9LWFsaWFzYCA6IGAke3BsdWdpbi5uYW1lfS1hbGlhc2A7XG59XG5cbi8qKiBUaGUgZmllbGRzIG9mIGEgcGx1Z2luIFJFRkVSRU5DRSB0aGF0IGlkZW50aWZ5IGl0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5SZWZJZGVudGl0eSB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgYWxpYXM/OiBzdHJpbmc7XG4gIC8qKiBQdWJsaXNoZXIgaGFuZGxlIG9mIGFuIGluc3RhbGxlZCBsaXN0aW5nOyBhYnNlbnQgZm9yIGFuIHVucXVhbGlmaWVkIHJlZmVyZW5jZS4gKi9cbiAgcmVhZG9ubHkgcHVibGlzaGVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgcHVibGlzaGVyIGhhbmRsZSBhcyBpdCBtYXkgYXBwZWFyIGluIGEgY29uc3RydWN0IGlkIG9yIGEga2V5OiBvbmx5XG4gKiBgW0EtWmEtejAtOV8tXWAgKGhhbmRsZXMgYWxyZWFkeSBhcmU7IHRoaXMgaXMgdGhlIGd1YXJhbnRlZSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYW5pdGl6ZVB1Ymxpc2hlcihwdWJsaXNoZXI6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBwdWJsaXNoZXIucmVwbGFjZSgvW15BLVphLXowLTlfLV0vZywgJy0nKTtcbn1cblxuLyoqXG4gKiBUaGUgY29uc3RydWN0LWlkIHNlZ21lbnQgb2YgYSBwbHVnaW4gc3RlcDogdGhlIGV4cGxpY2l0IGFsaWFzLCBlbHNlXG4gKiBgPHB1Ymxpc2hlcj4tPG5hbWU+YCBmb3IgYSBxdWFsaWZpZWQgcmVmZXJlbmNlLCBlbHNlIHRoZSBiYXJlIG5hbWUg4oCUIHNvIGFcbiAqIHN0ZXAgdXNpbmcgYGFjbWVgJ3MgYGxpbnRgIGFuZCBvbmUgdXNpbmcgdGhlIG9yZydzIG93biBgbGludGAgbmV2ZXIgY29sbGlkZSxcbiAqIHdoaWxlIGFuIHVucXVhbGlmaWVkIHN0ZXAga2VlcHMgdGhlIGlkIGl0IGFsd2F5cyBoYWQgKHJlbmFtaW5nIGl0IHdvdWxkIG1ha2VcbiAqIENsb3VkRm9ybWF0aW9uIHJlcGxhY2UgaXRzIENvZGVCdWlsZCBwcm9qZWN0KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsdWdpblN0ZXBJZEFsaWFzKHBsdWdpbjogUGx1Z2luUmVmSWRlbnRpdHkpOiBzdHJpbmcge1xuICAvLyBgPz9gLCBub3QgYHx8YDogYW4gZXhwbGljaXQgKGV2ZW4gZW1wdHkpIGFsaWFzIGtlZXBzIHRoZSBpZCBpdCBhbHdheXMgaGFkLlxuICByZXR1cm4gcGx1Z2luLmFsaWFzID8/IChwbHVnaW4ucHVibGlzaGVyID8gYCR7c2FuaXRpemVQdWJsaXNoZXIocGx1Z2luLnB1Ymxpc2hlcil9LSR7cGx1Z2luLm5hbWV9YCA6IHBsdWdpbi5uYW1lKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Plugin } from '@pipeline-builder/pipeline-data';
|
|
2
|
+
/**
|
|
3
|
+
* Unwrap a `/plugins/lookup` answer. The platform's success envelope is
|
|
4
|
+
* `{ success, statusCode, data: { plugin, warnings } }` (note the double
|
|
5
|
+
* nesting: `data.plugin`); `{ data: Plugin }`, `{ plugin }` and a bare Plugin
|
|
6
|
+
* are tolerated too. Returns the plugin (null when absent or nameless) and the
|
|
7
|
+
* lifecycle warning messages (deprecated / yanked-but-pinned) that ride beside it.
|
|
8
|
+
*
|
|
9
|
+
* Dependency-free (type-only imports) so the plugin-lookup Lambda can bundle it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function unwrapLookup(body: unknown): {
|
|
12
|
+
plugin: Plugin | null;
|
|
13
|
+
warnings: string[];
|
|
14
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Unwrap a `/plugins/lookup` answer. The platform's success envelope is
|
|
5
|
+
* `{ success, statusCode, data: { plugin, warnings } }` (note the double
|
|
6
|
+
* nesting: `data.plugin`); `{ data: Plugin }`, `{ plugin }` and a bare Plugin
|
|
7
|
+
* are tolerated too. Returns the plugin (null when absent or nameless) and the
|
|
8
|
+
* lifecycle warning messages (deprecated / yanked-but-pinned) that ride beside it.
|
|
9
|
+
*
|
|
10
|
+
* Dependency-free (type-only imports) so the plugin-lookup Lambda can bundle it.
|
|
11
|
+
*/
|
|
12
|
+
export function unwrapLookup(body) {
|
|
13
|
+
if (!body || typeof body !== 'object')
|
|
14
|
+
return { plugin: null, warnings: [] };
|
|
15
|
+
const inner = body.data;
|
|
16
|
+
const container = (inner && typeof inner === 'object' ? inner : body);
|
|
17
|
+
const candidate = container.plugin ?? container;
|
|
18
|
+
const plugin = candidate && typeof candidate === 'object' && typeof candidate.name === 'string'
|
|
19
|
+
&& candidate.name.length > 0
|
|
20
|
+
? candidate
|
|
21
|
+
: null;
|
|
22
|
+
const warnings = Array.isArray(container.warnings)
|
|
23
|
+
? container.warnings
|
|
24
|
+
.map((w) => (w && typeof w === 'object' ? w.message : undefined))
|
|
25
|
+
.filter((m) => typeof m === 'string' && m.length > 0)
|
|
26
|
+
: [];
|
|
27
|
+
return { plugin, warnings };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWxvb2t1cC1lbnZlbG9wZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL3BsdWdpbi1sb29rdXAtZW52ZWxvcGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUl0Qzs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsSUFBYTtJQUN4QyxJQUFJLENBQUMsSUFBSSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVE7UUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDN0UsTUFBTSxLQUFLLEdBQUksSUFBMkIsQ0FBQyxJQUFJLENBQUM7SUFDaEQsTUFBTSxTQUFTLEdBQUcsQ0FBQyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBNkMsQ0FBQztJQUNsSCxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQztJQUNoRCxNQUFNLE1BQU0sR0FBRyxTQUFTLElBQUksT0FBTyxTQUFTLEtBQUssUUFBUSxJQUFJLE9BQVEsU0FBZ0MsQ0FBQyxJQUFJLEtBQUssUUFBUTtXQUNqSCxTQUE4QixDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUNsRCxDQUFDLENBQUMsU0FBbUI7UUFDckIsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNULE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztRQUNoRCxDQUFDLENBQUMsU0FBUyxDQUFDLFFBQVE7YUFDakIsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFFLENBQTJCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUMzRixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQWUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztRQUNwRSxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ1AsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHsgUGx1Z2luIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvcGlwZWxpbmUtZGF0YSc7XG5cbi8qKlxuICogVW53cmFwIGEgYC9wbHVnaW5zL2xvb2t1cGAgYW5zd2VyLiBUaGUgcGxhdGZvcm0ncyBzdWNjZXNzIGVudmVsb3BlIGlzXG4gKiBgeyBzdWNjZXNzLCBzdGF0dXNDb2RlLCBkYXRhOiB7IHBsdWdpbiwgd2FybmluZ3MgfSB9YCAobm90ZSB0aGUgZG91YmxlXG4gKiBuZXN0aW5nOiBgZGF0YS5wbHVnaW5gKTsgYHsgZGF0YTogUGx1Z2luIH1gLCBgeyBwbHVnaW4gfWAgYW5kIGEgYmFyZSBQbHVnaW5cbiAqIGFyZSB0b2xlcmF0ZWQgdG9vLiBSZXR1cm5zIHRoZSBwbHVnaW4gKG51bGwgd2hlbiBhYnNlbnQgb3IgbmFtZWxlc3MpIGFuZCB0aGVcbiAqIGxpZmVjeWNsZSB3YXJuaW5nIG1lc3NhZ2VzIChkZXByZWNhdGVkIC8geWFua2VkLWJ1dC1waW5uZWQpIHRoYXQgcmlkZSBiZXNpZGUgaXQuXG4gKlxuICogRGVwZW5kZW5jeS1mcmVlICh0eXBlLW9ubHkgaW1wb3J0cykgc28gdGhlIHBsdWdpbi1sb29rdXAgTGFtYmRhIGNhbiBidW5kbGUgaXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bndyYXBMb29rdXAoYm9keTogdW5rbm93bik6IHsgcGx1Z2luOiBQbHVnaW4gfCBudWxsOyB3YXJuaW5nczogc3RyaW5nW10gfSB7XG4gIGlmICghYm9keSB8fCB0eXBlb2YgYm9keSAhPT0gJ29iamVjdCcpIHJldHVybiB7IHBsdWdpbjogbnVsbCwgd2FybmluZ3M6IFtdIH07XG4gIGNvbnN0IGlubmVyID0gKGJvZHkgYXMgeyBkYXRhPzogdW5rbm93biB9KS5kYXRhO1xuICBjb25zdCBjb250YWluZXIgPSAoaW5uZXIgJiYgdHlwZW9mIGlubmVyID09PSAnb2JqZWN0JyA/IGlubmVyIDogYm9keSkgYXMgeyBwbHVnaW4/OiB1bmtub3duOyB3YXJuaW5ncz86IHVua25vd24gfTtcbiAgY29uc3QgY2FuZGlkYXRlID0gY29udGFpbmVyLnBsdWdpbiA/PyBjb250YWluZXI7XG4gIGNvbnN0IHBsdWdpbiA9IGNhbmRpZGF0ZSAmJiB0eXBlb2YgY2FuZGlkYXRlID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgKGNhbmRpZGF0ZSBhcyB7IG5hbWU/OiB1bmtub3duIH0pLm5hbWUgPT09ICdzdHJpbmcnXG4gICAgJiYgKGNhbmRpZGF0ZSBhcyB7IG5hbWU6IHN0cmluZyB9KS5uYW1lLmxlbmd0aCA+IDBcbiAgICA/IGNhbmRpZGF0ZSBhcyBQbHVnaW5cbiAgICA6IG51bGw7XG4gIGNvbnN0IHdhcm5pbmdzID0gQXJyYXkuaXNBcnJheShjb250YWluZXIud2FybmluZ3MpXG4gICAgPyBjb250YWluZXIud2FybmluZ3NcbiAgICAgIC5tYXAoKHcpID0+ICh3ICYmIHR5cGVvZiB3ID09PSAnb2JqZWN0JyA/ICh3IGFzIHsgbWVzc2FnZT86IHVua25vd24gfSkubWVzc2FnZSA6IHVuZGVmaW5lZCkpXG4gICAgICAuZmlsdGVyKChtKTogbSBpcyBzdHJpbmcgPT4gdHlwZW9mIG0gPT09ICdzdHJpbmcnICYmIG0ubGVuZ3RoID4gMClcbiAgICA6IFtdO1xuICByZXR1cm4geyBwbHVnaW4sIHdhcm5pbmdzIH07XG59XG4iXX0=
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File the synth app writes the manifest to, inside the cloud assembly
|
|
3
|
+
* directory (`cdk deploy --output=<dir>`). The CLI reads it back after a
|
|
4
|
+
* successful deploy and forwards it on the registry POST.
|
|
5
|
+
*/
|
|
6
|
+
export declare const STEP_MANIFEST_FILE = "pb-step-manifest.json";
|
|
7
|
+
/**
|
|
8
|
+
* `id` of every synthesized placeholder plugin (PluginLookup `fallback()` /
|
|
9
|
+
* `bootstrap()`) — a record standing in for a lookup that could not resolve at
|
|
10
|
+
* synth. Never a real `plugins` row, so the step manifest never records it.
|
|
11
|
+
*/
|
|
12
|
+
export declare const PLACEHOLDER_PLUGIN_ID = "00000000-0000-0000-0000-000000000000";
|
|
13
|
+
/**
|
|
14
|
+
* One manifest entry as the synth records it. Carries the resolved plugin
|
|
15
|
+
* record's id so the pipeline service can re-resolve the authoritative
|
|
16
|
+
* name/version/digest/owner itself — the CLI's claim is never trusted for
|
|
17
|
+
* anything that feeds cross-org stats (publisher, verified use).
|
|
18
|
+
*/
|
|
19
|
+
export interface StepManifestEntry {
|
|
20
|
+
/** CodePipeline stage name, as the built pipeline names it. */
|
|
21
|
+
readonly stageName: string;
|
|
22
|
+
/** CodePipeline action name, as the built pipeline names it. */
|
|
23
|
+
readonly actionName: string;
|
|
24
|
+
/** `plugins.id` of the resolved plugin record. */
|
|
25
|
+
readonly pluginId: string;
|
|
26
|
+
readonly pluginName: string;
|
|
27
|
+
readonly pluginVersion: string;
|
|
28
|
+
/** Signed image digest the step is pinned to; null for image-less plugins. */
|
|
29
|
+
readonly imageDigest: string | null;
|
|
30
|
+
}
|
|
31
|
+
/** The plugin fields {@link pluginImageRepository} reads. */
|
|
32
|
+
export interface PluginImageRef {
|
|
33
|
+
readonly orgId: string;
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly buildType?: string | null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Registry repository an org-owned plugin ROW's image lives at
|
|
39
|
+
* (`<namespace>/<name>`, no host, no digest): the system org's under
|
|
40
|
+
* `system/`, a tenant's under `org-<orgId>/`. Must match the push side
|
|
41
|
+
* (api/plugin `pluginUri`). Returns null for a `metadata_only` plugin.
|
|
42
|
+
*
|
|
43
|
+
* Only for rows the caller's org resolves as its OWN (or its parent's): the
|
|
44
|
+
* plugin lookup stamps it as the record's `imageRepository`. A listed plugin's
|
|
45
|
+
* repository is its listing version's `public/<publisher>/<name>` copy —
|
|
46
|
+
* synth never derives a repository itself.
|
|
47
|
+
*/
|
|
48
|
+
export declare function pluginImageRepository(plugin: PluginImageRef): string | null;
|
|
49
|
+
/** A plugin image repository lookup may return: `public/<publisher>/<name>`, `org-<id>/<name>` or `system/<name>`. */
|
|
50
|
+
export declare const PLUGIN_IMAGE_REPOSITORY_RE: RegExp;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Step manifest: which plugin each CodePipeline action
|
|
5
|
+
* of a deployed pipeline runs. CDK-free half — the shapes and helpers shared by
|
|
6
|
+
* the synth (which records it, see `pipeline/step-manifest-recorder.ts`), the
|
|
7
|
+
* CLI (which ships it with the registry registration) and the pipeline service
|
|
8
|
+
* (which validates and stores it in `pipeline_step_manifests`).
|
|
9
|
+
*
|
|
10
|
+
* Event ingest joins `pipeline_events` on (pipeline_id, stage_name,
|
|
11
|
+
* action_name), so `stageName`/`actionName` here are read off the BUILT
|
|
12
|
+
* CodePipeline, never recomputed from our own ids — they are exactly the names
|
|
13
|
+
* CodePipeline state-change events report.
|
|
14
|
+
*/
|
|
15
|
+
import { SYSTEM_ORG_ID } from '@pipeline-builder/api-core';
|
|
16
|
+
/**
|
|
17
|
+
* File the synth app writes the manifest to, inside the cloud assembly
|
|
18
|
+
* directory (`cdk deploy --output=<dir>`). The CLI reads it back after a
|
|
19
|
+
* successful deploy and forwards it on the registry POST.
|
|
20
|
+
*/
|
|
21
|
+
export const STEP_MANIFEST_FILE = 'pb-step-manifest.json';
|
|
22
|
+
/**
|
|
23
|
+
* `id` of every synthesized placeholder plugin (PluginLookup `fallback()` /
|
|
24
|
+
* `bootstrap()`) — a record standing in for a lookup that could not resolve at
|
|
25
|
+
* synth. Never a real `plugins` row, so the step manifest never records it.
|
|
26
|
+
*/
|
|
27
|
+
export const PLACEHOLDER_PLUGIN_ID = '00000000-0000-0000-0000-000000000000';
|
|
28
|
+
/**
|
|
29
|
+
* Registry repository an org-owned plugin ROW's image lives at
|
|
30
|
+
* (`<namespace>/<name>`, no host, no digest): the system org's under
|
|
31
|
+
* `system/`, a tenant's under `org-<orgId>/`. Must match the push side
|
|
32
|
+
* (api/plugin `pluginUri`). Returns null for a `metadata_only` plugin.
|
|
33
|
+
*
|
|
34
|
+
* Only for rows the caller's org resolves as its OWN (or its parent's): the
|
|
35
|
+
* plugin lookup stamps it as the record's `imageRepository`. A listed plugin's
|
|
36
|
+
* repository is its listing version's `public/<publisher>/<name>` copy —
|
|
37
|
+
* synth never derives a repository itself.
|
|
38
|
+
*/
|
|
39
|
+
export function pluginImageRepository(plugin) {
|
|
40
|
+
if (plugin.buildType === 'metadata_only')
|
|
41
|
+
return null;
|
|
42
|
+
const namespace = plugin.orgId === SYSTEM_ORG_ID ? 'system' : `org-${plugin.orgId}`;
|
|
43
|
+
return `${namespace}/${plugin.name}`;
|
|
44
|
+
}
|
|
45
|
+
/** A plugin image repository lookup may return: `public/<publisher>/<name>`, `org-<id>/<name>` or `system/<name>`. */
|
|
46
|
+
export const PLUGIN_IMAGE_REPOSITORY_RE = /^(?:public\/[a-z0-9]+(?:-[a-z0-9]+)*|org-[a-z0-9][a-z0-9-]*|system)\/[a-z0-9][a-z0-9._-]*$/;
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1tYW5pZmVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL3N0ZXAtbWFuaWZlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7R0FXRztBQUVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUUzRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsdUJBQXVCLENBQUM7QUFFMUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLHNDQUFzQyxDQUFDO0FBNEI1RTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQixDQUFDLE1BQXNCO0lBQzFELElBQUksTUFBTSxDQUFDLFNBQVMsS0FBSyxlQUFlO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDdEQsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLEtBQUssS0FBSyxhQUFhLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDcEYsT0FBTyxHQUFHLFNBQVMsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDdkMsQ0FBQztBQUVELHNIQUFzSDtBQUN0SCxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyw0RkFBNEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFN0ZXAgbWFuaWZlc3Q6IHdoaWNoIHBsdWdpbiBlYWNoIENvZGVQaXBlbGluZSBhY3Rpb25cbiAqIG9mIGEgZGVwbG95ZWQgcGlwZWxpbmUgcnVucy4gQ0RLLWZyZWUgaGFsZiDigJQgdGhlIHNoYXBlcyBhbmQgaGVscGVycyBzaGFyZWQgYnlcbiAqIHRoZSBzeW50aCAod2hpY2ggcmVjb3JkcyBpdCwgc2VlIGBwaXBlbGluZS9zdGVwLW1hbmlmZXN0LXJlY29yZGVyLnRzYCksIHRoZVxuICogQ0xJICh3aGljaCBzaGlwcyBpdCB3aXRoIHRoZSByZWdpc3RyeSByZWdpc3RyYXRpb24pIGFuZCB0aGUgcGlwZWxpbmUgc2VydmljZVxuICogKHdoaWNoIHZhbGlkYXRlcyBhbmQgc3RvcmVzIGl0IGluIGBwaXBlbGluZV9zdGVwX21hbmlmZXN0c2ApLlxuICpcbiAqIEV2ZW50IGluZ2VzdCBqb2lucyBgcGlwZWxpbmVfZXZlbnRzYCBvbiAocGlwZWxpbmVfaWQsIHN0YWdlX25hbWUsXG4gKiBhY3Rpb25fbmFtZSksIHNvIGBzdGFnZU5hbWVgL2BhY3Rpb25OYW1lYCBoZXJlIGFyZSByZWFkIG9mZiB0aGUgQlVJTFRcbiAqIENvZGVQaXBlbGluZSwgbmV2ZXIgcmVjb21wdXRlZCBmcm9tIG91ciBvd24gaWRzIOKAlCB0aGV5IGFyZSBleGFjdGx5IHRoZSBuYW1lc1xuICogQ29kZVBpcGVsaW5lIHN0YXRlLWNoYW5nZSBldmVudHMgcmVwb3J0LlxuICovXG5cbmltcG9ydCB7IFNZU1RFTV9PUkdfSUQgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5cbi8qKlxuICogRmlsZSB0aGUgc3ludGggYXBwIHdyaXRlcyB0aGUgbWFuaWZlc3QgdG8sIGluc2lkZSB0aGUgY2xvdWQgYXNzZW1ibHlcbiAqIGRpcmVjdG9yeSAoYGNkayBkZXBsb3kgLS1vdXRwdXQ9PGRpcj5gKS4gVGhlIENMSSByZWFkcyBpdCBiYWNrIGFmdGVyIGFcbiAqIHN1Y2Nlc3NmdWwgZGVwbG95IGFuZCBmb3J3YXJkcyBpdCBvbiB0aGUgcmVnaXN0cnkgUE9TVC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNURVBfTUFOSUZFU1RfRklMRSA9ICdwYi1zdGVwLW1hbmlmZXN0Lmpzb24nO1xuXG4vKipcbiAqIGBpZGAgb2YgZXZlcnkgc3ludGhlc2l6ZWQgcGxhY2Vob2xkZXIgcGx1Z2luIChQbHVnaW5Mb29rdXAgYGZhbGxiYWNrKClgIC9cbiAqIGBib290c3RyYXAoKWApIOKAlCBhIHJlY29yZCBzdGFuZGluZyBpbiBmb3IgYSBsb29rdXAgdGhhdCBjb3VsZCBub3QgcmVzb2x2ZSBhdFxuICogc3ludGguIE5ldmVyIGEgcmVhbCBgcGx1Z2luc2Agcm93LCBzbyB0aGUgc3RlcCBtYW5pZmVzdCBuZXZlciByZWNvcmRzIGl0LlxuICovXG5leHBvcnQgY29uc3QgUExBQ0VIT0xERVJfUExVR0lOX0lEID0gJzAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCc7XG5cbi8qKlxuICogT25lIG1hbmlmZXN0IGVudHJ5IGFzIHRoZSBzeW50aCByZWNvcmRzIGl0LiBDYXJyaWVzIHRoZSByZXNvbHZlZCBwbHVnaW5cbiAqIHJlY29yZCdzIGlkIHNvIHRoZSBwaXBlbGluZSBzZXJ2aWNlIGNhbiByZS1yZXNvbHZlIHRoZSBhdXRob3JpdGF0aXZlXG4gKiBuYW1lL3ZlcnNpb24vZGlnZXN0L293bmVyIGl0c2VsZiDigJQgdGhlIENMSSdzIGNsYWltIGlzIG5ldmVyIHRydXN0ZWQgZm9yXG4gKiBhbnl0aGluZyB0aGF0IGZlZWRzIGNyb3NzLW9yZyBzdGF0cyAocHVibGlzaGVyLCB2ZXJpZmllZCB1c2UpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0ZXBNYW5pZmVzdEVudHJ5IHtcbiAgLyoqIENvZGVQaXBlbGluZSBzdGFnZSBuYW1lLCBhcyB0aGUgYnVpbHQgcGlwZWxpbmUgbmFtZXMgaXQuICovXG4gIHJlYWRvbmx5IHN0YWdlTmFtZTogc3RyaW5nO1xuICAvKiogQ29kZVBpcGVsaW5lIGFjdGlvbiBuYW1lLCBhcyB0aGUgYnVpbHQgcGlwZWxpbmUgbmFtZXMgaXQuICovXG4gIHJlYWRvbmx5IGFjdGlvbk5hbWU6IHN0cmluZztcbiAgLyoqIGBwbHVnaW5zLmlkYCBvZiB0aGUgcmVzb2x2ZWQgcGx1Z2luIHJlY29yZC4gKi9cbiAgcmVhZG9ubHkgcGx1Z2luSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcGx1Z2luTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBwbHVnaW5WZXJzaW9uOiBzdHJpbmc7XG4gIC8qKiBTaWduZWQgaW1hZ2UgZGlnZXN0IHRoZSBzdGVwIGlzIHBpbm5lZCB0bzsgbnVsbCBmb3IgaW1hZ2UtbGVzcyBwbHVnaW5zLiAqL1xuICByZWFkb25seSBpbWFnZURpZ2VzdDogc3RyaW5nIHwgbnVsbDtcbn1cblxuLyoqIFRoZSBwbHVnaW4gZmllbGRzIHtAbGluayBwbHVnaW5JbWFnZVJlcG9zaXRvcnl9IHJlYWRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5JbWFnZVJlZiB7XG4gIHJlYWRvbmx5IG9yZ0lkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgYnVpbGRUeXBlPzogc3RyaW5nIHwgbnVsbDtcbn1cblxuLyoqXG4gKiBSZWdpc3RyeSByZXBvc2l0b3J5IGFuIG9yZy1vd25lZCBwbHVnaW4gUk9XJ3MgaW1hZ2UgbGl2ZXMgYXRcbiAqIChgPG5hbWVzcGFjZT4vPG5hbWU+YCwgbm8gaG9zdCwgbm8gZGlnZXN0KTogdGhlIHN5c3RlbSBvcmcncyB1bmRlclxuICogYHN5c3RlbS9gLCBhIHRlbmFudCdzIHVuZGVyIGBvcmctPG9yZ0lkPi9gLiBNdXN0IG1hdGNoIHRoZSBwdXNoIHNpZGVcbiAqIChhcGkvcGx1Z2luIGBwbHVnaW5VcmlgKS4gUmV0dXJucyBudWxsIGZvciBhIGBtZXRhZGF0YV9vbmx5YCBwbHVnaW4uXG4gKlxuICogT25seSBmb3Igcm93cyB0aGUgY2FsbGVyJ3Mgb3JnIHJlc29sdmVzIGFzIGl0cyBPV04gKG9yIGl0cyBwYXJlbnQncyk6IHRoZVxuICogcGx1Z2luIGxvb2t1cCBzdGFtcHMgaXQgYXMgdGhlIHJlY29yZCdzIGBpbWFnZVJlcG9zaXRvcnlgLiBBIGxpc3RlZCBwbHVnaW4nc1xuICogcmVwb3NpdG9yeSBpcyBpdHMgbGlzdGluZyB2ZXJzaW9uJ3MgYHB1YmxpYy88cHVibGlzaGVyPi88bmFtZT5gIGNvcHkg4oCUXG4gKiBzeW50aCBuZXZlciBkZXJpdmVzIGEgcmVwb3NpdG9yeSBpdHNlbGYuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwbHVnaW5JbWFnZVJlcG9zaXRvcnkocGx1Z2luOiBQbHVnaW5JbWFnZVJlZik6IHN0cmluZyB8IG51bGwge1xuICBpZiAocGx1Z2luLmJ1aWxkVHlwZSA9PT0gJ21ldGFkYXRhX29ubHknKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbmFtZXNwYWNlID0gcGx1Z2luLm9yZ0lkID09PSBTWVNURU1fT1JHX0lEID8gJ3N5c3RlbScgOiBgb3JnLSR7cGx1Z2luLm9yZ0lkfWA7XG4gIHJldHVybiBgJHtuYW1lc3BhY2V9LyR7cGx1Z2luLm5hbWV9YDtcbn1cblxuLyoqIEEgcGx1Z2luIGltYWdlIHJlcG9zaXRvcnkgbG9va3VwIG1heSByZXR1cm46IGBwdWJsaWMvPHB1Ymxpc2hlcj4vPG5hbWU+YCwgYG9yZy08aWQ+LzxuYW1lPmAgb3IgYHN5c3RlbS88bmFtZT5gLiAqL1xuZXhwb3J0IGNvbnN0IFBMVUdJTl9JTUFHRV9SRVBPU0lUT1JZX1JFID0gL14oPzpwdWJsaWNcXC9bYS16MC05XSsoPzotW2EtejAtOV0rKSp8b3JnLVthLXowLTldW2EtejAtOS1dKnxzeXN0ZW0pXFwvW2EtejAtOV1bYS16MC05Ll8tXSokLztcbiJdfQ==
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { SecretsManagerClient } from '@aws-sdk/client-secrets-manager';
|
|
2
|
+
/**
|
|
3
|
+
* The platform credential a deployed Lambda holds: an opaque service-account key
|
|
4
|
+
* (`pb_sa_…`), stored in the `password` field of the Secrets Manager secret that
|
|
5
|
+
* `pipeline-manager infra store-token` writes. `password` stays the canonical
|
|
6
|
+
* field because CodeBuild's `secretsManagerCredentials` reads the same one.
|
|
7
|
+
*
|
|
8
|
+
* Dependency-free apart from the Secrets Manager client so every Lambda bundle
|
|
9
|
+
* can import it without dragging in aws-cdk-lib.
|
|
10
|
+
*/
|
|
11
|
+
/** Access-key prefixes platform issues. A stored JWT is NOT one of these. */
|
|
12
|
+
export declare const ACCESS_KEY_PREFIXES: readonly string[];
|
|
13
|
+
/** True for an HTTP status that means "this credential was refused". */
|
|
14
|
+
export declare function isCredentialRefusal(status: number | undefined): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Refuse anything that is not an opaque access key, naming where it came from.
|
|
17
|
+
* A stored JWT would otherwise surface much later as an opaque 401 from the API,
|
|
18
|
+
* several layers away from the secret an operator has to fix.
|
|
19
|
+
*/
|
|
20
|
+
export declare function assertAccessKey(value: string, source: string): void;
|
|
21
|
+
/** Read and parse a Secrets Manager secret holding a JSON credential record. */
|
|
22
|
+
export declare function readCredentialSecret<T extends Record<string, unknown>>(secretName: string, client?: Pick<SecretsManagerClient, 'send'>): Promise<T>;
|
|
23
|
+
/** Read the `pb_sa_…` key from a credential secret, refusing a missing or non-key value. */
|
|
24
|
+
export declare function readAccessKeyFromSecret(secretName: string): Promise<string>;
|
|
25
|
+
export interface PlatformCredential {
|
|
26
|
+
/** The cached key, read from the secret on first use (or after {@link invalidate}). */
|
|
27
|
+
getKey(): Promise<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Forget the cached key after the API refused it (401/403). The token-renew
|
|
30
|
+
* Lambda rotates the secret and then revokes the predecessor, so a warm
|
|
31
|
+
* container that kept its cached key would present the retired one forever.
|
|
32
|
+
* The next {@link getKey} re-reads the secret and picks up the replacement.
|
|
33
|
+
*/
|
|
34
|
+
invalidate(): void;
|
|
35
|
+
/** Forget everything, including an env-provided key (tests). */
|
|
36
|
+
reset(): void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A per-container cached platform credential. `envKeyVar` names an optional env
|
|
40
|
+
* var holding the key directly; an env-provided key cannot change without a new
|
|
41
|
+
* container, so {@link PlatformCredential.invalidate} keeps it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createPlatformCredential(opts: {
|
|
44
|
+
/** The secret name, or a getter read at first use (env set after module load). */
|
|
45
|
+
secretName?: string | (() => string | undefined);
|
|
46
|
+
envKeyVar?: string;
|
|
47
|
+
}): PlatformCredential;
|