@fjall/generator 31.0.0 → 32.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,7 @@
9
9
  "package.json",
10
10
  "tsconfig.json"
11
11
  ],
12
- "hash": "f6fe0cf1bd62c37ef4f0bd6a7bdb0214ebec66f14fe6564df2548372a4e25ca8",
12
+ "hash": "bb74d661d0fb263d4707d77119b7d703afb09bfb8b158fbee179e9c0f4299234",
13
13
  "files": {
14
14
  "src/ast/astTestHelpers.ts": "026cac849eb88bdb",
15
15
  "src/ast/domain/astDomainParser.ts": "12107a9864c6670c",
@@ -25,7 +25,7 @@
25
25
  "src/ast/parsers/resources/astCdnParser.ts": "726b298b0b580d68",
26
26
  "src/ast/parsers/resources/astClickHouseParser.ts": "52dda31086619b09",
27
27
  "src/ast/parsers/resources/astComputeConnectionParser.ts": "e0f1533845f3ce8a",
28
- "src/ast/parsers/resources/astComputeParser.ts": "8caa5cc22af1913a",
28
+ "src/ast/parsers/resources/astComputeParser.ts": "4ae45796570e0b4d",
29
29
  "src/ast/parsers/resources/astComputeParserHelpers.ts": "4763a0f0afbd4880",
30
30
  "src/ast/parsers/resources/astDatabaseParser.ts": "e18f5483f5e23297",
31
31
  "src/ast/parsers/resources/astDynamoDBParser.ts": "809c2c633447b388",
@@ -122,7 +122,7 @@
122
122
  "src/generation/common.ts": "50bbd875b9dd737e",
123
123
  "src/generation/compute.ts": "068f6fa241838b25",
124
124
  "src/generation/compute/ec2.ts": "a906b9076481f66b",
125
- "src/generation/compute/ecs.ts": "7bc7dcfc5c20ce4e",
125
+ "src/generation/compute/ecs.ts": "fd7686863100cdcd",
126
126
  "src/generation/compute/lambda.ts": "932a45cdc26a5730",
127
127
  "src/generation/compute/shared.ts": "3724d4bfe92cfcb7",
128
128
  "src/generation/connectionWiring.ts": "9afb0227f2584ab2",
@@ -162,7 +162,7 @@
162
162
  "src/schemas/baseSchemas.ts": "93d9bd1c0adfcaa0",
163
163
  "src/schemas/buildkiteSchemas.ts": "a28ec3b40f7851ec",
164
164
  "src/schemas/cdnSchemas.ts": "16784f15894c62ba",
165
- "src/schemas/computeSchemas.ts": "7105193fd34c8bcb",
165
+ "src/schemas/computeSchemas.ts": "8bb5d3ebcdab5bab",
166
166
  "src/schemas/constants.ts": "b0abe53d7a42feb0",
167
167
  "src/schemas/databaseSchemas.ts": "7d33a96789cbfdb5",
168
168
  "src/schemas/devRolePolicies.ts": "73000c87ea0de1d2",
@@ -181,11 +181,11 @@
181
181
  "src/validation/patterns.ts": "f9629eafdad7ac3e",
182
182
  "src/validation/validationMessages.ts": "b03413b3953c3e79",
183
183
  "src/validation/validationPatterns.ts": "865f3d688975b7c8",
184
- "src/version.ts": "44796fa69ed21d3a",
184
+ "src/version.ts": "c559d9f46fc76d17",
185
185
  "../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
186
- "package.json": "d78da7528d41e1e1",
186
+ "package.json": "eb94caf8b1a62d9b",
187
187
  "tsconfig.json": "1929cf3f99fe9b1e"
188
188
  },
189
- "outputHash": "49be50db43b701a3a7c54d94132304d0ecce076bc9c30df481ed694a87cce1e4",
189
+ "outputHash": "f389d7568c9ad46a3d2df5ef8bb9e0154d806d448d7bf588c76a1f4849684635",
190
190
  "outputFileCount": 343
191
191
  }
package/dist/.minified CHANGED
@@ -1 +1 @@
1
- 171 files minified at 2026-09-03T09:13:58.800Z
1
+ 171 files minified at 2026-09-05T02:09:37.969Z
@@ -140,6 +140,7 @@ export declare function parseAndConvert(code: string): {
140
140
  sourceText: string;
141
141
  }[] | undefined;
142
142
  } | undefined;
143
+ containerInsights?: true | undefined;
143
144
  services?: {
144
145
  name: string;
145
146
  capacityProvider: "FARGATE" | "FARGATE_SPOT" | "EC2";
@@ -1 +1 @@
1
- var v=Object.defineProperty;var f=(e,n)=>v(e,"name",{value:n,configurable:!0});import*as E from"typescript";import{asString as a,asNumber as y,asBoolean as m,asStringArray as u,asStringUnion as d,captureExtraProperties as T,collectFromAst as _,extractVariableName as b,isFactoryBuildCall as A,isFactoryMethodCall as x,isParsedObject as S,parseObjectLiteral as O}from"../common/astCommonParser.js";import{COMPUTE_ARCHITECTURES as D,COMPUTE_TYPES as R,DEPLOYMENT_TYPES as Y,EC2_INSTANCE_TYPES as K,FUNCTION_URL_AUTH_TYPES as U}from"../../../schemas/constants.js";import{assignIfDefined as c,extractCallStringArg as F,extractClusterConfig as L,extractEnumString as N,isEnvironmentRecord as h,parseEcsService as k}from"./astComputeParserHelpers.js";import{inferDatabaseConnectionsFromEnv as H,inferStorageConnectionsFromEnv as V,resolveConnectedDatabaseNames as I,resolveConnectedStorageNames as M}from"./astComputeConnectionParser.js";function W(e){if(e.arguments.length<2)return null;const n=e.arguments[0],i=e.arguments[1];if(!E.isStringLiteral(n)||!E.isObjectLiteralExpression(i))return null;const t=n.text,r=O(i);return{resourceName:t,type:a(r.type)??"ecs",config:r,node:e}}f(W,"extractComputeResource");function Z(e){return _(e,n=>{if(!E.isCallExpression(n)||!x(n,"addCompute"))return null;const i=n.arguments[0];if(!A(i,"ComputeFactory"))return null;const t=W(i);if(t){const r=b(n);r&&(t.variableName=r)}return t})}f(Z,"findComputeResources");function C(e,n,i){const t=T(e.config,i);t.length>0&&(n.extraProperties=t)}f(C,"applyExtras");function z(e,n){const i=e.config.docker;if(S(i)){const o=a(i.path),g=a(i.context),l=a(i.target);(o!==void 0||g!==void 0||l!==void 0)&&(n.docker={...o!==void 0&&{path:o},...g!==void 0&&{context:g},...l!==void 0&&{target:l}})}const t=e.config.cluster;t!==void 0&&(n.cluster=L(t));const r=e.config.services;r!==void 0&&Array.isArray(r)&&(n.services=r.filter(o=>S(o)).map(k)),C(e,n,new Set(["type","ecrRepository","docker","cluster","services","connections"]))}f(z,"convertEcsCompute");function p(e,n){if(c(n,"deployment",d(e.config.deployment,Y)),c(n,"timeout",y(e.config.timeout)),c(n,"memory",y(e.config.memorySize)??y(e.config.memory)),c(n,"handler",a(e.config.handler)),c(n,"runtime",N(e.config.runtime,"Runtime")),h(e.config.environment)&&(n.environment=e.config.environment),h(e.config.secrets))n.secrets=e.config.secrets;else{const s=u(e.config.secrets);s&&(n.ssmSecrets=s)}const i=e.config.functionUrl;if(S(i)){const s=d(N(i.authType,"FunctionUrlAuthType"),U);s!==void 0&&(n.functionUrl={authType:s})}const t=e.config.code;if(t!==void 0){const s=F(t);s&&(n.codePath=s)}c(n,"description",a(e.config.description)??a(e.config.lambdaDescription)),c(n,"architecture",d(N(e.config.architecture,"Architecture"),D)),c(n,"ephemeralStorageSize",y(e.config.ephemeralStorageSize)),c(n,"functionName",a(e.config.functionName)),c(n,"ssmSecretsPath",a(e.config.ssmSecretsPath)),C(e,n,new Set(["type","deployment","timeout","memorySize","memory","handler","runtime","environment","secrets","functionUrl","code","connections","ecrRepository","containerSecretsImport","secretsImport","lambdaDescription","description","architecture","ephemeralStorageSize","functionName","ssmSecretsPath"]))}f(p,"convertLambdaCompute");function B(e,n){c(n,"instanceType",d(e.config.instanceType,K));const i=e.config.ssh;i===!1?n.enableSSH=!1:i!==void 0&&S(i)?n.enableSSH=!0:c(n,"enableSSH",m(e.config.enableSSH)),c(n,"keyName",a(e.config.keyName)),c(n,"userData",a(e.config.userData)),e.config.securityGroups!==void 0&&(n.securityGroups=u(e.config.securityGroups)),C(e,n,new Set(["type","instanceType","ssh","enableSSH","keyName","userData","securityGroups","connections"]))}f(B,"convertEc2Compute");function G(e,n,i,t){let r=n.config.connections;if(!r&&Array.isArray(n.config.services)){const g=n.config.services[0];S(g)&&(r=g.connections)}if(!r)return;const s=I(r,i);s.length>0&&(e.needsConnection=!0,e.connectedDatabase=s);const o=M(r,t);o.length>0&&(e.connectedStorage=o)}f(G,"applyConnectionConfig");function j(e,n){({ecs:z,lambda:p,ec2:B})[e.type]?.(n,e)}f(j,"applyTypeSpecificConfig");function $(e,n,i,t){return e.map(r=>{const s=d(r.config.type,R)??"ecs",o={name:r.resourceName,type:s,needsConnection:!1,connectedDatabase:[],...r.variableName&&{variableName:r.variableName}};return G(o,r,n,i),j(o,r),H(o,r.config.services,t.database),V(o,r.config.services,t.s3),o})}f($,"convertComputeResources");export{$ as convertComputeResources,Z as findComputeResources};
1
+ var T=Object.defineProperty;var f=(e,n)=>T(e,"name",{value:n,configurable:!0});import*as N from"typescript";import{asString as c,asNumber as y,asBoolean as h,asStringArray as v,asStringUnion as d,captureExtraProperties as b,collectFromAst as _,extractVariableName as A,isFactoryBuildCall as x,isFactoryMethodCall as D,isParsedObject as S,parseObjectLiteral as O}from"../common/astCommonParser.js";import{COMPUTE_ARCHITECTURES as R,COMPUTE_TYPES as U,DEPLOYMENT_TYPES as Y,EC2_INSTANCE_TYPES as I,FUNCTION_URL_AUTH_TYPES as K}from"../../../schemas/constants.js";import{assignIfDefined as o,extractCallStringArg as F,extractClusterConfig as L,extractEnumString as u,isEnvironmentRecord as m,parseEcsService as k}from"./astComputeParserHelpers.js";import{inferDatabaseConnectionsFromEnv as H,inferStorageConnectionsFromEnv as V,resolveConnectedDatabaseNames as M,resolveConnectedStorageNames as z}from"./astComputeConnectionParser.js";function W(e){if(e.arguments.length<2)return null;const n=e.arguments[0],r=e.arguments[1];if(!N.isStringLiteral(n)||!N.isObjectLiteralExpression(r))return null;const t=n.text,i=O(r);return{resourceName:t,type:c(i.type)??"ecs",config:i,node:e}}f(W,"extractComputeResource");function $(e){return _(e,n=>{if(!N.isCallExpression(n)||!D(n,"addCompute"))return null;const r=n.arguments[0];if(!x(r,"ComputeFactory"))return null;const t=W(r);if(t){const i=A(n);i&&(t.variableName=i)}return t})}f($,"findComputeResources");function C(e,n,r){const t=b(e.config,r);t.length>0&&(n.extraProperties=t)}f(C,"applyExtras");function B(e,n){const r=e.config.docker;if(S(r)){const g=c(r.path),l=c(r.context),E=c(r.target);(g!==void 0||l!==void 0||E!==void 0)&&(n.docker={...g!==void 0&&{path:g},...l!==void 0&&{context:l},...E!==void 0&&{target:E}})}const t=e.config.cluster;t!==void 0&&(n.cluster=L(t));const i=h(e.config.containerInsights)===!0;i&&(n.containerInsights=!0);const s=e.config.services;s!==void 0&&Array.isArray(s)&&(n.services=s.filter(g=>S(g)).map(k));const a=new Set(["type","ecrRepository","docker","cluster","services","connections",...i?["containerInsights"]:[]]);C(e,n,a)}f(B,"convertEcsCompute");function G(e,n){if(o(n,"deployment",d(e.config.deployment,Y)),o(n,"timeout",y(e.config.timeout)),o(n,"memory",y(e.config.memorySize)??y(e.config.memory)),o(n,"handler",c(e.config.handler)),o(n,"runtime",u(e.config.runtime,"Runtime")),m(e.config.environment)&&(n.environment=e.config.environment),m(e.config.secrets))n.secrets=e.config.secrets;else{const s=v(e.config.secrets);s&&(n.ssmSecrets=s)}const r=e.config.functionUrl;if(S(r)){const s=d(u(r.authType,"FunctionUrlAuthType"),K);s!==void 0&&(n.functionUrl={authType:s})}const t=e.config.code;if(t!==void 0){const s=F(t);s&&(n.codePath=s)}o(n,"description",c(e.config.description)??c(e.config.lambdaDescription)),o(n,"architecture",d(u(e.config.architecture,"Architecture"),R)),o(n,"ephemeralStorageSize",y(e.config.ephemeralStorageSize)),o(n,"functionName",c(e.config.functionName)),o(n,"ssmSecretsPath",c(e.config.ssmSecretsPath)),C(e,n,new Set(["type","deployment","timeout","memorySize","memory","handler","runtime","environment","secrets","functionUrl","code","connections","ecrRepository","containerSecretsImport","secretsImport","lambdaDescription","description","architecture","ephemeralStorageSize","functionName","ssmSecretsPath"]))}f(G,"convertLambdaCompute");function j(e,n){o(n,"instanceType",d(e.config.instanceType,I));const r=e.config.ssh;r===!1?n.enableSSH=!1:r!==void 0&&S(r)?n.enableSSH=!0:o(n,"enableSSH",h(e.config.enableSSH)),o(n,"keyName",c(e.config.keyName)),o(n,"userData",c(e.config.userData)),e.config.securityGroups!==void 0&&(n.securityGroups=v(e.config.securityGroups)),C(e,n,new Set(["type","instanceType","ssh","enableSSH","keyName","userData","securityGroups","connections"]))}f(j,"convertEc2Compute");function w(e,n,r,t){let i=n.config.connections;if(!i&&Array.isArray(n.config.services)){const g=n.config.services[0];S(g)&&(i=g.connections)}if(!i)return;const s=M(i,r);s.length>0&&(e.needsConnection=!0,e.connectedDatabase=s);const a=z(i,t);a.length>0&&(e.connectedStorage=a)}f(w,"applyConnectionConfig");function p(e,n){({ecs:B,lambda:G,ec2:j})[e.type]?.(n,e)}f(p,"applyTypeSpecificConfig");function P(e,n,r,t){return e.map(i=>{const s=d(i.config.type,U)??"ecs",a={name:i.resourceName,type:s,needsConnection:!1,connectedDatabase:[],...i.variableName&&{variableName:i.variableName}};return w(a,i,n,r),p(a,i),H(a,i.config.services,t.database),V(a,i.config.services,t.s3),a})}f(P,"convertComputeResources");export{P as convertComputeResources,$ as findComputeResources};
@@ -1,12 +1,12 @@
1
- var O=Object.defineProperty;var m=(e,n)=>O(e,"name",{value:n,configurable:!0});import{scalingTypeBinding as k}from"../../projection/compute.js";import{formatValue as v,emitExtraProperties as E,escapeStringLiteral as o,formatStringArray as N,emitProductionAlertsTopicSpread as R}from"../common.js";import{renderStructuredValueSource as B}from"../structuredSource.js";import{DATABASE_ENV_VARS as y,getConnectedDatabases as D,buildDatabaseEnvVars as j}from"../database.js";import{STORAGE_ENV_VARS as L,getConnectedStorage as _,buildStorageEnvVars as w,formatAllConnectionsCode as H}from"../storageConnections.js";import{MESSAGING_ENV_VARS as C,getConnectedMessaging as I,buildMessagingEnvVars as G}from"../messagingConnections.js";import{BASE_ENVIRONMENT_VARS as J,computeHasConnections as K,computeHasDatabaseConnections as P,computeHasMessagingConnections as T,computeHasStorageConnections as V,formatCompactOrExpandedObject as $,formatEnvBlock as M}from"./shared.js";function U(e){const n=[];if(e.instanceType!==void 0&&n.push(`instanceType: ${o(e.instanceType)}`),e.amiHardwareType!==void 0&&n.push(`amiHardwareType: ${o(e.amiHardwareType)}`),e.minCapacity!==void 0&&n.push(`minCapacity: ${e.minCapacity}`),e.maxCapacity!==void 0&&n.push(`maxCapacity: ${e.maxCapacity}`),e.memoryLimitMiB!==void 0&&n.push(`memoryLimitMiB: ${e.memoryLimitMiB}`),e.warmPool!==void 0&&n.push(`warmPool: ${v(e.warmPool," ")}`),e.extraProperties?.length)for(const s of e.extraProperties)n.push(`${s.key}: ${s.sourceText}`);return`
1
+ var O=Object.defineProperty;var m=(e,n)=>O(e,"name",{value:n,configurable:!0});import{scalingTypeBinding as k}from"../../projection/compute.js";import{formatValue as v,emitExtraProperties as E,escapeStringLiteral as o,formatStringArray as N,emitProductionAlertsTopicSpread as R}from"../common.js";import{renderStructuredValueSource as B}from"../structuredSource.js";import{DATABASE_ENV_VARS as y,getConnectedDatabases as D,buildDatabaseEnvVars as j}from"../database.js";import{STORAGE_ENV_VARS as L,getConnectedStorage as _,buildStorageEnvVars as I,formatAllConnectionsCode as w}from"../storageConnections.js";import{MESSAGING_ENV_VARS as C,getConnectedMessaging as H,buildMessagingEnvVars as G}from"../messagingConnections.js";import{BASE_ENVIRONMENT_VARS as J,computeHasConnections as K,computeHasDatabaseConnections as P,computeHasMessagingConnections as T,computeHasStorageConnections as V,formatCompactOrExpandedObject as $,formatEnvBlock as M}from"./shared.js";function U(e){const n=[];if(e.instanceType!==void 0&&n.push(`instanceType: ${o(e.instanceType)}`),e.amiHardwareType!==void 0&&n.push(`amiHardwareType: ${o(e.amiHardwareType)}`),e.minCapacity!==void 0&&n.push(`minCapacity: ${e.minCapacity}`),e.maxCapacity!==void 0&&n.push(`maxCapacity: ${e.maxCapacity}`),e.memoryLimitMiB!==void 0&&n.push(`memoryLimitMiB: ${e.memoryLimitMiB}`),e.warmPool!==void 0&&n.push(`warmPool: ${v(e.warmPool," ")}`),e.extraProperties?.length)for(const s of e.extraProperties)n.push(`${s.key}: ${s.sourceText}`);return`
2
2
  ec2Config: ${$(n," "," ")},`}m(U,"generateEcsServiceEc2ConfigCode");function W(e){if(!e.cluster)return"";const n=[];if(e.cluster.directAccess&&n.push("directAccess: true"),e.cluster.domain&&n.push(`domain: ${o(e.cluster.domain)}`),e.cluster.loadBalancer!==void 0&&n.push(e.cluster.loadBalancer===!1?"loadBalancer: false":`loadBalancer: ${o(e.cluster.loadBalancer)}`),e.cluster.extraProperties?.length)for(const s of e.cluster.extraProperties)n.push(`${s.key}: ${s.sourceText}`);return`
3
- cluster: ${$(n," "," ")},`}m(W,"generateEcsClusterCode");function z(e,n,s,f,l,h){let i="";e.name&&(i+=`
3
+ cluster: ${$(n," "," ")},`}m(W,"generateEcsClusterCode");function z(e,n,s,f,p,h){let i="";e.name&&(i+=`
4
4
  name: ${o(e.name)},`),e.image&&(i+=`
5
5
  image: ${o(e.image)},`),e.port!==void 0&&(i+=`
6
6
  port: ${e.port},`),e.essential!==void 0&&(i+=`
7
7
  essential: ${e.essential},`),e.command?.length&&(i+=`
8
8
  command: ${JSON.stringify(e.command)},`),e.entryPoint?.length&&(i+=`
9
- entryPoint: ${JSON.stringify(e.entryPoint)},`);const c=[y.HOST,y.PORT,y.NAME,y.SSL,y.USERNAME,y.PASSWORD,L.NAME,C.URL,C.ARN],r=m(a=>{if(!a)return a;const d={};for(const[p,g]of Object.entries(a))c.some(S=>p===S||p.startsWith(`${S}_`))||(d[p]=g);return Object.keys(d).length>0?d:void 0},"stripConnectionEnv"),u=n?{...h,...s.env,...f.env,...l.env,...e.environment}:{...h,...r(e.environment)},t=n?{...s.secrets,...e.secretsImport}:r(e.secretsImport);return u&&Object.keys(u).length>0&&(i+=`
9
+ entryPoint: ${JSON.stringify(e.entryPoint)},`);const c=[y.HOST,y.PORT,y.NAME,y.SSL,y.USERNAME,y.PASSWORD,L.NAME,C.URL,C.ARN],r=m(a=>{if(!a)return a;const d={};for(const[l,g]of Object.entries(a))c.some(S=>l===S||l.startsWith(`${S}_`))||(d[l]=g);return Object.keys(d).length>0?d:void 0},"stripConnectionEnv"),u=n?{...h,...s.env,...f.env,...p.env,...e.environment}:{...h,...r(e.environment)},t=n?{...s.secrets,...e.secretsImport}:r(e.secretsImport);return u&&Object.keys(u).length>0&&(i+=`
10
10
  environment: {
11
11
  ${M(u," ")}
12
12
  },`),t&&Object.keys(t).length>0&&(i+=`
@@ -21,23 +21,24 @@ ${M(t," ")}
21
21
  `)},
22
22
  ],`}m(Y,"generateEcsServiceRoutingCode");function q(e){if(e===!1)return`
23
23
  scaling: false,`;if(typeof e!="object"||!(e.minCapacity!==void 0||e.maxCapacity!==void 0||e.desiredCount!==void 0||e.scalingType!==void 0))return"";const s=[];if(e.minCapacity!==void 0&&s.push(`minCapacity: ${e.minCapacity}`),e.maxCapacity!==void 0&&s.push(`maxCapacity: ${e.maxCapacity}`),e.desiredCount!==void 0&&s.push(`desiredCount: ${e.desiredCount}`),e.scalingType){const f=k(e.scalingType);if(f===void 0)throw new Error(`services[].scaling.scalingType \`${e.scalingType}\` is not a ScalingType member name \u2014 the schema gate (z.enum(SCALING_TYPES)) should have refused this plan.`);s.push(`scalingType: ${B("scalingType",f.expression)}`)}return`
24
- scaling: ${$(s," "," ")},`}m(q,"generateEcsServiceScalingCode");function F(e,n,s){return{needsDb:e.needsDatabaseConnection!==void 0?e.needsDatabaseConnection:n&&P(s),needsStorage:e.needsStorageConnection!==void 0?e.needsStorageConnection:n&&V(s),needsMessaging:e.needsMessagingConnection!==void 0?e.needsMessagingConnection:n&&T(s)}}m(F,"deriveServiceConnectionNeeds");function Q(e){const{service:n,isFirstService:s,hasConnections:f,dbEnvVars:l,storageEnvVars:h,messagingEnvVars:i,baseEnvVars:c,plan:r,compute:u}=e;let t=`
24
+ scaling: ${$(s," "," ")},`}m(q,"generateEcsServiceScalingCode");function F(e,n,s){return{needsDb:e.needsDatabaseConnection!==void 0?e.needsDatabaseConnection:n&&P(s),needsStorage:e.needsStorageConnection!==void 0?e.needsStorageConnection:n&&V(s),needsMessaging:e.needsMessagingConnection!==void 0?e.needsMessagingConnection:n&&T(s)}}m(F,"deriveServiceConnectionNeeds");function Q(e){const{service:n,isFirstService:s,hasConnections:f,dbEnvVars:p,storageEnvVars:h,messagingEnvVars:i,baseEnvVars:c,plan:r,compute:u}=e;let t=`
25
25
  name: ${o(n.name)},`;t+=`
26
26
  capacityProvider: ${o(n.capacityProvider)},`,n.serviceType!==void 0&&(t+=`
27
27
  serviceType: ${o(n.serviceType)},`),n.ec2Config&&(t+=U(n.ec2Config)),n.docker&&(t+=`
28
28
  docker: ${v(n.docker," ")},`),n.image&&(t+=`
29
29
  image: ${o(n.image)},`),n.ssmSecretsPath&&(t+=`
30
30
  ssmSecretsPath: ${o(n.ssmSecretsPath)},`);const a=F(n,s,u);if(n.containers?.length){t+=`
31
- containers: [{`;for(let d=0;d<n.containers.length;d++){const p=n.containers[d];if(!p)continue;const g=d===0&&(a.needsDb||a.needsStorage||a.needsMessaging)&&f,b=a.needsDb?l:{env:{},secrets:{}},S=a.needsStorage?h:{env:{},secrets:{}},A=a.needsMessaging?i:{env:{},secrets:{}};d>0&&(t+=`
32
- }, {`),t+=z(p,g,b,S,A,c)}t+=`
31
+ containers: [{`;for(let d=0;d<n.containers.length;d++){const l=n.containers[d];if(!l)continue;const g=d===0&&(a.needsDb||a.needsStorage||a.needsMessaging)&&f,b=a.needsDb?p:{env:{},secrets:{}},S=a.needsStorage?h:{env:{},secrets:{}},A=a.needsMessaging?i:{env:{},secrets:{}};d>0&&(t+=`
32
+ }, {`),t+=z(l,g,b,S,A,c)}t+=`
33
33
  }],`}if(n.routing&&(t+=Y(n.routing)),n.cpu!==void 0&&(t+=`
34
34
  cpu: ${n.cpu},`),n.memoryLimitMiB!==void 0&&(t+=`
35
35
  memoryLimitMiB: ${n.memoryLimitMiB},`),n.desiredCount!==void 0&&(t+=`
36
36
  desiredCount: ${n.desiredCount},`),n.scaling!==void 0&&(t+=q(n.scaling)),n.alarms===!1?t+=`
37
37
  alarms: false,`:typeof n.alarms=="object"&&(t+=`
38
- alarms: ${v(n.alarms," ")},`),t+=E(n.extraProperties," "),a.needsDb||a.needsStorage||a.needsMessaging){const d=a.needsDb?D(r,u):[],p=a.needsStorage?_(r,u):[],g=a.needsMessaging?I(r,u):[];(d.length>0||p.length>0||g.length>0)&&(t+=`
39
- ${H(d,p,g)}`)}return t}m(Q,"generateEcsServiceCode");function ae(e,n){const s=K(e),f={...J},l={env:{},secrets:{}};if(P(e)){const r=j(n,e);Object.assign(l.env,r.env),Object.assign(l.secrets,r.secrets)}const h={env:{},secrets:{}};if(V(e)){const r=w(n,e);Object.assign(h.env,r.env)}const i={env:{},secrets:{}};if(T(e)){const r=G(n,e);Object.assign(i.env,r.env)}let c=`
40
- ecrRepository: app.getDefaultContainerRegistry(),`;if(c+=W(e),e.services?.length){c+=`
38
+ alarms: ${v(n.alarms," ")},`),t+=E(n.extraProperties," "),a.needsDb||a.needsStorage||a.needsMessaging){const d=a.needsDb?D(r,u):[],l=a.needsStorage?_(r,u):[],g=a.needsMessaging?H(r,u):[];(d.length>0||l.length>0||g.length>0)&&(t+=`
39
+ ${w(d,l,g)}`)}return t}m(Q,"generateEcsServiceCode");function ae(e,n){const s=K(e),f={...J},p={env:{},secrets:{}};if(P(e)){const r=j(n,e);Object.assign(p.env,r.env),Object.assign(p.secrets,r.secrets)}const h={env:{},secrets:{}};if(V(e)){const r=I(n,e);Object.assign(h.env,r.env)}const i={env:{},secrets:{}};if(T(e)){const r=G(n,e);Object.assign(i.env,r.env)}let c=`
40
+ ecrRepository: app.getDefaultContainerRegistry(),`;if(e.containerInsights===!0&&(c+=`
41
+ containerInsights: true,`),c+=W(e),e.services?.length){c+=`
41
42
  services: [{`;for(let r=0;r<e.services.length;r++){const u=e.services[r];u&&(r>0&&(c+=`
42
- }, {`),c+=Q({service:u,isFirstService:r===0,hasConnections:s,dbEnvVars:l,storageEnvVars:h,messagingEnvVars:i,baseEnvVars:f,plan:n,compute:e}))}c+=`
43
+ }, {`),c+=Q({service:u,isFirstService:r===0,hasConnections:s,dbEnvVars:p,storageEnvVars:h,messagingEnvVars:i,baseEnvVars:f,plan:n,compute:e}))}c+=`
43
44
  }],`}return c+=E(e.extraProperties),c+=R(),c}m(ae,"generateEcsCode");export{ae as generateEcsCode};
@@ -556,6 +556,7 @@ export declare const ApplicationResourcePlanSchema: z.ZodObject<{
556
556
  sourceText: z.ZodString;
557
557
  }, z.core.$strict>>>;
558
558
  }, z.core.$strict>>;
559
+ containerInsights: z.ZodOptional<z.ZodLiteral<true>>;
559
560
  services: z.ZodOptional<z.ZodArray<z.ZodObject<{
560
561
  name: z.ZodString;
561
562
  docker: z.ZodOptional<z.ZodObject<{
@@ -300,6 +300,7 @@ export declare const ComputeResourcePlanSchema: z.ZodObject<{
300
300
  sourceText: z.ZodString;
301
301
  }, z.core.$strict>>>;
302
302
  }, z.core.$strict>>;
303
+ containerInsights: z.ZodOptional<z.ZodLiteral<true>>;
303
304
  services: z.ZodOptional<z.ZodArray<z.ZodObject<{
304
305
  name: z.ZodString;
305
306
  docker: z.ZodOptional<z.ZodObject<{
@@ -1 +1 @@
1
- var W=Object.defineProperty;var h=(n,t)=>W(n,"name",{value:t,configurable:!0});import{z as e}from"zod";import{VALIDATION_PATTERNS as m,VALIDATION_MESSAGES as o}from"../validation/patterns.js";import{COMPUTE_TYPES as f,ECS_CAPACITY_PROVIDERS as O,EC2_INSTANCE_TYPES as w,HTTP_METHODS as V,MIN_LAMBDA_MEMORY as K,MAX_LAMBDA_MEMORY as F,MIN_LAMBDA_TIMEOUT as S,MAX_LAMBDA_TIMEOUT as N,MIN_ECS_CAPACITY as x,MAX_ECS_CAPACITY as L,MAX_SCALING_CAPACITY as p,MAX_WARM_POOL_SIZE as Q,constIncludes as Z,COMPUTE_ARCHITECTURES as z,FUNCTION_URL_AUTH_TYPES as D,DEPLOYMENT_TYPES as $,AMI_HARDWARE_TYPES as q,LOAD_BALANCER_TYPES as J,SCALING_TYPES as ee,SCHEDULE_STACK_PLACEMENTS as oe,ECS_SERVICE_TYPES as H}from"./constants.js";import{validateArchitectureMatch as ne,getArchitectureForInstanceType as te}from"./instanceTypeArchitecture.js";import{optionalOrDisabled as ie,CAPACITY_REFINEMENT as r,memoryLimitMiBSchema as I,ResourceNameSchema as c,AppNameSchema as s,PortSchema as T,ExtraPropertySchema as E,EnvironmentRecordSchema as l,SecretsImportRecordSchema as ae}from"./baseSchemas.js";import{DockerBuildSchema as A}from"@fjall/util/manifest/schemas";import{EcsServiceAlarmConfigSchema as re,LambdaAlarmConfigSchema as ce}from"./alarmSchemas.js";function se(n){return!(n.image!==void 0&&n.docker!==void 0)}h(se,"imageDockerMutexCheck");const G=e.number().int(o.CAPACITY.MIN.INTEGER).min(x,o.GENERATOR_CAPACITY.MIN.MIN).max(L,o.GENERATOR_CAPACITY.MIN.MAX),U=e.number().int(o.CAPACITY.MAX.INTEGER).min(x,o.GENERATOR_CAPACITY.MAX.MIN).max(L,o.GENERATOR_CAPACITY.MAX.MAX),g=e.number().int(o.LAMBDA.MEMORY.INTEGER).min(K,o.LAMBDA.MEMORY.MIN).max(F,o.LAMBDA.MEMORY.MAX).refine(n=>n===128||n%64===0,o.LAMBDA.MEMORY.MULTIPLE),Y=e.string().regex(m.LAMBDA_RUNTIME_IDENTIFIER,o.LAMBDA.RUNTIME),d=e.number().int(o.CPU.INTEGER).min(256,o.CPU.MIN).max(4096,o.CPU.MAX),u=e.number().int(o.CAPACITY.DESIRED.INTEGER).min(0,o.CAPACITY.DESIRED.MIN).max(p,o.CAPACITY.DESIRED.MAX),C=e.object({connectToDatabase:e.array(e.string()).optional()}).strict(),me=e.object({minSize:e.number().int(o.CAPACITY.WARM_POOL.MIN_SIZE.INTEGER).min(0,o.CAPACITY.WARM_POOL.MIN_SIZE.MIN).max(Q,o.CAPACITY.WARM_POOL.MIN_SIZE.MAX).optional(),reuseOnScaleIn:e.boolean().optional()}).strict(),_=e.object({instanceType:e.string().optional(),amiHardwareType:e.enum(q).optional(),minCapacity:e.number().int(o.CAPACITY.MIN.INTEGER).min(0,o.CAPACITY.MIN.MIN_0).max(p,o.CAPACITY.MIN.MAX).optional(),maxCapacity:e.number().int(o.CAPACITY.MAX.INTEGER).min(1,o.CAPACITY.MAX.MIN_1).max(p,o.CAPACITY.MAX.MAX).optional(),memoryLimitMiB:I(128).optional(),warmPool:me.optional(),extraProperties:e.array(E).optional()}).strict().superRefine((n,t)=>{if(!n.instanceType||!n.amiHardwareType)return;const i=ne(n.instanceType,n.amiHardwareType);i.valid||t.addIssue({code:"custom",message:i.message??o.ARCHITECTURE_MISMATCH,path:["instanceType"]})}).superRefine((n,t)=>{n.minCapacity===0&&!n.warmPool&&t.addIssue({code:"custom",message:o.CAPACITY.WARM_POOL_REQUIRED,path:["minCapacity"]}),n.warmPool?.minSize!==void 0&&n.maxCapacity!==void 0&&n.warmPool.minSize>n.maxCapacity&&t.addIssue({code:"custom",message:o.CAPACITY.WARM_POOL.MIN_SIZE_EXCEEDS_MAX_CAPACITY,path:["warmPool","minSize"]})}),pe=e.enum(f).describe(`Compute type must be one of: ${f.join(", ")}`),y=e.enum(O).describe(`ECS capacity provider must be one of: ${O.join(", ")}`),P=e.string().refine(n=>Z(w,n),{message:o.INSTANCE_TYPE}),v=e.object({sourceType:e.enum(["sqs","dynamodb","eventbridge"]),sourceRef:e.string().describe("Name of the source resource"),batchSize:e.number().int(o.BATCH_SIZE.INTEGER).min(1,o.BATCH_SIZE.MIN).max(1e4,o.BATCH_SIZE.MAX).optional(),startingPosition:e.enum(["TRIM_HORIZON","LATEST"]).optional(),maxBatchingWindow:e.number().int(o.BATCHING_WINDOW.INTEGER).min(0,o.BATCHING_WINDOW.MIN).max(300,o.BATCHING_WINDOW.MAX).optional(),reportBatchItemFailures:e.boolean().optional()}).strict(),Ee=e.object({name:e.string().min(1,o.REQUIRED.CONTAINER_NAME).optional(),image:e.string().optional(),port:T.optional(),environment:l.optional(),secretsImport:ae.optional(),command:e.array(e.string()).optional(),entryPoint:e.array(e.string()).optional(),essential:e.boolean().optional(),healthCheck:e.object({command:e.array(e.string()),interval:e.number().int(o.HEALTH_CHECK.INTERVAL.INTEGER).min(5,o.HEALTH_CHECK.INTERVAL.MIN).max(300,o.HEALTH_CHECK.INTERVAL.MAX).optional(),timeout:e.number().int(o.HEALTH_CHECK.TIMEOUT.INTEGER).min(2,o.HEALTH_CHECK.TIMEOUT.MIN).max(60,o.HEALTH_CHECK.TIMEOUT.MAX).optional(),retries:e.number().int(o.HEALTH_CHECK.RETRIES.INTEGER).min(1,o.HEALTH_CHECK.RETRIES.MIN).max(10,o.HEALTH_CHECK.RETRIES.MAX).optional(),startPeriod:e.number().int(o.HEALTH_CHECK.START_PERIOD.INTEGER).min(0,o.HEALTH_CHECK.START_PERIOD.MIN).max(300,o.HEALTH_CHECK.START_PERIOD.MAX).optional()}).strict().optional(),ssmSecrets:e.array(e.string().regex(m.SECRET_NAME,o.SECRET_NAME)).optional(),extraProperties:e.array(E).optional()}).strict(),B=e.string().min(1,o.REQUIRED.SERVICE_NAME).max(255,o.MAX_LENGTH.SERVICE_NAME).regex(m.ECS_SERVICE_NAME,o.ECS_SERVICE_NAME),X=e.object({domain:e.string().optional(),loadBalancer:e.union([e.literal(!1),e.enum(J)]).optional(),directAccess:e.boolean().optional(),extraProperties:e.array(E).optional()}).strict().refine(n=>!(n.directAccess&&n.domain),{message:o.DIRECT_ACCESS.NO_DOMAIN,path:["directAccess"]}).refine(n=>!(n.directAccess&&typeof n.loadBalancer=="string"),{message:o.DIRECT_ACCESS.NO_LOAD_BALANCER}).describe("Cluster-level configuration"),M=e.object({path:e.string().optional(),host:e.string().optional(),priority:e.number().int(o.PRIORITY.INTEGER).min(1,o.PRIORITY.MIN).max(5e4,o.PRIORITY.MAX).optional(),healthCheckPath:e.string().optional()}).strict().describe("Path/host-based routing configuration"),le=e.object({desiredCount:u.optional(),minCapacity:e.number().int(o.CAPACITY.MIN.INTEGER).min(0,o.CAPACITY.MIN.MIN_0).max(p,o.CAPACITY.MIN.MAX).optional(),maxCapacity:e.number().int(o.CAPACITY.MAX.INTEGER).min(1,o.CAPACITY.MAX.MIN_1).max(p,o.CAPACITY.MAX.MAX).optional(),scalingType:e.enum(ee).optional()}).strict().refine(r.check,r.params).describe("ECS service scaling configuration"),k=e.object({name:B,docker:A.optional(),needsDatabaseConnection:e.boolean().optional(),needsStorageConnection:e.boolean().optional(),needsMessagingConnection:e.boolean().optional(),image:e.string().optional(),containers:e.array(Ee).optional(),routing:e.union([M,e.array(M).min(1)]).optional(),serviceType:e.enum(H).optional(),cpu:d.optional(),memoryLimitMiB:I(512).optional(),desiredCount:u.optional(),scaling:ie(le).optional(),capacityProvider:y,ec2Config:_.optional(),ssmSecretsPath:e.string().regex(m.SSM_PATH,o.SSM_PATH).optional(),extraProperties:e.array(E).optional(),alarms:re.optional()}).strict().superRefine((n,t)=>{se(n)||t.addIssue({code:"custom",path:["docker"],message:o.IMAGE_DOCKER_MUTEX})}).describe("Configuration for a service in an ECS cluster"),_e=e.object({name:c,type:pe,needsConnection:e.boolean(),connectedDatabase:e.array(e.string().min(1,o.REQUIRED.CONNECTED_RESOURCE_NAME)).optional(),connectedStorage:e.array(e.string().min(1,o.REQUIRED.CONNECTED_RESOURCE_NAME)).optional(),connectedMessaging:e.array(e.string().min(1,o.REQUIRED.CONNECTED_RESOURCE_NAME)).optional(),cluster:X.optional(),services:e.array(k).optional(),docker:A.partial().optional(),deployment:e.enum($).optional(),codePath:e.string().optional(),timeout:e.number().int(o.LAMBDA.TIMEOUT.INTEGER).min(S,o.LAMBDA.TIMEOUT.MIN).max(N,o.LAMBDA.TIMEOUT.MAX).optional(),memory:g.optional(),handler:e.string().optional(),runtime:Y.optional(),environment:l.optional(),secrets:l.optional(),eventSources:e.array(v).optional(),functionUrl:e.object({authType:e.enum(D)}).strict().optional(),description:e.string().optional(),scheduleExpression:e.string().optional(),scheduleStackPlacement:e.enum(oe).optional(),architecture:e.enum(z).optional(),ephemeralStorageSize:e.number().int(o.EPHEMERAL_STORAGE.INTEGER).min(512,o.EPHEMERAL_STORAGE.MIN).max(10240,o.EPHEMERAL_STORAGE.MAX).optional(),functionName:e.string().optional(),ssmSecrets:e.array(e.string()).optional(),ssmSecretsPath:e.string().optional(),alarms:ce.optional(),instanceType:P.optional(),enableSSH:e.boolean().optional(),keyName:e.string().optional(),userData:e.string().optional(),securityGroups:e.array(e.string()).optional(),variableName:e.string().optional(),extraProperties:e.array(E).optional()}).strict().superRefine((n,t)=>{if(n.type==="ecs"&&n.services)for(let i=0;i<n.services.length;i++){const a=n.services[i];a?.ec2Config?.instanceType&&!a.ec2Config.amiHardwareType&&te(a.ec2Config.instanceType)!=="ARM"&&t.addIssue({code:"custom",message:`Service '${a.name??i}' uses instance type '${a.ec2Config.instanceType}' (x86), which requires Docker images built for linux/amd64. The default build targets linux/arm64 (Graviton). Use a Graviton instance type (t4g, c6g, r6g, m6g, etc.) or set amiHardwareType: "STANDARD" to acknowledge x86.`,path:["services",i,"ec2Config","instanceType"]})}n.type==="lambda"&&n.deployment==="container"&&n.architecture==="X86_64"&&t.addIssue({code:"custom",message:"Lambda architecture 'X86_64' requires Docker images built for linux/amd64, but the default build targets linux/arm64. Use 'ARM_64' for Graviton Lambdas (recommended) or ensure your build pipeline targets linux/amd64.",path:["architecture"]})}),ye=e.object({appName:s,clusterName:c,containerPort:T,nameProvidedByFlag:e.boolean().optional(),ecrRepository:e.string().optional(),capacityProvider:y.optional(),useAppEcr:e.boolean().optional(),desiredCount:u.optional(),cpu:d.optional(),memoryLimitMiB:I(512).optional(),minCapacity:G.optional(),maxCapacity:U.optional(),ec2Config:_.optional(),connectionConfig:C.optional()}).strict().refine(r.check,r.params),Pe=e.object({appName:s,functionName:c,nameProvidedByFlag:e.boolean().optional(),lambdaType:e.enum(["basic","web","custom"]).optional(),ecrRepository:e.string().optional(),timeout:e.number().int(o.LAMBDA.TIMEOUT.INTEGER).min(S,o.LAMBDA.TIMEOUT.MIN).max(N,o.LAMBDA.TIMEOUT.MAX).optional(),memory:g.optional(),enableFunctionUrl:e.boolean().optional(),description:e.string().optional(),enableCors:e.boolean().optional(),corsOrigins:e.string().optional(),corsHeaders:e.string().optional(),corsMethods:e.array(e.enum(V)).optional(),corsCredentials:e.boolean().optional(),connectionConfig:C.optional()}).strict(),be=e.object({appName:s,instanceName:c,nameProvidedByFlag:e.boolean().optional(),instanceType:P.optional(),enableSSH:e.boolean().optional(),minCapacity:G.optional(),maxCapacity:U.optional(),connectionConfig:C.optional()}).strict().refine(r.check,r.params),he=e.object({appName:s,clusterName:c,serviceName:B,capacityProvider:y,containerPort:T.optional(),cpu:d.optional(),memoryLimitMiB:I(512).optional(),desiredCount:u.optional(),ec2Config:_.optional(),routing:e.union([M,e.array(M).min(1)]).optional(),docker:A.partial().optional(),nameProvidedByFlag:e.boolean().optional(),connectionConfig:C.optional()}).strict(),b=e.object({appName:s,computeName:c,nameProvidedByFlag:e.boolean().optional(),connectionConfig:C.optional()}).strict(),Ae=b.extend({type:e.literal("ecs"),cluster:X.optional(),services:e.array(k).min(1,o.SERVICE.MIN_REQUIRED),docker:A.partial().optional()}).strict().refine(n=>{const t=n.services.filter(i=>i.containers?.some(a=>a.port));return t.length>1?t.every(i=>(Array.isArray(i.routing)?i.routing:i.routing?[i.routing]:[]).some(R=>R.path||R.host)):!0},{message:o.SERVICE.ROUTING_REQUIRED}).refine(n=>{const t=n.services.map(i=>i.name);return new Set(t).size===t.length},{message:o.SERVICE.UNIQUE_WITHIN_CLUSTER}),Ce=b.extend({type:e.literal("lambda"),timeout:e.number().int(o.LAMBDA.TIMEOUT.INTEGER).min(S,o.LAMBDA.TIMEOUT.MIN).max(N,o.LAMBDA.TIMEOUT.MAX).optional(),memory:g.optional(),handler:e.string().optional(),runtime:Y.optional(),environment:l.optional(),secrets:l.optional(),description:e.string().optional(),functionUrl:e.union([e.object({authType:e.enum(D).optional()}).strict(),e.literal(!1)]).optional(),eventSources:e.array(v).optional()}).strict(),Ie=b.extend({type:e.literal("ec2"),instanceType:P.optional(),enableSSH:e.boolean().optional(),keyName:e.string().optional(),userData:e.string().optional(),securityGroups:e.array(e.string()).optional()}).strict(),fe=e.discriminatedUnion("type",[Ae,Ce,Ie]),j=e.object({path:e.string().min(1,o.REQUIRED.ROUTING_PATH),priority:e.number().int(o.PRIORITY.INTEGER).min(1,o.PRIORITY.MIN).max(5e4,o.PRIORITY.MAX).optional()}).strict(),Oe=e.object({name:e.string().min(1,o.REQUIRED.SERVICE_NAME).max(255,o.MAX_LENGTH.SERVICE_NAME).regex(m.RESOURCE_NAME,o.RESOURCE_NAME),serviceType:e.enum(H).optional(),docker:A.partial().optional(),containerPort:T.optional(),needsDatabaseConnection:e.boolean().optional(),routing:e.union([j,e.array(j).min(1)]).optional()}).strict().superRefine((n,t)=>{n.serviceType==="worker"&&(n.containerPort!==void 0&&t.addIssue({code:"custom",path:["containerPort"],message:"Worker services are not reachable inbound; remove containerPort."}),n.routing!==void 0&&t.addIssue({code:"custom",path:["routing"],message:"Worker services have no ALB route; remove routing."}))}),xe=e.object({appName:s,instanceType:e.string().optional()}).strict();export{he as AddServiceGeneratorSchema,Oe as ApplicationServiceConfigSchema,j as ApplicationServiceRoutingSchema,fe as ComputeGeneratorSchema,_e as ComputeResourcePlanSchema,pe as ComputeTypeSchema,Ee as ContainerConfigSchema,be as EC2GeneratorSchema,ye as ECSGeneratorSchema,_ as Ec2ConfigSchema,y as EcsCapacityProviderSchema,X as EcsClusterConfigSchema,M as EcsRoutingConfigSchema,le as EcsScalingConfigSchema,k as EcsServiceConfigSchema,B as EcsServiceNameSchema,P as InstanceTypeSchema,v as LambdaEventSourceSchema,Pe as LambdaGeneratorSchema,g as LambdaMemorySchema,Y as LambdaRuntimeSchema,xe as TunnelGeneratorSchema,me as WarmPoolSchema};
1
+ var W=Object.defineProperty;var h=(n,t)=>W(n,"name",{value:t,configurable:!0});import{z as e}from"zod";import{VALIDATION_PATTERNS as m,VALIDATION_MESSAGES as o}from"../validation/patterns.js";import{COMPUTE_TYPES as f,ECS_CAPACITY_PROVIDERS as O,EC2_INSTANCE_TYPES as w,HTTP_METHODS as V,MIN_LAMBDA_MEMORY as K,MAX_LAMBDA_MEMORY as F,MIN_LAMBDA_TIMEOUT as S,MAX_LAMBDA_TIMEOUT as N,MIN_ECS_CAPACITY as x,MAX_ECS_CAPACITY as L,MAX_SCALING_CAPACITY as p,MAX_WARM_POOL_SIZE as Q,constIncludes as Z,COMPUTE_ARCHITECTURES as z,FUNCTION_URL_AUTH_TYPES as D,DEPLOYMENT_TYPES as $,AMI_HARDWARE_TYPES as q,LOAD_BALANCER_TYPES as J,SCALING_TYPES as ee,SCHEDULE_STACK_PLACEMENTS as oe,ECS_SERVICE_TYPES as H}from"./constants.js";import{validateArchitectureMatch as ne,getArchitectureForInstanceType as te}from"./instanceTypeArchitecture.js";import{optionalOrDisabled as ie,CAPACITY_REFINEMENT as r,memoryLimitMiBSchema as I,ResourceNameSchema as c,AppNameSchema as s,PortSchema as T,ExtraPropertySchema as E,EnvironmentRecordSchema as l,SecretsImportRecordSchema as ae}from"./baseSchemas.js";import{DockerBuildSchema as A}from"@fjall/util/manifest/schemas";import{EcsServiceAlarmConfigSchema as re,LambdaAlarmConfigSchema as ce}from"./alarmSchemas.js";function se(n){return!(n.image!==void 0&&n.docker!==void 0)}h(se,"imageDockerMutexCheck");const G=e.number().int(o.CAPACITY.MIN.INTEGER).min(x,o.GENERATOR_CAPACITY.MIN.MIN).max(L,o.GENERATOR_CAPACITY.MIN.MAX),U=e.number().int(o.CAPACITY.MAX.INTEGER).min(x,o.GENERATOR_CAPACITY.MAX.MIN).max(L,o.GENERATOR_CAPACITY.MAX.MAX),g=e.number().int(o.LAMBDA.MEMORY.INTEGER).min(K,o.LAMBDA.MEMORY.MIN).max(F,o.LAMBDA.MEMORY.MAX).refine(n=>n===128||n%64===0,o.LAMBDA.MEMORY.MULTIPLE),Y=e.string().regex(m.LAMBDA_RUNTIME_IDENTIFIER,o.LAMBDA.RUNTIME),d=e.number().int(o.CPU.INTEGER).min(256,o.CPU.MIN).max(4096,o.CPU.MAX),u=e.number().int(o.CAPACITY.DESIRED.INTEGER).min(0,o.CAPACITY.DESIRED.MIN).max(p,o.CAPACITY.DESIRED.MAX),C=e.object({connectToDatabase:e.array(e.string()).optional()}).strict(),me=e.object({minSize:e.number().int(o.CAPACITY.WARM_POOL.MIN_SIZE.INTEGER).min(0,o.CAPACITY.WARM_POOL.MIN_SIZE.MIN).max(Q,o.CAPACITY.WARM_POOL.MIN_SIZE.MAX).optional(),reuseOnScaleIn:e.boolean().optional()}).strict(),_=e.object({instanceType:e.string().optional(),amiHardwareType:e.enum(q).optional(),minCapacity:e.number().int(o.CAPACITY.MIN.INTEGER).min(0,o.CAPACITY.MIN.MIN_0).max(p,o.CAPACITY.MIN.MAX).optional(),maxCapacity:e.number().int(o.CAPACITY.MAX.INTEGER).min(1,o.CAPACITY.MAX.MIN_1).max(p,o.CAPACITY.MAX.MAX).optional(),memoryLimitMiB:I(128).optional(),warmPool:me.optional(),extraProperties:e.array(E).optional()}).strict().superRefine((n,t)=>{if(!n.instanceType||!n.amiHardwareType)return;const i=ne(n.instanceType,n.amiHardwareType);i.valid||t.addIssue({code:"custom",message:i.message??o.ARCHITECTURE_MISMATCH,path:["instanceType"]})}).superRefine((n,t)=>{n.minCapacity===0&&!n.warmPool&&t.addIssue({code:"custom",message:o.CAPACITY.WARM_POOL_REQUIRED,path:["minCapacity"]}),n.warmPool?.minSize!==void 0&&n.maxCapacity!==void 0&&n.warmPool.minSize>n.maxCapacity&&t.addIssue({code:"custom",message:o.CAPACITY.WARM_POOL.MIN_SIZE_EXCEEDS_MAX_CAPACITY,path:["warmPool","minSize"]})}),pe=e.enum(f).describe(`Compute type must be one of: ${f.join(", ")}`),y=e.enum(O).describe(`ECS capacity provider must be one of: ${O.join(", ")}`),P=e.string().refine(n=>Z(w,n),{message:o.INSTANCE_TYPE}),v=e.object({sourceType:e.enum(["sqs","dynamodb","eventbridge"]),sourceRef:e.string().describe("Name of the source resource"),batchSize:e.number().int(o.BATCH_SIZE.INTEGER).min(1,o.BATCH_SIZE.MIN).max(1e4,o.BATCH_SIZE.MAX).optional(),startingPosition:e.enum(["TRIM_HORIZON","LATEST"]).optional(),maxBatchingWindow:e.number().int(o.BATCHING_WINDOW.INTEGER).min(0,o.BATCHING_WINDOW.MIN).max(300,o.BATCHING_WINDOW.MAX).optional(),reportBatchItemFailures:e.boolean().optional()}).strict(),Ee=e.object({name:e.string().min(1,o.REQUIRED.CONTAINER_NAME).optional(),image:e.string().optional(),port:T.optional(),environment:l.optional(),secretsImport:ae.optional(),command:e.array(e.string()).optional(),entryPoint:e.array(e.string()).optional(),essential:e.boolean().optional(),healthCheck:e.object({command:e.array(e.string()),interval:e.number().int(o.HEALTH_CHECK.INTERVAL.INTEGER).min(5,o.HEALTH_CHECK.INTERVAL.MIN).max(300,o.HEALTH_CHECK.INTERVAL.MAX).optional(),timeout:e.number().int(o.HEALTH_CHECK.TIMEOUT.INTEGER).min(2,o.HEALTH_CHECK.TIMEOUT.MIN).max(60,o.HEALTH_CHECK.TIMEOUT.MAX).optional(),retries:e.number().int(o.HEALTH_CHECK.RETRIES.INTEGER).min(1,o.HEALTH_CHECK.RETRIES.MIN).max(10,o.HEALTH_CHECK.RETRIES.MAX).optional(),startPeriod:e.number().int(o.HEALTH_CHECK.START_PERIOD.INTEGER).min(0,o.HEALTH_CHECK.START_PERIOD.MIN).max(300,o.HEALTH_CHECK.START_PERIOD.MAX).optional()}).strict().optional(),ssmSecrets:e.array(e.string().regex(m.SECRET_NAME,o.SECRET_NAME)).optional(),extraProperties:e.array(E).optional()}).strict(),B=e.string().min(1,o.REQUIRED.SERVICE_NAME).max(255,o.MAX_LENGTH.SERVICE_NAME).regex(m.ECS_SERVICE_NAME,o.ECS_SERVICE_NAME),X=e.object({domain:e.string().optional(),loadBalancer:e.union([e.literal(!1),e.enum(J)]).optional(),directAccess:e.boolean().optional(),extraProperties:e.array(E).optional()}).strict().refine(n=>!(n.directAccess&&n.domain),{message:o.DIRECT_ACCESS.NO_DOMAIN,path:["directAccess"]}).refine(n=>!(n.directAccess&&typeof n.loadBalancer=="string"),{message:o.DIRECT_ACCESS.NO_LOAD_BALANCER}).describe("Cluster-level configuration"),M=e.object({path:e.string().optional(),host:e.string().optional(),priority:e.number().int(o.PRIORITY.INTEGER).min(1,o.PRIORITY.MIN).max(5e4,o.PRIORITY.MAX).optional(),healthCheckPath:e.string().optional()}).strict().describe("Path/host-based routing configuration"),le=e.object({desiredCount:u.optional(),minCapacity:e.number().int(o.CAPACITY.MIN.INTEGER).min(0,o.CAPACITY.MIN.MIN_0).max(p,o.CAPACITY.MIN.MAX).optional(),maxCapacity:e.number().int(o.CAPACITY.MAX.INTEGER).min(1,o.CAPACITY.MAX.MIN_1).max(p,o.CAPACITY.MAX.MAX).optional(),scalingType:e.enum(ee).optional()}).strict().refine(r.check,r.params).describe("ECS service scaling configuration"),k=e.object({name:B,docker:A.optional(),needsDatabaseConnection:e.boolean().optional(),needsStorageConnection:e.boolean().optional(),needsMessagingConnection:e.boolean().optional(),image:e.string().optional(),containers:e.array(Ee).optional(),routing:e.union([M,e.array(M).min(1)]).optional(),serviceType:e.enum(H).optional(),cpu:d.optional(),memoryLimitMiB:I(512).optional(),desiredCount:u.optional(),scaling:ie(le).optional(),capacityProvider:y,ec2Config:_.optional(),ssmSecretsPath:e.string().regex(m.SSM_PATH,o.SSM_PATH).optional(),extraProperties:e.array(E).optional(),alarms:re.optional()}).strict().superRefine((n,t)=>{se(n)||t.addIssue({code:"custom",path:["docker"],message:o.IMAGE_DOCKER_MUTEX})}).describe("Configuration for a service in an ECS cluster"),_e=e.object({name:c,type:pe,needsConnection:e.boolean(),connectedDatabase:e.array(e.string().min(1,o.REQUIRED.CONNECTED_RESOURCE_NAME)).optional(),connectedStorage:e.array(e.string().min(1,o.REQUIRED.CONNECTED_RESOURCE_NAME)).optional(),connectedMessaging:e.array(e.string().min(1,o.REQUIRED.CONNECTED_RESOURCE_NAME)).optional(),cluster:X.optional(),containerInsights:e.literal(!0).optional(),services:e.array(k).optional(),docker:A.partial().optional(),deployment:e.enum($).optional(),codePath:e.string().optional(),timeout:e.number().int(o.LAMBDA.TIMEOUT.INTEGER).min(S,o.LAMBDA.TIMEOUT.MIN).max(N,o.LAMBDA.TIMEOUT.MAX).optional(),memory:g.optional(),handler:e.string().optional(),runtime:Y.optional(),environment:l.optional(),secrets:l.optional(),eventSources:e.array(v).optional(),functionUrl:e.object({authType:e.enum(D)}).strict().optional(),description:e.string().optional(),scheduleExpression:e.string().optional(),scheduleStackPlacement:e.enum(oe).optional(),architecture:e.enum(z).optional(),ephemeralStorageSize:e.number().int(o.EPHEMERAL_STORAGE.INTEGER).min(512,o.EPHEMERAL_STORAGE.MIN).max(10240,o.EPHEMERAL_STORAGE.MAX).optional(),functionName:e.string().optional(),ssmSecrets:e.array(e.string()).optional(),ssmSecretsPath:e.string().optional(),alarms:ce.optional(),instanceType:P.optional(),enableSSH:e.boolean().optional(),keyName:e.string().optional(),userData:e.string().optional(),securityGroups:e.array(e.string()).optional(),variableName:e.string().optional(),extraProperties:e.array(E).optional()}).strict().superRefine((n,t)=>{if(n.type==="ecs"&&n.services)for(let i=0;i<n.services.length;i++){const a=n.services[i];a?.ec2Config?.instanceType&&!a.ec2Config.amiHardwareType&&te(a.ec2Config.instanceType)!=="ARM"&&t.addIssue({code:"custom",message:`Service '${a.name??i}' uses instance type '${a.ec2Config.instanceType}' (x86), which requires Docker images built for linux/amd64. The default build targets linux/arm64 (Graviton). Use a Graviton instance type (t4g, c6g, r6g, m6g, etc.) or set amiHardwareType: "STANDARD" to acknowledge x86.`,path:["services",i,"ec2Config","instanceType"]})}n.type==="lambda"&&n.deployment==="container"&&n.architecture==="X86_64"&&t.addIssue({code:"custom",message:"Lambda architecture 'X86_64' requires Docker images built for linux/amd64, but the default build targets linux/arm64. Use 'ARM_64' for Graviton Lambdas (recommended) or ensure your build pipeline targets linux/amd64.",path:["architecture"]})}),ye=e.object({appName:s,clusterName:c,containerPort:T,nameProvidedByFlag:e.boolean().optional(),ecrRepository:e.string().optional(),capacityProvider:y.optional(),useAppEcr:e.boolean().optional(),desiredCount:u.optional(),cpu:d.optional(),memoryLimitMiB:I(512).optional(),minCapacity:G.optional(),maxCapacity:U.optional(),ec2Config:_.optional(),connectionConfig:C.optional()}).strict().refine(r.check,r.params),Pe=e.object({appName:s,functionName:c,nameProvidedByFlag:e.boolean().optional(),lambdaType:e.enum(["basic","web","custom"]).optional(),ecrRepository:e.string().optional(),timeout:e.number().int(o.LAMBDA.TIMEOUT.INTEGER).min(S,o.LAMBDA.TIMEOUT.MIN).max(N,o.LAMBDA.TIMEOUT.MAX).optional(),memory:g.optional(),enableFunctionUrl:e.boolean().optional(),description:e.string().optional(),enableCors:e.boolean().optional(),corsOrigins:e.string().optional(),corsHeaders:e.string().optional(),corsMethods:e.array(e.enum(V)).optional(),corsCredentials:e.boolean().optional(),connectionConfig:C.optional()}).strict(),be=e.object({appName:s,instanceName:c,nameProvidedByFlag:e.boolean().optional(),instanceType:P.optional(),enableSSH:e.boolean().optional(),minCapacity:G.optional(),maxCapacity:U.optional(),connectionConfig:C.optional()}).strict().refine(r.check,r.params),he=e.object({appName:s,clusterName:c,serviceName:B,capacityProvider:y,containerPort:T.optional(),cpu:d.optional(),memoryLimitMiB:I(512).optional(),desiredCount:u.optional(),ec2Config:_.optional(),routing:e.union([M,e.array(M).min(1)]).optional(),docker:A.partial().optional(),nameProvidedByFlag:e.boolean().optional(),connectionConfig:C.optional()}).strict(),b=e.object({appName:s,computeName:c,nameProvidedByFlag:e.boolean().optional(),connectionConfig:C.optional()}).strict(),Ae=b.extend({type:e.literal("ecs"),cluster:X.optional(),services:e.array(k).min(1,o.SERVICE.MIN_REQUIRED),docker:A.partial().optional()}).strict().refine(n=>{const t=n.services.filter(i=>i.containers?.some(a=>a.port));return t.length>1?t.every(i=>(Array.isArray(i.routing)?i.routing:i.routing?[i.routing]:[]).some(R=>R.path||R.host)):!0},{message:o.SERVICE.ROUTING_REQUIRED}).refine(n=>{const t=n.services.map(i=>i.name);return new Set(t).size===t.length},{message:o.SERVICE.UNIQUE_WITHIN_CLUSTER}),Ce=b.extend({type:e.literal("lambda"),timeout:e.number().int(o.LAMBDA.TIMEOUT.INTEGER).min(S,o.LAMBDA.TIMEOUT.MIN).max(N,o.LAMBDA.TIMEOUT.MAX).optional(),memory:g.optional(),handler:e.string().optional(),runtime:Y.optional(),environment:l.optional(),secrets:l.optional(),description:e.string().optional(),functionUrl:e.union([e.object({authType:e.enum(D).optional()}).strict(),e.literal(!1)]).optional(),eventSources:e.array(v).optional()}).strict(),Ie=b.extend({type:e.literal("ec2"),instanceType:P.optional(),enableSSH:e.boolean().optional(),keyName:e.string().optional(),userData:e.string().optional(),securityGroups:e.array(e.string()).optional()}).strict(),fe=e.discriminatedUnion("type",[Ae,Ce,Ie]),j=e.object({path:e.string().min(1,o.REQUIRED.ROUTING_PATH),priority:e.number().int(o.PRIORITY.INTEGER).min(1,o.PRIORITY.MIN).max(5e4,o.PRIORITY.MAX).optional()}).strict(),Oe=e.object({name:e.string().min(1,o.REQUIRED.SERVICE_NAME).max(255,o.MAX_LENGTH.SERVICE_NAME).regex(m.RESOURCE_NAME,o.RESOURCE_NAME),serviceType:e.enum(H).optional(),docker:A.partial().optional(),containerPort:T.optional(),needsDatabaseConnection:e.boolean().optional(),routing:e.union([j,e.array(j).min(1)]).optional()}).strict().superRefine((n,t)=>{n.serviceType==="worker"&&(n.containerPort!==void 0&&t.addIssue({code:"custom",path:["containerPort"],message:"Worker services are not reachable inbound; remove containerPort."}),n.routing!==void 0&&t.addIssue({code:"custom",path:["routing"],message:"Worker services have no ALB route; remove routing."}))}),xe=e.object({appName:s,instanceType:e.string().optional()}).strict();export{he as AddServiceGeneratorSchema,Oe as ApplicationServiceConfigSchema,j as ApplicationServiceRoutingSchema,fe as ComputeGeneratorSchema,_e as ComputeResourcePlanSchema,pe as ComputeTypeSchema,Ee as ContainerConfigSchema,be as EC2GeneratorSchema,ye as ECSGeneratorSchema,_ as Ec2ConfigSchema,y as EcsCapacityProviderSchema,X as EcsClusterConfigSchema,M as EcsRoutingConfigSchema,le as EcsScalingConfigSchema,k as EcsServiceConfigSchema,B as EcsServiceNameSchema,P as InstanceTypeSchema,v as LambdaEventSourceSchema,Pe as LambdaGeneratorSchema,g as LambdaMemorySchema,Y as LambdaRuntimeSchema,xe as TunnelGeneratorSchema,me as WarmPoolSchema};
@@ -1 +1 @@
1
- export declare const GENERATOR_VERSION = "31.0.0";
1
+ export declare const GENERATOR_VERSION = "32.0.0";
@@ -1 +1 @@
1
- const E="31.0.0";export{E as GENERATOR_VERSION};
1
+ const E="32.0.0";export{E as GENERATOR_VERSION};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/generator",
3
- "version": "31.0.0",
3
+ "version": "32.0.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/fjall-tech/fjall.git",
@@ -58,7 +58,7 @@
58
58
  "license": "SEE LICENSE IN LICENSE",
59
59
  "dependencies": {
60
60
  "@babel/parser": "^7.29.8",
61
- "@fjall/util": "^31.0.0",
61
+ "@fjall/util": "^32.0.0",
62
62
  "ast-types": "^0.16.1",
63
63
  "recast": "^0.23.12",
64
64
  "ts-morph": "^28.0.0",