@fjall/deploy-core 2.29.0 → 2.30.3

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.
Files changed (37) hide show
  1. package/dist/.minified +1 -1
  2. package/dist/src/index.d.ts +4 -2
  3. package/dist/src/index.js +1 -1
  4. package/dist/src/orchestration/application/applicationDeploy.js +1 -1
  5. package/dist/src/orchestration/application/applicationDeployHelpers.d.ts +18 -0
  6. package/dist/src/orchestration/application/applicationDeployHelpers.js +3 -3
  7. package/dist/src/orchestration/application/artefactCollection.d.ts +8 -1
  8. package/dist/src/orchestration/application/artefactCollection.js +1 -1
  9. package/dist/src/orchestration/application/codeOnlyDeploy.d.ts +32 -1
  10. package/dist/src/orchestration/application/codeOnlyDeploy.js +1 -1
  11. package/dist/src/orchestration/application/dockerBuildHelper.d.ts +1 -0
  12. package/dist/src/orchestration/application/dockerBuildHelper.js +1 -1
  13. package/dist/src/orchestration/application/lambdaCodeOnlyRollout.d.ts +58 -0
  14. package/dist/src/orchestration/application/lambdaCodeOnlyRollout.js +1 -0
  15. package/dist/src/orchestration/application/openNextBuild.d.ts +1 -1
  16. package/dist/src/orchestration/application/openNextBuild.js +3 -3
  17. package/dist/src/orchestration/builders/frameworkRegistry.js +1 -1
  18. package/dist/src/orchestration/builders/index.d.ts +1 -0
  19. package/dist/src/orchestration/builders/index.js +1 -1
  20. package/dist/src/orchestration/builders/openNextBuilder.js +1 -1
  21. package/dist/src/orchestration/builders/staticSiteBuilder.d.ts +27 -0
  22. package/dist/src/orchestration/builders/staticSiteBuilder.js +2 -0
  23. package/dist/src/orchestration/serviceFactory.d.ts +2 -0
  24. package/dist/src/orchestration/serviceFactory.js +1 -1
  25. package/dist/src/orchestration/spawnHelpers.d.ts +9 -0
  26. package/dist/src/orchestration/spawnHelpers.js +1 -1
  27. package/dist/src/services/infrastructure/LambdaService.d.ts +45 -0
  28. package/dist/src/services/infrastructure/LambdaService.js +1 -0
  29. package/dist/src/types/deployEvent.d.ts +10 -3
  30. package/dist/src/types/deployEvent.js +1 -1
  31. package/dist/src/types/detection/patternTypes.d.ts +9 -4
  32. package/dist/src/types/detection/patternTypes.js +1 -1
  33. package/dist/src/types/frameworkBuilder.d.ts +14 -0
  34. package/dist/src/types/index.d.ts +36 -2
  35. package/dist/src/types/index.js +1 -1
  36. package/dist/src/types/operations.d.ts +2 -1
  37. package/package.json +6 -4
@@ -1,3 +1,3 @@
1
- import{createRequire as _}from"module";import{existsSync as g,statSync as S,rmSync as $}from"fs";import{join as l}from"path";import{success as f,failure as i}from"@fjall/generator";import{filterDangerousEnvVars as y,maskSensitiveOutput as d,parseShellArgs as v}from"@fjall/util";import{logger as c}from"@fjall/util/logger";import{isOpenNextPattern as b}from"../../types/detection/patternDetection.js";import{spawnWithTimeout as E}from"../spawnHelpers.js";const x="@opennextjs/aws",P=6e5,w=3e4;function T(s){const n=_(l(s,"package.json"));let e;try{e=n.resolve.paths(x)}catch(r){return i(new Error(`Cannot determine module search paths for ${x}. Ensure it is installed in your project. (${r instanceof Error?r.message:String(r)})`))}if(!e||e.length===0)return i(new Error(`Cannot determine module search paths for ${x}. Ensure it is installed in your project.`));for(const r of e){const t=l(r,"@opennextjs","aws");try{if(S(t).isDirectory()){const p=l(r,".bin","open-next");if(!g(p)){c.debug("openNextBuild","Package found but binary missing",{nodeModulesPath:r,binPath:p});continue}return c.debug("openNextBuild","Resolved OpenNext binary",{binPath:p}),f(p)}}catch(o){c.debug("openNextBuild","Package not at location",{nodeModulesPath:r,error:String(o)})}}return i(new Error(`Cannot find ${x} package. Ensure it is installed in your project: npm install ${x}`))}function O(s){const n=l(s,".open-next");if(g(n))try{$(n,{recursive:!0,force:!0}),c.debug("openNextBuild","Cleaned up stale .open-next directory",{path:n})}catch(e){c.debug("openNextBuild","Failed to clean up .open-next",{error:String(e)})}}function B(s,n,e,r){switch(s.type){case"timeout":return e?.(),r?.(n.timeoutMsg),i(new Error(n.timeoutMsg));case"enoent":return e?.(),r?.(n.enoentMsg),i(new Error(n.enoentMsg));case"spawn_error":{const t=`${n.spawnErrorPrefix}: ${s.error.message}`;return e?.(),r?.(t),i(new Error(t))}default:return}}async function D(s,n){n.onOpenNextProgress?.(d("Generating Payload import map..."));const[e,...r]=v("npx payload generate:importmap"),t=y(globalThis.process.env),o=await E({command:e,args:r,cwd:s,env:{...t,FORCE_COLOR:"0"},timeout:w,onStdoutData:m=>{n.onOpenNextProgress?.(d(m.trim()))}}),p=B(o,{timeoutMsg:`Payload import map generation timed out after ${w/1e3} seconds`,enoentMsg:"Payload CLI not found. Ensure payload is installed: npm install payload",spawnErrorPrefix:"Failed to generate Payload import map"});if(p)return p;if(o.type!=="success")return i(new Error("Unexpected spawn result"));if(o.code!==0){const m=d(o.stderr||o.stdout);return i(new Error(`Payload import map generation failed (exit code ${o.code}):
2
- ${m}`))}return c.debug("openNextBuild","Payload import map generated",{appPath:s}),n.onOpenNextProgress?.(d("Payload import map generated")),f(void 0)}async function H(s,n,e,r){if(!b(n))return f(void 0);if(r?.skipBuild||r?.infraOnly)return c.debug("openNextBuild","Build skipped",{skipBuild:r?.skipBuild,infraOnly:r?.infraOnly}),e.onLog?.(r?.infraOnly?"Infrastructure-only mode \u2014 skipping OpenNext build":"Build skipped (--skip-build)","info"),f(void 0);const t=s.path;if(n==="payload"){const u=await D(t,e);if(!u.success)return e.onOpenNextBuildError?.(d(u.error.message)),O(t),i(u.error)}const o=T(t);if(!o.success)return e.onOpenNextBuildError?.(d(o.error.message)),i(o.error);const p=o.data;e.onOpenNextBuildStart?.(),e.onOpenNextProgress?.(d("Starting OpenNext build..."));const m=y(globalThis.process.env),M=l(t,"node_modules"),a=await E({command:p,args:["build"],cwd:t,env:{...m,FORCE_COLOR:"0",NODE_PATH:M,npm_config_loglevel:"error",PNPM_HOME:m.PNPM_HOME||""},timeout:P,onStdoutData:u=>{e.onOpenNextProgress?.(d(u.trim()))},onStderrData:u=>{e.onOpenNextProgress?.(d(u.trim()))}}),N=B(a,{timeoutMsg:`OpenNext build timed out after ${P/1e3} seconds`,enoentMsg:"OpenNext binary not found. Ensure Node.js is installed and in PATH.",spawnErrorPrefix:"Failed to spawn OpenNext build"},()=>O(t),u=>e.onOpenNextBuildError?.(u));if(N)return N;if(a.type!=="success")return i(new Error("Unexpected spawn result"));if(a.code!==0){O(t);const u=d(a.stderr||a.stdout);return e.onOpenNextBuildError?.(`OpenNext build failed (exit code ${a.code})`),i(new Error(`OpenNext build failed (exit code ${a.code}):
3
- ${u}`))}const h=l(t,".open-next");return g(h)?(e.onOpenNextBuildComplete?.(),e.onOpenNextProgress?.(d("OpenNext build completed successfully")),f(void 0)):(e.onOpenNextBuildError?.("OpenNext build completed but .open-next directory not found"),i(new Error("OpenNext build completed but .open-next directory not found")))}export{P as BUILD_TIMEOUT_MS,w as IMPORT_MAP_TIMEOUT_MS,H as runOpenNextBuild};
1
+ import{createRequire as $}from"module";import{existsSync as O,statSync as v,rmSync as S}from"fs";import{join as f}from"path";import{success as l,failure as o}from"@fjall/generator";import{filterDangerousEnvVars as E,maskSensitiveOutput as u,parseShellArgs as b}from"@fjall/util";import{logger as c}from"@fjall/util/logger";import{isOpenNextPattern as T}from"../../types/detection/patternDetection.js";import{spawnWithTimeout as P}from"../spawnHelpers.js";const x="@opennextjs/aws",w=6e5,M=3e4;function D(s){const n=$(f(s,"package.json"));let e;try{e=n.resolve.paths(x)}catch(r){return o(new Error(`Cannot determine module search paths for ${x}. Ensure it is installed in your project. (${r instanceof Error?r.message:String(r)})`))}if(!e||e.length===0)return o(new Error(`Cannot determine module search paths for ${x}. Ensure it is installed in your project.`));for(const r of e){const p=f(r,"@opennextjs","aws");try{if(v(p).isDirectory()){const t=f(r,".bin","open-next");if(!O(t)){c.debug("openNextBuild","Package found but binary missing",{nodeModulesPath:r,binPath:t});continue}return c.debug("openNextBuild","Resolved OpenNext binary",{binPath:t}),l(t)}}catch(i){c.debug("openNextBuild","Package not at location",{nodeModulesPath:r,error:String(i)})}}return o(new Error(`Cannot find ${x} package. Ensure it is installed in your project: npm install ${x}`))}function N(s){const n=f(s,".open-next");if(O(n))try{S(n,{recursive:!0,force:!0}),c.debug("openNextBuild","Cleaned up stale .open-next directory",{path:n})}catch(e){c.debug("openNextBuild","Failed to clean up .open-next",{error:String(e)})}}function B(s,n,e,r){switch(s.type){case"timeout":return e?.(),r?.(n.timeoutMsg),o(new Error(n.timeoutMsg));case"aborted":return e?.(),r?.(n.abortedMsg),o(new Error(n.abortedMsg));case"enoent":return e?.(),r?.(n.enoentMsg),o(new Error(n.enoentMsg));case"spawn_error":{const p=`${n.spawnErrorPrefix}: ${s.error.message}`;return e?.(),r?.(p),o(new Error(p))}default:return}}async function j(s,n,e){n.onOpenNextProgress?.(u("Generating Payload import map..."));const[r,...p]=b("npx payload generate:importmap"),i=E(globalThis.process.env),t=await P({command:r,args:p,cwd:s,env:{...i,FORCE_COLOR:"0"},timeout:M,...e!==void 0&&{abortSignal:e},onStdoutData:m=>{n.onOpenNextProgress?.(u(m.trim()))}}),g=B(t,{timeoutMsg:`Payload import map generation timed out after ${M/1e3} seconds`,abortedMsg:"Payload import map generation cancelled",enoentMsg:"Payload CLI not found. Ensure payload is installed: npm install payload",spawnErrorPrefix:"Failed to generate Payload import map"});if(g)return g;if(t.type!=="success")return o(new Error("Unexpected spawn result"));if(t.code!==0){const m=u(t.stderr||t.stdout);return o(new Error(`Payload import map generation failed (exit code ${t.code}):
2
+ ${m}`))}return c.debug("openNextBuild","Payload import map generated",{appPath:s}),n.onOpenNextProgress?.(u("Payload import map generated")),l(void 0)}async function q(s,n,e,r,p){if(!T(n))return l(void 0);if(r?.skipBuild||r?.infraOnly)return c.debug("openNextBuild","Build skipped",{skipBuild:r?.skipBuild,infraOnly:r?.infraOnly}),e.onLog?.(r?.infraOnly?"Infrastructure-only mode \u2014 skipping OpenNext build":"Build skipped (--skip-build)","info"),l(void 0);const i=s.path;if(n==="payload"){const d=await j(i,e,p);if(!d.success)return e.onOpenNextBuildError?.(u(d.error.message)),N(i),o(d.error)}const t=D(i);if(!t.success)return e.onOpenNextBuildError?.(u(t.error.message)),o(t.error);const g=t.data;e.onOpenNextBuildStart?.(),e.onOpenNextProgress?.(u("Starting OpenNext build..."));const m=E(globalThis.process.env),h=f(i,"node_modules"),a=await P({command:g,args:["build"],cwd:i,env:{...m,FORCE_COLOR:"0",NODE_PATH:h,npm_config_loglevel:"error",PNPM_HOME:m.PNPM_HOME||""},timeout:w,...p!==void 0&&{abortSignal:p},onStdoutData:d=>{e.onOpenNextProgress?.(u(d.trim()))},onStderrData:d=>{e.onOpenNextProgress?.(u(d.trim()))}}),y=B(a,{timeoutMsg:`OpenNext build timed out after ${w/1e3} seconds`,abortedMsg:"OpenNext build cancelled",enoentMsg:"OpenNext binary not found. Ensure Node.js is installed and in PATH.",spawnErrorPrefix:"Failed to spawn OpenNext build"},()=>N(i),d=>e.onOpenNextBuildError?.(d));if(y)return y;if(a.type!=="success")return o(new Error("Unexpected spawn result"));if(a.code!==0){N(i);const d=u(a.stderr||a.stdout);return e.onOpenNextBuildError?.(`OpenNext build failed (exit code ${a.code})`),o(new Error(`OpenNext build failed (exit code ${a.code}):
3
+ ${d}`))}const _=f(i,".open-next");return O(_)?(e.onOpenNextBuildComplete?.(),e.onOpenNextProgress?.(u("OpenNext build completed successfully")),l(void 0)):(e.onOpenNextBuildError?.("OpenNext build completed but .open-next directory not found"),o(new Error("OpenNext build completed but .open-next directory not found")))}export{w as BUILD_TIMEOUT_MS,M as IMPORT_MAP_TIMEOUT_MS,q as runOpenNextBuild};
@@ -1 +1 @@
1
- import{openNextBuilder as u}from"./openNextBuilder.js";import{dockerBuilder as d}from"./dockerBuilder.js";class n{builders;constructor(e){this.builders=[...e].sort((r,t)=>r.priority-t.priority)}resolve(e,r){if(r){const t=this.builders.find(o=>o.name===r);if(!t)return null;const i=t.detect(e);return{builder:t,detection:{...i,detected:!0}}}for(const t of this.builders){const i=t.detect(e);if(i.detected)return{builder:t,detection:i}}return null}static createDefault(){return new n([u,d])}static create(e){return new n(e)}}export{n as FrameworkRegistry};
1
+ import{openNextBuilder as d}from"./openNextBuilder.js";import{staticSiteBuilder as n}from"./staticSiteBuilder.js";import{dockerBuilder as c}from"./dockerBuilder.js";class o{builders;constructor(e){this.builders=[...e].sort((r,t)=>r.priority-t.priority)}resolve(e,r){if(r){const t=this.builders.find(u=>u.name===r);if(!t)return null;const i=t.detect(e);return{builder:t,detection:{...i,detected:!0}}}for(const t of this.builders){const i=t.detect(e);if(i.detected)return{builder:t,detection:i}}return null}static createDefault(){return new o([d,n,c])}static create(e){return new o(e)}}export{o as FrameworkRegistry};
@@ -1,4 +1,5 @@
1
1
  export { dockerBuilder } from "./dockerBuilder.js";
2
2
  export { openNextBuilder } from "./openNextBuilder.js";
3
+ export { staticSiteBuilder } from "./staticSiteBuilder.js";
3
4
  export { FrameworkRegistry } from "./frameworkRegistry.js";
4
5
  export type { ResolvedBuilder } from "./frameworkRegistry.js";
@@ -1 +1 @@
1
- import{dockerBuilder as o}from"./dockerBuilder.js";import{openNextBuilder as m}from"./openNextBuilder.js";import{FrameworkRegistry as x}from"./frameworkRegistry.js";export{x as FrameworkRegistry,o as dockerBuilder,m as openNextBuilder};
1
+ import{dockerBuilder as o}from"./dockerBuilder.js";import{openNextBuilder as i}from"./openNextBuilder.js";import{staticSiteBuilder as p}from"./staticSiteBuilder.js";import{FrameworkRegistry as d}from"./frameworkRegistry.js";export{d as FrameworkRegistry,o as dockerBuilder,i as openNextBuilder,p as staticSiteBuilder};
@@ -1 +1 @@
1
- import{basename as i}from"path";import{success as p}from"@fjall/generator";import{logger as d}from"@fjall/util/logger";import{OPENNEXT_DEPLOY_ORDER as l,OPENNEXT_DESTROY_ORDER as c}from"../../types/operations.js";import{readInfrastructureContent as m}from"../../types/detection/patternDetection.js";import{runOpenNextBuild as f,BUILD_TIMEOUT_MS as y,IMPORT_MAP_TIMEOUT_MS as x}from"../application/openNextBuild.js";function o(r){return{hasNetwork:!0,hasCompute:!0,hasDatabase:r,hasStorage:!0,hasMessaging:!0,hasCdn:!0}}const E={name:"opennext",priority:10,detect(r){const t={detected:!1,pattern:null,reason:"No OpenNext pattern found",resources:o(!1),hasDatabase:!1,hasDockerfile:!1},e=m(r.appPath);if(!e)return{...t,reason:"No infrastructure.ts found"};if(!e.includes("PatternFactory"))return{...t,reason:"No PatternFactory reference in infrastructure.ts"};if(e.includes('type: "payload"'))return{detected:!0,pattern:"payload",reason:'PatternFactory with type: "payload" detected',resources:o(!0),hasDatabase:!0,hasDockerfile:!1};if(e.includes('type: "nextjs"')){const n=e.includes("DatabaseFactory.build(")||e.includes("database:");return{detected:!0,pattern:"nextjs",reason:'PatternFactory with type: "nextjs" detected',resources:o(n),hasDatabase:n,hasDockerfile:!1}}return{...t,reason:"PatternFactory found but no recognised pattern type"}},plan(r,t){const e=t.pattern==="payload"?[{name:"payload-import-map",binary:"npx",args:["payload","generate:importmap"],timeoutMs:x}]:[];return{builderName:"opennext",deployOrder:l,destroyOrder:c,parallelDestroy:!0,preBuildCommands:e,buildCommand:{name:"open-next-build",binary:"open-next",args:["build"],timeoutMs:y},requiresDockerBuild:!1,resources:t.resources}},async build(r,t,e,n){if(n?.skipBuild||n?.infraOnly)return d.debug("openNextBuilder","Build skipped",{skipBuild:n.skipBuild,infraOnly:n.infraOnly}),p(void 0);const s={kind:"application",appName:i(r)||"app",path:r},u=t.preBuildCommands.some(a=>a.name==="payload-import-map")?"payload":"nextjs";return await f(s,u,{onOpenNextBuildStart:()=>e.onBuildStart?.("opennext"),onOpenNextProgress:a=>e.onBuildProgress?.("opennext",a),onOpenNextBuildComplete:()=>e.onBuildComplete?.("opennext"),onOpenNextBuildError:a=>e.onBuildError?.("opennext",a)})}};export{E as openNextBuilder};
1
+ import{basename as d}from"path";import{success as i,parseInfrastructure as l,isOpenNextPatternType as c}from"@fjall/generator";import{logger as f}from"@fjall/util/logger";import{OPENNEXT_DEPLOY_ORDER as m,OPENNEXT_DESTROY_ORDER as y}from"../../types/operations.js";import{readInfrastructureContent as x}from"../../types/detection/patternDetection.js";import{runOpenNextBuild as N,BUILD_TIMEOUT_MS as O,IMPORT_MAP_TIMEOUT_MS as B}from"../application/openNextBuild.js";function p(r){return{hasNetwork:!0,hasCompute:!0,hasDatabase:r,hasStorage:!0,hasMessaging:!0,hasCdn:!0}}const M={name:"opennext",priority:10,detect(r){const t={detected:!1,pattern:null,reason:"No OpenNext pattern found",resources:p(!1),hasDatabase:!1,hasDockerfile:!1},e=x(r.appPath);if(e===null||e==="")return{...t,reason:"No infrastructure.ts found"};const a=l(e).patternResources.find(o=>c(o.type));if(a===void 0)return{...t,reason:'No PatternFactory with type: "payload" or "nextjs" in infrastructure.ts'};if(a.type==="payload")return{detected:!0,pattern:"payload",reason:'PatternFactory with type: "payload" detected',resources:p(!0),hasDatabase:!0,hasDockerfile:!1};if(a.type==="nextjs"){const o=a.config.database!==void 0;return{detected:!0,pattern:"nextjs",reason:'PatternFactory with type: "nextjs" detected',resources:p(o),hasDatabase:o,hasDockerfile:!1}}return{...t,reason:"PatternFactory found but no recognised pattern type"}},plan(r,t){const e=t.pattern==="payload"?[{name:"payload-import-map",binary:"npx",args:["payload","generate:importmap"],timeoutMs:B}]:[];return{builderName:"opennext",deployOrder:m,destroyOrder:y,parallelDestroy:!0,preBuildCommands:e,buildCommand:{name:"open-next-build",binary:"open-next",args:["build"],timeoutMs:O},requiresDockerBuild:!1,resources:t.resources}},async build(r,t,e,n){if(n?.skipBuild||n?.infraOnly)return f.debug("openNextBuilder","Build skipped",{skipBuild:n.skipBuild,infraOnly:n.infraOnly}),i(void 0);const a={kind:"application",appName:d(r)||"app",path:r},u=t.preBuildCommands.some(s=>s.name==="payload-import-map")?"payload":"nextjs";return await N(a,u,{onOpenNextBuildStart:()=>e.onBuildStart?.("opennext"),onOpenNextProgress:s=>e.onBuildProgress?.("opennext",s),onOpenNextBuildComplete:()=>e.onBuildComplete?.("opennext"),onOpenNextBuildError:s=>e.onBuildError?.("opennext",s)},void 0,n?.abortSignal)}};export{M as openNextBuilder};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * StaticSiteBuilder — FrameworkBuilder implementation for static-site apps.
3
+ *
4
+ * Detects a `type: "staticsite"` PatternFactory call in infrastructure.ts,
5
+ * produces a single-stack (Cdn) build plan, and runs the app's own build
6
+ * command to produce the static artefacts that CDK's BucketDeployment then
7
+ * uploads to S3.
8
+ *
9
+ * Priority 50 — strictly between OpenNext (10) and Docker (100). This is
10
+ * load-bearing: without it the Docker catch-all (priority 100) would claim
11
+ * the static site and emit a container deployment plan.
12
+ *
13
+ * Unlike OpenNext, the build command and its working directory are not
14
+ * hardcoded — they are the app's own, read out of infrastructure.ts with the
15
+ * generator's AST parser (`@fjall/generator` is already a dependency, and its
16
+ * barrel already pulls the parser in, so this costs nothing over a regex).
17
+ */
18
+ import type { FrameworkBuilder } from "../../types/frameworkBuilder.js";
19
+ /** Default static-site build timeout: 10 minutes (mirrors the OpenNext budget) */
20
+ export declare const STATIC_BUILD_TIMEOUT_MS = 600000;
21
+ /**
22
+ * Static-site FrameworkBuilder.
23
+ *
24
+ * Priority 50 — checked after OpenNext (more specific) and before Docker
25
+ * (the fallback catch-all).
26
+ */
27
+ export declare const staticSiteBuilder: FrameworkBuilder;
@@ -0,0 +1,2 @@
1
+ import{existsSync as y}from"fs";import{resolve as f}from"path";import{success as m,failure as u,parseInfrastructure as p}from"@fjall/generator";import{filterDangerousEnvVars as b,maskSensitiveOutput as d,parseShellArgs as B}from"@fjall/util";import{logger as D}from"@fjall/util/logger";import{getApplicationDeployOrder as E,getApplicationDestroyOrder as h}from"../../types/operations.js";import{readInfrastructureContent as g}from"../../types/detection/patternDetection.js";import{spawnWithTimeout as w}from"../spawnHelpers.js";const O=6e5,S={hasNetwork:!1,hasCompute:!1,hasDatabase:!1,hasStorage:!1,hasMessaging:!1,hasCdn:!0};function C(o){return p(o).patternResources.some(r=>r.type==="staticsite")}function P(o){const r=g(o);if(r===null||r==="")return;const t=p(r).patternResources.find(n=>n.type==="staticsite");if(t===void 0||t.type!=="staticsite")return;const{source:i,build:s}=t.config,a=s?.command,c=s?.outputDir;if(!(i===void 0||i===""||a===void 0||a===""||c===void 0||c===""))return{source:i,command:a,outputDir:c}}const R={name:"staticsite",priority:50,detect(o){const r={detected:!1,pattern:null,reason:"No static-site pattern found",resources:S,hasDatabase:!1,hasDockerfile:!1},t=g(o.appPath);return t===null||t===""?{...r,reason:"No infrastructure.ts found"}:C(t)?{detected:!0,pattern:"staticsite",reason:'PatternFactory with type: "staticsite" detected',resources:S,hasDatabase:!1,hasDockerfile:!1}:{...r,reason:'No PatternFactory with type: "staticsite"'}},plan(o,r){const t=P(o.appPath);let i=null;if(t!==void 0){const[s,...a]=B(t.command);s!==void 0&&(i={name:"static-site-build",binary:s,args:a,timeoutMs:O,cwd:t.source})}return{builderName:"staticsite",deployOrder:E({resources:r.resources}),destroyOrder:h({resources:r.resources}),parallelDestroy:!1,preBuildCommands:[],buildCommand:i,requiresDockerBuild:!1,artefactDir:t?.outputDir,resources:r.resources}},async build(o,r,t,i){if(i?.skipBuild||i?.infraOnly)return D.debug("staticSiteBuilder","Build skipped",{skipBuild:i.skipBuild,infraOnly:i.infraOnly}),m(void 0);const{buildCommand:s}=r;if(s===null){const e='Static-site build command could not be read from infrastructure.ts. The pattern needs an inline build block \u2014 build: { command: "npm run build", outputDir: "out" } \u2014 with literal strings, not variables or expressions.';return t.onBuildError?.("staticsite",e),u(new Error(e))}const a=f(o,s.cwd??"."),c=b(globalThis.process.env);t.onBuildStart?.("staticsite"),t.onBuildProgress?.("staticsite",d("Starting static-site build..."));const n=await w({command:s.binary,args:[...s.args],cwd:a,env:{...c,FORCE_COLOR:"0"},timeout:s.timeoutMs,...i?.abortSignal!==void 0&&{abortSignal:i.abortSignal},onStdoutData:e=>t.onBuildProgress?.("staticsite",d(e.trim())),onStderrData:e=>t.onBuildProgress?.("staticsite",d(e.trim()))});if(n.type==="timeout"){const e=`Static-site build timed out after ${s.timeoutMs/1e3} seconds`;return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.type==="aborted"){const e="Static-site build cancelled";return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.type==="enoent"){const e=`Static-site build command not found: ${s.binary}. Ensure it is installed and in PATH.`;return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.type==="spawn_error"){const e=d(`Failed to spawn static-site build: ${n.error.message}`);return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.code!==0){const e=d(n.stderr||n.stdout);return t.onBuildError?.("staticsite",`Static-site build failed (exit code ${n.code})`),u(new Error(`Static-site build failed (exit code ${n.code}):
2
+ ${e}`))}if(r.artefactDir!==void 0){const e=f(a,r.artefactDir);if(!y(e)){const l=`Static-site build completed but output directory '${r.artefactDir}' was not found`;return t.onBuildError?.("staticsite",l),u(new Error(l))}}return t.onBuildComplete?.("staticsite"),t.onBuildProgress?.("staticsite",d("Static-site build completed successfully")),m(void 0)}};export{O as STATIC_BUILD_TIMEOUT_MS,R as staticSiteBuilder};
@@ -3,6 +3,7 @@ import { CdkService } from "../services/infrastructure/CdkService.js";
3
3
  import { CloudFormationService } from "../services/infrastructure/CloudFormationService.js";
4
4
  import { EcsService } from "../services/infrastructure/EcsService.js";
5
5
  import { EcsServiceResolver } from "../services/infrastructure/EcsServiceResolver.js";
6
+ import { LambdaService } from "../services/infrastructure/LambdaService.js";
6
7
  import { EcrImageInspectorService } from "../services/infrastructure/EcrImageInspectorService.js";
7
8
  import { ApplicationStackService } from "../services/application/ApplicationStackService.js";
8
9
  import { TemplateHashService } from "../services/supporting/TemplateHashService.js";
@@ -14,6 +15,7 @@ export interface DeployServices {
14
15
  cfnService: CloudFormationService;
15
16
  ecsService: EcsService;
16
17
  ecsResolver: EcsServiceResolver;
18
+ lambdaService: LambdaService;
17
19
  ecrImageInspector: EcrImageInspectorService;
18
20
  stackService: ApplicationStackService;
19
21
  hashService: TemplateHashService;
@@ -1 +1 @@
1
- import{SimpleAwsProvider as d}from"../aws/SimpleAwsProvider.js";import{CdkService as f}from"../services/infrastructure/CdkService.js";import{CdkArgumentBuilder as v}from"../services/infrastructure/CdkArgumentBuilder.js";import{CdkProcessManager as p}from"../services/infrastructure/CdkProcessManager.js";import{CloudFormationService as g}from"../services/infrastructure/CloudFormationService.js";import{EcsService as w}from"../services/infrastructure/EcsService.js";import{EcsServiceResolver as u}from"../services/infrastructure/EcsServiceResolver.js";import{EcrImageInspectorService as k}from"../services/infrastructure/EcrImageInspectorService.js";import{ApplicationStackService as b}from"../services/application/ApplicationStackService.js";import{TemplateHashService as y}from"../services/supporting/TemplateHashService.js";import{FrameworkRegistry as A}from"./builders/frameworkRegistry.js";function T(e){const r=new d(e.awsCredentials,e.mintScopedBuildSecretSession);r.exportToEnv();const t=new v,i=new p(t,e.abortSignal),n=new f({processManager:i,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},...e.callbacks.onFailureAnalysis!==void 0?{onFailureAnalysis:e.callbacks.onFailureAnalysis}:{}}),o=new g(r),c=new w(r),s=new u(o),a=new k(r),l=new b(n,o,r),S=new y,m=A.createDefault();return{awsProvider:r,cdkService:n,cfnService:o,ecsService:c,ecsResolver:s,ecrImageInspector:a,stackService:l,hashService:S,frameworkRegistry:m,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},dispose(){i.dispose()}}}export{T as createDeployServices};
1
+ import{SimpleAwsProvider as v}from"../aws/SimpleAwsProvider.js";import{CdkService as f}from"../services/infrastructure/CdkService.js";import{CdkArgumentBuilder as p}from"../services/infrastructure/CdkArgumentBuilder.js";import{CdkProcessManager as w}from"../services/infrastructure/CdkProcessManager.js";import{CloudFormationService as g}from"../services/infrastructure/CloudFormationService.js";import{EcsService as u}from"../services/infrastructure/EcsService.js";import{EcsServiceResolver as b}from"../services/infrastructure/EcsServiceResolver.js";import{LambdaService as k}from"../services/infrastructure/LambdaService.js";import{EcrImageInspectorService as y}from"../services/infrastructure/EcrImageInspectorService.js";import{ApplicationStackService as A}from"../services/application/ApplicationStackService.js";import{TemplateHashService as C}from"../services/supporting/TemplateHashService.js";import{FrameworkRegistry as F}from"./builders/frameworkRegistry.js";function j(e){const r=new v(e.awsCredentials,e.mintScopedBuildSecretSession);r.exportToEnv();const c=new p,i=new w(c,e.abortSignal),n=new f({processManager:i,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},...e.callbacks.onFailureAnalysis!==void 0?{onFailureAnalysis:e.callbacks.onFailureAnalysis}:{}}),o=new g(r),t=new u(r),s=new b(o),a=new k(r),l=new y(r),m=new A(n,o,r),S=new C,d=F.createDefault();return{awsProvider:r,cdkService:n,cfnService:o,ecsService:t,ecsResolver:s,lambdaService:a,ecrImageInspector:l,stackService:m,hashService:S,frameworkRegistry:d,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},dispose(){i.dispose()}}}export{j as createDeployServices};
@@ -18,6 +18,10 @@ export type SpawnResult = {
18
18
  type: "timeout";
19
19
  stdout: string;
20
20
  stderr: string;
21
+ } | {
22
+ type: "aborted";
23
+ stdout: string;
24
+ stderr: string;
21
25
  } | {
22
26
  type: "enoent";
23
27
  error: Error;
@@ -35,6 +39,10 @@ export declare function destroyProcessStreams(childProcess: ReturnType<typeof sp
35
39
  export declare function isEnoentError(err: unknown): err is NodeJS.ErrnoException;
36
40
  /**
37
41
  * Spawn a child process with timeout handling and stream collection.
42
+ *
43
+ * `abortSignal` is the caller's cancellation signal (`DeployParams.abortSignal`
44
+ * — Ctrl-C, or `fjall deployments cancel`). Without it a cancelled deploy still
45
+ * waits out the full build timeout, because nothing else can reach the child.
38
46
  */
39
47
  export declare function spawnWithTimeout(options: {
40
48
  command: string;
@@ -42,6 +50,7 @@ export declare function spawnWithTimeout(options: {
42
50
  cwd: string;
43
51
  env: Record<string, string | undefined>;
44
52
  timeout: number;
53
+ abortSignal?: AbortSignal;
45
54
  onStdoutData?: (data: string) => void;
46
55
  onStderrData?: (data: string) => void;
47
56
  }): Promise<SpawnResult>;
@@ -1 +1 @@
1
- import{spawn as S}from"child_process";import{logger as a}from"@fjall/util/logger";function w(o){try{o.stdout?.destroy()}catch(r){a.debug("spawnHelpers","stdout destroy failed",{error:String(r)})}try{o.stderr?.destroy()}catch(r){a.debug("spawnHelpers","stderr destroy failed",{error:String(r)})}}function E(o){return o instanceof Error&&"code"in o&&o.code==="ENOENT"}function k(o){const{command:r,args:p,cwd:l,env:m,timeout:f,onStdoutData:y,onStderrData:g}=o;return new Promise(h=>{let u=!1;const n=t=>{u||(u=!0,h(t))},e=S(r,p,{cwd:l,shell:!1,stdio:["ignore","pipe","pipe"],env:m}),i=[],d=[];e.stdout?.on("data",t=>{const s=t.toString();i.push(s),y?.(s)}),e.stderr?.on("data",t=>{const s=t.toString();d.push(s),g?.(s)});const c=setTimeout(()=>{w(e),e.kill("SIGTERM"),n({type:"timeout",stdout:i.join(""),stderr:d.join("")})},f);e.on("close",t=>{clearTimeout(c),n({type:"success",code:t??1,stdout:i.join(""),stderr:d.join("")})}),e.on("error",t=>{clearTimeout(c),E(t)?n({type:"enoent",error:t}):n({type:"spawn_error",error:t})})})}export{w as destroyProcessStreams,E as isEnoentError,k as spawnWithTimeout};
1
+ import{spawn as j}from"child_process";import{logger as l}from"@fjall/util/logger";function m(e){try{e.stdout?.destroy()}catch(s){l.debug("spawnHelpers","stdout destroy failed",{error:String(s)})}try{e.stderr?.destroy()}catch(s){l.debug("spawnHelpers","stderr destroy failed",{error:String(s)})}}function v(e){return e instanceof Error&&"code"in e&&e.code==="ENOENT"}function x(e){const{command:s,args:f,cwd:y,env:g,timeout:S,abortSignal:a,onStdoutData:b,onStderrData:E}=e;return new Promise(h=>{let c=!1;const r=t=>{c||(c=!0,h(t))};if(a?.aborted===!0){r({type:"aborted",stdout:"",stderr:""});return}const o=j(s,f,{cwd:y,shell:!1,stdio:["ignore","pipe","pipe"],env:g}),d=[],i=[];o.stdout?.on("data",t=>{const n=t.toString();d.push(n),b?.(n)}),o.stderr?.on("data",t=>{const n=t.toString();i.push(n),E?.(n)});const w=setTimeout(()=>{m(o),o.kill("SIGTERM"),u(),r({type:"timeout",stdout:d.join(""),stderr:i.join("")})},S),p=()=>{m(o),o.kill("SIGTERM"),u(),r({type:"aborted",stdout:d.join(""),stderr:i.join("")})},u=()=>{clearTimeout(w),a?.removeEventListener("abort",p)};a?.addEventListener("abort",p,{once:!0}),o.on("close",t=>{u(),r({type:"success",code:t??1,stdout:d.join(""),stderr:i.join("")})}),o.on("error",t=>{u(),v(t)?r({type:"enoent",error:t}):r({type:"spawn_error",error:t})})})}export{m as destroyProcessStreams,v as isEnoentError,x as spawnWithTimeout};
@@ -0,0 +1,45 @@
1
+ import type { AwsProvider } from "../../aws/AwsProvider.js";
2
+ import { type Result } from "@fjall/generator";
3
+ import { BaseServiceError } from "../../types/errors/ServiceError.js";
4
+ export declare class LambdaError extends BaseServiceError {
5
+ readonly functionName: string;
6
+ readonly operation: "publish_version" | "update_function_code";
7
+ constructor(message: string, functionName: string, operation: "publish_version" | "update_function_code", details?: unknown);
8
+ }
9
+ export interface PublishedLambdaVersion {
10
+ functionArn: string;
11
+ version: string;
12
+ }
13
+ export interface UpdatedLambdaFunctionCode {
14
+ functionArn: string;
15
+ version: string;
16
+ }
17
+ /**
18
+ * Lambda service using the AwsProvider interface. Constructor-injected
19
+ * provider matches the `EcsService`/`CloudFormationService` pattern.
20
+ */
21
+ export declare class LambdaService {
22
+ private aws;
23
+ constructor(aws: AwsProvider);
24
+ private getClient;
25
+ /**
26
+ * Publish a new immutable version of a Lambda function pointing at
27
+ * whatever is currently deployed as `$LATEST`. Used right after a
28
+ * container-image Lambda's `cdk deploy` succeeds — CDK's `.currentVersion`
29
+ * can't be trusted to do this itself when the image reference is a
30
+ * `CfnParameter` (its logical-id hash is computed from synth-time template
31
+ * shape, not the parameter's deploy-time resolved value, so the hash
32
+ * doesn't change between deploys even though the underlying image does).
33
+ */
34
+ publishVersion(functionName: string): Promise<Result<PublishedLambdaVersion, LambdaError>>;
35
+ /**
36
+ * Update a container-image Lambda function's code directly — the Lambda
37
+ * equivalent of ECS's `UpdateService`/`RegisterTaskDefinition` for a
38
+ * code-only deploy, bypassing CloudFormation entirely. Publishes a new
39
+ * version in the same call (`Publish: true`) since we own this API call
40
+ * directly here — unlike the full-deploy path, where CloudFormation
41
+ * performs the code update and `publishVersion` has to run as a separate
42
+ * step afterward.
43
+ */
44
+ updateFunctionCode(functionName: string, imageUri: string): Promise<Result<UpdatedLambdaFunctionCode, LambdaError>>;
45
+ }
@@ -0,0 +1 @@
1
+ import{LambdaClient as h,PublishVersionCommand as $,UpdateFunctionCodeCommand as f}from"@aws-sdk/client-lambda";import{success as l,failure as a}from"@fjall/generator";import{BaseServiceError as g}from"../../types/errors/ServiceError.js";import{logger as d}from"@fjall/util/logger";import{maskSensitiveOutput as p}from"@fjall/util";import{getAwsErrorDetails as m}from"../../aws/utils/awsErrorHandler.js";class c extends g{functionName;operation;constructor(e,t,r,o){super(`LAMBDA_${r.toUpperCase()}_FAILED`,e,o,!1),this.functionName=t,this.operation=r}}class V{aws;constructor(e){this.aws=e}getClient(){return this.aws.getClient(h)}async publishVersion(e){try{const r=await this.getClient().send(new $({FunctionName:e}));return!r.FunctionArn||!r.Version?a(new c("PublishVersion returned no function ARN or version",e,"publish_version",r)):(d.debug("LambdaService",`Published version ${r.Version} for ${e}`),l({functionArn:r.FunctionArn,version:r.Version}))}catch(t){const{message:r,name:o,httpCode:n}=m(t),s=p(r);d.error("LambdaService",`PublishVersion failed for ${e}: ${o} - ${s}`,{functionName:e,httpCode:n,error:t});let i=`Failed to publish Lambda version for '${e}': ${s}`;return n&&(i+=` (HTTP ${n})`),a(new c(i,e,"publish_version",{error:t,httpCode:n,errorName:o}))}}async updateFunctionCode(e,t){try{const o=await this.getClient().send(new f({FunctionName:e,ImageUri:t,Publish:!0}));return!o.FunctionArn||!o.Version?a(new c("UpdateFunctionCode returned no function ARN or version",e,"update_function_code",o)):(d.debug("LambdaService",`Updated ${e} to ${t}, published version ${o.Version}`),l({functionArn:o.FunctionArn,version:o.Version}))}catch(r){const{message:o,name:n,httpCode:s}=m(r),i=p(o);d.error("LambdaService",`UpdateFunctionCode failed for ${e}: ${n} - ${i}`,{functionName:e,imageUri:t,httpCode:s,error:r});let u=`Failed to update Lambda function code for '${e}': ${i}`;return s&&(u+=` (HTTP ${s})`),a(new c(u,e,"update_function_code",{error:r,httpCode:s,errorName:n}))}}}export{c as LambdaError,V as LambdaService};
@@ -13,8 +13,12 @@
13
13
  * `deploymentEventSchema.ts`, superseded in a later phase). They coexist during
14
14
  * the migration; do not conflate them.
15
15
  *
16
- * Browser-safe: this module imports only Zod, pure constant tuples, and
17
- * `@fjall/util/config` no Node-only modules.
16
+ * Browser-safe: imports only Zod, pure constant tuples, and the static const
17
+ * `TRAIL_LIFECYCLE_STATES` from `@fjall/util/config`. `config.js` DOES carry
18
+ * `import * as fs`/`import * as path`, but they are used only inside functions
19
+ * (never at module-eval), so importing this module accesses no Node builtin —
20
+ * see the eval-safety invariant in `./index.ts`. Keep the import to that static
21
+ * const; do not pull a config.js helper that touches fs/path into eval scope.
18
22
  */
19
23
  import { z } from "zod";
20
24
  /** The contract marker stamped on every event this build emits. */
@@ -64,7 +68,7 @@ export declare const DETECTION_PHASES: readonly ["detect", "synth", "hash", "val
64
68
  /** started/completed — reused across the phase-boundary events in this contract. */
65
69
  export declare const PHASE_STATUSES: readonly ["started", "completed"];
66
70
  /** Build-pipeline kinds carried by the `build.*` events. */
67
- export declare const BUILDERS: readonly ["docker", "buildpush", "opennext"];
71
+ export declare const BUILDERS: readonly ["docker", "buildpush", "opennext", "staticsite"];
68
72
  /**
69
73
  * Cascade per-target outcome. Mirrors the engine-side `CascadeOutcomeResult`
70
74
  * (orchestration/organisation/cascadeSummary.ts); the wire ledger owns its own
@@ -314,6 +318,7 @@ export declare const DeployEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
314
318
  progressKind: z.ZodLiteral<"build.started">;
315
319
  builder: z.ZodEnum<{
316
320
  docker: "docker";
321
+ staticsite: "staticsite";
317
322
  buildpush: "buildpush";
318
323
  opennext: "opennext";
319
324
  }>;
@@ -331,6 +336,7 @@ export declare const DeployEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
331
336
  progressKind: z.ZodLiteral<"build.progress">;
332
337
  builder: z.ZodEnum<{
333
338
  docker: "docker";
339
+ staticsite: "staticsite";
334
340
  buildpush: "buildpush";
335
341
  opennext: "opennext";
336
342
  }>;
@@ -350,6 +356,7 @@ export declare const DeployEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
350
356
  progressKind: z.ZodLiteral<"build.completed">;
351
357
  builder: z.ZodEnum<{
352
358
  docker: "docker";
359
+ staticsite: "staticsite";
353
360
  buildpush: "buildpush";
354
361
  opennext: "opennext";
355
362
  }>;
@@ -1 +1 @@
1
- import{z as e}from"zod";import{CASCADE_PHASES as h,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as E}from"./deploymentEventSchema.js";import{TRAIL_MIGRATION_PHASES as A,TRAIL_MIGRATION_STATUSES as C}from"./events.js";import{TRAIL_LIFECYCLE_STATES as p}from"@fjall/util/config";const Ue="fjall.deploy/1.1",Ve=1,Ye=1,_=["fjall.deploy/1.0","fjall.deploy/1.1"],a=256,o=256,s=2048,i=2048,n=4096,j=2048,m=8192,r=2048,g=4096,T=["completed","skipped","error","cancelled"],y=["info","debug","warn"],D=["emptying-bucket","deleting-stack","waiting","complete","error","quarantine-suspected","retained-buckets"],v=["bootstrap","synth","deploy","destroy"],P=["success","failure","cancelled","no-changes","rejected"],R=["detect","synth","hash","validate"],c=["started","completed"],l=["docker","buildpush","opennext"],d=["succeeded","skipped","failed"],N=["create","update","replace","delete","read","no-op"],K=["will","may","conditional","none"],O=["destructive","cost","policy"],f=["approved","rejected","expired","superseded"],u=e.object({create:e.number().int().nonnegative(),update:e.number().int().nonnegative(),replace:e.number().int().nonnegative(),delete:e.number().int().nonnegative(),read:e.number().int().nonnegative(),"no-op":e.number().int().nonnegative()}).strict(),L={create:!0,update:!0,replace:!0,delete:!0,read:!0,"no-op":!0},t={contract:e.enum(_),deploymentId:e.string().min(1).max(a),seq:e.number().int().nonnegative(),time:e.string().datetime()},x=e.object({index:e.number().int().nonnegative(),total:e.number().int().positive()}).strict(),b=e.object({id:e.string().max(a),name:e.string().max(o)}).strict(),k=e.object({logicalId:e.string().max(a),resourceType:e.string().max(a),status:e.string().max(64),displayName:e.string().max(o).optional(),category:e.enum(E).optional(),group:e.string().max(128).optional(),constructPath:e.string().max(512).optional(),statusReason:e.string().max(i).optional(),physicalId:e.string().max(r).optional(),expectedDurationSeconds:e.number().nonnegative().optional()}).strict(),M=e.object({pattern:e.string().max(128).nullable(),hasDockerfile:e.boolean(),hasDifferences:e.boolean(),resources:e.object({hasNetwork:e.boolean(),hasCompute:e.boolean(),hasDatabase:e.boolean(),hasStorage:e.boolean(),hasMessaging:e.boolean(),hasCdn:e.boolean()}).strict(),requiredSecrets:e.array(e.string().max(512)).max(100).optional()}).strict(),I=e.object({path:e.string().max(512),forcesReplacement:e.boolean()}).strict(),U=e.object({address:e.string().max(512),resourceType:e.string().max(a),action:e.enum(N),stack:e.string().max(a).optional(),replacementMode:e.enum(K).optional(),dataLoss:e.boolean().optional(),propertyChanges:e.array(I).max(100).optional()}).strict(),S=e.object({accountId:e.string().max(a),error:e.string().max(n)}).strict(),V=e.object({platformDeployed:e.boolean(),platformSkipped:e.boolean(),platformFailed:e.boolean(),domainsDeployed:e.boolean(),accountsDeployed:e.number().int().nonnegative(),accountsSkipped:e.number().int().nonnegative(),accountsFailed:e.number().int().nonnegative(),errors:e.array(S).max(1e3)}).strict(),Y=e.object({accountId:e.string().max(a),accountName:e.string().max(o),region:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),B=e.object({accountId:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),G=e.object({members:e.array(Y).max(1e3),platform:B.optional(),domainsDeployed:e.boolean(),errors:e.array(S).max(1e3),totalDurationMs:e.number().nonnegative()}).strict(),X=e.object({bucketName:e.string().max(o),accountId:e.string().max(a).optional()}).strict(),w=e.object({retainedBuckets:e.array(e.string().max(o)).max(1e3),message:e.string().max(s)}).strict(),H=e.union([X,w]),q=e.object({stack:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional()}).strict(),F=e.object({accountId:e.string().max(a),region:e.string().max(a),profileName:e.string().max(o).optional()}).strict(),z=e.object({...t,progressKind:e.literal("step.started"),step:b,progress:x.optional()}).strict(),J=e.object({...t,progressKind:e.literal("step.completed"),step:b,status:e.enum(T),progress:x.optional(),errorMessage:e.string().max(n).optional()}).strict(),Q=e.object({...t,progressKind:e.literal("log"),level:e.enum(y),message:e.string().max(s)}).strict(),W=e.object({...t,progressKind:e.literal("output"),chunk:e.string().max(m)}).strict(),Z=e.object({...t,progressKind:e.literal("resource"),resource:k,scope:e.object({stack:e.string().max(a).optional(),operationKey:e.string().max(a).optional(),region:e.string().max(a).optional()}).strict().optional()}).strict(),$=e.object({...t,progressKind:e.literal("phase.parallel"),status:e.enum(c),stacks:e.array(e.string().max(a)).max(50),description:e.string().max(o).optional(),results:e.array(q).max(50).optional()}).strict(),ee=e.object({...t,progressKind:e.literal("build.started"),builder:e.enum(l),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),ecrRepositoryUri:e.string().max(r).optional()}).strict(),te=e.object({...t,progressKind:e.literal("build.progress"),builder:e.enum(l),message:e.string().max(s),serviceName:e.string().max(o).optional(),percentage:e.number().optional(),layerId:e.string().max(a).optional(),status:e.string().max(64).optional()}).strict(),ae=e.object({...t,progressKind:e.literal("build.completed"),builder:e.enum(l),success:e.boolean(),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),imageDigest:e.string().max(a).optional(),imageUri:e.string().max(g).optional(),ecrRepositoryArn:e.string().max(r).optional(),durationMs:e.number().nonnegative().optional(),error:e.string().max(n).optional()}).strict(),oe=e.object({...t,progressKind:e.literal("taskdef.registered"),serviceName:e.string().max(o),taskDefinitionArn:e.string().max(r),previousTaskDefinitionArn:e.string().max(r),revision:e.number().int().nonnegative(),family:e.string().max(o),imageDigest:e.string().max(a).optional()}).strict(),re=e.object({...t,progressKind:e.literal("ecs.update"),status:e.string().max(64),service:e.string().max(o).optional()}).strict(),se=e.object({...t,progressKind:e.literal("ecs.progress"),message:e.string().max(s),percentage:e.number().optional()}).strict(),ne=e.object({...t,progressKind:e.literal("ecs.completed"),serviceName:e.string().max(o),serviceArn:e.string().max(r),success:e.boolean(),taskDefinitionArn:e.string().max(r),durationMs:e.number().nonnegative(),reason:e.string().max(i).optional(),finalRunningCount:e.number().int().nonnegative().optional(),finalDesiredCount:e.number().int().nonnegative().optional()}).strict(),ie=e.object({...t,progressKind:e.literal("migrations.started"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),imageDigest:e.string().max(a)}).strict(),ce=e.object({...t,progressKind:e.literal("migrations.completed"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),success:e.boolean(),durationMs:e.number().nonnegative(),exitCode:e.number().int().optional(),reason:e.string().max(i).optional()}).strict(),le=e.object({...t,progressKind:e.literal("cdk.bootstrap"),status:e.string().max(s)}).strict(),pe=e.object({...t,progressKind:e.literal("cdk.output"),outputType:e.enum(["synth","diff"]),output:e.string().max(m)}).strict(),me=e.object({...t,progressKind:e.literal("detection.completed"),detection:M}).strict(),ge=e.object({...t,progressKind:e.literal("detection.phase"),phase:e.enum(R),status:e.enum(c)}).strict(),de=e.object({...t,progressKind:e.literal("cascade.started")}).strict(),ue=e.object({...t,progressKind:e.literal("cascade.accountsReconciled"),hasPlatformAccount:e.boolean(),hasMemberAccounts:e.boolean()}).strict(),xe=e.object({...t,progressKind:e.literal("cascade.orgChanges"),hasOrgChanges:e.boolean()}).strict(),be=e.object({...t,progressKind:e.literal("cascade.missingAccounts"),accountNames:e.array(e.string().max(o)).max(256)}).strict(),Se=e.object({...t,progressKind:e.literal("cascade.phase"),phase:e.enum(h),status:e.enum(c)}).strict(),he=e.object({...t,progressKind:e.literal("cascade.account.started"),operationKey:e.string().max(a),accountId:e.string().max(a),region:e.string().max(a),deployType:e.string().max(64).optional()}).strict(),Ee=e.object({...t,progressKind:e.literal("cascade.account.phase"),operationKey:e.string().max(a),phase:e.enum(v),region:e.string().max(a).optional()}).strict(),Ae=e.object({...t,progressKind:e.literal("cascade.account.completed"),operationKey:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional(),region:e.string().max(a).optional(),outputs:e.record(e.string().max(o),e.string().max(i)).optional(),skipped:e.boolean().optional()}).strict(),Ce=e.object({...t,progressKind:e.literal("cascade.completed"),result:V}).strict(),_e=e.object({...t,progressKind:e.literal("cascade.ledger"),ledger:G}).strict(),je=e.object({...t,progressKind:e.literal("trail.phase"),accountId:e.string().max(a),accountName:e.string().max(o),phase:e.enum(A),status:e.enum(C),detail:e.string().max(j).optional()}).strict(),Te=e.object({...t,progressKind:e.literal("trail.lifecycle"),accountId:e.string().max(a),to:e.enum(p),from:e.enum(p).optional()}).strict(),ye=e.object({...t,progressKind:e.literal("cleanup.progress"),stackName:e.string().max(a),phase:e.enum(D),detail:H.optional()}).strict(),De=e.object({...t,progressKind:e.literal("auth.ssoUrl"),url:e.string().max(g).nullable()}).strict(),ve=e.object({...t,progressKind:e.literal("auth.completed"),result:F.nullable()}).strict(),Pe=e.object({...t,progressKind:e.literal("error"),message:e.string().max(n),name:e.string().max(o).optional()}).strict(),Re=e.object({...t,progressKind:e.literal("deploy.completed"),result:e.enum(P),ok:e.boolean(),errorType:e.string().max(128).optional(),message:e.string().max(s)}).strict(),Ne=e.object({...t,progressKind:e.literal("plan.available"),plan:e.object({summary:e.string().max(s),changeCount:e.number().int().nonnegative(),hasDestructiveChanges:e.boolean(),changes:e.array(U).max(1e3).optional(),diffRef:e.string().max(512).optional(),iamBroadening:e.boolean().optional(),securityGroupBroadening:e.boolean().optional(),changeCountsByAction:u.optional()}).strict()}).strict(),Ke=e.object({...t,progressKind:e.literal("approval.awaiting"),approval:e.object({token:e.string().max(512),kind:e.enum(O),reason:e.string().max(s),expiresAt:e.string().datetime(),assemblyDigest:e.string().max(128).optional(),changeCounts:u.optional(),approvalClass:e.string().max(64).optional(),requiredApprovers:e.array(e.string().max(256)).max(50).optional()}).strict()}).strict(),Oe=e.object({...t,progressKind:e.literal("approval.resolved"),approval:e.object({token:e.string().max(512),decision:e.enum(f),actor:e.string().max(o).optional()}).strict()}).strict(),Be=e.discriminatedUnion("progressKind",[z,J,Q,W,Z,$,ee,te,ae,oe,re,se,ne,ie,ce,le,pe,me,ge,de,ue,xe,be,Se,he,Ee,Ae,Ce,_e,je,Te,ye,De,ve,Pe,Re,Ne,Ke,Oe]),fe={"step.started":!0,"step.completed":!0,log:!0,output:!0,resource:!0,"phase.parallel":!0,"build.started":!0,"build.progress":!0,"build.completed":!0,"taskdef.registered":!0,"ecs.update":!0,"ecs.progress":!0,"ecs.completed":!0,"migrations.started":!0,"migrations.completed":!0,"cdk.bootstrap":!0,"cdk.output":!0,"detection.completed":!0,"detection.phase":!0,"cascade.started":!0,"cascade.accountsReconciled":!0,"cascade.orgChanges":!0,"cascade.missingAccounts":!0,"cascade.phase":!0,"cascade.account.started":!0,"cascade.account.phase":!0,"cascade.account.completed":!0,"cascade.completed":!0,"cascade.ledger":!0,"trail.phase":!0,"trail.lifecycle":!0,"cleanup.progress":!0,"auth.ssoUrl":!0,"auth.completed":!0,error:!0,"deploy.completed":!0,"plan.available":!0,"approval.awaiting":!0,"approval.resolved":!0},Ge=Object.keys(fe);export{Ge as ALL_PROGRESS_KINDS,f as APPROVAL_DECISIONS,O as APPROVAL_KINDS,l as BUILDERS,v as CASCADE_ACCOUNT_PHASES,d as CASCADE_OUTCOME_RESULTS,u as ChangeCountsSchema,r as DEPLOY_EVENT_ARN_MAX,Ue as DEPLOY_EVENT_CONTRACT,Ve as DEPLOY_EVENT_CONTRACT_MAJOR,Ye as DEPLOY_EVENT_CONTRACT_MINOR,n as DEPLOY_EVENT_ERROR_MESSAGE_MAX,a as DEPLOY_EVENT_ID_MAX,s as DEPLOY_EVENT_MESSAGE_MAX,o as DEPLOY_EVENT_NAME_MAX,m as DEPLOY_EVENT_OUTPUT_MAX,i as DEPLOY_EVENT_STATUS_REASON_MAX,j as DEPLOY_EVENT_TRAIL_DETAIL_MAX,g as DEPLOY_EVENT_URL_MAX,P as DEPLOY_RESULTS,R as DETECTION_PHASES,Be as DeployEventSchema,k as DeployResourceSchema,y as LOG_LEVELS,c as PHASE_STATUSES,N as PLAN_ACTIONS,U as PlanChangeSchema,I as PlanPropertyChangeSchema,K as REPLACEMENT_MODES,D as STACK_CLEANUP_PHASES,T as STEP_COMPLETE_STATUSES,_ as SUPPORTED_CONTRACT_MARKERS,x as StepProgressSchema};
1
+ import{z as e}from"zod";import{CASCADE_PHASES as h,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as E}from"./deploymentEventSchema.js";import{TRAIL_MIGRATION_PHASES as A,TRAIL_MIGRATION_STATUSES as C}from"./events.js";import{TRAIL_LIFECYCLE_STATES as p}from"@fjall/util/config";const Ue="fjall.deploy/1.1",Ve=1,Ye=1,_=["fjall.deploy/1.0","fjall.deploy/1.1"],a=256,o=256,s=2048,i=2048,n=4096,j=2048,m=8192,r=2048,g=4096,T=["completed","skipped","error","cancelled"],y=["info","debug","warn"],D=["emptying-bucket","deleting-stack","waiting","complete","error","quarantine-suspected","retained-buckets"],v=["bootstrap","synth","deploy","destroy"],P=["success","failure","cancelled","no-changes","rejected"],R=["detect","synth","hash","validate"],c=["started","completed"],l=["docker","buildpush","opennext","staticsite"],d=["succeeded","skipped","failed"],N=["create","update","replace","delete","read","no-op"],K=["will","may","conditional","none"],O=["destructive","cost","policy"],f=["approved","rejected","expired","superseded"],u=e.object({create:e.number().int().nonnegative(),update:e.number().int().nonnegative(),replace:e.number().int().nonnegative(),delete:e.number().int().nonnegative(),read:e.number().int().nonnegative(),"no-op":e.number().int().nonnegative()}).strict(),L={create:!0,update:!0,replace:!0,delete:!0,read:!0,"no-op":!0},t={contract:e.enum(_),deploymentId:e.string().min(1).max(a),seq:e.number().int().nonnegative(),time:e.string().datetime()},x=e.object({index:e.number().int().nonnegative(),total:e.number().int().positive()}).strict(),b=e.object({id:e.string().max(a),name:e.string().max(o)}).strict(),k=e.object({logicalId:e.string().max(a),resourceType:e.string().max(a),status:e.string().max(64),displayName:e.string().max(o).optional(),category:e.enum(E).optional(),group:e.string().max(128).optional(),constructPath:e.string().max(512).optional(),statusReason:e.string().max(i).optional(),physicalId:e.string().max(r).optional(),expectedDurationSeconds:e.number().nonnegative().optional()}).strict(),M=e.object({pattern:e.string().max(128).nullable(),hasDockerfile:e.boolean(),hasDifferences:e.boolean(),resources:e.object({hasNetwork:e.boolean(),hasCompute:e.boolean(),hasDatabase:e.boolean(),hasStorage:e.boolean(),hasMessaging:e.boolean(),hasCdn:e.boolean()}).strict(),requiredSecrets:e.array(e.string().max(512)).max(100).optional()}).strict(),I=e.object({path:e.string().max(512),forcesReplacement:e.boolean()}).strict(),U=e.object({address:e.string().max(512),resourceType:e.string().max(a),action:e.enum(N),stack:e.string().max(a).optional(),replacementMode:e.enum(K).optional(),dataLoss:e.boolean().optional(),propertyChanges:e.array(I).max(100).optional()}).strict(),S=e.object({accountId:e.string().max(a),error:e.string().max(n)}).strict(),V=e.object({platformDeployed:e.boolean(),platformSkipped:e.boolean(),platformFailed:e.boolean(),domainsDeployed:e.boolean(),accountsDeployed:e.number().int().nonnegative(),accountsSkipped:e.number().int().nonnegative(),accountsFailed:e.number().int().nonnegative(),errors:e.array(S).max(1e3)}).strict(),Y=e.object({accountId:e.string().max(a),accountName:e.string().max(o),region:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),B=e.object({accountId:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),G=e.object({members:e.array(Y).max(1e3),platform:B.optional(),domainsDeployed:e.boolean(),errors:e.array(S).max(1e3),totalDurationMs:e.number().nonnegative()}).strict(),X=e.object({bucketName:e.string().max(o),accountId:e.string().max(a).optional()}).strict(),w=e.object({retainedBuckets:e.array(e.string().max(o)).max(1e3),message:e.string().max(s)}).strict(),H=e.union([X,w]),q=e.object({stack:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional()}).strict(),F=e.object({accountId:e.string().max(a),region:e.string().max(a),profileName:e.string().max(o).optional()}).strict(),z=e.object({...t,progressKind:e.literal("step.started"),step:b,progress:x.optional()}).strict(),J=e.object({...t,progressKind:e.literal("step.completed"),step:b,status:e.enum(T),progress:x.optional(),errorMessage:e.string().max(n).optional()}).strict(),Q=e.object({...t,progressKind:e.literal("log"),level:e.enum(y),message:e.string().max(s)}).strict(),W=e.object({...t,progressKind:e.literal("output"),chunk:e.string().max(m)}).strict(),Z=e.object({...t,progressKind:e.literal("resource"),resource:k,scope:e.object({stack:e.string().max(a).optional(),operationKey:e.string().max(a).optional(),region:e.string().max(a).optional()}).strict().optional()}).strict(),$=e.object({...t,progressKind:e.literal("phase.parallel"),status:e.enum(c),stacks:e.array(e.string().max(a)).max(50),description:e.string().max(o).optional(),results:e.array(q).max(50).optional()}).strict(),ee=e.object({...t,progressKind:e.literal("build.started"),builder:e.enum(l),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),ecrRepositoryUri:e.string().max(r).optional()}).strict(),te=e.object({...t,progressKind:e.literal("build.progress"),builder:e.enum(l),message:e.string().max(s),serviceName:e.string().max(o).optional(),percentage:e.number().optional(),layerId:e.string().max(a).optional(),status:e.string().max(64).optional()}).strict(),ae=e.object({...t,progressKind:e.literal("build.completed"),builder:e.enum(l),success:e.boolean(),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),imageDigest:e.string().max(a).optional(),imageUri:e.string().max(g).optional(),ecrRepositoryArn:e.string().max(r).optional(),durationMs:e.number().nonnegative().optional(),error:e.string().max(n).optional()}).strict(),oe=e.object({...t,progressKind:e.literal("taskdef.registered"),serviceName:e.string().max(o),taskDefinitionArn:e.string().max(r),previousTaskDefinitionArn:e.string().max(r),revision:e.number().int().nonnegative(),family:e.string().max(o),imageDigest:e.string().max(a).optional()}).strict(),re=e.object({...t,progressKind:e.literal("ecs.update"),status:e.string().max(64),service:e.string().max(o).optional()}).strict(),se=e.object({...t,progressKind:e.literal("ecs.progress"),message:e.string().max(s),percentage:e.number().optional()}).strict(),ne=e.object({...t,progressKind:e.literal("ecs.completed"),serviceName:e.string().max(o),serviceArn:e.string().max(r),success:e.boolean(),taskDefinitionArn:e.string().max(r),durationMs:e.number().nonnegative(),reason:e.string().max(i).optional(),finalRunningCount:e.number().int().nonnegative().optional(),finalDesiredCount:e.number().int().nonnegative().optional()}).strict(),ie=e.object({...t,progressKind:e.literal("migrations.started"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),imageDigest:e.string().max(a)}).strict(),ce=e.object({...t,progressKind:e.literal("migrations.completed"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),success:e.boolean(),durationMs:e.number().nonnegative(),exitCode:e.number().int().optional(),reason:e.string().max(i).optional()}).strict(),le=e.object({...t,progressKind:e.literal("cdk.bootstrap"),status:e.string().max(s)}).strict(),pe=e.object({...t,progressKind:e.literal("cdk.output"),outputType:e.enum(["synth","diff"]),output:e.string().max(m)}).strict(),me=e.object({...t,progressKind:e.literal("detection.completed"),detection:M}).strict(),ge=e.object({...t,progressKind:e.literal("detection.phase"),phase:e.enum(R),status:e.enum(c)}).strict(),de=e.object({...t,progressKind:e.literal("cascade.started")}).strict(),ue=e.object({...t,progressKind:e.literal("cascade.accountsReconciled"),hasPlatformAccount:e.boolean(),hasMemberAccounts:e.boolean()}).strict(),xe=e.object({...t,progressKind:e.literal("cascade.orgChanges"),hasOrgChanges:e.boolean()}).strict(),be=e.object({...t,progressKind:e.literal("cascade.missingAccounts"),accountNames:e.array(e.string().max(o)).max(256)}).strict(),Se=e.object({...t,progressKind:e.literal("cascade.phase"),phase:e.enum(h),status:e.enum(c)}).strict(),he=e.object({...t,progressKind:e.literal("cascade.account.started"),operationKey:e.string().max(a),accountId:e.string().max(a),region:e.string().max(a),deployType:e.string().max(64).optional()}).strict(),Ee=e.object({...t,progressKind:e.literal("cascade.account.phase"),operationKey:e.string().max(a),phase:e.enum(v),region:e.string().max(a).optional()}).strict(),Ae=e.object({...t,progressKind:e.literal("cascade.account.completed"),operationKey:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional(),region:e.string().max(a).optional(),outputs:e.record(e.string().max(o),e.string().max(i)).optional(),skipped:e.boolean().optional()}).strict(),Ce=e.object({...t,progressKind:e.literal("cascade.completed"),result:V}).strict(),_e=e.object({...t,progressKind:e.literal("cascade.ledger"),ledger:G}).strict(),je=e.object({...t,progressKind:e.literal("trail.phase"),accountId:e.string().max(a),accountName:e.string().max(o),phase:e.enum(A),status:e.enum(C),detail:e.string().max(j).optional()}).strict(),Te=e.object({...t,progressKind:e.literal("trail.lifecycle"),accountId:e.string().max(a),to:e.enum(p),from:e.enum(p).optional()}).strict(),ye=e.object({...t,progressKind:e.literal("cleanup.progress"),stackName:e.string().max(a),phase:e.enum(D),detail:H.optional()}).strict(),De=e.object({...t,progressKind:e.literal("auth.ssoUrl"),url:e.string().max(g).nullable()}).strict(),ve=e.object({...t,progressKind:e.literal("auth.completed"),result:F.nullable()}).strict(),Pe=e.object({...t,progressKind:e.literal("error"),message:e.string().max(n),name:e.string().max(o).optional()}).strict(),Re=e.object({...t,progressKind:e.literal("deploy.completed"),result:e.enum(P),ok:e.boolean(),errorType:e.string().max(128).optional(),message:e.string().max(s)}).strict(),Ne=e.object({...t,progressKind:e.literal("plan.available"),plan:e.object({summary:e.string().max(s),changeCount:e.number().int().nonnegative(),hasDestructiveChanges:e.boolean(),changes:e.array(U).max(1e3).optional(),diffRef:e.string().max(512).optional(),iamBroadening:e.boolean().optional(),securityGroupBroadening:e.boolean().optional(),changeCountsByAction:u.optional()}).strict()}).strict(),Ke=e.object({...t,progressKind:e.literal("approval.awaiting"),approval:e.object({token:e.string().max(512),kind:e.enum(O),reason:e.string().max(s),expiresAt:e.string().datetime(),assemblyDigest:e.string().max(128).optional(),changeCounts:u.optional(),approvalClass:e.string().max(64).optional(),requiredApprovers:e.array(e.string().max(256)).max(50).optional()}).strict()}).strict(),Oe=e.object({...t,progressKind:e.literal("approval.resolved"),approval:e.object({token:e.string().max(512),decision:e.enum(f),actor:e.string().max(o).optional()}).strict()}).strict(),Be=e.discriminatedUnion("progressKind",[z,J,Q,W,Z,$,ee,te,ae,oe,re,se,ne,ie,ce,le,pe,me,ge,de,ue,xe,be,Se,he,Ee,Ae,Ce,_e,je,Te,ye,De,ve,Pe,Re,Ne,Ke,Oe]),fe={"step.started":!0,"step.completed":!0,log:!0,output:!0,resource:!0,"phase.parallel":!0,"build.started":!0,"build.progress":!0,"build.completed":!0,"taskdef.registered":!0,"ecs.update":!0,"ecs.progress":!0,"ecs.completed":!0,"migrations.started":!0,"migrations.completed":!0,"cdk.bootstrap":!0,"cdk.output":!0,"detection.completed":!0,"detection.phase":!0,"cascade.started":!0,"cascade.accountsReconciled":!0,"cascade.orgChanges":!0,"cascade.missingAccounts":!0,"cascade.phase":!0,"cascade.account.started":!0,"cascade.account.phase":!0,"cascade.account.completed":!0,"cascade.completed":!0,"cascade.ledger":!0,"trail.phase":!0,"trail.lifecycle":!0,"cleanup.progress":!0,"auth.ssoUrl":!0,"auth.completed":!0,error:!0,"deploy.completed":!0,"plan.available":!0,"approval.awaiting":!0,"approval.resolved":!0},Ge=Object.keys(fe);export{Ge as ALL_PROGRESS_KINDS,f as APPROVAL_DECISIONS,O as APPROVAL_KINDS,l as BUILDERS,v as CASCADE_ACCOUNT_PHASES,d as CASCADE_OUTCOME_RESULTS,u as ChangeCountsSchema,r as DEPLOY_EVENT_ARN_MAX,Ue as DEPLOY_EVENT_CONTRACT,Ve as DEPLOY_EVENT_CONTRACT_MAJOR,Ye as DEPLOY_EVENT_CONTRACT_MINOR,n as DEPLOY_EVENT_ERROR_MESSAGE_MAX,a as DEPLOY_EVENT_ID_MAX,s as DEPLOY_EVENT_MESSAGE_MAX,o as DEPLOY_EVENT_NAME_MAX,m as DEPLOY_EVENT_OUTPUT_MAX,i as DEPLOY_EVENT_STATUS_REASON_MAX,j as DEPLOY_EVENT_TRAIL_DETAIL_MAX,g as DEPLOY_EVENT_URL_MAX,P as DEPLOY_RESULTS,R as DETECTION_PHASES,Be as DeployEventSchema,k as DeployResourceSchema,y as LOG_LEVELS,c as PHASE_STATUSES,N as PLAN_ACTIONS,U as PlanChangeSchema,I as PlanPropertyChangeSchema,K as REPLACEMENT_MODES,D as STACK_CLEANUP_PHASES,T as STEP_COMPLETE_STATUSES,_ as SUPPORTED_CONTRACT_MARKERS,x as StepProgressSchema};
@@ -4,10 +4,16 @@
4
4
  * These are safe for browser bundles. Filesystem-based detection functions
5
5
  * remain in patternDetection.ts.
6
6
  */
7
- declare const OPENNEXT_PATTERNS_ARRAY: readonly ["payload", "nextjs"];
8
- export type OpenNextPattern = (typeof OPENNEXT_PATTERNS_ARRAY)[number];
7
+ import { isOpenNextPatternType, type OpenNextPatternType } from "@fjall/util/patterns";
8
+ /**
9
+ * The OpenNext accept-set is derived from `PATTERN_REGISTRY` in `@fjall/util`:
10
+ * a pattern is OpenNext-shaped iff its declared artefact is an OpenNext Lambda
11
+ * bundle. Re-listing the members here is how `staticsite` would silently join
12
+ * the OpenNext build path.
13
+ */
14
+ export type OpenNextPattern = OpenNextPatternType;
9
15
  export declare const OPENNEXT_PATTERNS: ReadonlySet<string>;
10
- export declare function isOpenNextPattern(pattern: string | undefined | null): pattern is OpenNextPattern;
16
+ export declare const isOpenNextPattern: typeof isOpenNextPatternType;
11
17
  export interface AppResourceFlags {
12
18
  hasNetwork: boolean;
13
19
  hasCompute: boolean;
@@ -16,4 +22,3 @@ export interface AppResourceFlags {
16
22
  hasMessaging: boolean;
17
23
  hasCdn: boolean;
18
24
  }
19
- export {};
@@ -1 +1 @@
1
- const e=["payload","nextjs"],t=new Set(e);function N(n){return n!=null&&t.has(n)}export{t as OPENNEXT_PATTERNS,N as isOpenNextPattern};
1
+ import{OPENNEXT_PATTERN_TYPES as t,isOpenNextPatternType as e}from"@fjall/util/patterns";const T=new Set(t),n=e;export{T as OPENNEXT_PATTERNS,n as isOpenNextPattern};
@@ -40,6 +40,13 @@ export interface BuildPlan {
40
40
  readonly buildCommand: BuildCommand | null;
41
41
  /** Whether this plan requires a Docker build (standard apps with Dockerfile) */
42
42
  readonly requiresDockerBuild: boolean;
43
+ /**
44
+ * Directory the build must produce, relative to the build command's `cwd`.
45
+ * Verified to exist after `build()` completes. Set by builders whose artefacts
46
+ * are uploaded to a bucket rather than containerised (static sites); the
47
+ * Docker/OpenNext builders leave it undefined.
48
+ */
49
+ readonly artefactDir?: string;
43
50
  /** Infrastructure requirements */
44
51
  readonly resources: AppResourceFlags;
45
52
  }
@@ -71,6 +78,13 @@ export interface BuildOptions {
71
78
  readonly skipBuild?: boolean;
72
79
  /** Only deploy infrastructure, skip application build */
73
80
  readonly infraOnly?: boolean;
81
+ /**
82
+ * The deploy's cancellation signal (`DeployParams.abortSignal` — Ctrl-C, or
83
+ * `fjall deployments cancel`). A build can run for minutes; without the
84
+ * signal a cancelled deploy has no way to reach the child process and waits
85
+ * out the full build timeout before noticing.
86
+ */
87
+ readonly abortSignal?: AbortSignal;
74
88
  }
75
89
  /** The FrameworkBuilder interface — detect/plan/build lifecycle */
76
90
  export interface FrameworkBuilder {
@@ -1,3 +1,39 @@
1
+ /**
2
+ * `@fjall/deploy-core/types` — the BROWSER-SAFE type/schema barrel.
3
+ *
4
+ * INVARIANT: nothing re-exported here may ACCESS a Node builtin at MODULE-EVAL.
5
+ * The webapp imports this subpath from CLIENT-reachable modules (e.g.
6
+ * `app/types/approval-plan.ts`, `app/types/destruction-consent.ts`); Vite's dev
7
+ * esbuild bundles the whole barrel without tree-shaking and stubs each Node
8
+ * builtin with a shim that THROWS ON ACCESS, killing React hydration app-wide in
9
+ * dev — while prod Rollup tree-shakes the unused module out, so CI stays green
10
+ * and the breakage is invisible to CI (the 2026-07-07 incident). Two shapes trip
11
+ * the eval-time access: a NAMED builtin import (`import { readFileSync } from
12
+ * "fs"`) binds to the throwing shim at link time, and a top-level builtin call
13
+ * (`readFileSync(...)` at module scope) calls it immediately. A bare NAMESPACE
14
+ * import (`import * as fs from "fs"`) used only inside functions does NOT trip it
15
+ * — the shim is never accessed at eval.
16
+ *
17
+ * deploy-core's OWN re-exported modules are kept fully Node-builtin-free: the
18
+ * fs-based helpers (`deriveResourcesFromManifestStacks` with its named `fs`
19
+ * import; the FjallState IO functions with named `fs`/`crypto`) — the two
20
+ * modules that tripped the 2026-07-07 incident — are NOT re-exported here. Their
21
+ * server-only consumers import them straight from the LEAF modules
22
+ * (`./detection/patternDetection.js`, `./config/FjallState.js`) and the ROOT
23
+ * barrel (`../index.js`) re-exports them — never from here.
24
+ *
25
+ * One TOLERATED cross-package builtin edge: `deployEvent.js` imports the static
26
+ * const `TRAIL_LIFECYCLE_STATES` from `@fjall/util/config`, which carries
27
+ * `import * as fs`/`import * as path` used ONLY inside functions. That is
28
+ * import-safe (verified: esbuild-bundle this barrel for the browser with a
29
+ * throw-on-access builtin stub → importing it does not throw). FRAGILE: if
30
+ * `config.js` ever adds a top-level fs/path call or a named builtin import, this
31
+ * barrel breaks — `TRAIL_LIFECYCLE_STATES` should then move to a genuinely
32
+ * builtin-free `@fjall/util` module. Before adding a re-export here, prefer a
33
+ * Node-builtin-free module; if it transitively pulls a builtin, that builtin
34
+ * MUST be a namespace import never accessed at eval (`import type` is always
35
+ * fine — it is erased).
36
+ */
1
37
  export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURCE_CATEGORIES, DEPLOYMENT_EVENT_STATUS_REASON_MAX, DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX, DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX, CASCADE_PHASES, CASCADE_ACCOUNT_STATUSES, toCascadePhase } from "./deploymentEventSchema.js";
2
38
  export type { DeploymentEvent, DeploymentEventType, DeploymentEventResourceCategory, DeploymentEventCascadePhase, DeploymentEventCascadeAccountStatus } from "./deploymentEventSchema.js";
3
39
  export type { AwsCredentials, DeployIdentity, ScopedBuildSecretSessionMinter } from "./credentials.js";
@@ -32,11 +68,9 @@ export type { ParallelDeploymentResult, ParallelDeployGroup, ParallelOperation,
32
68
  export { PARALLEL_OPERATION_TYPES } from "./deployment/index.js";
33
69
  export type { OpenNextPattern, AppResourceFlags } from "./detection/patternTypes.js";
34
70
  export { isOpenNextPattern, OPENNEXT_PATTERNS } from "./detection/patternTypes.js";
35
- export { deriveResourcesFromManifestStacks } from "./detection/patternDetection.js";
36
71
  export { STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME } from "./constants.js";
37
72
  export { ApplicationError, wrapApplicationError, type ApplicationErrorType, type StackDeploymentData, type StackDeploymentOptions, type ApplicationDeploymentData, type ApplicationDestructionData } from "./application/index.js";
38
73
  export type { FjallStateFile, TemplateHashEntry } from "./config/FjallState.js";
39
- export { FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, regionSuffix } from "./config/FjallState.js";
40
74
  export type { FrameworkBuilder, FrameworkDetection, BuildPlan, BuildCommand, BuildCallbacks, DetectionContext, BuildOptions } from "./frameworkBuilder.js";
41
75
  export { STEP_IDS, STEP_NAMES, INFRASTRUCTURE_STEP_NAMES, INFRA_STEP_NAME } from "./stepDefinitions.js";
42
76
  export type { StepId, InfrastructureStepName, StepDefinition, StepDeploymentType, Operation, StepContext } from "./stepDefinitions.js";
@@ -1 +1 @@
1
- import{DeploymentEventSchema as S,DEPLOYMENT_EVENT_TYPES as t,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as _,DEPLOYMENT_EVENT_STATUS_REASON_MAX as T,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as r,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as A,CASCADE_PHASES as a,CASCADE_ACCOUNT_STATUSES as o,toCascadePhase as i}from"./deploymentEventSchema.js";import{isQuarantineDetail as O,isRetainedBucketsDetail as P}from"./callbacks.js";import{DeployEventSchema as D,StepProgressSchema as c,DeployResourceSchema as p,PlanChangeSchema as m,PlanPropertyChangeSchema as L,ChangeCountsSchema as n,DEPLOY_EVENT_CONTRACT as C,DEPLOY_EVENT_CONTRACT_MAJOR as I,DEPLOY_EVENT_CONTRACT_MINOR as l,SUPPORTED_CONTRACT_MARKERS as s,DEPLOY_EVENT_ID_MAX as M,DEPLOY_EVENT_NAME_MAX as h,DEPLOY_EVENT_MESSAGE_MAX as d,DEPLOY_EVENT_STATUS_REASON_MAX as V,DEPLOY_EVENT_ERROR_MESSAGE_MAX as f,DEPLOY_EVENT_TRAIL_DETAIL_MAX as U,DEPLOY_EVENT_OUTPUT_MAX as Y,DEPLOY_EVENT_ARN_MAX as u,DEPLOY_EVENT_URL_MAX as g,STEP_COMPLETE_STATUSES as x,LOG_LEVELS as F,STACK_CLEANUP_PHASES as y,CASCADE_ACCOUNT_PHASES as G,DEPLOY_RESULTS as X,DETECTION_PHASES as K,PHASE_STATUSES as k,BUILDERS as H,CASCADE_OUTCOME_RESULTS as v,PLAN_ACTIONS as b,REPLACEMENT_MODES as B,APPROVAL_KINDS as J,APPROVAL_DECISIONS as w,ALL_PROGRESS_KINDS as j}from"./deployEvent.js";import{createDeployEmitter as W}from"./deployEmitter.js";import{parseDeployEvent as z,parseDeployContractVersion as Z}from"./deployEventParse.js";import{TRAIL_MIGRATION_PHASES as ee,TRAIL_MIGRATION_STATUSES as Ee}from"./events.js";import{RemediationVerbSchema as te,REMEDIATION_VERB_GLOSS as _e,DestructionFindingSchema as Te,DestructionTicketResourceSchema as re,DestructionTicketSchema as Ae,DestructionConsentSchema as ae,DestructionOutcomeSchema as oe,DESTRUCTION_FINDINGS as ie,CONSENT_VERDICTS as Re,TICKET_VERDICT_SOURCES as Oe,TicketVerdictSourceSchema as Pe}from"./destruction.js";import{DRIFT_VERDICTS as De,DriftVerdictSchema as ce,DriftSuspectSchema as pe,DriftFindingSchema as me,DriftJournalRecordSchema as Le,verbsForDriftVerdict as ne}from"./drift.js";import{REMEDIATION_PHASES as Ie,RemediationPhaseSchema as le,RemediationTargetSchema as se,RemediationFlipProofSchema as Me,RemediationJournalRecordSchema as he,RemediationVerbWithSurgerySchema as de,remediationPhaseRank as Ve,remediationPlaceholderPhysicalId as fe,isRemediationPlaceholderPhysicalId as Ue}from"./remediation.js";import{stubCallerIdentity as ue}from"./deployment/index.js";import{ProgressReporter as xe}from"./ProgressEvent.js";import{APPLICATION_STACKS as ye,ORGANISATION_TYPES as Ge,APPLICATION_DEPLOY_ORDER as Xe,APPLICATION_DESTROY_ORDER as Ke,OPENNEXT_DEPLOY_ORDER as ke,OPENNEXT_DESTROY_ORDER as He,PARALLEL_DEPLOY_GROUPS as ve,PARALLEL_DESTROY_GROUPS as be,OPENNEXT_PARALLEL_GROUPS as Be,isApplicationOperation as Je,isOrganisationOperation as we,getParallelDeployGroups as je,getParallelDestroyGroups as Qe,getApplicationDeployOrder as We,getApplicationDestroyOrder as qe,getApplicationStackName as ze,getOrganisationStackName as Ze,isApplicationStack as $e,getApplicationStepName as eE,getApplicationStepId as EE,toPascalCase as SE}from"./operations.js";import{PARALLEL_OPERATION_TYPES as _E}from"./deployment/index.js";import{isOpenNextPattern as rE,OPENNEXT_PATTERNS as AE}from"./detection/patternTypes.js";import{deriveResourcesFromManifestStacks as oE}from"./detection/patternDetection.js";import{STACK_NOT_FOUND_PATTERN as RE,STACK_FAILED_STATE_PATTERN as OE,CDK_NO_STACKS_MATCH as PE,INFRASTRUCTURE_FILENAME as NE}from"./constants.js";import{ApplicationError as cE,wrapApplicationError as pE}from"./application/index.js";import{FjallStateFileSchema as LE,readStateFile as nE,writeStateFile as CE,createEmptyState as IE,deleteStateFile as lE,updateTemplateHash as sE,getStateFilePath as ME,regionSuffix as hE}from"./config/FjallState.js";import{STEP_IDS as VE,STEP_NAMES as fE,INFRASTRUCTURE_STEP_NAMES as UE,INFRA_STEP_NAME as YE}from"./stepDefinitions.js";export{j as ALL_PROGRESS_KINDS,Xe as APPLICATION_DEPLOY_ORDER,Ke as APPLICATION_DESTROY_ORDER,ye as APPLICATION_STACKS,w as APPROVAL_DECISIONS,J as APPROVAL_KINDS,cE as ApplicationError,H as BUILDERS,G as CASCADE_ACCOUNT_PHASES,o as CASCADE_ACCOUNT_STATUSES,v as CASCADE_OUTCOME_RESULTS,a as CASCADE_PHASES,PE as CDK_NO_STACKS_MATCH,Re as CONSENT_VERDICTS,n as ChangeCountsSchema,r as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,_ as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,T as DEPLOYMENT_EVENT_STATUS_REASON_MAX,A as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,t as DEPLOYMENT_EVENT_TYPES,u as DEPLOY_EVENT_ARN_MAX,C as DEPLOY_EVENT_CONTRACT,I as DEPLOY_EVENT_CONTRACT_MAJOR,l as DEPLOY_EVENT_CONTRACT_MINOR,f as DEPLOY_EVENT_ERROR_MESSAGE_MAX,M as DEPLOY_EVENT_ID_MAX,d as DEPLOY_EVENT_MESSAGE_MAX,h as DEPLOY_EVENT_NAME_MAX,Y as DEPLOY_EVENT_OUTPUT_MAX,V as DEPLOY_EVENT_STATUS_REASON_MAX,U as DEPLOY_EVENT_TRAIL_DETAIL_MAX,g as DEPLOY_EVENT_URL_MAX,X as DEPLOY_RESULTS,ie as DESTRUCTION_FINDINGS,K as DETECTION_PHASES,De as DRIFT_VERDICTS,D as DeployEventSchema,p as DeployResourceSchema,S as DeploymentEventSchema,ae as DestructionConsentSchema,Te as DestructionFindingSchema,oe as DestructionOutcomeSchema,re as DestructionTicketResourceSchema,Ae as DestructionTicketSchema,me as DriftFindingSchema,Le as DriftJournalRecordSchema,pe as DriftSuspectSchema,ce as DriftVerdictSchema,LE as FjallStateFileSchema,NE as INFRASTRUCTURE_FILENAME,UE as INFRASTRUCTURE_STEP_NAMES,YE as INFRA_STEP_NAME,F as LOG_LEVELS,ke as OPENNEXT_DEPLOY_ORDER,He as OPENNEXT_DESTROY_ORDER,Be as OPENNEXT_PARALLEL_GROUPS,AE as OPENNEXT_PATTERNS,Ge as ORGANISATION_TYPES,ve as PARALLEL_DEPLOY_GROUPS,be as PARALLEL_DESTROY_GROUPS,_E as PARALLEL_OPERATION_TYPES,k as PHASE_STATUSES,b as PLAN_ACTIONS,m as PlanChangeSchema,L as PlanPropertyChangeSchema,xe as ProgressReporter,Ie as REMEDIATION_PHASES,_e as REMEDIATION_VERB_GLOSS,B as REPLACEMENT_MODES,Me as RemediationFlipProofSchema,he as RemediationJournalRecordSchema,le as RemediationPhaseSchema,se as RemediationTargetSchema,te as RemediationVerbSchema,de as RemediationVerbWithSurgerySchema,y as STACK_CLEANUP_PHASES,OE as STACK_FAILED_STATE_PATTERN,RE as STACK_NOT_FOUND_PATTERN,x as STEP_COMPLETE_STATUSES,VE as STEP_IDS,fE as STEP_NAMES,s as SUPPORTED_CONTRACT_MARKERS,c as StepProgressSchema,Oe as TICKET_VERDICT_SOURCES,ee as TRAIL_MIGRATION_PHASES,Ee as TRAIL_MIGRATION_STATUSES,Pe as TicketVerdictSourceSchema,W as createDeployEmitter,IE as createEmptyState,lE as deleteStateFile,oE as deriveResourcesFromManifestStacks,We as getApplicationDeployOrder,qe as getApplicationDestroyOrder,ze as getApplicationStackName,EE as getApplicationStepId,eE as getApplicationStepName,Ze as getOrganisationStackName,je as getParallelDeployGroups,Qe as getParallelDestroyGroups,ME as getStateFilePath,Je as isApplicationOperation,$e as isApplicationStack,rE as isOpenNextPattern,we as isOrganisationOperation,O as isQuarantineDetail,Ue as isRemediationPlaceholderPhysicalId,P as isRetainedBucketsDetail,Z as parseDeployContractVersion,z as parseDeployEvent,nE as readStateFile,hE as regionSuffix,Ve as remediationPhaseRank,fe as remediationPlaceholderPhysicalId,ue as stubCallerIdentity,i as toCascadePhase,SE as toPascalCase,sE as updateTemplateHash,ne as verbsForDriftVerdict,pE as wrapApplicationError,CE as writeStateFile};
1
+ import{DeploymentEventSchema as S,DEPLOYMENT_EVENT_TYPES as _,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as T,DEPLOYMENT_EVENT_STATUS_REASON_MAX as A,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as t,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as r,CASCADE_PHASES as o,CASCADE_ACCOUNT_STATUSES as a,toCascadePhase as R}from"./deploymentEventSchema.js";import{isQuarantineDetail as P,isRetainedBucketsDetail as N}from"./callbacks.js";import{DeployEventSchema as D,StepProgressSchema as c,DeployResourceSchema as L,PlanChangeSchema as p,PlanPropertyChangeSchema as C,ChangeCountsSchema as n,DEPLOY_EVENT_CONTRACT as m,DEPLOY_EVENT_CONTRACT_MAJOR as I,DEPLOY_EVENT_CONTRACT_MINOR as s,SUPPORTED_CONTRACT_MARKERS as l,DEPLOY_EVENT_ID_MAX as M,DEPLOY_EVENT_NAME_MAX as h,DEPLOY_EVENT_MESSAGE_MAX as V,DEPLOY_EVENT_STATUS_REASON_MAX as U,DEPLOY_EVENT_ERROR_MESSAGE_MAX as Y,DEPLOY_EVENT_TRAIL_DETAIL_MAX as d,DEPLOY_EVENT_OUTPUT_MAX as f,DEPLOY_EVENT_ARN_MAX as g,DEPLOY_EVENT_URL_MAX as u,STEP_COMPLETE_STATUSES as x,LOG_LEVELS as G,STACK_CLEANUP_PHASES as X,CASCADE_ACCOUNT_PHASES as y,DEPLOY_RESULTS as F,DETECTION_PHASES as K,PHASE_STATUSES as k,BUILDERS as H,CASCADE_OUTCOME_RESULTS as b,PLAN_ACTIONS as v,REPLACEMENT_MODES as B,APPROVAL_KINDS as J,APPROVAL_DECISIONS as w,ALL_PROGRESS_KINDS as Q}from"./deployEvent.js";import{createDeployEmitter as j}from"./deployEmitter.js";import{parseDeployEvent as z,parseDeployContractVersion as Z}from"./deployEventParse.js";import{TRAIL_MIGRATION_PHASES as EE,TRAIL_MIGRATION_STATUSES as eE}from"./events.js";import{RemediationVerbSchema as _E,REMEDIATION_VERB_GLOSS as TE,DestructionFindingSchema as AE,DestructionTicketResourceSchema as tE,DestructionTicketSchema as rE,DestructionConsentSchema as oE,DestructionOutcomeSchema as aE,DESTRUCTION_FINDINGS as RE,CONSENT_VERDICTS as OE,TICKET_VERDICT_SOURCES as PE,TicketVerdictSourceSchema as NE}from"./destruction.js";import{DRIFT_VERDICTS as DE,DriftVerdictSchema as cE,DriftSuspectSchema as LE,DriftFindingSchema as pE,DriftJournalRecordSchema as CE,verbsForDriftVerdict as nE}from"./drift.js";import{REMEDIATION_PHASES as IE,RemediationPhaseSchema as sE,RemediationTargetSchema as lE,RemediationFlipProofSchema as ME,RemediationJournalRecordSchema as hE,RemediationVerbWithSurgerySchema as VE,remediationPhaseRank as UE,remediationPlaceholderPhysicalId as YE,isRemediationPlaceholderPhysicalId as dE}from"./remediation.js";import{stubCallerIdentity as gE}from"./deployment/index.js";import{ProgressReporter as xE}from"./ProgressEvent.js";import{APPLICATION_STACKS as XE,ORGANISATION_TYPES as yE,APPLICATION_DEPLOY_ORDER as FE,APPLICATION_DESTROY_ORDER as KE,OPENNEXT_DEPLOY_ORDER as kE,OPENNEXT_DESTROY_ORDER as HE,PARALLEL_DEPLOY_GROUPS as bE,PARALLEL_DESTROY_GROUPS as vE,OPENNEXT_PARALLEL_GROUPS as BE,isApplicationOperation as JE,isOrganisationOperation as wE,getParallelDeployGroups as QE,getParallelDestroyGroups as WE,getApplicationDeployOrder as jE,getApplicationDestroyOrder as qE,getApplicationStackName as zE,getOrganisationStackName as ZE,isApplicationStack as $E,getApplicationStepName as Ee,getApplicationStepId as ee,toPascalCase as Se}from"./operations.js";import{PARALLEL_OPERATION_TYPES as Te}from"./deployment/index.js";import{isOpenNextPattern as te,OPENNEXT_PATTERNS as re}from"./detection/patternTypes.js";import{STACK_NOT_FOUND_PATTERN as ae,STACK_FAILED_STATE_PATTERN as Re,CDK_NO_STACKS_MATCH as Oe,INFRASTRUCTURE_FILENAME as Pe}from"./constants.js";import{ApplicationError as ie,wrapApplicationError as De}from"./application/index.js";import{STEP_IDS as Le,STEP_NAMES as pe,INFRASTRUCTURE_STEP_NAMES as Ce,INFRA_STEP_NAME as ne}from"./stepDefinitions.js";export{Q as ALL_PROGRESS_KINDS,FE as APPLICATION_DEPLOY_ORDER,KE as APPLICATION_DESTROY_ORDER,XE as APPLICATION_STACKS,w as APPROVAL_DECISIONS,J as APPROVAL_KINDS,ie as ApplicationError,H as BUILDERS,y as CASCADE_ACCOUNT_PHASES,a as CASCADE_ACCOUNT_STATUSES,b as CASCADE_OUTCOME_RESULTS,o as CASCADE_PHASES,Oe as CDK_NO_STACKS_MATCH,OE as CONSENT_VERDICTS,n as ChangeCountsSchema,t as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,T as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,A as DEPLOYMENT_EVENT_STATUS_REASON_MAX,r as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,_ as DEPLOYMENT_EVENT_TYPES,g as DEPLOY_EVENT_ARN_MAX,m as DEPLOY_EVENT_CONTRACT,I as DEPLOY_EVENT_CONTRACT_MAJOR,s as DEPLOY_EVENT_CONTRACT_MINOR,Y as DEPLOY_EVENT_ERROR_MESSAGE_MAX,M as DEPLOY_EVENT_ID_MAX,V as DEPLOY_EVENT_MESSAGE_MAX,h as DEPLOY_EVENT_NAME_MAX,f as DEPLOY_EVENT_OUTPUT_MAX,U as DEPLOY_EVENT_STATUS_REASON_MAX,d as DEPLOY_EVENT_TRAIL_DETAIL_MAX,u as DEPLOY_EVENT_URL_MAX,F as DEPLOY_RESULTS,RE as DESTRUCTION_FINDINGS,K as DETECTION_PHASES,DE as DRIFT_VERDICTS,D as DeployEventSchema,L as DeployResourceSchema,S as DeploymentEventSchema,oE as DestructionConsentSchema,AE as DestructionFindingSchema,aE as DestructionOutcomeSchema,tE as DestructionTicketResourceSchema,rE as DestructionTicketSchema,pE as DriftFindingSchema,CE as DriftJournalRecordSchema,LE as DriftSuspectSchema,cE as DriftVerdictSchema,Pe as INFRASTRUCTURE_FILENAME,Ce as INFRASTRUCTURE_STEP_NAMES,ne as INFRA_STEP_NAME,G as LOG_LEVELS,kE as OPENNEXT_DEPLOY_ORDER,HE as OPENNEXT_DESTROY_ORDER,BE as OPENNEXT_PARALLEL_GROUPS,re as OPENNEXT_PATTERNS,yE as ORGANISATION_TYPES,bE as PARALLEL_DEPLOY_GROUPS,vE as PARALLEL_DESTROY_GROUPS,Te as PARALLEL_OPERATION_TYPES,k as PHASE_STATUSES,v as PLAN_ACTIONS,p as PlanChangeSchema,C as PlanPropertyChangeSchema,xE as ProgressReporter,IE as REMEDIATION_PHASES,TE as REMEDIATION_VERB_GLOSS,B as REPLACEMENT_MODES,ME as RemediationFlipProofSchema,hE as RemediationJournalRecordSchema,sE as RemediationPhaseSchema,lE as RemediationTargetSchema,_E as RemediationVerbSchema,VE as RemediationVerbWithSurgerySchema,X as STACK_CLEANUP_PHASES,Re as STACK_FAILED_STATE_PATTERN,ae as STACK_NOT_FOUND_PATTERN,x as STEP_COMPLETE_STATUSES,Le as STEP_IDS,pe as STEP_NAMES,l as SUPPORTED_CONTRACT_MARKERS,c as StepProgressSchema,PE as TICKET_VERDICT_SOURCES,EE as TRAIL_MIGRATION_PHASES,eE as TRAIL_MIGRATION_STATUSES,NE as TicketVerdictSourceSchema,j as createDeployEmitter,jE as getApplicationDeployOrder,qE as getApplicationDestroyOrder,zE as getApplicationStackName,ee as getApplicationStepId,Ee as getApplicationStepName,ZE as getOrganisationStackName,QE as getParallelDeployGroups,WE as getParallelDestroyGroups,JE as isApplicationOperation,$E as isApplicationStack,te as isOpenNextPattern,wE as isOrganisationOperation,P as isQuarantineDetail,dE as isRemediationPlaceholderPhysicalId,N as isRetainedBucketsDetail,Z as parseDeployContractVersion,z as parseDeployEvent,UE as remediationPhaseRank,YE as remediationPlaceholderPhysicalId,gE as stubCallerIdentity,R as toCascadePhase,Se as toPascalCase,nE as verbsForDriftVerdict,De as wrapApplicationError};
@@ -1,6 +1,7 @@
1
1
  import { type AppResourceFlags } from "./detection/patternTypes.js";
2
2
  import { type StepId } from "./stepDefinitions.js";
3
3
  import { toPascalCase } from "@fjall/util";
4
+ import type { PatternType } from "@fjall/generator";
4
5
  /**
5
6
  * Application infrastructure stacks
6
7
  */
@@ -157,7 +158,7 @@ export declare function getParallelDestroyGroups(): ReadonlyArray<(typeof PARALL
157
158
  * Options for determining deployment order
158
159
  */
159
160
  export interface DeployOrderOptions {
160
- pattern?: "payload" | "nextjs" | null;
161
+ pattern?: PatternType | null;
161
162
  resources?: AppResourceFlags;
162
163
  }
163
164
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/deploy-core",
3
- "version": "2.29.0",
3
+ "version": "2.30.3",
4
4
  "description": "Shared deployment engine for Fjall — used by CLI and webapp worker",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -48,6 +48,7 @@
48
48
  "scripts": {
49
49
  "clean": "rm -rf ./dist ./sourcemaps",
50
50
  "build": "npm run clean && tsc && node ../scripts/minify-dist.mjs dist",
51
+ "prepack": "node ../scripts/check-dist-freshness.mjs",
51
52
  "watch": "npm run build && tsc --watch --preserveWatchOutput",
52
53
  "watch:only": "tsc --watch --preserveWatchOutput",
53
54
  "typecheck": "tsc --noEmit",
@@ -74,6 +75,7 @@
74
75
  "@aws-sdk/client-iam": "^3.1038.0",
75
76
  "@aws-sdk/client-identitystore": "^3.1079.0",
76
77
  "@aws-sdk/client-kms": "^3.1065.0",
78
+ "@aws-sdk/client-lambda": "^3.1038.0",
77
79
  "@aws-sdk/client-organizations": "^3.1038.0",
78
80
  "@aws-sdk/client-ram": "^3.1038.0",
79
81
  "@aws-sdk/client-rds": "^3.1038.0",
@@ -83,8 +85,8 @@
83
85
  "@aws-sdk/client-ssm": "^3.1038.0",
84
86
  "@aws-sdk/client-sso-admin": "^3.1038.0",
85
87
  "@aws-sdk/client-sts": "^3.1038.0",
86
- "@fjall/generator": "^2.29.0",
87
- "@fjall/util": "^2.29.0",
88
+ "@fjall/generator": "^2.30.3",
89
+ "@fjall/util": "^2.30.3",
88
90
  "@smithy/node-http-handler": "^4.6.1",
89
91
  "aws-cdk": "^2.1128.1",
90
92
  "tsx": "^4.21.0",
@@ -95,5 +97,5 @@
95
97
  "typescript": "^6.0.3",
96
98
  "vitest": "^4.1.5"
97
99
  },
98
- "gitHead": "c40ea0e1435400f3f42faaad5bcbf50e4400c1d4"
100
+ "gitHead": "d398edc0c0edf661d7ab6e5a47623529f68dfd2a"
99
101
  }