@fjall/util 3.10.0 → 3.11.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/.minified +1 -1
- package/dist/docker/DockerCli.build.d.ts +20 -7
- package/dist/docker/DockerCli.build.js +1 -1
- package/dist/docker/DockerCli.d.ts +4 -3
- package/dist/docker/architecture.d.ts +12 -0
- package/dist/docker/architecture.js +1 -0
- package/dist/docker/index.d.ts +1 -0
- package/dist/docker/index.js +1 -1
- package/dist/manifest/io.d.ts +16 -6
- package/dist/manifest/io.js +1 -1
- package/dist/manifest/schemas.d.ts +17 -0
- package/dist/manifest/schemas.js +1 -1
- package/package.json +2 -2
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
90 files minified at 2026-07-23T21:49:13.499Z
|
|
@@ -22,14 +22,27 @@ import { type BuildxBuildArgs, type BuildxBuildResult, type DockerCliError } fro
|
|
|
22
22
|
import { type BuildxProgressEvent, type DockerCliState, type ImagetoolsInspect, type Result } from "./DockerCli.js";
|
|
23
23
|
export declare function _buildxBuild(state: DockerCliState, args: BuildxBuildArgs, onProgress: (event: BuildxProgressEvent) => void, abortSignal?: AbortSignal): Promise<Result<BuildxBuildResult, DockerCliError>>;
|
|
24
24
|
/**
|
|
25
|
-
* Create one or more
|
|
26
|
-
*
|
|
25
|
+
* Create one or more tags pointing at an existing image digest without
|
|
26
|
+
* re-uploading layers.
|
|
27
27
|
*
|
|
28
|
-
* Implementation: `docker buildx imagetools create --
|
|
29
|
-
* <tag2> ... <sourceImage>@<digest>`. The source
|
|
30
|
-
* pins the immutable content; each `--tag`
|
|
31
|
-
* mutable name pointing at that digest. The
|
|
32
|
-
* only a new manifest reference per tag.
|
|
28
|
+
* Implementation: `docker buildx imagetools create --prefer-index=false
|
|
29
|
+
* --tag <tag1> --tag <tag2> ... <sourceImage>@<digest>`. The source
|
|
30
|
+
* `image@digest` reference pins the immutable content; each `--tag`
|
|
31
|
+
* argument creates (or moves) a mutable name pointing at that digest. The
|
|
32
|
+
* registry stores no new blobs, only a new manifest reference per tag.
|
|
33
|
+
*
|
|
34
|
+
* `--prefer-index=false` is required: `imagetools create` defaults to
|
|
35
|
+
* wrapping even a SINGLE source manifest in a new image index (a "fat
|
|
36
|
+
* manifest") rather than carbon-copying it, on the assumption that its
|
|
37
|
+
* caller might be assembling a multi-arch tag from several
|
|
38
|
+
* platform-specific sources. fjall never does that — every call here
|
|
39
|
+
* re-tags exactly one already-built (single-platform) digest — so the
|
|
40
|
+
* index wrapper is pure overhead, and worse: AWS Lambda's
|
|
41
|
+
* CreateFunction/UpdateFunctionCode rejects an image index outright, so a
|
|
42
|
+
* Lambda pulling by this tag would fail even though the digest-addressed
|
|
43
|
+
* push (buildAndPush) produced a flat manifest. `--prefer-index=false`
|
|
44
|
+
* makes `imagetools create` copy the source manifest byte-for-byte under
|
|
45
|
+
* the new tag instead.
|
|
33
46
|
*
|
|
34
47
|
* Discipline:
|
|
35
48
|
* - argv-only spawn (`shell: false` via `runDocker`)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var A=Object.defineProperty;var g=(s,l)=>A(s,"name",{value:l,configurable:!0});import{rm as R}from"node:fs/promises";import{buildxArgvBuilder as j}from"./buildxArgvBuilder.js";import{BuildxBuildArgsSchema as N}from"./dockerCliSchemas.js";import{DEFAULT_INSPECT_TIMEOUT_MS as M,DOCKER_CLI_BUILDX_LOG_CATEGORY as C}from"./dockerCliConstants.js";import{BuildxBuildMonitor as U,buildPhaseTimeoutMessage as G,publishStallTimeoutMessage as J,resolveBuildxBudgets as P}from"./buildxBuildMonitor.js";import{parseMetadataFile as H}from"./metadataFileParser.js";import{parseRawjsonLine as K}from"./rawjsonParser.js";import{rawjsonToVertexEvent as V}from"./rawjsonToVertexEvent.js";import{maskSensitiveOutput as b}from"../securityHelpers.js";import{failure as t,makeError as a,maskOutput as T,runDocker as F,spawnFailureToError as W,streamDocker as X,success as _}from"./DockerCli.js";function O(s){return s instanceof Error?s.message:String(s)}g(O,"getErrorMessage");async function oe(s,l,e,u){const r=N.safeParse(l);if(!r.success){const n=b(r.error.message);return t(a("validation",`Invalid BuildxBuildArgs: ${n}`,{issues:r.error.issues}))}const o=P(s.env);if(!o.success)return t(a("validation",b(o.error.message)));const p=o.data,c=j(r.data);let f=0,k=0;const E=new Set;let h,v;try{const n=new U(p);h=n,v=r.data.metadataFile;const I=g(x=>{const S=K(x);if(S===null){x.trim()!==""&&s.logger.debug(C,"Skipping malformed rawjson line",{line:b(x)});return}const m=V(S);if(m===null)return;const w=n.observe(m);w!==void 0&&e({type:"status",message:T(w.message),...w.percentage!==void 0&&{percentage:w.percentage}});for(const i of m.vertexes)i.completed!==void 0&&!E.has(i.digest)&&(E.add(i.digest),i.cached===!0?f++:k++),e({type:"vertex",message:T(i.name),vertex:i.digest});for(const i of m.logs)e({type:"log",message:T(i.data),vertex:i.vertex});for(const i of m.statuses)e({type:"status",message:T(`${i.name} ${i.current}`),vertex:i.vertex});for(const i of m.warnings)e({type:"warning",message:T(i.short),vertex:i.vertex})},"onStdoutLine"),L=u!==void 0?AbortSignal.any([n.signal,u]):n.signal,d=await X(s,{args:c,abortSignal:L},I);if(d.spawnError!==void 0)return t(a("daemon_unreachable",`Docker CLI is not available: ${d.spawnError}`,{stderrTail:d.stderrTail}));if(d.aborted||d.exitCode===null)return n.timedOutPhase==="build"?t(a("timeout",G(p),{stderrTail:d.stderrTail})):n.timedOutPhase==="publish"?t(a("timeout",J(p,n.progressSummary()),{stderrTail:d.stderrTail})):t(a("abort","docker buildx build was aborted",{stderrTail:d.stderrTail}));if(d.exitCode!==0)return t(a("build_failed",`docker buildx build failed (exit ${d.exitCode})`,{stderrTail:d.stderrTail}));const B=await H(r.data.metadataFile);if(!B.success)return B;const $=B.data,y=$["containerimage.digest"];if(typeof y!="string"||y==="")return t(a("metadata_missing_digest","Buildx metadata file does not contain containerimage.digest",{metadataFile:r.data.metadataFile}));const D={};for(const x of r.data.tags)D[x]=y;return _({digest:y,imageDigests:D,metadata:$,platforms:r.data.platforms,cacheHits:f,cacheMisses:k})}finally{h!==void 0&&h.dispose(),v!==void 0&&await R(v,{force:!0}).catch(n=>{s.logger.warn(C,"Failed to clean up buildx metadata file",{path:v,error:b(O(n))})})}}g(oe,"_buildxBuild");async function ne(s,l,e,u){if(l.trim()==="")return t(a("validation","tagByDigest: sourceImage must be non-empty"));if(!e.startsWith("sha256:"))return t(a("validation",`tagByDigest: expected sha256:... digest, got ${e.slice(0,32)}`));if(u.length===0)return t(a("validation","tagByDigest: tags must be a non-empty list"));for(const f of u)if(typeof f!="string"||f.trim()==="")return t(a("validation","tagByDigest: every tag must be non-empty"));const r=`${l}@${e}`,o=[];for(const f of u)o.push("--tag",f);const p=["buildx","imagetools","create",...o,r],c=await F(s,{args:p,timeoutMs:M});return c.spawnError!==void 0?t(W(c)):c.exitCode===null?t(a("abort",`docker buildx imagetools create for ${r} was aborted`,{stderrTail:c.stderrTail})):c.exitCode!==0?t(a("tag_failed",`docker buildx imagetools create for ${r} failed (exit ${c.exitCode})`,{stderrTail:c.stderrTail})):_(void 0)}g(ne,"_tagByDigest");async function de(s,l){const e=await F(s,{args:["buildx","imagetools","inspect",l,"--raw"],timeoutMs:M});if(e.spawnError!==void 0)return t(a("daemon_unreachable",`Docker CLI is not available: ${e.spawnError}`,{stderrTail:e.stderrTail}));if(e.exitCode===null)return t(a("abort",`docker buildx imagetools inspect ${l} was aborted`,{stderrTail:e.stderrTail}));if(e.exitCode!==0)return t(a("inspect_failed",`docker buildx imagetools inspect ${l} failed (exit ${e.exitCode})`,{stderrTail:e.stderrTail}));let u,r;try{const o=JSON.parse(e.stdout);typeof o.mediaType=="string"&&(u=o.mediaType),typeof o.digest=="string"&&(r=o.digest)}catch(o){s.logger.debug(C,"imagetools inspect output is not JSON; preserving raw",{error:b(O(o))})}return _({raw:e.stdout,...u!==void 0&&{mediaType:u},...r!==void 0&&{digest:r}})}g(de,"_imagetoolsInspect");export{oe as _buildxBuild,de as _imagetoolsInspect,ne as _tagByDigest};
|
|
1
|
+
var A=Object.defineProperty;var g=(s,l)=>A(s,"name",{value:l,configurable:!0});import{rm as R}from"node:fs/promises";import{buildxArgvBuilder as j}from"./buildxArgvBuilder.js";import{BuildxBuildArgsSchema as N}from"./dockerCliSchemas.js";import{DEFAULT_INSPECT_TIMEOUT_MS as M,DOCKER_CLI_BUILDX_LOG_CATEGORY as C}from"./dockerCliConstants.js";import{BuildxBuildMonitor as U,buildPhaseTimeoutMessage as G,publishStallTimeoutMessage as J,resolveBuildxBudgets as P}from"./buildxBuildMonitor.js";import{parseMetadataFile as H}from"./metadataFileParser.js";import{parseRawjsonLine as K}from"./rawjsonParser.js";import{rawjsonToVertexEvent as V}from"./rawjsonToVertexEvent.js";import{maskSensitiveOutput as b}from"../securityHelpers.js";import{failure as t,makeError as a,maskOutput as T,runDocker as F,spawnFailureToError as W,streamDocker as X,success as _}from"./DockerCli.js";function O(s){return s instanceof Error?s.message:String(s)}g(O,"getErrorMessage");async function oe(s,l,e,u){const r=N.safeParse(l);if(!r.success){const n=b(r.error.message);return t(a("validation",`Invalid BuildxBuildArgs: ${n}`,{issues:r.error.issues}))}const o=P(s.env);if(!o.success)return t(a("validation",b(o.error.message)));const p=o.data,c=j(r.data);let f=0,k=0;const E=new Set;let h,v;try{const n=new U(p);h=n,v=r.data.metadataFile;const I=g(x=>{const S=K(x);if(S===null){x.trim()!==""&&s.logger.debug(C,"Skipping malformed rawjson line",{line:b(x)});return}const m=V(S);if(m===null)return;const w=n.observe(m);w!==void 0&&e({type:"status",message:T(w.message),...w.percentage!==void 0&&{percentage:w.percentage}});for(const i of m.vertexes)i.completed!==void 0&&!E.has(i.digest)&&(E.add(i.digest),i.cached===!0?f++:k++),e({type:"vertex",message:T(i.name),vertex:i.digest});for(const i of m.logs)e({type:"log",message:T(i.data),vertex:i.vertex});for(const i of m.statuses)e({type:"status",message:T(`${i.name} ${i.current}`),vertex:i.vertex});for(const i of m.warnings)e({type:"warning",message:T(i.short),vertex:i.vertex})},"onStdoutLine"),L=u!==void 0?AbortSignal.any([n.signal,u]):n.signal,d=await X(s,{args:c,abortSignal:L},I);if(d.spawnError!==void 0)return t(a("daemon_unreachable",`Docker CLI is not available: ${d.spawnError}`,{stderrTail:d.stderrTail}));if(d.aborted||d.exitCode===null)return n.timedOutPhase==="build"?t(a("timeout",G(p),{stderrTail:d.stderrTail})):n.timedOutPhase==="publish"?t(a("timeout",J(p,n.progressSummary()),{stderrTail:d.stderrTail})):t(a("abort","docker buildx build was aborted",{stderrTail:d.stderrTail}));if(d.exitCode!==0)return t(a("build_failed",`docker buildx build failed (exit ${d.exitCode})`,{stderrTail:d.stderrTail}));const B=await H(r.data.metadataFile);if(!B.success)return B;const $=B.data,y=$["containerimage.digest"];if(typeof y!="string"||y==="")return t(a("metadata_missing_digest","Buildx metadata file does not contain containerimage.digest",{metadataFile:r.data.metadataFile}));const D={};for(const x of r.data.tags)D[x]=y;return _({digest:y,imageDigests:D,metadata:$,platforms:r.data.platforms,cacheHits:f,cacheMisses:k})}finally{h!==void 0&&h.dispose(),v!==void 0&&await R(v,{force:!0}).catch(n=>{s.logger.warn(C,"Failed to clean up buildx metadata file",{path:v,error:b(O(n))})})}}g(oe,"_buildxBuild");async function ne(s,l,e,u){if(l.trim()==="")return t(a("validation","tagByDigest: sourceImage must be non-empty"));if(!e.startsWith("sha256:"))return t(a("validation",`tagByDigest: expected sha256:... digest, got ${e.slice(0,32)}`));if(u.length===0)return t(a("validation","tagByDigest: tags must be a non-empty list"));for(const f of u)if(typeof f!="string"||f.trim()==="")return t(a("validation","tagByDigest: every tag must be non-empty"));const r=`${l}@${e}`,o=[];for(const f of u)o.push("--tag",f);const p=["buildx","imagetools","create","--prefer-index=false",...o,r],c=await F(s,{args:p,timeoutMs:M});return c.spawnError!==void 0?t(W(c)):c.exitCode===null?t(a("abort",`docker buildx imagetools create for ${r} was aborted`,{stderrTail:c.stderrTail})):c.exitCode!==0?t(a("tag_failed",`docker buildx imagetools create for ${r} failed (exit ${c.exitCode})`,{stderrTail:c.stderrTail})):_(void 0)}g(ne,"_tagByDigest");async function de(s,l){const e=await F(s,{args:["buildx","imagetools","inspect",l,"--raw"],timeoutMs:M});if(e.spawnError!==void 0)return t(a("daemon_unreachable",`Docker CLI is not available: ${e.spawnError}`,{stderrTail:e.stderrTail}));if(e.exitCode===null)return t(a("abort",`docker buildx imagetools inspect ${l} was aborted`,{stderrTail:e.stderrTail}));if(e.exitCode!==0)return t(a("inspect_failed",`docker buildx imagetools inspect ${l} failed (exit ${e.exitCode})`,{stderrTail:e.stderrTail}));let u,r;try{const o=JSON.parse(e.stdout);typeof o.mediaType=="string"&&(u=o.mediaType),typeof o.digest=="string"&&(r=o.digest)}catch(o){s.logger.debug(C,"imagetools inspect output is not JSON; preserving raw",{error:b(O(o))})}return _({raw:e.stdout,...u!==void 0&&{mediaType:u},...r!==void 0&&{digest:r}})}g(de,"_imagetoolsInspect");export{oe as _buildxBuild,de as _imagetoolsInspect,ne as _tagByDigest};
|
|
@@ -97,9 +97,10 @@ export declare class DockerCli {
|
|
|
97
97
|
buildxBuild(args: BuildxBuildArgs, onProgress: (event: BuildxProgressEvent) => void, abortSignal?: AbortSignal): Promise<Result<BuildxBuildResult, DockerCliError>>;
|
|
98
98
|
tag(source: string, target: string): Promise<Result<void, DockerCliError>>;
|
|
99
99
|
/**
|
|
100
|
-
* Create one or more
|
|
101
|
-
*
|
|
102
|
-
*
|
|
100
|
+
* Create one or more tags pointing at a previously pushed digest without
|
|
101
|
+
* re-uploading layers. Uses `docker buildx imagetools create
|
|
102
|
+
* --prefer-index=false` (a flat carbon-copy, not an image index — see
|
|
103
|
+
* `_tagByDigest`) against `<sourceImage>@<digest>`.
|
|
103
104
|
*/
|
|
104
105
|
tagByDigest(sourceImage: string, digest: string, tags: readonly string[]): Promise<Result<void, DockerCliError>>;
|
|
105
106
|
push(image: string, onProgress?: (event: PushProgressEvent) => void): Promise<Result<PushResult, DockerCliError>>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LambdaArchitecture } from "../manifest/schemas.js";
|
|
2
|
+
export declare function dockerPlatformForArchitecture(architecture: LambdaArchitecture): string;
|
|
3
|
+
/**
|
|
4
|
+
* The CPU architecture every fjall ECS task runs on. Coupled to the construct
|
|
5
|
+
* pin `runtimePlatform.cpuArchitecture: CpuArchitecture.ARM64` in
|
|
6
|
+
* `components/infrastructure/lib/resources/aws/compute/ecsTaskDefinition.ts`
|
|
7
|
+
* (both task-definition call sites) — ECS manifest entries carry no
|
|
8
|
+
* `architecture` field, so build orchestrators consume this constant to
|
|
9
|
+
* enumerate the implicit constraint when an ECS service shares a build group
|
|
10
|
+
* with an architecture-declaring Lambda.
|
|
11
|
+
*/
|
|
12
|
+
export declare const ECS_TASK_ARCHITECTURE: LambdaArchitecture;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var n=Object.defineProperty;var t=(r,o)=>n(r,"name",{value:o,configurable:!0});const A={arm64:"linux/arm64",x86_64:"linux/amd64"};function _(r){return A[r]}t(_,"dockerPlatformForArchitecture");const c="arm64";export{c as ECS_TASK_ARCHITECTURE,_ as dockerPlatformForArchitecture};
|
package/dist/docker/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { type Result, isSuccess, isFailure, success, failure } from "./result.js
|
|
|
2
2
|
export { DOCKER_CLI_LOG_CATEGORY, DOCKER_CLI_BUILDX_LOG_CATEGORY, BUILDX_VERSION_FLOOR, ENGINE_VERSION_FLOOR, PrerequisiteMissingExitCode, DEFAULT_BUILDER_NAME, DEFAULT_DOCKER_BIN, SIGTERM_GRACE_MS, STDERR_TAIL_LINES, DEFAULT_BUILD_TIMEOUT_MS, DEFAULT_PUSH_STALL_TIMEOUT_MS, DEFAULT_PUSH_TIMEOUT_MS, DEFAULT_PULL_TIMEOUT_MS, DEFAULT_INSPECT_TIMEOUT_MS, DEFAULT_DAEMON_PROBE_TIMEOUT_MS } from "./dockerCliConstants.js";
|
|
3
3
|
export { BuildxBuildArgsSchema, BuildxBuildResultSchema, DockerCliErrorKindSchema, DockerCliErrorSchema, isDockerCliErrorKind, type BuildxBuildArgs, type BuildxBuildResult, type DockerCliError, type DockerCliErrorKind } from "./dockerCliSchemas.js";
|
|
4
4
|
export { buildxArgvBuilder } from "./buildxArgvBuilder.js";
|
|
5
|
+
export { dockerPlatformForArchitecture, ECS_TASK_ARCHITECTURE } from "./architecture.js";
|
|
5
6
|
export { BUILD_TIMEOUT_ENV_VAR, PUSH_STALL_TIMEOUT_ENV_VAR, BuildxBuildMonitor, buildPhaseTimeoutMessage, publishStallTimeoutMessage, resolveBuildxBudgets, type BuildxBudgets, type BuildxTimeoutPhase, type SyntheticBuildxProgress } from "./buildxBuildMonitor.js";
|
|
6
7
|
export { evaluateBakeGuard, evaluateResolvedBuildArgValues, acknowledgedBuildArgKeys, createBakeWarningDeduper, BAKE_GUARD_EXPOSURE_CLAUSE, type BakeGuardFinding, type BakeGuardFindingReason, type BakeGuardWarning, type BakeGuardResult } from "./bakeGuard.js";
|
|
7
8
|
export { PUBLIC_BUILD_ARG_PREFIXES, isPublicBuildVarName, inferPublicBuildArgKeys, type InferPublicBuildArgKeysInput } from "./buildArgInference.js";
|
package/dist/docker/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isSuccess as _,isFailure as
|
|
1
|
+
import{isSuccess as _,isFailure as o,success as E,failure as i}from"./result.js";import{DOCKER_CLI_LOG_CATEGORY as t,DOCKER_CLI_BUILDX_LOG_CATEGORY as T,BUILDX_VERSION_FLOOR as s,ENGINE_VERSION_FLOOR as u,PrerequisiteMissingExitCode as a,DEFAULT_BUILDER_NAME as A,DEFAULT_DOCKER_BIN as L,SIGTERM_GRACE_MS as U,STDERR_TAIL_LINES as R,DEFAULT_BUILD_TIMEOUT_MS as d,DEFAULT_PUSH_STALL_TIMEOUT_MS as S,DEFAULT_PUSH_TIMEOUT_MS as D,DEFAULT_PULL_TIMEOUT_MS as I,DEFAULT_INSPECT_TIMEOUT_MS as c,DEFAULT_DAEMON_PROBE_TIMEOUT_MS as B}from"./dockerCliConstants.js";import{BuildxBuildArgsSchema as O,BuildxBuildResultSchema as M,DockerCliErrorKindSchema as m,DockerCliErrorSchema as x,isDockerCliErrorKind as p}from"./dockerCliSchemas.js";import{buildxArgvBuilder as N}from"./buildxArgvBuilder.js";import{dockerPlatformForArchitecture as g,ECS_TASK_ARCHITECTURE as n}from"./architecture.js";import{BUILD_TIMEOUT_ENV_VAR as h,PUSH_STALL_TIMEOUT_ENV_VAR as G,BuildxBuildMonitor as V,buildPhaseTimeoutMessage as K,publishStallTimeoutMessage as b,resolveBuildxBudgets as k}from"./buildxBuildMonitor.js";import{evaluateBakeGuard as H,evaluateResolvedBuildArgValues as y,acknowledgedBuildArgKeys as X,createBakeWarningDeduper as j,BAKE_GUARD_EXPOSURE_CLAUSE as w}from"./bakeGuard.js";import{PUBLIC_BUILD_ARG_PREFIXES as q,isPublicBuildVarName as W,inferPublicBuildArgKeys as z}from"./buildArgInference.js";import{parseRawjsonLine as Q}from"./rawjsonParser.js";import{rawjsonToVertexEvent as $}from"./rawjsonToVertexEvent.js";import{parseMetadataFile as re}from"./metadataFileParser.js";import{projectBuildxResult as oe}from"./projectBuildxResult.js";import{abortChildProcess as ie}from"./abortHelpers.js";import{DockerCli as te}from"./DockerCli.js";import{createEcrAuthSession as se}from"./ecrCredentialStore.js";import{buildCacheRepositoryName as ae,buildRegistryCacheRefs as Ae,resolveBuildCacheMode as Le,untaggedLifecyclePolicyText as Ue,BUILD_CACHE_MODE_ENV_VAR as Re,BUILD_CACHE_MODES as de,CACHE_REPO_UNTAGGED_RETENTION_DAYS as Se}from"./cacheRepository.js";export{w as BAKE_GUARD_EXPOSURE_CLAUSE,s as BUILDX_VERSION_FLOOR,de as BUILD_CACHE_MODES,Re as BUILD_CACHE_MODE_ENV_VAR,h as BUILD_TIMEOUT_ENV_VAR,O as BuildxBuildArgsSchema,V as BuildxBuildMonitor,M as BuildxBuildResultSchema,Se as CACHE_REPO_UNTAGGED_RETENTION_DAYS,A as DEFAULT_BUILDER_NAME,d as DEFAULT_BUILD_TIMEOUT_MS,B as DEFAULT_DAEMON_PROBE_TIMEOUT_MS,L as DEFAULT_DOCKER_BIN,c as DEFAULT_INSPECT_TIMEOUT_MS,I as DEFAULT_PULL_TIMEOUT_MS,S as DEFAULT_PUSH_STALL_TIMEOUT_MS,D as DEFAULT_PUSH_TIMEOUT_MS,T as DOCKER_CLI_BUILDX_LOG_CATEGORY,t as DOCKER_CLI_LOG_CATEGORY,te as DockerCli,m as DockerCliErrorKindSchema,x as DockerCliErrorSchema,n as ECS_TASK_ARCHITECTURE,u as ENGINE_VERSION_FLOOR,q as PUBLIC_BUILD_ARG_PREFIXES,G as PUSH_STALL_TIMEOUT_ENV_VAR,a as PrerequisiteMissingExitCode,U as SIGTERM_GRACE_MS,R as STDERR_TAIL_LINES,ie as abortChildProcess,X as acknowledgedBuildArgKeys,ae as buildCacheRepositoryName,K as buildPhaseTimeoutMessage,Ae as buildRegistryCacheRefs,N as buildxArgvBuilder,j as createBakeWarningDeduper,se as createEcrAuthSession,g as dockerPlatformForArchitecture,H as evaluateBakeGuard,y as evaluateResolvedBuildArgValues,i as failure,z as inferPublicBuildArgKeys,p as isDockerCliErrorKind,o as isFailure,W as isPublicBuildVarName,_ as isSuccess,re as parseMetadataFile,Q as parseRawjsonLine,oe as projectBuildxResult,b as publishStallTimeoutMessage,$ as rawjsonToVertexEvent,Le as resolveBuildCacheMode,k as resolveBuildxBudgets,E as success,Ue as untaggedLifecyclePolicyText};
|
package/dist/manifest/io.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* that need the docker-shape types without I/O (e.g. the generator) MUST
|
|
7
7
|
* import from `./schemas` directly.
|
|
8
8
|
*/
|
|
9
|
-
import { type DockerBuild, type FjallManifest, type ResourceMapEntry } from "./schemas.js";
|
|
9
|
+
import { type DockerBuild, type FjallManifest, type LambdaArchitecture, type ResourceMapEntry } from "./schemas.js";
|
|
10
10
|
/**
|
|
11
11
|
* Get the manifest file path for a cdk.out directory.
|
|
12
12
|
*/
|
|
@@ -49,6 +49,14 @@ export interface ManifestDockerService {
|
|
|
49
49
|
* (`@fjall/deploy-core` dockerInterface.ts).
|
|
50
50
|
*/
|
|
51
51
|
readonly isLambda?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The Lambda's CPU architecture (absent for ECS services and for
|
|
54
|
+
* bring-your-own-image Lambdas). Lets the Docker build pipeline pick a
|
|
55
|
+
* `buildx --platform` matching the function's configured `Architectures`
|
|
56
|
+
* instead of always building the default arm64 — see
|
|
57
|
+
* `dockerPlatformForArchitecture` in `@fjall/util/docker`.
|
|
58
|
+
*/
|
|
59
|
+
readonly architecture?: LambdaArchitecture;
|
|
52
60
|
}
|
|
53
61
|
/**
|
|
54
62
|
* Extract services with a Docker build configuration from the Fjall manifest.
|
|
@@ -84,13 +92,14 @@ export declare function parseDockerServicesFromManifest(cdkOutPath: string): Man
|
|
|
84
92
|
* contains no Lambda Docker entries. Lambdas without a `docker` block
|
|
85
93
|
* (bring-your-own-image) are skipped, not an error.
|
|
86
94
|
*
|
|
87
|
-
* Throws deliberately (not a `Result`) on
|
|
88
|
-
* configs even though `Result`-returning
|
|
89
|
-
* config error surfaced before any build
|
|
90
|
-
* boundary converts it — the CLI's `catch` in
|
|
95
|
+
* Throws deliberately (not a `Result`) on entries sharing an `imageKey` with
|
|
96
|
+
* divergent docker configs or `architecture` even though `Result`-returning
|
|
97
|
+
* callers sit above it: the throw is a config error surfaced before any build
|
|
98
|
+
* starts, and every production boundary converts it — the CLI's `catch` in
|
|
99
|
+
* `deployApplication`
|
|
91
100
|
* (`cli/src/services/deployment/applicationDeployment.ts`), the webapp
|
|
92
101
|
* worker's job-level `catch` in `deploymentJobHandler`, and the `fjall build`
|
|
93
|
-
* orchestrator's call-site `catch` in `
|
|
102
|
+
* orchestrator's call-site `catch` in `resolveLambdaBuildIdentities`
|
|
94
103
|
* (`cli/src/services/container/EcrBuildOrchestrator.ts`). Sanctioned per the
|
|
95
104
|
* 2026-07-16 docker-lambda review; do not re-litigate as a Pitfall-4 escape.
|
|
96
105
|
*/
|
|
@@ -102,6 +111,7 @@ export interface ManifestLambdaDockerEntry {
|
|
|
102
111
|
/** Shared build/tag key — `imageKey` if set, else `name`. */
|
|
103
112
|
readonly imageKey: string;
|
|
104
113
|
readonly docker: DockerBuild;
|
|
114
|
+
readonly architecture?: LambdaArchitecture;
|
|
105
115
|
}
|
|
106
116
|
/**
|
|
107
117
|
* Extract every container-Lambda manifest entry that declared a `docker`
|
package/dist/manifest/io.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var y=Object.defineProperty;var i=(t,
|
|
1
|
+
var y=Object.defineProperty;var i=(t,r)=>y(t,"name",{value:r,configurable:!0});import{readFile as M,writeFile as b,unlink as F,rename as k,mkdir as S}from"fs/promises";import{readFileSync as A}from"fs";import{dirname as w,join as u}from"path";import{logger as c}from"../logger.js";import{maskSensitiveOutput as E}from"../securityHelpers.js";import{fileExists as v}from"../fsHelpers.js";import{getErrorMessage as d}from"../errorUtils.js";import{recordToConstructMap as x}from"../constructMap.js";import{FjallManifestSchema as L,FJALL_MANIFEST_FILENAME as m,MANIFEST_SCHEMA_VERSION as D,normaliseDockerBuild as l,LAMBDA_ARCHITECTURE_VALUES as j}from"./schemas.js";function p(t){return u(t,m)}i(p,"getManifestFilePath");async function N(t){const r=p(t);if(!await v(r))return null;try{const n=await M(r,"utf-8"),e=JSON.parse(n),a=L.safeParse(e);return a.success||c.debug("FjallManifest","Manifest validation failed",{path:r,errors:a.error.issues.map(o=>`${o.path.join(".")}: ${o.message}`)}),a.success?a.data:null}catch(n){return c.debug("FjallManifest","Failed to read manifest file",{path:r,error:d(n)}),null}}i(N,"readManifestFile");async function H(t,r){const n=p(t),e=`${n}.${Date.now()}.tmp`;await S(w(n),{recursive:!0});try{await b(e,JSON.stringify(r,null,2),"utf-8"),await k(e,n)}catch(a){try{await F(e)}catch(o){c.debug("FjallManifest","Temp file cleanup failed (non-fatal)",{path:e,error:d(o)})}throw a}}i(H,"writeManifestFile");function U(t){return{version:D,generatedAt:new Date().toISOString(),appName:t,services:[],lambdas:[],stacks:{}}}i(U,"createEmptyManifest");async function V(t){const r=await N(t);return r?.resourceMap?x(r.resourceMap):new Map}i(V,"readConstructMap");function f(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}i(f,"isRecord");function g(t,r){const n=u(t,m);let e;try{e=A(n,"utf-8")}catch{c.debug("FjallManifest",`Manifest file not readable \u2014 no ${r} extracted`,{path:n});return}let a;try{a=JSON.parse(e)}catch{c.debug("FjallManifest",`Manifest is not valid JSON \u2014 no ${r} extracted`,{path:n});return}return f(a)?a:void 0}i(g,"readManifestRecord");function I(t){const r=g(t,"Docker services");if(r===void 0||!Array.isArray(r.services))return[];const n=[];for(const e of r.services){if(!f(e)||typeof e.name!="string")continue;const a=l(e.docker);a!==void 0&&n.push({name:e.name,docker:a,isLambda:!1})}return n}i(I,"parseDockerServicesFromManifest");function q(t){const r=new Map;for(const{name:n,imageKey:e,docker:a,architecture:o}of h(t)){const s=r.get(e);if(s===void 0){r.set(e,{name:e,docker:a,isLambda:!0,...o!==void 0&&{architecture:o}});continue}if(JSON.stringify(s.docker)!==JSON.stringify(a)||s.architecture!==o)throw new Error(`Lambda functions sharing image key "${e}" 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: "${n}").`)}return Array.from(r.values())}i(q,"parseLambdaDockerServicesFromManifest");function h(t){const r=g(t,"Lambda Docker entries");if(r===void 0||!Array.isArray(r.lambdas))return[];const n=[];for(const e of r.lambdas){if(!f(e)||typeof e.name!="string")continue;const a=l(e.docker);if(a===void 0)continue;const o=typeof e.imageKey=="string"&&e.imageKey.length>0?e.imageKey:e.name;let s;typeof e.architecture=="string"&&(j.includes(e.architecture)?s=e.architecture:c.debug("FjallManifest","Ignoring unrecognised Lambda architecture \u2014 build falls back to the default platform",{lambda:e.name,architecture:E(e.architecture)})),n.push({name:e.name,imageKey:o,docker:a,...s!==void 0&&{architecture:s}})}return n}i(h,"parseLambdaDockerEntriesFromManifest");function z(t){const r=I(t),n=h(t);return{ecsServices:r,lambdaEntries:n,declaresBuild:r.length>0||n.length>0}}i(z,"parseDockerDeclarationsFromManifest");export{U as createEmptyManifest,p as getManifestFilePath,z as parseDockerDeclarationsFromManifest,I as parseDockerServicesFromManifest,h as parseLambdaDockerEntriesFromManifest,q as parseLambdaDockerServicesFromManifest,V as readConstructMap,N as readManifestFile,H as writeManifestFile};
|
|
@@ -253,6 +253,15 @@ declare const ManifestEcrSchema: z.ZodObject<{
|
|
|
253
253
|
repositoryName: z.ZodString;
|
|
254
254
|
}, z.core.$strict>;
|
|
255
255
|
export type ManifestEcr = z.infer<typeof ManifestEcrSchema>;
|
|
256
|
+
/**
|
|
257
|
+
* CPU architecture values a container Lambda's `architecture` prop can take,
|
|
258
|
+
* mirrored from CDK's `Architecture.ARM_64.name` / `Architecture.X86_64.name`
|
|
259
|
+
* so the manifest never depends on aws-cdk-lib. Consumed by the Docker build
|
|
260
|
+
* pipeline (`dockerPlatformForArchitecture`, `@fjall/util/docker`) to pick the
|
|
261
|
+
* `buildx --platform` that matches the Lambda's own CPU architecture.
|
|
262
|
+
*/
|
|
263
|
+
export declare const LAMBDA_ARCHITECTURE_VALUES: readonly ["x86_64", "arm64"];
|
|
264
|
+
export type LambdaArchitecture = (typeof LAMBDA_ARCHITECTURE_VALUES)[number];
|
|
256
265
|
declare const ManifestLambdaSchema: z.ZodObject<{
|
|
257
266
|
name: z.ZodString;
|
|
258
267
|
secrets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -284,6 +293,10 @@ declare const ManifestLambdaSchema: z.ZodObject<{
|
|
|
284
293
|
}, z.core.$strict>>>;
|
|
285
294
|
}, z.core.$strict>>;
|
|
286
295
|
imageKey: z.ZodOptional<z.ZodString>;
|
|
296
|
+
architecture: z.ZodOptional<z.ZodEnum<{
|
|
297
|
+
x86_64: "x86_64";
|
|
298
|
+
arm64: "arm64";
|
|
299
|
+
}>>;
|
|
287
300
|
}, z.core.$strict>;
|
|
288
301
|
export type ManifestLambda = z.infer<typeof ManifestLambdaSchema>;
|
|
289
302
|
declare const ManifestStackHashSchema: z.ZodObject<{
|
|
@@ -375,6 +388,10 @@ export declare const FjallManifestSchema: z.ZodObject<{
|
|
|
375
388
|
}, z.core.$strict>>>;
|
|
376
389
|
}, z.core.$strict>>;
|
|
377
390
|
imageKey: z.ZodOptional<z.ZodString>;
|
|
391
|
+
architecture: z.ZodOptional<z.ZodEnum<{
|
|
392
|
+
x86_64: "x86_64";
|
|
393
|
+
arm64: "arm64";
|
|
394
|
+
}>>;
|
|
378
395
|
}, z.core.$strict>>;
|
|
379
396
|
pattern: z.ZodOptional<z.ZodObject<{
|
|
380
397
|
type: z.ZodEnum<{
|
package/dist/manifest/schemas.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var y=Object.defineProperty;var i=(t,n)=>y(t,"name",{value:n,configurable:!0});import{z as e}from"zod";import{PATTERN_TYPE_VALUES as S}from"../patterns/patternTypes.js";const
|
|
1
|
+
var y=Object.defineProperty;var i=(t,n)=>y(t,"name",{value:n,configurable:!0});import{z as e}from"zod";import{PATTERN_TYPE_VALUES as S}from"../patterns/patternTypes.js";const I="fjall-manifest.json",h=1,x=/^[A-Za-z0-9_.-]+$/,A=e.object({id:e.string().min(1,"buildSecret id cannot be empty").regex(x,"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)"})}),M=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(),M).optional(),buildSecrets:e.array(A).optional()}).strict(),N=c.partial();function B(t,n){if(n===void 0)return t;const o=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,...o!==void 0&&{context:o},...r!==void 0&&{target:r},...s!==void 0&&{buildArgs:s},...a!==void 0&&{buildSecrets:a}}}i(B,"mergeDockerBuild");function m(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}i(m,"isRecord");function j(t){if(!m(t)||typeof t.path!="string"||t.path.length===0)return;const n=typeof t.context=="string"&&t.context.length>0?t.context:void 0,o=typeof t.target=="string"&&t.target.length>0?t.target:void 0,r=m(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},...o!==void 0&&{target:o},...r!==void 0&&{buildArgs:r},...s!==void 0&&{buildSecrets:s}},d=c.safeParse(a);return d.success?d.data:void 0}i(j,"normaliseDockerBuild");function P(t){if(t===void 0)return;const n=j(t);return n===void 0?void 0:JSON.stringify(n)}i(P,"dockerBuildFingerprint");const p=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(),g=e.object({type:e.enum(S),name:e.string(),source:e.string()}).strict(),l=e.object({repositoryName:e.string()}).strict(),E=["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(E).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(),R=e.object({version:e.literal(h),generatedAt:e.string(),appName:e.string(),services:e.array(p),lambdas:e.array(u),pattern:g.optional(),ecr:l.optional(),stacks:e.record(e.string(),f),resourceMap:e.record(e.string(),b).optional()}).strict();export{x as BUILDKIT_SECRET_ID_PATTERN,M as DockerBuildArgValueSchema,N as DockerBuildPartialSchema,c as DockerBuildSchema,A as DockerBuildSecretRefSchema,I as FJALL_MANIFEST_FILENAME,R as FjallManifestSchema,E as LAMBDA_ARCHITECTURE_VALUES,h as MANIFEST_SCHEMA_VERSION,l as ManifestEcrSchema,u as ManifestLambdaSchema,g as ManifestPatternSchema,p as ManifestServiceSchema,f as ManifestStackHashSchema,b as ResourceMapEntrySchema,P 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.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"description": "Common utility methods",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -134,5 +134,5 @@
|
|
|
134
134
|
"engines": {
|
|
135
135
|
"node": ">=22.0.0"
|
|
136
136
|
},
|
|
137
|
-
"gitHead": "
|
|
137
|
+
"gitHead": "a15125ea026d52428ff5433d098699899695ca3f"
|
|
138
138
|
}
|