@fjall/util 6.0.0 → 7.0.0
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/dist/.build-source-hash +10 -9
- package/dist/.minified +1 -1
- package/dist/capacityIdentity.d.ts +77 -0
- package/dist/capacityIdentity.js +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/manifest/index.d.ts +2 -2
- package/dist/manifest/index.js +1 -1
- package/dist/manifest/io.d.ts +46 -0
- package/dist/manifest/io.js +1 -1
- package/dist/manifest/schemas.d.ts +40 -1
- package/dist/manifest/schemas.js +1 -1
- package/package.json +2 -3
package/dist/.build-source-hash
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"package.json",
|
|
10
10
|
"tsconfig.json"
|
|
11
11
|
],
|
|
12
|
-
"hash": "
|
|
12
|
+
"hash": "3de34c201d7566360e7f623c5429a95610accc983fd1057113844a0d2e1a41d0",
|
|
13
13
|
"files": {
|
|
14
14
|
"src/async/concurrency.ts": "3c7ebe0222a720f9",
|
|
15
15
|
"src/async/singleton.ts": "7bcc21b0fb920561",
|
|
@@ -26,9 +26,10 @@
|
|
|
26
26
|
"src/aws/maskFailureAnalysis.ts": "ae11250412cd6fd8",
|
|
27
27
|
"src/aws/monitoringRole.ts": "70c8b5947dc9138d",
|
|
28
28
|
"src/buildConcurrency.ts": "1804e76ddc4f8216",
|
|
29
|
+
"src/capacityIdentity.ts": "9e59bfc92a5ba361",
|
|
29
30
|
"src/cdkTmpdirCleanup.ts": "4574b3f10e3ab0f9",
|
|
30
31
|
"src/cfn/physicalNameProperties.ts": "35d3c6f28079c593",
|
|
31
|
-
"src/config.ts": "
|
|
32
|
+
"src/config.ts": "11c577414a91c542",
|
|
32
33
|
"src/constructMap.ts": "b81fc8e90015467f",
|
|
33
34
|
"src/deploy/approvalTokenOutput.ts": "4be7b52825d88a37",
|
|
34
35
|
"src/devSubstrate/entrypoint.ts": "0526b88258174aa6",
|
|
@@ -59,7 +60,7 @@
|
|
|
59
60
|
"src/errorUtils.ts": "c601f2905c74b8d0",
|
|
60
61
|
"src/fsHelpers.ts": "0869d9739d523572",
|
|
61
62
|
"src/fsScan.ts": "feb187758481443f",
|
|
62
|
-
"src/index.ts": "
|
|
63
|
+
"src/index.ts": "80f518c9eb6f13e6",
|
|
63
64
|
"src/infra/backupVault.ts": "661678a6dfb0b648",
|
|
64
65
|
"src/infra/connectionsWire.ts": "125c099da0e17ac1",
|
|
65
66
|
"src/infra/deployArtefacts.ts": "235ac21dd3ccf0b2",
|
|
@@ -70,9 +71,9 @@
|
|
|
70
71
|
"src/infra/tokenScopes.ts": "88c6a1f0da3fa491",
|
|
71
72
|
"src/insights/computePatternFingerprint.ts": "b5d3a4704f42cc1f",
|
|
72
73
|
"src/logger.ts": "865ec4ec62a9a588",
|
|
73
|
-
"src/manifest/index.ts": "
|
|
74
|
-
"src/manifest/io.ts": "
|
|
75
|
-
"src/manifest/schemas.ts": "
|
|
74
|
+
"src/manifest/index.ts": "b03afdad45154d67",
|
|
75
|
+
"src/manifest/io.ts": "681888437b87c9d3",
|
|
76
|
+
"src/manifest/schemas.ts": "8e1f739cb68d6938",
|
|
76
77
|
"src/mcpProtocol/index.ts": "55df3209915a5043",
|
|
77
78
|
"src/migration/clickhouseSqlUsers.ts": "c916e148367715bb",
|
|
78
79
|
"src/migration/compareSchemaVersion.ts": "1c9247e722ec5d5b",
|
|
@@ -101,9 +102,9 @@
|
|
|
101
102
|
"src/securityHelpers.ts": "acbf209255468ff4",
|
|
102
103
|
"src/targets.ts": "126280f0a5762e21",
|
|
103
104
|
"../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
|
|
104
|
-
"package.json": "
|
|
105
|
+
"package.json": "0c25e937fdaa1004",
|
|
105
106
|
"tsconfig.json": "db759831ad95f396"
|
|
106
107
|
},
|
|
107
|
-
"outputHash": "
|
|
108
|
-
"outputFileCount":
|
|
108
|
+
"outputHash": "166b490f9c6abdcc3c873063892822255ad80ee8bb947828b5e48920cf78a41c",
|
|
109
|
+
"outputFileCount": 187
|
|
109
110
|
}
|
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
93 files minified at 2026-08-03T01:43:40.198Z
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Stable capacity identity — the shared vocabulary for capacity SLOTS and
|
|
4
|
+
* their identity ANCHORS (design
|
|
5
|
+
* `aiDocs/designs/2026-08-01-stable-capacity-identity-and-rename-safe-deploys.md`).
|
|
6
|
+
*
|
|
7
|
+
* A capacity slot is the operator-chosen, config-independent name for one EC2
|
|
8
|
+
* auto-scaling group within a cluster ("primary", "clickhouse-data"). Its
|
|
9
|
+
* anchor is the PascalCase token every CloudFormation identity surface derives
|
|
10
|
+
* from (logical-ID prefixes, the physical service name, the launch-template
|
|
11
|
+
* name). Pins freeze a deployed pre-6.0 stack's config-derived anchor so a
|
|
12
|
+
* re-synth reproduces the deployed identity byte-for-byte instead of renaming
|
|
13
|
+
* every stateful resource.
|
|
14
|
+
*
|
|
15
|
+
* Three shapes share this module so the producer and every consumer stay on
|
|
16
|
+
* one contract (code-quality § coupled values):
|
|
17
|
+
* - the PIN — identity facts captured from a deployed stack;
|
|
18
|
+
* - the WIRE shape — what the deploy engine injects as CDK context and the
|
|
19
|
+
* constructs Zod-validate (`fjall:capacityIdentity`);
|
|
20
|
+
* - the CONFIG shape — the target-keyed `capacityIdentity` section of
|
|
21
|
+
* fjall-config.json the engine projects the wire shape from.
|
|
22
|
+
*/
|
|
23
|
+
/** Slot-name grammar: lowercase kebab, letter first (`web`, `clickhouse-data`). */
|
|
24
|
+
export declare const CAPACITY_SLOT_PATTERN: RegExp;
|
|
25
|
+
export declare const CAPACITY_SLOT_MAX_LENGTH = 64;
|
|
26
|
+
export declare const DEFAULT_CAPACITY_SLOT = "primary";
|
|
27
|
+
/**
|
|
28
|
+
* Anchor grammar: alphanumeric, letter first — must be a valid CloudFormation
|
|
29
|
+
* logical-ID prefix AND a valid segment of a physical service name. Legacy
|
|
30
|
+
* pre-6.0 anchors (alphanumeric-stripped `getEc2ConfigKey` output such as
|
|
31
|
+
* `m7gmediumARMnowppdvdevxvdf80useast2aazuseast2a`) satisfy this by
|
|
32
|
+
* construction.
|
|
33
|
+
*/
|
|
34
|
+
export declare const CAPACITY_ANCHOR_PATTERN: RegExp;
|
|
35
|
+
export declare const CAPACITY_ANCHOR_MAX_LENGTH = 128;
|
|
36
|
+
/** CDK context key the deploy engine injects the wire shape under. */
|
|
37
|
+
export declare const CAPACITY_IDENTITY_CONTEXT_KEY = "fjall:capacityIdentity";
|
|
38
|
+
/**
|
|
39
|
+
* One frozen slot identity, captured from the deployed stack at pin time.
|
|
40
|
+
* Kept in fjall-config.json for the stack's whole life — deleting a pin
|
|
41
|
+
* renames (replaces) every stateful resource in the slot on the next deploy.
|
|
42
|
+
*/
|
|
43
|
+
export declare const CapacityIdentityPinSchema: z.ZodObject<{
|
|
44
|
+
legacyAnchor: z.ZodString;
|
|
45
|
+
legacyOwnerId: z.ZodOptional<z.ZodString>;
|
|
46
|
+
legacySgDescription: z.ZodOptional<z.ZodString>;
|
|
47
|
+
}, z.core.$strict>;
|
|
48
|
+
export type CapacityIdentityPin = z.infer<typeof CapacityIdentityPinSchema>;
|
|
49
|
+
/**
|
|
50
|
+
* Wire shape injected as the `fjall:capacityIdentity` CDK context value:
|
|
51
|
+
* `{ <appName>: { <slot>: pin } }` — already projected to the current deploy
|
|
52
|
+
* target. Constructs route by the manifest appName plus the resolved slot.
|
|
53
|
+
*/
|
|
54
|
+
export declare const CapacityIdentityWireSchema: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
55
|
+
legacyAnchor: z.ZodString;
|
|
56
|
+
legacyOwnerId: z.ZodOptional<z.ZodString>;
|
|
57
|
+
legacySgDescription: z.ZodOptional<z.ZodString>;
|
|
58
|
+
}, z.core.$strict>>>;
|
|
59
|
+
export type CapacityIdentityWire = z.infer<typeof CapacityIdentityWireSchema>;
|
|
60
|
+
/**
|
|
61
|
+
* Config-file shape (`capacityIdentity` in fjall-config.json):
|
|
62
|
+
* `{ <appName>: { <targetName>: { <slot>: pin } } }`. Target-keyed because
|
|
63
|
+
* the same app deploys to several targets, each with its own deployed
|
|
64
|
+
* identity history.
|
|
65
|
+
*/
|
|
66
|
+
export declare const CapacityIdentityConfigSchema: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
67
|
+
legacyAnchor: z.ZodString;
|
|
68
|
+
legacyOwnerId: z.ZodOptional<z.ZodString>;
|
|
69
|
+
legacySgDescription: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}, z.core.$strict>>>>;
|
|
71
|
+
export type CapacityIdentityConfig = z.infer<typeof CapacityIdentityConfigSchema>;
|
|
72
|
+
/**
|
|
73
|
+
* Project the config-file shape onto ONE deploy target, producing the wire
|
|
74
|
+
* shape. Apps with no pins for the target are omitted; returns `undefined`
|
|
75
|
+
* when nothing survives so callers can skip context injection entirely.
|
|
76
|
+
*/
|
|
77
|
+
export declare function projectCapacityIdentityToTarget(config: CapacityIdentityConfig | undefined, targetName: string): CapacityIdentityWire | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.defineProperty;var o=(e,n)=>p(e,"name",{value:n,configurable:!0});import{z as t}from"zod";const C=/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,g=64,y="primary",A=/^[A-Za-z][A-Za-z0-9]*$/,T=128,_="fjall:capacityIdentity",c=t.object({legacyAnchor:t.string().min(1).max(T).regex(A,"legacyAnchor must be alphanumeric and start with a letter"),legacyOwnerId:t.string().min(1).max(512).optional(),legacySgDescription:t.string().min(1).max(255).optional()}).strict(),x=t.record(t.string().min(1),t.record(t.string().min(1),c)),I=t.record(t.string().min(1),t.record(t.string().min(1),t.record(t.string().min(1),c)));function l(e,n){if(e===void 0)return;const r={};for(const[a,s]of Object.entries(e)){const i=s[n];i===void 0||Object.keys(i).length===0||(r[a]=i)}return Object.keys(r).length===0?void 0:r}o(l,"projectCapacityIdentityToTarget");export{T as CAPACITY_ANCHOR_MAX_LENGTH,A as CAPACITY_ANCHOR_PATTERN,_ as CAPACITY_IDENTITY_CONTEXT_KEY,g as CAPACITY_SLOT_MAX_LENGTH,C as CAPACITY_SLOT_PATTERN,I as CapacityIdentityConfigSchema,c as CapacityIdentityPinSchema,x as CapacityIdentityWireSchema,y as DEFAULT_CAPACITY_SLOT,l as projectCapacityIdentityToTarget};
|
package/dist/config.d.ts
CHANGED
|
@@ -159,6 +159,11 @@ export declare const RootConfigSchema: z.ZodObject<{
|
|
|
159
159
|
account: z.ZodOptional<z.ZodString>;
|
|
160
160
|
region: z.ZodOptional<z.ZodString>;
|
|
161
161
|
}, z.core.$strict>>>;
|
|
162
|
+
capacityIdentity: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
163
|
+
legacyAnchor: z.ZodString;
|
|
164
|
+
legacyOwnerId: z.ZodOptional<z.ZodString>;
|
|
165
|
+
legacySgDescription: z.ZodOptional<z.ZodString>;
|
|
166
|
+
}, z.core.$strict>>>>>;
|
|
162
167
|
}, z.core.$strict>;
|
|
163
168
|
export type RootConfig = z.infer<typeof RootConfigSchema>;
|
|
164
169
|
/**
|
|
@@ -184,6 +189,11 @@ export declare const RootConfigReadSchema: z.ZodObject<{
|
|
|
184
189
|
account: z.ZodOptional<z.ZodString>;
|
|
185
190
|
region: z.ZodOptional<z.ZodString>;
|
|
186
191
|
}, z.core.$strict>>>;
|
|
192
|
+
capacityIdentity: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
193
|
+
legacyAnchor: z.ZodString;
|
|
194
|
+
legacyOwnerId: z.ZodOptional<z.ZodString>;
|
|
195
|
+
legacySgDescription: z.ZodOptional<z.ZodString>;
|
|
196
|
+
}, z.core.$strict>>>>>;
|
|
187
197
|
}, z.core.$strip>;
|
|
188
198
|
export type RootConfigRead = z.infer<typeof RootConfigReadSchema>;
|
|
189
199
|
/**
|
package/dist/config.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,{encoding:"utf8"}),this.localConfigCache=e}static warnLegacyActiveTargetOnce(){
|
|
1
|
+
var b=Object.defineProperty;var h=(u,e)=>b(u,"name",{value:e,configurable:!0});import*as a from"fs";import*as g from"path";import{z as l}from"zod";import{CapacityIdentityConfigSchema as j}from"./capacityIdentity.js";import{failure as p,success as T}from"./docker/result.js";import{getErrorMessage as S}from"./errorUtils.js";import{logger as E}from"./logger.js";import{maskSensitiveOutput as C}from"./securityHelpers.js";const x=10,w="fjall-config.json",W=["compliance","governance","none"],Y=["enforced","off"],Z=["centralised","off"],H=["account","draining","org"],q="managementEvents",z="organisationManagementEvents",V=["active","draining","removed"],X="FjallTrailBucketName",Q="FjallTrailKeyArn",ee="OrganisationTrailBucketName",k=l.object({name:l.string(),type:l.enum(["apex","delegated"]),parentDomain:l.string().optional(),account:l.string().optional(),region:l.string().optional()}).strict(),A=l.object({activeTarget:l.string().optional(),domains:l.array(k).optional(),capacityIdentity:j.optional()}).strict(),L=l.object({activeTarget:l.string().optional(),domains:l.array(k).optional(),capacityIdentity:j.optional()}),N=".fjall",_="local.json",$=l.object({activeTarget:l.string().optional()});function I(u={}){return JSON.stringify(u,null,2)}h(I,"serialiseRootConfig");const D=A.keyof().options;function R(u,e,n){const t=e[n];t!==void 0&&(u[n]=t)}h(R,"copyDefinedKey");function F(u,e){if(e===void 0)return!1;const n=new Set([...Object.keys(u),...Object.keys(e)]);for(const t of n)if(u[t]!==e[t])return!1;return!0}h(F,"domainEntriesEqual");class d{static{h(this,"Config")}rootConfig;configPath=null;loadFailed=!1;parseDegraded=!1;loadedSnapshot={};constructor(e,n){this.rootConfig=e??{},this.configPath=n??null}static findConfigDirectory(e){let n=e!==void 0&&e!==""?e:process.cwd();for(let t=0;t<x;t++){const o=g.join(n,"fjall"),r=g.join(o,w);if(a.existsSync(r))return o;const i=g.join(n,w);if(a.existsSync(i))return n;const c=g.dirname(n);if(c===n)break;n=c}return null}static loadConfigFile(e){try{return a.accessSync(e,a.constants.R_OK),a.readFileSync(e,{encoding:"utf8"})}catch(n){return E.warn("Config",`Config file at ${e} could not be read; using defaults`,{file:e,error:C(S(n))}),null}}static loadConfig(e){const n=d.findConfigDirectory(e);if(!n)return new d;const t=g.join(n,w),o=d.loadConfigFile(t);if(o===null){const f=new d(void 0,t);return f.loadFailed=!0,f}let r,i=!1;if(o!==""){let f;try{f=JSON.parse(o)}catch(s){throw d.formatZodError(s,w)}const y=A.safeParse(f);if(y.success)r=y.data;else{const s=L.safeParse(f);r=s.success?s.data:{},i=!s.success,s.success?E.warn("Config","fjall-config.json contains keys this version does not recognise (only activeTarget, domains and capacityIdentity are read). They were most likely written by a newer fjall version \u2014 leave them in place; saves preserve them verbatim.",{file:t}):E.warn("Config","fjall-config.json has a malformed activeTarget, domains or capacityIdentity value, so its contents were ignored for this run \u2014 any capacity-identity pins it holds will NOT apply (a pinned stack deploys unpinned and is blocked by the rename gate). Fix the file by hand; do NOT regenerate it, which would discard the pins.",{file:t})}}const c=new d(r,t);return c.parseDegraded=i,c.loadedSnapshot=structuredClone(c.rootConfig),c}static formatZodError(e,n){if(e instanceof l.ZodError&&e.issues.length>0){const r=e.issues.map(i=>`${i.path.join(".")}: ${i.message}`).join("; ");return new Error(`Failed to parse ${n}: ${r}`)}const o=(e instanceof Error?e.message:String(e)).replace(/\n/g," ").substring(0,500);return new Error(`Failed to parse ${n}: ${o}`)}saveConfig(){let e=this.configPath;if(!e){const c=d.findConfigDirectory()||g.join(process.cwd(),"fjall");e=g.join(c,w)}if(this.loadFailed)return p(new Error(`Refusing to save ${e}: the file exists but could not be read when this config loaded, so saving would replace its contents with state that never included them. Fix the file permissions (e.g. chmod u+rw ${e}) and retry.`));const n=g.dirname(e);try{a.mkdirSync(n,{recursive:!0})}catch(c){return p(new Error(`Cannot create config directory ${n}: ${C(S(c))}`))}const t=d.assertWritable(e,n);if(!t.success)return t;const o=this.mergeWithDisk(e);if(!o.success)return o;const r=I(o.data),i=`${e}.tmp-${process.pid}`;try{a.writeFileSync(i,r,{mode:384}),a.renameSync(i,e)}catch(c){return p(new Error(`Failed to save ${e}: ${C(S(c))}`))}return T(void 0)}static assertWritable(e,n){if(a.existsSync(e))try{a.accessSync(e,a.constants.W_OK)}catch{return p(new Error(`Cannot save ${e}: the file is read-only. Make it writable (e.g. chmod u+w ${e}) and retry.`))}try{a.accessSync(n,a.constants.W_OK)}catch{return p(new Error(`Cannot save ${e}: the directory ${n} is not writable. Make it writable (e.g. chmod u+w ${n}) and retry.`))}return T(void 0)}mergeWithDisk(e){const n=d.readDiskConfigForMerge(e);if(n.kind==="unmergeable")return p(new Error(`Refusing to save ${e}: ${n.reason}. Writing now would keep only this session's state and drop everything else the file carries (including keys written by other fjall versions). Fix or remove the file and retry.`));if(n.kind==="absent")return T(this.rootConfig);const t=n.disk,o={...t.foreign,...t.known};for(const i of D)i!=="domains"&&this.sessionChangedKey(i)&&(this.rootConfig[i]===void 0?delete o[i]:R(o,this.rootConfig,i));const r=this.mergeDomains(t.known.domains);return r!==void 0?o.domains=r:delete o.domains,T(o)}sessionChangedKey(e){return JSON.stringify(this.rootConfig[e])!==JSON.stringify(this.loadedSnapshot[e])}mergeDomains(e){const n=this.rootConfig.domains,t=this.loadedSnapshot.domains??[];if(n===void 0&&t.length===0)return e;const o=h(s=>s.toLowerCase(),"norm"),r=n??[],i=new Map(t.map(s=>[o(s.name),s])),c=new Map(r.map(s=>[o(s.name),s])),f=[],y=new Set;for(const s of e??[]){const m=o(s.name);y.add(m);const v=c.get(m),O=i.get(m);if(v!==void 0&&!F(v,O)){f.push(v);continue}v===void 0&&O!==void 0||f.push(s)}for(const s of r){const m=o(s.name);y.has(m)||F(s,i.get(m))||f.push(s)}return f}static readDiskConfigForMerge(e){if(!a.existsSync(e))return{kind:"absent"};let n;try{const r=a.readFileSync(e,{encoding:"utf8"});if(r==="")return{kind:"absent"};n=JSON.parse(r)}catch(r){return{kind:"unmergeable",reason:`the existing file could not be read or parsed as JSON (${C(S(r))})`}}const t=L.safeParse(n);if(!t.success){const r=t.error.issues.map(i=>`${i.path.join(".")}: ${i.message}`).join("; ");return{kind:"unmergeable",reason:`a recognised key in the existing file is malformed (${C(r)})`}}const o={};if(typeof n=="object"&&n!==null){const r=D;for(const[i,c]of Object.entries(n))r.includes(i)||(o[i]=c)}return{kind:"ok",disk:{known:t.data,foreign:o}}}static getConfigDirectory(e){return d.findConfigDirectory(e)}getConfigPath(){return this.configPath}isContentUnavailable(){return this.loadFailed||this.parseDegraded}static warnedLegacyActiveTarget=!1;localConfigCache;localConfigFile(){const e=this.configPath!==null?g.dirname(this.configPath):process.cwd();return g.join(e,N,_)}loadLocalConfig(){if(this.localConfigCache===void 0)try{const e=a.readFileSync(this.localConfigFile(),{encoding:"utf8"}),n=$.safeParse(JSON.parse(e));this.localConfigCache=n.success?n.data:{}}catch{this.localConfigCache={}}return this.localConfigCache}writeLocalConfig(e){const n=this.localConfigFile();a.mkdirSync(g.dirname(n),{recursive:!0}),a.writeFileSync(n,JSON.stringify(e,null,2)+`
|
|
2
|
+
`,{encoding:"utf8"}),this.localConfigCache=e}static warnLegacyActiveTargetOnce(){d.warnedLegacyActiveTarget||(d.warnedLegacyActiveTarget=!0,E.warn("Config","`activeTarget` in fjall-config.json is deprecated and ignored: a committed target must never re-aim a deploy or CI pipeline. Run `fjall target set <name>` to store it locally in .fjall/local.json, then remove `activeTarget` from the committed fjall-config.json."))}getActiveTarget(){const e=this.loadLocalConfig().activeTarget;if(e!==void 0)return e;this.rootConfig.activeTarget!==void 0&&d.warnLegacyActiveTargetOnce()}setActiveTarget(e){const n=this.loadLocalConfig();n.activeTarget=e,this.writeLocalConfig(n)}clearActiveTarget(){const e=this.loadLocalConfig();delete e.activeTarget,this.writeLocalConfig(e)}getDomains(){return this.rootConfig.domains??[]}setDomains(e){this.rootConfig.domains=e}addDomain(e){this.rootConfig.domains||(this.rootConfig.domains=[]),this.rootConfig.domains.push(e)}getDomain(e){return this.rootConfig.domains?.find(n=>n.name.toLowerCase()===e.toLowerCase())}removeDomain(e){if(!this.rootConfig.domains)return!1;const n=this.rootConfig.domains.findIndex(t=>t.name.toLowerCase()===e.toLowerCase());return n===-1?!1:(this.rootConfig.domains.splice(n,1),!0)}}export{q as ACCOUNT_TRAIL_NAME,V as ACCOUNT_TRAIL_STATES,d as Config,k as DomainConfigSchema,N as LOCAL_CONFIG_DIRNAME,_ as LOCAL_CONFIG_FILENAME,z as ORGANISATION_TRAIL_NAME,ee as ORG_TRAIL_BUCKET_OUTPUT_KEY,Z as ROOT_ACCESS_MANAGEMENT_MODES,w as ROOT_CONFIG_FILENAME,L as RootConfigReadSchema,A as RootConfigSchema,Y as S3_BPA_MODES,X as TRAIL_BUCKET_OUTPUT_KEY,Q as TRAIL_KEY_ARN_OUTPUT_KEY,H as TRAIL_LIFECYCLE_STATES,W as VAULT_LOCK_MODES,I as serialiseRootConfig};
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { BACKUP_VAULT_NAME } from "./infra/backupVault.js";
|
|
|
3
3
|
export { APPROVAL_TOKEN_OUTPUT_PREFIX, TOKEN_STDERR_PREFIX } from "./deploy/approvalTokenOutput.js";
|
|
4
4
|
export { imageTagParameterName } from "./infra/imageTags.js";
|
|
5
5
|
export { toPascalCase, toKebab, toValidDatabaseName, toScreamingSnake, capitalise, getSafeZoneName, accountConstructKey, hasAsciiStableConstructKey } from "./naming/caseConversion.js";
|
|
6
|
+
export { CAPACITY_SLOT_PATTERN, CAPACITY_SLOT_MAX_LENGTH, DEFAULT_CAPACITY_SLOT, CAPACITY_ANCHOR_PATTERN, CAPACITY_ANCHOR_MAX_LENGTH, CAPACITY_IDENTITY_CONTEXT_KEY, CapacityIdentityPinSchema, type CapacityIdentityPin, CapacityIdentityWireSchema, type CapacityIdentityWire, CapacityIdentityConfigSchema, type CapacityIdentityConfig, projectCapacityIdentityToTarget } from "./capacityIdentity.js";
|
|
6
7
|
export { findAccountNameCollision, type AccountNameCollision } from "./naming/accountNameCollision.js";
|
|
7
8
|
export { defaultConnectedAccountName, suffixedAccountName, REGION_SHORT_CODES, findTrailingRegionShortCode, regionSuffixRejectionMessage } from "./naming/connectedAccountName.js";
|
|
8
9
|
export { normaliseError, getErrorMessage, hasErrorCode, getErrorCode, getErrorStack, formatErrorString } from "./errorUtils.js";
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DNS_APEX as E,getDomainExportNames as
|
|
1
|
+
import{DNS_APEX as E,getDomainExportNames as t,getDomainStackName as o,getDomainUsEast1CertificatesStackName as _,isManagedDomainBinding as a,DOMAIN_DEPLOY_DEFAULT_PHASE as A}from"./infra/domainExports.js";import{BACKUP_VAULT_NAME as T}from"./infra/backupVault.js";import{APPROVAL_TOKEN_OUTPUT_PREFIX as R,TOKEN_STDERR_PREFIX as n}from"./deploy/approvalTokenOutput.js";import{imageTagParameterName as C}from"./infra/imageTags.js";import{toPascalCase as O,toKebab as P,toValidDatabaseName as s,toScreamingSnake as c,capitalise as p,getSafeZoneName as I,accountConstructKey as f,hasAsciiStableConstructKey as g}from"./naming/caseConversion.js";import{CAPACITY_SLOT_PATTERN as M,CAPACITY_SLOT_MAX_LENGTH as d,DEFAULT_CAPACITY_SLOT as x,CAPACITY_ANCHOR_PATTERN as u,CAPACITY_ANCHOR_MAX_LENGTH as U,CAPACITY_IDENTITY_CONTEXT_KEY as L,CapacityIdentityPinSchema as V,CapacityIdentityWireSchema as l,CapacityIdentityConfigSchema as G,projectCapacityIdentityToTarget as h}from"./capacityIdentity.js";import{findAccountNameCollision as H}from"./naming/accountNameCollision.js";import{defaultConnectedAccountName as v,suffixedAccountName as y,REGION_SHORT_CODES as X,findTrailingRegionShortCode as b,regionSuffixRejectionMessage as K}from"./naming/connectedAccountName.js";import{normaliseError as W,getErrorMessage as k,hasErrorCode as j,getErrorCode as z,getErrorStack as Q,formatErrorString as Z}from"./errorUtils.js";import{singleton as w}from"./async/singleton.js";import{DANGEROUS_ENV_VARS as $,filterDangerousEnvVars as ee,maskSensitiveOutput as re,parseShellArgs as Ee,SCOPED_TOKEN_REGEX as te}from"./securityHelpers.js";import{sleep as _e}from"./async/sleep.js";import{mapSettledWithConcurrency as Ae}from"./async/concurrency.js";import{ACCOUNT_STAGES_WITH_ROOT as Te,STRUCTURAL_ENVIRONMENTS as ie,ACCOUNT_STAGES as Re,ACCOUNT_STAGE_LABELS as ne,isAccountStage as Ne,ACCOUNT_TIERS as Ce,AccountTierSchema as me,isAccountTier as Oe,GOVERNANCE_ACCOUNT_TIERS as Pe,isGovernanceTier as se,environmentToTier as ce,stageFromWireEnvironment as pe,accountTier as Ie,getEnvironmentLabel as fe,ACCOUNT_ROLES as ge}from"./environments.js";import{RESOURCE_CATEGORIES as Me,categoriseResource as de,getExpectedDuration as xe,getFriendlyResourceType as ue}from"./resourceCategorisation.js";import{parseGitRemoteUrl as Le}from"./repo/gitRemoteParser.js";import{abbreviateRegion as le,AWS_REGIONS_METADATA as Ge,DEFAULT_REGION as he,getRegionInfo as Fe,MAX_SECONDARY_REGIONS as He,OPT_IN_REGION_CODES as Ye,optInRegionWarning as ve,regions as ye,suggestRegionForTimezone as Xe}from"./infra/regions.js";import{SCOPE_VALUES as Ke,MACHINE_ONLY_SCOPES as Be,USER_GRANTABLE_SCOPES as We,GOVERNANCE_SCOPE_REQUIRED_CODE as ke}from"./infra/tokenScopes.js";import{SECRET_NAME_PATTERN as ze,SECRET_NAME_ERROR as Qe,SSM_COMPONENT_PATTERN as Ze,SSM_COMPONENT_ERROR as qe,SSM_STANDARD_MAX_VALUE_BYTES as we,SecretNamespaceSchema as Je,buildNamespaceParts as $e,buildParameterPath as er,parseParameterPath as rr,isManageablePath as Er,parseDotEnv as tr,escapeDotEnvValue as or}from"./secrets.js";import{ConnectionWireSchema as ar,ConnectionsListResponseSchema as Ar}from"./infra/connectionsWire.js";import{deriveRegionsFromOrgConfig as Tr,deriveTargets as ir,deriveAllTargets as Rr,environmentOrTier as nr,findTarget as Nr,generateTargetName as Cr}from"./targets.js";import{buildAppConfigPath as Or}from"./repo/appPath.js";import{findInfrastructurePaths as sr,findBoundaryPath as cr,isInfrastructureFile as pr}from"./repo/findInfrastructurePaths.js";import{inferContainerFromCandidates as fr}from"./repo/inferContainerFromCandidates.js";import{RESERVED_APP_NAMES as Dr,RESERVED_APP_NAME_MESSAGE as Mr,isReservedAppName as dr,RESERVED_APP_NAME_SUFFIX as xr,RESERVED_APP_NAME_SUFFIX_MESSAGE as ur,hasReservedAppNameSuffix as Ur}from"./naming/reservedAppNames.js";import{deriveContentHashTag as Vr,CONTENT_HASH_TAG_PATTERN as lr}from"./infra/deriveContentHashTag.js";import{DEPLOY_MODES as hr,DeployModeSchema as Fr,IMAGE_TAG_PATTERN as Hr,ImageTagSchema as Yr,ServiceArtefactSchema as vr,ServiceArtefactsSchema as yr,ARTEFACT_OUTPUT_FIELDS as Xr,artefactOutputKey as br}from"./infra/deployArtefacts.js";import{MIGRATION_SNAPSHOT_NAME_PREFIX as Br,EXPECTED_SCHEMA_VERSION_ENV as Wr,EXPECTED_SCHEMA_VERSION_TOOL_ENV as kr,EXPECTED_CH_SCHEMA_VERSION_ENV as jr,SCHEMA_ADMIN_USER_ENV as zr,SCHEMA_ADMIN_PASSWORD_ENV as Qr,PRISMA_MIGRATION_DIR_RE as Zr,CLICKHOUSE_MIGRATION_SKIP_RE as qr}from"./migration/constants.js";import{PHYSICAL_NAME_FALLBACK_PROPERTIES as Jr}from"./cfn/physicalNameProperties.js";import{PATTERN_TYPE_VALUES as eE,PATTERN_TYPES as rE,isPatternType as EE,PATTERN_REGISTRY as tE,DEPLOYABLE_PATTERN_TYPES as oE,OPENNEXT_PATTERN_TYPES as _E,isOpenNextPatternType as aE,STATIC_SITE_ROUTING_VALUES as AE}from"./patterns/patternTypes.js";import{DEFAULT_FORMS_FROM_LOCAL_PART as TE,defaultFormsFromAddress as iE,defaultFormsCorsOrigin as RE,isAddressAtDomain as nE}from"./patterns/staticSiteForms.js";import{DEV_SUBSTRATE_PARAMS_SCHEMA_VERSION as CE,DEV_SUBSTRATE_PARAMS_FILENAME as mE,DevSubstrateSynthPropsSchema as OE,DevSubstrateParamsSchema as PE}from"./devSubstrate/params.js";import{DEV_SUBSTRATE_ENTRYPOINT_SOURCE as cE}from"./devSubstrate/entrypoint.js";export{ge as ACCOUNT_ROLES,Re as ACCOUNT_STAGES,Te as ACCOUNT_STAGES_WITH_ROOT,ne as ACCOUNT_STAGE_LABELS,Ce as ACCOUNT_TIERS,R as APPROVAL_TOKEN_OUTPUT_PREFIX,Xr as ARTEFACT_OUTPUT_FIELDS,Ge as AWS_REGIONS_METADATA,me as AccountTierSchema,T as BACKUP_VAULT_NAME,U as CAPACITY_ANCHOR_MAX_LENGTH,u as CAPACITY_ANCHOR_PATTERN,L as CAPACITY_IDENTITY_CONTEXT_KEY,d as CAPACITY_SLOT_MAX_LENGTH,M as CAPACITY_SLOT_PATTERN,qr as CLICKHOUSE_MIGRATION_SKIP_RE,lr as CONTENT_HASH_TAG_PATTERN,G as CapacityIdentityConfigSchema,V as CapacityIdentityPinSchema,l as CapacityIdentityWireSchema,ar as ConnectionWireSchema,Ar as ConnectionsListResponseSchema,$ as DANGEROUS_ENV_VARS,x as DEFAULT_CAPACITY_SLOT,TE as DEFAULT_FORMS_FROM_LOCAL_PART,he as DEFAULT_REGION,oE as DEPLOYABLE_PATTERN_TYPES,hr as DEPLOY_MODES,cE as DEV_SUBSTRATE_ENTRYPOINT_SOURCE,mE as DEV_SUBSTRATE_PARAMS_FILENAME,CE as DEV_SUBSTRATE_PARAMS_SCHEMA_VERSION,E as DNS_APEX,A as DOMAIN_DEPLOY_DEFAULT_PHASE,Fr as DeployModeSchema,PE as DevSubstrateParamsSchema,OE as DevSubstrateSynthPropsSchema,jr as EXPECTED_CH_SCHEMA_VERSION_ENV,Wr as EXPECTED_SCHEMA_VERSION_ENV,kr as EXPECTED_SCHEMA_VERSION_TOOL_ENV,Pe as GOVERNANCE_ACCOUNT_TIERS,ke as GOVERNANCE_SCOPE_REQUIRED_CODE,Hr as IMAGE_TAG_PATTERN,Yr as ImageTagSchema,Be as MACHINE_ONLY_SCOPES,He as MAX_SECONDARY_REGIONS,Br as MIGRATION_SNAPSHOT_NAME_PREFIX,_E as OPENNEXT_PATTERN_TYPES,Ye as OPT_IN_REGION_CODES,tE as PATTERN_REGISTRY,rE as PATTERN_TYPES,eE as PATTERN_TYPE_VALUES,Jr as PHYSICAL_NAME_FALLBACK_PROPERTIES,Zr as PRISMA_MIGRATION_DIR_RE,X as REGION_SHORT_CODES,Dr as RESERVED_APP_NAMES,Mr as RESERVED_APP_NAME_MESSAGE,xr as RESERVED_APP_NAME_SUFFIX,ur as RESERVED_APP_NAME_SUFFIX_MESSAGE,Me as RESOURCE_CATEGORIES,Qr as SCHEMA_ADMIN_PASSWORD_ENV,zr as SCHEMA_ADMIN_USER_ENV,te as SCOPED_TOKEN_REGEX,Ke as SCOPE_VALUES,Qe as SECRET_NAME_ERROR,ze as SECRET_NAME_PATTERN,qe as SSM_COMPONENT_ERROR,Ze as SSM_COMPONENT_PATTERN,we as SSM_STANDARD_MAX_VALUE_BYTES,AE as STATIC_SITE_ROUTING_VALUES,ie as STRUCTURAL_ENVIRONMENTS,Je as SecretNamespaceSchema,vr as ServiceArtefactSchema,yr as ServiceArtefactsSchema,n as TOKEN_STDERR_PREFIX,We as USER_GRANTABLE_SCOPES,le as abbreviateRegion,f as accountConstructKey,Ie as accountTier,br as artefactOutputKey,Or as buildAppConfigPath,$e as buildNamespaceParts,er as buildParameterPath,p as capitalise,de as categoriseResource,v as defaultConnectedAccountName,RE as defaultFormsCorsOrigin,iE as defaultFormsFromAddress,Rr as deriveAllTargets,Vr as deriveContentHashTag,Tr as deriveRegionsFromOrgConfig,ir as deriveTargets,nr as environmentOrTier,ce as environmentToTier,or as escapeDotEnvValue,ee as filterDangerousEnvVars,H as findAccountNameCollision,cr as findBoundaryPath,sr as findInfrastructurePaths,Nr as findTarget,b as findTrailingRegionShortCode,Z as formatErrorString,Cr as generateTargetName,t as getDomainExportNames,o as getDomainStackName,_ as getDomainUsEast1CertificatesStackName,fe as getEnvironmentLabel,z as getErrorCode,k as getErrorMessage,Q as getErrorStack,xe as getExpectedDuration,ue as getFriendlyResourceType,Fe as getRegionInfo,I as getSafeZoneName,g as hasAsciiStableConstructKey,j as hasErrorCode,Ur as hasReservedAppNameSuffix,C as imageTagParameterName,fr as inferContainerFromCandidates,Ne as isAccountStage,Oe as isAccountTier,nE as isAddressAtDomain,se as isGovernanceTier,pr as isInfrastructureFile,Er as isManageablePath,a as isManagedDomainBinding,aE as isOpenNextPatternType,EE as isPatternType,dr as isReservedAppName,Ae as mapSettledWithConcurrency,re as maskSensitiveOutput,W as normaliseError,ve as optInRegionWarning,tr as parseDotEnv,Le as parseGitRemoteUrl,rr as parseParameterPath,Ee as parseShellArgs,h as projectCapacityIdentityToTarget,K as regionSuffixRejectionMessage,ye as regions,w as singleton,_e as sleep,pe as stageFromWireEnvironment,y as suffixedAccountName,Xe as suggestRegionForTimezone,P as toKebab,O as toPascalCase,c as toScreamingSnake,s as toValidDatabaseName};
|
package/dist/manifest/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* pure CDK synth path) MUST import directly from `./schemas` instead of
|
|
7
7
|
* the barrel — the package.json `exports` map exposes both subpaths.
|
|
8
8
|
*/
|
|
9
|
-
export { DockerBuildSchema, DockerBuildArgValueSchema, DockerBuildSecretRefSchema, DockerBuildPartialSchema, mergeDockerBuild, ManifestServiceSchema, ManifestPatternSchema, ManifestEcrSchema, ManifestLambdaSchema, ManifestStackHashSchema, ResourceMapEntrySchema, FjallManifestSchema, EngineCompatSchema, FJALL_MANIFEST_FILENAME, MANIFEST_SCHEMA_VERSION, MAX_SUPPORTED_MANIFEST_SCHEMA_VERSION, BUILDKIT_SECRET_ID_PATTERN, type DockerBuild, type DockerBuildArgValue, type DockerBuildSecretRef, type DockerBuildPartial, type ManifestService, type ManifestPattern, type ManifestEcr, type ManifestLambda, type ManifestStackHash, type ResourceMapEntry, type FjallManifest, type EngineCompat } from "./schemas.js";
|
|
10
|
-
export { getManifestFilePath, readManifestFile, writeManifestFile, createEmptyManifest, readConstructMap, parseDockerServicesFromManifest, parseLambdaDockerServicesFromManifest, parseLambdaDockerEntriesFromManifest, parseDockerDeclarationsFromManifest, readEngineCompatEnvelope, type ManifestDockerService, type ManifestLambdaDockerEntry, type ManifestDockerDeclarations, type EngineCompatEnvelope } from "./io.js";
|
|
9
|
+
export { DockerBuildSchema, DockerBuildArgValueSchema, DockerBuildSecretRefSchema, DockerBuildPartialSchema, mergeDockerBuild, ManifestServiceSchema, ManifestPatternSchema, ManifestEcrSchema, ManifestLambdaSchema, ManifestStackHashSchema, ResourceMapEntrySchema, FjallManifestSchema, EngineCompatSchema, ManifestCapacityAliasSchema, FJALL_MANIFEST_FILENAME, MANIFEST_SCHEMA_VERSION, MAX_SUPPORTED_MANIFEST_SCHEMA_VERSION, BUILDKIT_SECRET_ID_PATTERN, type DockerBuild, type DockerBuildArgValue, type DockerBuildSecretRef, type DockerBuildPartial, type ManifestService, type ManifestPattern, type ManifestEcr, type ManifestLambda, type ManifestStackHash, type ResourceMapEntry, type FjallManifest, type EngineCompat, type ManifestCapacityAlias } from "./schemas.js";
|
|
10
|
+
export { getManifestFilePath, readManifestFile, readManifestFileOutcome, writeManifestFile, createEmptyManifest, readConstructMap, parseDockerServicesFromManifest, parseLambdaDockerServicesFromManifest, parseLambdaDockerEntriesFromManifest, parseDockerDeclarationsFromManifest, readEngineCompatEnvelope, readManifestAppName, readManifestAppNameOutcome, type ManifestAppNameOutcome, type ManifestDockerService, type ManifestFileReadOutcome, type ManifestLambdaDockerEntry, type ManifestDockerDeclarations, type EngineCompatEnvelope } from "./io.js";
|
package/dist/manifest/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DockerBuildSchema as r,DockerBuildArgValueSchema as t,DockerBuildSecretRefSchema as
|
|
1
|
+
import{DockerBuildSchema as r,DockerBuildArgValueSchema as t,DockerBuildSecretRefSchema as i,DockerBuildPartialSchema as c,mergeDockerBuild as m,ManifestServiceSchema as s,ManifestPatternSchema as n,ManifestEcrSchema as M,ManifestLambdaSchema as S,ManifestStackHashSchema as o,ResourceMapEntrySchema as f,FjallManifestSchema as E,EngineCompatSchema as p,ManifestCapacityAliasSchema as l,FJALL_MANIFEST_FILENAME as h,MANIFEST_SCHEMA_VERSION as d,MAX_SUPPORTED_MANIFEST_SCHEMA_VERSION as F,BUILDKIT_SECRET_ID_PATTERN as A}from"./schemas.js";import{getManifestFilePath as _,readManifestFile as k,readManifestFileOutcome as u,writeManifestFile as I,createEmptyManifest as N,readConstructMap as T,parseDockerServicesFromManifest as C,parseLambdaDockerServicesFromManifest as L,parseLambdaDockerEntriesFromManifest as R,parseDockerDeclarationsFromManifest as B,readEngineCompatEnvelope as P,readManifestAppName as g,readManifestAppNameOutcome as O}from"./io.js";export{A as BUILDKIT_SECRET_ID_PATTERN,t as DockerBuildArgValueSchema,c as DockerBuildPartialSchema,r as DockerBuildSchema,i as DockerBuildSecretRefSchema,p as EngineCompatSchema,h as FJALL_MANIFEST_FILENAME,E as FjallManifestSchema,d as MANIFEST_SCHEMA_VERSION,F as MAX_SUPPORTED_MANIFEST_SCHEMA_VERSION,l as ManifestCapacityAliasSchema,M as ManifestEcrSchema,S as ManifestLambdaSchema,n as ManifestPatternSchema,s as ManifestServiceSchema,o as ManifestStackHashSchema,f as ResourceMapEntrySchema,N as createEmptyManifest,_ as getManifestFilePath,m as mergeDockerBuild,B as parseDockerDeclarationsFromManifest,C as parseDockerServicesFromManifest,R as parseLambdaDockerEntriesFromManifest,L as parseLambdaDockerServicesFromManifest,T as readConstructMap,P as readEngineCompatEnvelope,g as readManifestAppName,O as readManifestAppNameOutcome,k as readManifestFile,u as readManifestFileOutcome,I as writeManifestFile};
|
package/dist/manifest/io.d.ts
CHANGED
|
@@ -11,6 +11,24 @@ import { type DockerBuild, type EngineCompat, type FjallManifest, type LambdaArc
|
|
|
11
11
|
* Get the manifest file path for a cdk.out directory.
|
|
12
12
|
*/
|
|
13
13
|
export declare function getManifestFilePath(cdkOutPath: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Completeness-signalled manifest read: consumers whose verdicts authorise
|
|
16
|
+
* or withhold work (identity-pin candidate collection, compatibility gates)
|
|
17
|
+
* must distinguish a genuinely absent manifest from one that is present but
|
|
18
|
+
* unreadable — collapsing both to "no manifest" turns a corrupt assembly
|
|
19
|
+
* into a clean "nothing to do" verdict. `detail` is pre-masked at
|
|
20
|
+
* construction.
|
|
21
|
+
*/
|
|
22
|
+
export type ManifestFileReadOutcome = {
|
|
23
|
+
status: "ok";
|
|
24
|
+
manifest: FjallManifest;
|
|
25
|
+
} | {
|
|
26
|
+
status: "absent";
|
|
27
|
+
} | {
|
|
28
|
+
status: "unreadable";
|
|
29
|
+
detail: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function readManifestFileOutcome(cdkOutPath: string): Promise<ManifestFileReadOutcome>;
|
|
14
32
|
/**
|
|
15
33
|
* Read manifest file from cdk.out directory.
|
|
16
34
|
* Returns null if file doesn't exist or is corrupt.
|
|
@@ -99,6 +117,34 @@ export interface EngineCompatEnvelope {
|
|
|
99
117
|
* the deploy phase.
|
|
100
118
|
*/
|
|
101
119
|
export declare function readEngineCompatEnvelope(cdkOutPath: string): EngineCompatEnvelope;
|
|
120
|
+
/**
|
|
121
|
+
* Read the manifest's declared `appName` from a cdk.out directory — the
|
|
122
|
+
* assembly's own identity, which can diverge from the deploy operation's
|
|
123
|
+
* on-disk app name (folder "web-app" vs manifest "WebApp"). Returns undefined
|
|
124
|
+
* when the manifest is missing/unreadable or carries no usable appName.
|
|
125
|
+
*
|
|
126
|
+
* Reads synchronously to match the deploy-core chokepoints' synchronous
|
|
127
|
+
* orchestration context; the file is small and sealed by CDK synth ahead of
|
|
128
|
+
* the deploy phase.
|
|
129
|
+
*/
|
|
130
|
+
export declare function readManifestAppName(cdkOutPath: string): string | undefined;
|
|
131
|
+
/**
|
|
132
|
+
* Completeness-signalled variant of {@link readManifestAppName}: gates whose
|
|
133
|
+
* verdicts hinge on the manifest identity (the AC-3.7 downgrade tripwire)
|
|
134
|
+
* must distinguish an absent manifest (no identity to diverge from — folder
|
|
135
|
+
* matching is complete) from a present-but-unreadable one (the identity
|
|
136
|
+
* exists but cannot be proven — fail closed). `appName: undefined` on an
|
|
137
|
+
* `ok` outcome means the manifest is readable but declares no usable name.
|
|
138
|
+
*/
|
|
139
|
+
export type ManifestAppNameOutcome = {
|
|
140
|
+
status: "ok";
|
|
141
|
+
appName: string | undefined;
|
|
142
|
+
} | {
|
|
143
|
+
status: "absent";
|
|
144
|
+
} | {
|
|
145
|
+
status: "unreadable";
|
|
146
|
+
};
|
|
147
|
+
export declare function readManifestAppNameOutcome(cdkOutPath: string): ManifestAppNameOutcome;
|
|
102
148
|
/**
|
|
103
149
|
* Extract services with a Docker build configuration from the Fjall manifest.
|
|
104
150
|
*
|
package/dist/manifest/io.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var b=Object.defineProperty;var s=(n,e)=>b(n,"name",{value:e,configurable:!0});import{readFile as E,writeFile as k,unlink as F,rename as w,mkdir as x}from"fs/promises";import{readFileSync as g}from"fs";import{dirname as A,join as m}from"path";import{logger as c}from"../logger.js";import{maskSensitiveOutput as f}from"../securityHelpers.js";import{fileExists as N}from"../fsHelpers.js";import{getErrorMessage as d}from"../errorUtils.js";import{recordToConstructMap as S}from"../constructMap.js";import{FjallManifestSchema as j,FJALL_MANIFEST_FILENAME as p,MANIFEST_SCHEMA_VERSION as C,normaliseDockerBuild as y,LAMBDA_ARCHITECTURE_VALUES as v}from"./schemas.js";function h(n){return m(n,p)}s(h,"getManifestFilePath");async function O(n){const e=h(n);if(!await N(e))return{status:"absent"};try{const r=await E(e,"utf-8"),t=JSON.parse(r),a=j.safeParse(t);if(!a.success){const i=f(a.error.issues.map(o=>`${o.path.join(".")}: ${o.message}`).join("; "));return c.debug("FjallManifest","Manifest validation failed",{path:e,errors:i}),{status:"unreadable",detail:i}}return{status:"ok",manifest:a.data}}catch(r){const t=f(d(r));return c.debug("FjallManifest","Failed to read manifest file",{path:e,error:t}),{status:"unreadable",detail:t}}}s(O,"readManifestFileOutcome");async function D(n){const e=await O(n);return e.status==="ok"?e.manifest:null}s(D,"readManifestFile");async function q(n,e){const r=h(n),t=`${r}.${Date.now()}.tmp`;await x(A(r),{recursive:!0});try{await k(t,JSON.stringify(e,null,2),"utf-8"),await w(t,r)}catch(a){try{await F(t)}catch(i){c.debug("FjallManifest","Temp file cleanup failed (non-fatal)",{path:t,error:d(i)})}throw a}}s(q,"writeManifestFile");function z(n){return{version:C,generatedAt:new Date().toISOString(),appName:n,services:[],lambdas:[],stacks:{}}}s(z,"createEmptyManifest");async function G(n){const e=await D(n);return e?.resourceMap?S(e.resourceMap):new Map}s(G,"readConstructMap");function u(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}s(u,"isRecord");function l(n,e){const r=m(n,p);let t;try{t=g(r,"utf-8")}catch{c.debug("FjallManifest",`Manifest file not readable \u2014 no ${e} extracted`,{path:r});return}let a;try{a=JSON.parse(t)}catch{c.debug("FjallManifest",`Manifest is not valid JSON \u2014 no ${e} extracted`,{path:r});return}return u(a)?a:void 0}s(l,"readManifestRecord");function L(n){const e=n.engineCompat;if(!u(e))return;const r=e.minimumEngineVersion;if(typeof r!="string"||r.length===0)return;const t=typeof e.synthesisedBy=="string"&&e.synthesisedBy.length>0?e.synthesisedBy:"",a=typeof e.maximumEngineMajor=="number"&&Number.isInteger(e.maximumEngineMajor)&&e.maximumEngineMajor>=0?e.maximumEngineMajor:void 0,i=e.minimumAwsCdkCli,o=i===void 0?void 0:typeof i=="string"?i:String(i);return{synthesisedBy:t,minimumEngineVersion:r,...a!==void 0&&{maximumEngineMajor:a},...o!==void 0&&{minimumAwsCdkCli:o}}}s(L,"extractEngineCompat");function Q(n){const e=l(n,"engine compatibility");if(e===void 0)return{manifestVersion:void 0,engineCompatPresent:!1,engineCompat:void 0};const r=typeof e.version=="number"?e.version:void 0,t=u(e.engineCompat),a=L(e);return{manifestVersion:r,engineCompatPresent:t,engineCompat:a}}s(Q,"readEngineCompatEnvelope");function W(n){const e=I(n);return e.status==="ok"?e.appName:void 0}s(W,"readManifestAppName");function I(n){const e=m(n,p);let r;try{r=g(e,"utf-8")}catch(a){const i=a!==null&&typeof a=="object"&&"code"in a?a.code:void 0;return i==="ENOENT"||i==="ENOTDIR"?{status:"absent"}:(c.debug("FjallManifest","Manifest file not readable \u2014 no app name",{path:e,error:f(d(a))}),{status:"unreadable"})}let t;try{t=JSON.parse(r)}catch(a){return c.debug("FjallManifest","Manifest is not valid JSON \u2014 no app name",{path:e,error:f(d(a))}),{status:"unreadable"}}return u(t)?{status:"ok",appName:typeof t.appName=="string"&&t.appName!==""?t.appName:void 0}:{status:"unreadable"}}s(I,"readManifestAppNameOutcome");function J(n){const e=l(n,"Docker services");if(e===void 0||!Array.isArray(e.services))return[];const r=[];for(const t of e.services){if(!u(t)||typeof t.name!="string")continue;const a=y(t.docker);a!==void 0&&r.push({name:t.name,docker:a,isLambda:!1})}return r}s(J,"parseDockerServicesFromManifest");function X(n){const e=new Map;for(const{name:r,imageKey:t,docker:a,architecture:i}of M(n)){const o=e.get(t);if(o===void 0){e.set(t,{name:t,docker:a,isLambda:!0,...i!==void 0&&{architecture:i}});continue}if(JSON.stringify(o.docker)!==JSON.stringify(a)||o.architecture!==i)throw new Error(`Lambda functions sharing image key "${t}" declare different \`docker\` configs or \`architecture\` \u2014 every Lambda function sharing an \`image\` must build from the identical Dockerfile/context/target/buildArgs and target the same architecture (offending function: "${r}").`)}return Array.from(e.values())}s(X,"parseLambdaDockerServicesFromManifest");function M(n){const e=l(n,"Lambda Docker entries");if(e===void 0||!Array.isArray(e.lambdas))return[];const r=[];for(const t of e.lambdas){if(!u(t)||typeof t.name!="string")continue;const a=y(t.docker);if(a===void 0)continue;const i=typeof t.imageKey=="string"&&t.imageKey.length>0?t.imageKey:t.name;let o;typeof t.architecture=="string"&&(v.includes(t.architecture)?o=t.architecture:c.debug("FjallManifest","Ignoring unrecognised Lambda architecture \u2014 build falls back to the default platform",{lambda:t.name,architecture:f(t.architecture)})),r.push({name:t.name,imageKey:i,docker:a,...o!==void 0&&{architecture:o}})}return r}s(M,"parseLambdaDockerEntriesFromManifest");function Y(n){const e=J(n),r=M(n);return{ecsServices:e,lambdaEntries:r,declaresBuild:e.length>0||r.length>0}}s(Y,"parseDockerDeclarationsFromManifest");export{z as createEmptyManifest,h as getManifestFilePath,Y as parseDockerDeclarationsFromManifest,J as parseDockerServicesFromManifest,M as parseLambdaDockerEntriesFromManifest,X as parseLambdaDockerServicesFromManifest,G as readConstructMap,Q as readEngineCompatEnvelope,W as readManifestAppName,I as readManifestAppNameOutcome,D as readManifestFile,O as readManifestFileOutcome,q as writeManifestFile};
|
|
@@ -361,6 +361,34 @@ declare const EngineCompatSchema: z.ZodObject<{
|
|
|
361
361
|
minimumAwsCdkCli: z.ZodOptional<z.ZodString>;
|
|
362
362
|
}, z.core.$strict>;
|
|
363
363
|
export type EngineCompat = z.infer<typeof EngineCompatSchema>;
|
|
364
|
+
/**
|
|
365
|
+
* One capacity-slot identity alias, emitted at synth for EVERY EC2 capacity
|
|
366
|
+
* slot unconditionally (pinned or not) by the constructs' capacity factory.
|
|
367
|
+
* Ties the slot's CURRENT identity derivation to the HYPOTHETICAL pre-6.0
|
|
368
|
+
* (config-keyed) derivation computed from the same config, so:
|
|
369
|
+
* - rename detection (deploy-core) can confirm a legacy→anchor rename pair
|
|
370
|
+
* from the emitter's own testimony (matcher (a), the highest-precedence
|
|
371
|
+
* evidence) and name the config fields that used to drive the identity;
|
|
372
|
+
* - the pin writer (`fjall migrate identity`) can route a CREATE-side row
|
|
373
|
+
* back to `{ appName, slot }` when composing a pin.
|
|
374
|
+
*
|
|
375
|
+
* WRITE contract: `.strict()` like `EngineCompatSchema` — emitter and reader
|
|
376
|
+
* live in Lerna FIXED lockstep, and a future additive field revs through
|
|
377
|
+
* `minimumEngineVersion` before any older reader can meet it.
|
|
378
|
+
*/
|
|
379
|
+
export declare const ManifestCapacityAliasSchema: z.ZodObject<{
|
|
380
|
+
appName: z.ZodString;
|
|
381
|
+
slot: z.ZodString;
|
|
382
|
+
clusterName: z.ZodString;
|
|
383
|
+
anchor: z.ZodString;
|
|
384
|
+
pinned: z.ZodBoolean;
|
|
385
|
+
currentServiceName: z.ZodString;
|
|
386
|
+
legacyKey: z.ZodString;
|
|
387
|
+
legacyAnchor: z.ZodString;
|
|
388
|
+
legacyServiceName: z.ZodString;
|
|
389
|
+
legacyKeyFields: z.ZodArray<z.ZodString>;
|
|
390
|
+
}, z.core.$strict>;
|
|
391
|
+
export type ManifestCapacityAlias = z.infer<typeof ManifestCapacityAliasSchema>;
|
|
364
392
|
/**
|
|
365
393
|
* Fjall manifest schema — generated during CDK synth.
|
|
366
394
|
* Location: `<cdk.out>/fjall-manifest.json`.
|
|
@@ -465,7 +493,18 @@ export declare const FjallManifestSchema: z.ZodObject<{
|
|
|
465
493
|
maximumEngineMajor: z.ZodOptional<z.ZodNumber>;
|
|
466
494
|
minimumAwsCdkCli: z.ZodOptional<z.ZodString>;
|
|
467
495
|
}, z.core.$strict>>;
|
|
468
|
-
identityAliases: z.ZodOptional<z.
|
|
496
|
+
identityAliases: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
497
|
+
appName: z.ZodString;
|
|
498
|
+
slot: z.ZodString;
|
|
499
|
+
clusterName: z.ZodString;
|
|
500
|
+
anchor: z.ZodString;
|
|
501
|
+
pinned: z.ZodBoolean;
|
|
502
|
+
currentServiceName: z.ZodString;
|
|
503
|
+
legacyKey: z.ZodString;
|
|
504
|
+
legacyAnchor: z.ZodString;
|
|
505
|
+
legacyServiceName: z.ZodString;
|
|
506
|
+
legacyKeyFields: z.ZodArray<z.ZodString>;
|
|
507
|
+
}, z.core.$strict>>>;
|
|
469
508
|
}, z.core.$strict>;
|
|
470
509
|
export type FjallManifest = z.infer<typeof FjallManifestSchema>;
|
|
471
510
|
export { ManifestServiceSchema, ManifestPatternSchema, ManifestEcrSchema, ManifestLambdaSchema, ManifestStackHashSchema, ResourceMapEntrySchema, EngineCompatSchema };
|
package/dist/manifest/schemas.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var x=Object.defineProperty;var o=(t,n)=>x(t,"name",{value:n,configurable:!0});import{z as e}from"zod";import{PATTERN_TYPE_VALUES as S}from"../patterns/patternTypes.js";const C="fjall-manifest.json",h=1,P=1,A=/^[A-Za-z0-9_.-]+$/,M=e.object({id:e.string().min(1,"buildSecret id cannot be empty").regex(A,"buildSecret id may contain only letters, digits, '_', '.', and '-' (no comma, '=', or whitespace, which would break the buildx --secret argv)"),ssm:e.string().min(1,"ssm parameter name cannot be empty").optional(),secretsManager:e.object({name:e.string().min(1,"secret name cannot be empty").optional(),arn:e.string().min(1,"secret arn cannot be empty").optional(),field:e.string().min(1,"secret field cannot be empty").optional()}).strict().refine(t=>t.name===void 0!=(t.arn===void 0),"secretsManager requires exactly one of name or arn").optional(),env:e.string().min(1,"env variable name cannot be empty").optional()}).strict().superRefine((t,n)=>{[t.ssm,t.secretsManager,t.env].filter(r=>r!==void 0).length!==1&&n.addIssue({code:e.ZodIssueCode.custom,message:"buildSecret requires exactly one source (ssm, secretsManager, or env)"})}),E=e.union([e.string(),e.object({ssm:e.string().min(1,"ssm parameter name cannot be empty").optional(),secretsManager:e.object({name:e.string().min(1,"secret name cannot be empty").optional(),arn:e.string().min(1,"secret arn cannot be empty").optional(),field:e.string().min(1,"secret field cannot be empty").optional()}).strict().refine(t=>t.name===void 0!=(t.arn===void 0),"secretsManager requires exactly one of name or arn").optional(),env:e.string().min(1,"env variable name cannot be empty").optional(),acknowledgePublic:e.boolean().optional()}).strict().superRefine((t,n)=>{[t.ssm,t.secretsManager,t.env].filter(r=>r!==void 0).length!==1&&n.addIssue({code:e.ZodIssueCode.custom,message:"buildArg value requires exactly one source (ssm, secretsManager, or env)"})})]),c=e.object({path:e.string(),context:e.string().min(1,"context cannot be empty").optional(),target:e.string().min(1,"target cannot be empty").optional(),buildArgs:e.record(e.string(),E).optional(),buildSecrets:e.array(M).optional()}).strict(),R=c.partial();function B(t,n){if(n===void 0)return t;const i=n.context??t.context,r=n.target??t.target,s=n.buildArgs??t.buildArgs,a=n.buildSecrets??t.buildSecrets;return{path:n.path??t.path,...i!==void 0&&{context:i},...r!==void 0&&{target:r},...s!==void 0&&{buildArgs:s},...a!==void 0&&{buildSecrets:a}}}o(B,"mergeDockerBuild");function d(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}o(d,"isRecord");function j(t){if(!d(t)||typeof t.path!="string"||t.path.length===0)return;const n=typeof t.context=="string"&&t.context.length>0?t.context:void 0,i=typeof t.target=="string"&&t.target.length>0?t.target:void 0,r=d(t.buildArgs)&&Object.keys(t.buildArgs).length>0?t.buildArgs:void 0,s=Array.isArray(t.buildSecrets)&&t.buildSecrets.length>0?t.buildSecrets:void 0,a={path:t.path,...n!==void 0&&{context:n},...i!==void 0&&{target:i},...r!==void 0&&{buildArgs:r},...s!==void 0&&{buildSecrets:s}},m=c.safeParse(a);return m.success?m.data:void 0}o(j,"normaliseDockerBuild");function D(t){if(t===void 0)return;const n=j(t);return n===void 0?void 0:JSON.stringify(n)}o(D,"dockerBuildFingerprint");const g=e.object({name:e.string(),clusterName:e.string().optional(),docker:c.optional(),containerPort:e.number().optional(),secrets:e.array(e.string()).optional(),ssmSecretsPath:e.string().optional(),importedSecretNames:e.array(e.string()).optional()}).strict(),p=e.object({type:e.enum(S),name:e.string(),source:e.string()}).strict(),l=e.object({repositoryName:e.string()}).strict(),N=["x86_64","arm64"],u=e.object({name:e.string(),secrets:e.array(e.string()).optional(),ssmSecretsPath:e.string().optional(),importedSecretNames:e.array(e.string()).optional(),docker:c.optional(),imageKey:e.string().optional(),architecture:e.enum(N).optional()}).strict(),f=e.object({templateHash:e.string(),synthTimestamp:e.string()}).strict(),b=e.object({constructPath:e.string().max(512),group:e.string().max(128),resourceType:e.string().max(256)}).strict(),y=e.object({synthesisedBy:e.string().min(1).max(128),minimumEngineVersion:e.string().min(1).max(32),maximumEngineMajor:e.number().int().min(0).optional(),minimumAwsCdkCli:e.string().min(1).max(32).optional()}).strict(),_=e.object({appName:e.string().min(1).max(128),slot:e.string().min(1).max(64),clusterName:e.string().min(1).max(128),anchor:e.string().min(1).max(128),pinned:e.boolean(),currentServiceName:e.string().min(1).max(256),legacyKey:e.string().min(1).max(256),legacyAnchor:e.string().min(1).max(256),legacyServiceName:e.string().min(1).max(512),legacyKeyFields:e.array(e.string().max(64)).max(32)}).strict(),F=e.object({version:e.literal(h),generatedAt:e.string(),appName:e.string(),services:e.array(g),lambdas:e.array(u),pattern:p.optional(),ecr:l.optional(),stacks:e.record(e.string(),f),resourceMap:e.record(e.string(),b).optional(),engineCompat:y.optional(),identityAliases:e.array(_).optional()}).strict();export{A as BUILDKIT_SECRET_ID_PATTERN,E as DockerBuildArgValueSchema,R as DockerBuildPartialSchema,c as DockerBuildSchema,M as DockerBuildSecretRefSchema,y as EngineCompatSchema,C as FJALL_MANIFEST_FILENAME,F as FjallManifestSchema,N as LAMBDA_ARCHITECTURE_VALUES,h as MANIFEST_SCHEMA_VERSION,P as MAX_SUPPORTED_MANIFEST_SCHEMA_VERSION,_ as ManifestCapacityAliasSchema,l as ManifestEcrSchema,u as ManifestLambdaSchema,p as ManifestPatternSchema,g as ManifestServiceSchema,f as ManifestStackHashSchema,b as ResourceMapEntrySchema,D as dockerBuildFingerprint,B as mergeDockerBuild,j as normaliseDockerBuild};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/util",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fjall-tech/fjall.git",
|
|
@@ -138,6 +138,5 @@
|
|
|
138
138
|
},
|
|
139
139
|
"engines": {
|
|
140
140
|
"node": ">=22.0.0"
|
|
141
|
-
}
|
|
142
|
-
"gitHead": "7620fc7c93bbef1046580d6568546afe3cd450a7"
|
|
141
|
+
}
|
|
143
142
|
}
|