@fjall/generator 14.2.0 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-source-hash +36 -34
- package/dist/.minified +1 -1
- package/dist/src/ast/astTestHelpers.d.ts +2 -1
- package/dist/src/ast/domain/astDomainParser.d.ts +12 -0
- package/dist/src/ast/domain/astDomainParser.js +1 -1
- package/dist/src/ast/parsers/orchestrator/astPlanConverter.js +1 -1
- package/dist/src/ast/parsers/resources/astComputeParserHelpers.js +1 -1
- package/dist/src/ast/parsers/resources/astScheduleParser.d.ts +3 -0
- package/dist/src/ast/parsers/resources/astScheduleParser.js +1 -1
- package/dist/src/codemod/drift/index.d.ts +1 -1
- package/dist/src/codemod/drift/index.js +1 -1
- package/dist/src/codemod/drift/snapshot.d.ts +33 -1
- package/dist/src/codemod/drift/snapshot.js +1 -1
- package/dist/src/codemod/drift/types.d.ts +18 -3
- package/dist/src/codemod/drift/types.js +1 -1
- package/dist/src/codemod/edits/addResource/propertyBuilder.d.ts +7 -0
- package/dist/src/codemod/edits/addResource/propertyBuilder.js +1 -1
- package/dist/src/codemod/fileRewriter/builders.d.ts +7 -0
- package/dist/src/codemod/fileRewriter/builders.js +1 -1
- package/dist/src/codemod/index.d.ts +2 -2
- package/dist/src/codemod/index.js +1 -1
- package/dist/src/codemod/llmFallback/index.d.ts +1 -1
- package/dist/src/codemod/llmFallback/index.js +1 -1
- package/dist/src/codemod/llmFallback/shouldTryFallback.d.ts +9 -0
- package/dist/src/codemod/llmFallback/shouldTryFallback.js +1 -1
- package/dist/src/codemod/types.d.ts +6 -6
- package/dist/src/dns/domainFileGenerator.js +8 -3
- package/dist/src/dns/domainRecords.d.ts +30 -0
- package/dist/src/dns/domainRecords.js +1 -1
- package/dist/src/dns/tsEmitter.js +9 -9
- package/dist/src/generation/common.d.ts +0 -7
- package/dist/src/generation/common.js +7 -8
- package/dist/src/generation/compute/ec2.d.ts +7 -0
- package/dist/src/generation/compute/ec2.js +2 -4
- package/dist/src/generation/compute/ecs.js +33 -33
- package/dist/src/generation/compute/lambda.d.ts +27 -0
- package/dist/src/generation/compute/lambda.js +9 -22
- package/dist/src/generation/compute.d.ts +18 -0
- package/dist/src/generation/compute.js +6 -6
- package/dist/src/generation/database.d.ts +2 -1
- package/dist/src/generation/database.js +20 -20
- package/dist/src/generation/generatePatternCode.js +9 -9
- package/dist/src/generation/index.d.ts +3 -2
- package/dist/src/generation/index.js +1 -1
- package/dist/src/generation/infrastructure.js +34 -34
- package/dist/src/generation/statementInvocation.d.ts +30 -0
- package/dist/src/generation/statementInvocation.js +1 -0
- package/dist/src/generation/storage.js +19 -19
- package/dist/src/generation/structuredSource.d.ts +61 -0
- package/dist/src/generation/structuredSource.js +9 -0
- package/dist/src/planning/resourcePlanning.d.ts +20 -0
- package/dist/src/planning/resourcePlanning.js +1 -1
- package/dist/src/projection/compute.d.ts +11 -1
- package/dist/src/projection/compute.js +1 -1
- package/dist/src/schemas/applicationSchemas.d.ts +5 -1
- package/dist/src/schemas/baseSchemas.d.ts +2 -2
- package/dist/src/schemas/computeSchemas.d.ts +4 -0
- package/dist/src/schemas/computeSchemas.js +1 -1
- package/dist/src/schemas/constants.d.ts +2 -0
- package/dist/src/schemas/constants.js +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +2 -2
|
@@ -2,4 +2,22 @@ import type { ApplicationResourcePlan } from "../schemas/resourceSchemas.js";
|
|
|
2
2
|
export { generateLambdaCode, generateLambdaConnectionsCode, } from "./compute/lambda.js";
|
|
3
3
|
export { generateEc2Code } from "./compute/ec2.js";
|
|
4
4
|
export { generateEcsCode } from "./compute/ecs.js";
|
|
5
|
+
export interface ComputeProjectionRefusal {
|
|
6
|
+
resourceName: string;
|
|
7
|
+
key: string;
|
|
8
|
+
reason: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The scaffold lane's fail-closed guard over the shared projection: an
|
|
12
|
+
* `unresolved-binding` unprojectable means a structured/live rule REFUSED the
|
|
13
|
+
* value — the emitters would otherwise drop the key silently, so a plan
|
|
14
|
+
* carrying `runtime: "python3.12"` (schema-valid, but not a `Runtime` member
|
|
15
|
+
* name) would scaffold a Lambda with no runtime at all. Runs the SAME
|
|
16
|
+
* fragment builders the emitters consume, so the guard cannot disagree with
|
|
17
|
+
* emission. Plan-only keys stay exempt — the scaffold consumes those through
|
|
18
|
+
* its own paths (`functionName`, `keyName`, …) — and ECS is skipped: its
|
|
19
|
+
* `services` binding is total and its emitter throws loudly on its own
|
|
20
|
+
* failure modes.
|
|
21
|
+
*/
|
|
22
|
+
export declare function findComputeProjectionRefusal(plan: ApplicationResourcePlan): ComputeProjectionRefusal | undefined;
|
|
5
23
|
export declare function generateComputeCode(plan: ApplicationResourcePlan, cdnReferencedResources: Set<string>): string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
`:""}${
|
|
3
|
-
|
|
4
|
-
type: ${
|
|
1
|
+
var f=Object.defineProperty;var s=(t,o)=>f(t,"name",{value:o,configurable:!0});import{projectPlanToConstructProps as i}from"../projection/index.js";import{getVariableName as g,escapeStringLiteral as d}from"./common.js";import{renderProjectedValueSource as b}from"./structuredSource.js";import{COMPUTE_INVOCATION as u}from"./statementInvocation.js";import{buildLambdaProjectionFragment as h,generateLambdaCode as C,generateLambdaConnectionsCode as $}from"./compute/lambda.js";import{buildEc2ProjectionFragment as x,generateEc2Code as y}from"./compute/ec2.js";import{generateEcsCode as k}from"./compute/ecs.js";import{generateLambdaCode as _,generateLambdaConnectionsCode as F}from"./compute/lambda.js";import{generateEc2Code as B}from"./compute/ec2.js";import{generateEcsCode as q}from"./compute/ecs.js";function M(t){for(const o of t.compute){let n;switch(o.type){case"lambda":n=h(o);break;case"ec2":n=x(o);break;case"ecs":continue;default:{const a=o.type;throw new Error(`Unhandled compute type: ${String(a)}`)}}const{unprojectable:r}=i("compute",n),e=r.find(a=>a.kind==="unresolved-binding");if(e!==void 0)return{resourceName:o.name,key:e.key,reason:e.reason}}}s(M,"findComputeProjectionRefusal");function O(t,o){if(t.compute.length===0)return"";let n="";for(let r=0;r<t.compute.length;r++){const e=t.compute[r],a=o.has(e.name)||e.scheduleExpression!==void 0,c=g(e),m=t.database.length>0||t.s3.length>0||r>0,p=a?`const ${c} = `:"";switch(n+=`${m?`
|
|
2
|
+
`:""}${p}app.${u.appMethod}(
|
|
3
|
+
${u.factory}.build(${d(e.name)}, {
|
|
4
|
+
type: ${d(e.type)},`,e.type){case"lambda":n+=C(e),n+=$(e,t);break;case"ec2":n+=y(e);break;case"ecs":n+=k(e,t);break;default:{const l=e.type;throw new Error(`Unhandled compute type: ${String(l)}`)}}n+=`
|
|
5
5
|
})
|
|
6
6
|
);
|
|
7
|
-
`,e.scheduleExpression!==void 0&&(o
|
|
8
|
-
`
|
|
7
|
+
`,e.scheduleExpression!==void 0&&(n+=E(e,c))}return n}s(O,"generateComputeCode");function E(t,o){const{siblings:n}=i("compute",{scheduleExpression:t.scheduleExpression,...t.scheduleStackPlacement!==void 0&&{scheduleStackPlacement:t.scheduleStackPlacement}},{resourceName:t.name});if(n===void 0)return"";let r="";for(const e of n){const a=e.props.map(c=>`${c.key}: ${b(c,{primaryBinding:o})}`).join(", ");r+=`app.${e.appMethod}(${d(e.constructId)}, { ${a} });
|
|
8
|
+
`}return r}s(E,"generateScheduleCode");export{M as findComputeProjectionRefusal,O as generateComputeCode,B as generateEc2Code,q as generateEcsCode,_ as generateLambdaCode,F as generateLambdaConnectionsCode};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Functions for generating database infrastructure code including
|
|
5
5
|
* RDS Instance, Aurora, and GlobalAurora configurations.
|
|
6
6
|
*/
|
|
7
|
-
import type { DatabaseResourcePlan, ApplicationResourcePlan, ComputeResourcePlan } from "../schemas/resourceSchemas.js";
|
|
7
|
+
import type { DatabaseResourcePlan, ClickHouseResourcePlan, ApplicationResourcePlan, ComputeResourcePlan } from "../schemas/resourceSchemas.js";
|
|
8
8
|
export { CREDENTIAL_KEYS, DATABASE_ACCESSORS, DATABASE_ENV_VARS, DATABASE_SSL_VALUE, } from "./connectionWiring.js";
|
|
9
9
|
export type DatabaseEnvVarEntry = {
|
|
10
10
|
key: string;
|
|
@@ -52,3 +52,4 @@ export declare function databaseNeedsVariable(database: DatabaseResourcePlan, pl
|
|
|
52
52
|
*/
|
|
53
53
|
export declare function generateDatabaseCode(plan: ApplicationResourcePlan): string;
|
|
54
54
|
export declare function generateClickHouseCode(plan: ApplicationResourcePlan): string;
|
|
55
|
+
export declare function clickhouseNeedsVariable(clickhouse: ClickHouseResourcePlan, plan: ApplicationResourcePlan): boolean;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
var
|
|
2
|
-
secondaryRegions: [${
|
|
3
|
-
`:""}${
|
|
4
|
-
|
|
1
|
+
var m=Object.defineProperty;var t=(e,n)=>m(e,"name",{value:n,configurable:!0});import{buildProperty as o,connectionEnvSuffix as b,formatValue as a,getVariableName as p,emitExtraProperties as g,escapeStringLiteral as s,formatStringArray as h,emitProductionAlertsTopicSpread as A}from"./common.js";import{DATABASE_INVOCATION as f}from"./statementInvocation.js";import{DATABASE_SSL_VALUE as y,buildConnectionWiringEntries as x,renderWiringValueSource as S}from"./connectionWiring.js";import{CREDENTIAL_KEYS as U,DATABASE_ACCESSORS as z,DATABASE_ENV_VARS as F,DATABASE_SSL_VALUE as O}from"./connectionWiring.js";function $(e,n){const i=n.connectedDatabase;return i?.length?e.database.filter(r=>i.includes(r.name)):[]}t($,"getConnectedDatabases");function k(e){const n=[];for(const[i,r]of e.entries()){const l=p(r),d=b(i);for(const c of x("database",d))n.push({key:c.key,expression:S(c.value,l),isSecret:c.target==="secretsImport"})}return n}t(k,"generateDatabaseEnvVarEntries");function P(e){return`connections: [${e.map(i=>p(i)).join(", ")}],`}t(P,"formatConnectionsCode");function E(e){return e.expression===s(y)?y:{__expression:e.expression}}t(E,"toDatabaseEnvVarValue");function W(e,n){const i={},r={};if(!n.needsConnection||!n.connectedDatabase?.length)return{env:i,secrets:r};const l=$(e,n),d=k(l);for(const c of d){const u=E(c);c.isSecret?r[c.key]={__expression:c.expression}:i[c.key]=u}return{env:i,secrets:r}}t(W,"buildDatabaseEnvVars");function D(e){let n="";return n+=o(e.port!==void 0,"port",e.port),n+=o(e.deletionProtection!==void 0,"deletionProtection",e.deletionProtection),n+=o(e.snapshotIdentifier!==void 0,"snapshotIdentifier",e.snapshotIdentifier,"string"),n+=o(e.snapshotUsername!==void 0,"snapshotUsername",e.snapshotUsername,"string"),n+=o(e.monitoringInterval!==void 0,"monitoringInterval",e.monitoringInterval),n}t(D,"generateDatabaseSharedProps");function I(e){if(e.type!=="Instance")return"";let n="";return n+=o(e.instanceType!==void 0,"instanceType",e.instanceType,"string"),n+=o(e.allocatedStorage!==void 0,"allocatedStorage",e.allocatedStorage),n+=o(e.multiAz!==void 0,"multiAz",e.multiAz),n+=o(e.publiclyAccessible!==void 0,"publiclyAccessible",e.publiclyAccessible),n+=o(e.encryption!==void 0,"encryption",e.encryption,"object"),n+=o(e.databaseInsights!==void 0,"databaseInsights",e.databaseInsights,"boolean-or-object"),n+=o(e.proxy!==void 0,"proxy",e.proxy,"boolean-or-object"),n+=o(e.readReplica!==void 0,"readReplica",e.readReplica,"boolean-or-object"),n+=o(e.credentials!==void 0,"credentials",e.credentials,"object"),n+=o(e.backupRetention!==void 0,"backupRetention",e.backupRetention),n}t(I,"generateDatabaseInstanceProps");function R(e){if(e.type!=="Aurora"&&e.type!=="GlobalAurora")return"";let n="";return n+=o(e.encryption!==void 0,"encryption",e.encryption,"object"),n+=o(e.databaseInsights!==void 0,"databaseInsights",e.databaseInsights,"boolean-or-object"),n+=o(e.proxy!==void 0,"proxy",e.proxy,"boolean-or-object"),n+=o(e.credentials!==void 0,"credentials",e.credentials,"object"),n+=o(e.writer!==void 0,"writer",e.writer,"object"),n+=o(e.readers!==void 0,"readers",e.readers,"boolean-or-object"),n+=o(e.backupRetention!==void 0,"backupRetention",e.backupRetention),n+=o(e.preferredMaintenanceWindow!==void 0,"preferredMaintenanceWindow",e.preferredMaintenanceWindow,"string"),n}t(R,"generateDatabaseAuroraProps");function C(e){if(e.type!=="GlobalAurora")return"";let n="";return n+=o(e.primaryRegion!==void 0,"primaryRegion",e.primaryRegion,"string"),e.secondaryRegions!==void 0&&e.secondaryRegions.length>0&&(n+=`
|
|
2
|
+
secondaryRegions: [${h(e.secondaryRegions)}],`),n+=o(e.globalClusterIdentifier!==void 0,"globalClusterIdentifier",e.globalClusterIdentifier,"string"),n+=o(e.enableGlobalWriteForwarding!==void 0,"enableGlobalWriteForwarding",e.enableGlobalWriteForwarding),n}t(C,"generateDatabaseGlobalAuroraProps");function V(e,n){return n.compute.some(i=>i.needsConnection&&i.connectedDatabase?.includes(e.name))}t(V,"databaseNeedsVariable");function G(e){if(e.database.length===0)return"";let n="";for(let i=0;i<e.database.length;i++){const r=e.database[i],l=p(r),d=V(r,e),c=i>0,u=d?`const ${l} = `:"";n+=`${c?`
|
|
3
|
+
`:""}${u}app.${f.appMethod}(
|
|
4
|
+
${f.factory}.build(${s(r.name)}, {
|
|
5
5
|
vpc: app.getVpc(),
|
|
6
|
-
type: ${s(
|
|
7
|
-
databaseName: ${s(
|
|
8
|
-
engine: ${
|
|
9
|
-
databaseEngine: ${s(
|
|
10
|
-
alarms: false,`:typeof
|
|
11
|
-
alarms: ${
|
|
6
|
+
type: ${s(r.type)},
|
|
7
|
+
databaseName: ${s(r.databaseName)},`,r.engineExpression?n+=`
|
|
8
|
+
engine: ${r.engineExpression},`:r.databaseEngine&&(n+=`
|
|
9
|
+
databaseEngine: ${s(r.databaseEngine)},`),n+=D(r),n+=I(r),n+=R(r),n+=C(r),n+=g(r.extraProperties),r.alarms===!1?n+=`
|
|
10
|
+
alarms: false,`:typeof r.alarms=="object"&&(n+=`
|
|
11
|
+
alarms: ${a(r.alarms," ")},`),r.type!=="GlobalAurora"&&(n+=A()),n+=`
|
|
12
12
|
})
|
|
13
13
|
);
|
|
14
|
-
`}return n}
|
|
15
|
-
`:"",d
|
|
16
|
-
|
|
14
|
+
`}return n}t(G,"generateDatabaseCode");function L(e){if(!e.clickhouse||e.clickhouse.length===0)return"";let n="";for(let i=0;i<e.clickhouse.length;i++){const r=e.clickhouse[i],l=p(r),d=T(r,e),c=i>0?`
|
|
15
|
+
`:"",u=d?`const ${l} = `:"";n+=`${c}${u}app.${f.appMethod}(
|
|
16
|
+
${f.factory}.build(${s(r.name)}, {
|
|
17
17
|
type: "ClickHouse",
|
|
18
|
-
databaseName: ${s(
|
|
19
|
-
instanceType: ${s(
|
|
20
|
-
coldTier: ${
|
|
21
|
-
optimiseSchedule: ${
|
|
22
|
-
backupSchedule: ${
|
|
23
|
-
backupRetentionDays: ${
|
|
18
|
+
databaseName: ${s(r.databaseName)},`,r.instanceType!==void 0&&(n+=`
|
|
19
|
+
instanceType: ${s(r.instanceType)},`),r.coldTier!==void 0&&(n+=`
|
|
20
|
+
coldTier: ${a(r.coldTier," ")},`),r.optimiseSchedule!==void 0&&(n+=`
|
|
21
|
+
optimiseSchedule: ${a(r.optimiseSchedule," ")},`),r.backupSchedule!==void 0&&(n+=`
|
|
22
|
+
backupSchedule: ${a(r.backupSchedule," ")},`),r.backupRetentionDays!==void 0&&(n+=`
|
|
23
|
+
backupRetentionDays: ${r.backupRetentionDays},`),n+=g(r.extraProperties),n+=`
|
|
24
24
|
})
|
|
25
25
|
);
|
|
26
|
-
`}return n}
|
|
26
|
+
`}return n}t(L,"generateClickHouseCode");function T(e,n){return n.compute.some(i=>i.connectedDatabase?.includes(e.name))}t(T,"clickhouseNeedsVariable");export{U as CREDENTIAL_KEYS,z as DATABASE_ACCESSORS,F as DATABASE_ENV_VARS,O as DATABASE_SSL_VALUE,W as buildDatabaseEnvVars,T as clickhouseNeedsVariable,V as databaseNeedsVariable,P as formatConnectionsCode,L as generateClickHouseCode,G as generateDatabaseCode,k as generateDatabaseEnvVarEntries,$ as getConnectedDatabases,E as toDatabaseEnvVarValue};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var
|
|
1
|
+
var $=Object.defineProperty;var r=(n,e)=>$(n,"name",{value:e,configurable:!0});import{formatValue as l}from"./common.js";import{PATTERN_INVOCATION as y}from"./statementInvocation.js";import{patternConstructId as b}from"@fjall/util";const m=Object.freeze({database:{type:"Instance",backupRetention:7,deletionProtection:!0},compute:{server:{memorySize:1536,timeout:30},imageOptimisation:{memorySize:1536,timeout:30},revalidation:{memorySize:768,timeout:300}}});function c(n,e,t){return e===void 0?"":`
|
|
2
2
|
${t}${n}: ${e},`}r(c,"emitScalar");function s(n,e,t){return e===void 0?"":`
|
|
3
3
|
${t}${n}: ${JSON.stringify(e)},`}r(s,"emitStringField");function d(n,e,t){return e===void 0?"":e===!1?`
|
|
4
4
|
${t}${n}: false,`:`
|
|
5
5
|
${t}${n}: ${l(e,t)},`}r(d,"emitObjectOrFalse");function a(n,e,t){return e===void 0||Object.keys(e).length===0?"":`
|
|
6
|
-
${t}${n}: ${l(e,t)},`}r(a,"emitObject");function
|
|
6
|
+
${t}${n}: ${l(e,t)},`}r(a,"emitObject");function g(n){const e=n??{},t=" ",o=e.type??m.database.type,u=e.backupRetention??m.database.backupRetention,p=e.deletionProtection??m.database.deletionProtection;let i=`
|
|
7
7
|
${t}type: "${o}",`;return i+=s("databaseName",e.databaseName,t),i+=s("databaseEngine",e.databaseEngine,t),o==="Instance"&&e.instanceType!==void 0&&(i+=s("instanceType",e.instanceType,t)),i+=c("allocatedStorage",e.allocatedStorage,t),i+=c("port",e.port,t),i+=`
|
|
8
8
|
${t}backupRetention: ${u},`,i+=`
|
|
9
9
|
${t}deletionProtection: ${p},`,i+=c("publiclyAccessible",e.publiclyAccessible,t),i+=s("allowedIpCidr",e.allowedIpCidr,t),i+=c("multiAz",e.multiAz,t),i+=c("allowVpcAccess",e.allowVpcAccess,t),i+=c("monitoringInterval",e.monitoringInterval,t),i+=s("preferredMaintenanceWindow",e.preferredMaintenanceWindow,t),i+=s("snapshotIdentifier",e.snapshotIdentifier,t),i+=s("snapshotUsername",e.snapshotUsername,t),i+=d("readReplica",e.readReplica,t),i+=a("writer",e.writer,t),i+=d("readers",e.readers,t),i+=d("databaseInsights",e.databaseInsights,t),i+=d("proxy",e.proxy,t),i+=a("credentials",e.credentials,t),i+=a("encryption",e.encryption,t),`
|
|
10
10
|
database: {${i}
|
|
11
|
-
},`}r(
|
|
11
|
+
},`}r(g,"emitDatabaseBlock");function S(n){const e=n??{},t=e.server?.memorySize??m.compute.server.memorySize,o=e.server?.timeout??m.compute.server.timeout,u=e.imageOptimisation?.memorySize??m.compute.imageOptimisation.memorySize,p=e.imageOptimisation?.timeout??m.compute.imageOptimisation.timeout,i=e.revalidation?.memorySize??m.compute.revalidation.memorySize,f=e.revalidation?.timeout??m.compute.revalidation.timeout;return`
|
|
12
12
|
compute: {
|
|
13
13
|
server: {
|
|
14
14
|
memorySize: ${t},
|
|
@@ -20,15 +20,15 @@ ${t}deletionProtection: ${p},`,i+=c("publiclyAccessible",e.publiclyAccessible,t)
|
|
|
20
20
|
},
|
|
21
21
|
revalidation: {
|
|
22
22
|
memorySize: ${i},
|
|
23
|
-
timeout: ${
|
|
23
|
+
timeout: ${f},
|
|
24
24
|
},
|
|
25
|
-
},`}r(
|
|
26
|
-
${e}domain: ${JSON.stringify(n.domain)},`),t+=a("forms",n.forms,e),t+=a("cdn",n.cdn,e),t}r(
|
|
27
|
-
|
|
25
|
+
},`}r(S,"emitComputeBlock");function v(n){return a("storage",n," ")}r(v,"emitStorageBlock");function O(n){return a("messaging",n," ")}r(O,"emitMessagingBlock");function z(n){return a("cdn",n," ")}r(z,"emitCdnBlock");function I(n){return a("environment",n," ")}r(I,"emitEnvironmentBlock");function T(n){const e=" ";let t="";return t+=s("source",n.source,e),t+=a("build",n.build,e),t+=s("routing",n.routing,e),t+=a("security",n.security,e),n.domain!==void 0&&n.domain!==""&&(t+=`
|
|
26
|
+
${e}domain: ${JSON.stringify(n.domain)},`),t+=a("forms",n.forms,e),t+=a("cdn",n.cdn,e),t}r(T,"emitStaticSiteFields");function N(n){if(!n.patternConfig)return"";const e=n.patternConfig,t=b(e.name,e.type);let o=`app.${y.appMethod}(
|
|
27
|
+
${y.factory}.build("${t}", {
|
|
28
28
|
type: "${e.type}",
|
|
29
29
|
name: "${e.name}",`;return e.type==="payload"||e.type==="nextjs"?(e.domain!==void 0&&e.domain!==""&&(o+=`
|
|
30
|
-
domain: "${e.domain}",`),o+=
|
|
30
|
+
domain: "${e.domain}",`),o+=g(e.database),o+=S(e.compute),o+=v(e.storage),o+=O(e.messaging),o+=z(e.cdn),o+=I(e.environment)):o+=T(e),o+=`
|
|
31
31
|
})
|
|
32
32
|
);
|
|
33
33
|
|
|
34
|
-
`,o}r(
|
|
34
|
+
`,o}r(N,"generatePatternCodeWithComments");export{m as OPENNEXT_DEFAULTS,N as generatePatternCodeWithComments};
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* infrastructure code from resource plans.
|
|
6
6
|
*/
|
|
7
7
|
export { type IdentifierValue, type ExpressionValue, type CallValue, type SpecialValue, isSpecialValue, toPascalCase, toKebab, toValidDatabaseName, toVariableName, formatValue, buildProperty, getVariableName, resolveResourceVariable, emitExtraProperties, } from "./common.js";
|
|
8
|
+
export { type StructuredRenderOptions, collectProjectedPropImports, emitProjectedProps, renderProjectedValueSource, renderStructuredValueSource, } from "./structuredSource.js";
|
|
8
9
|
export { CONNECTION_TYPE_ORDER, DATABASE_ACCESSORS, DATABASE_SSL_VALUE, MESSAGING_ACCESSORS, STORAGE_ACCESSORS, type ConnectionResourceType, type ConnectionWiringEntry, type ConnectionWiringValue, buildConnectionWiringEntries, renderWiringValueSource, } from "./connectionWiring.js";
|
|
9
|
-
export { DATABASE_ENV_VARS, CREDENTIAL_KEYS, type DatabaseEnvVarEntry, type DatabaseEnvVars, getConnectedDatabases, generateDatabaseEnvVarEntries, formatConnectionsCode, buildDatabaseEnvVars, databaseNeedsVariable, generateDatabaseCode, generateClickHouseCode, } from "./database.js";
|
|
10
|
+
export { DATABASE_ENV_VARS, CREDENTIAL_KEYS, type DatabaseEnvVarEntry, type DatabaseEnvVars, getConnectedDatabases, generateDatabaseEnvVarEntries, formatConnectionsCode, buildDatabaseEnvVars, databaseNeedsVariable, clickhouseNeedsVariable, generateDatabaseCode, generateClickHouseCode, } from "./database.js";
|
|
10
11
|
export { STORAGE_ENV_VARS, type StorageEnvVarEntry, type StorageEnvVars, getConnectedStorage, generateStorageEnvVarEntries, buildStorageEnvVars, formatAllConnectionsCode, } from "./storageConnections.js";
|
|
11
12
|
export { MESSAGING_ENV_VARS, type MessagingEnvVarEntry, type MessagingEnvVars, getConnectedMessaging, generateMessagingEnvVarEntries, buildMessagingEnvVars, } from "./messagingConnections.js";
|
|
12
|
-
export { generateLambdaCode, generateLambdaConnectionsCode, generateEc2Code, generateEcsCode, generateComputeCode, } from "./compute.js";
|
|
13
|
+
export { generateLambdaCode, generateLambdaConnectionsCode, generateEc2Code, generateEcsCode, generateComputeCode, findComputeProjectionRefusal, type ComputeProjectionRefusal, } from "./compute.js";
|
|
13
14
|
export { generateS3Code, generateDynamoDBCode, generateSQSCode, s3NeedsVariable, sqsNeedsVariable, } from "./storage.js";
|
|
14
15
|
export { generateNetworkCode, generateTags, generateAppInit, generateImports, generateCDNCode, collectCdnReferencedResources, usesPatternApproach, generatePatternCodeWithComments, } from "./infrastructure.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isSpecialValue as
|
|
1
|
+
import{isSpecialValue as a,toPascalCase as t,toKebab as o,toValidDatabaseName as n,toVariableName as s,formatValue as d,buildProperty as i,getVariableName as C,resolveResourceVariable as g,emitExtraProperties as S}from"./common.js";import{collectProjectedPropImports as c,emitProjectedProps as l,renderProjectedValueSource as m,renderStructuredValueSource as V}from"./structuredSource.js";import{CONNECTION_TYPE_ORDER as u,DATABASE_ACCESSORS as b,DATABASE_SSL_VALUE as p,MESSAGING_ACCESSORS as N,STORAGE_ACCESSORS as f,buildConnectionWiringEntries as R,renderWiringValueSource as _}from"./connectionWiring.js";import{DATABASE_ENV_VARS as P,CREDENTIAL_KEYS as x,getConnectedDatabases as T,generateDatabaseEnvVarEntries as O,formatConnectionsCode as v,buildDatabaseEnvVars as I,databaseNeedsVariable as G,clickhouseNeedsVariable as L,generateDatabaseCode as M,generateClickHouseCode as j}from"./database.js";import{STORAGE_ENV_VARS as h,getConnectedStorage as k,generateStorageEnvVarEntries as W,buildStorageEnvVars as y,formatAllConnectionsCode as K}from"./storageConnections.js";import{MESSAGING_ENV_VARS as q,getConnectedMessaging as w,generateMessagingEnvVarEntries as H,buildMessagingEnvVars as Q}from"./messagingConnections.js";import{generateLambdaCode as z,generateLambdaConnectionsCode as F,generateEc2Code as J,generateEcsCode as X,generateComputeCode as Z,findComputeProjectionRefusal as $}from"./compute.js";import{generateS3Code as re,generateDynamoDBCode as ae,generateSQSCode as te,s3NeedsVariable as oe,sqsNeedsVariable as ne}from"./storage.js";import{generateNetworkCode as de,generateTags as ie,generateAppInit as Ce,generateImports as ge,generateCDNCode as Se,collectCdnReferencedResources as Ee,usesPatternApproach as ce,generatePatternCodeWithComments as le}from"./infrastructure.js";export{u as CONNECTION_TYPE_ORDER,x as CREDENTIAL_KEYS,b as DATABASE_ACCESSORS,P as DATABASE_ENV_VARS,p as DATABASE_SSL_VALUE,N as MESSAGING_ACCESSORS,q as MESSAGING_ENV_VARS,f as STORAGE_ACCESSORS,h as STORAGE_ENV_VARS,R as buildConnectionWiringEntries,I as buildDatabaseEnvVars,Q as buildMessagingEnvVars,i as buildProperty,y as buildStorageEnvVars,L as clickhouseNeedsVariable,Ee as collectCdnReferencedResources,c as collectProjectedPropImports,G as databaseNeedsVariable,S as emitExtraProperties,l as emitProjectedProps,$ as findComputeProjectionRefusal,K as formatAllConnectionsCode,v as formatConnectionsCode,d as formatValue,Ce as generateAppInit,Se as generateCDNCode,j as generateClickHouseCode,Z as generateComputeCode,M as generateDatabaseCode,O as generateDatabaseEnvVarEntries,ae as generateDynamoDBCode,J as generateEc2Code,X as generateEcsCode,ge as generateImports,z as generateLambdaCode,F as generateLambdaConnectionsCode,H as generateMessagingEnvVarEntries,de as generateNetworkCode,le as generatePatternCodeWithComments,re as generateS3Code,te as generateSQSCode,W as generateStorageEnvVarEntries,ie as generateTags,T as getConnectedDatabases,w as getConnectedMessaging,k as getConnectedStorage,C as getVariableName,a as isSpecialValue,m as renderProjectedValueSource,V as renderStructuredValueSource,_ as renderWiringValueSource,g as resolveResourceVariable,oe as s3NeedsVariable,ne as sqsNeedsVariable,o as toKebab,t as toPascalCase,n as toValidDatabaseName,s as toVariableName,ce as usesPatternApproach};
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
1
|
+
var y=Object.defineProperty;var r=(e,t)=>y(e,"name",{value:t,configurable:!0});import{toVariableName as N,formatValue as f,resolveResourceVariable as p,emitExtraProperties as T}from"./common.js";import{COMPUTE_TYPE as g}from"../schemas/constants.js";import{scalingTypeBinding as b}from"../projection/compute.js";import{projectLambdaProps as $}from"./compute/lambda.js";import{collectProjectedPropImports as A}from"./structuredSource.js";import{CDN_INVOCATION as s,COMPUTE_INVOCATION as O,DATABASE_INVOCATION as d,MESSAGING_INVOCATION as C,NETWORK_INVOCATION as u,PATTERN_INVOCATION as I,STORAGE_INVOCATION as w}from"./statementInvocation.js";import{OPENNEXT_DEFAULTS as W,generatePatternCodeWithComments as Y}from"./generatePatternCode.js";const h="fjall:costAllocation:owner",P="engineering";function k(e){return typeof e=="object"&&e!==null&&Object.keys(e).length===0}r(k,"isEmptyObject");function l(e){const t={...e};return k(t.flowLogs)&&delete t.flowLogs,t}r(l,"cleanNetworkConfig");function V(e){if(!e.additionalNetworks||e.additionalNetworks.length===0)return"";let t="";for(const n of e.additionalNetworks){const i=N(n.name),o={};n.maxAzs!==void 0&&(o.maxAzs=n.maxAzs),n.natGateways!==void 0&&(o.natGateways=n.natGateways),n.flowLogs!==void 0&&(o.flowLogs=n.flowLogs),n.vpcEndpoints!==void 0&&(o.vpcEndpoints=n.vpcEndpoints);const c=l(o);t+=`const ${i} = app.${u.appMethod}(
|
|
2
|
+
${u.factory}.build("${n.name}", ${f(c," ")})
|
|
3
3
|
);
|
|
4
4
|
|
|
5
|
-
`}return t}
|
|
6
|
-
${Object.entries(t).map(([i,
|
|
5
|
+
`}return t}r(V,"generateNetworkCode");function D(e){const t={};return e.tags&&Object.keys(e.tags).length>0&&Object.assign(t,e.tags),t[h]||(t[h]=e.owner||P),`app.addTags({
|
|
6
|
+
${Object.entries(t).map(([i,o])=>` "${i}": "${o}"`).join(`,
|
|
7
7
|
`)}
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
`}
|
|
10
|
+
`}r(D,"generateTags");function M(e){let t=`
|
|
11
11
|
const appName = "${e.appName}";
|
|
12
|
-
`;const
|
|
13
|
-
network: { useExisting: "${e.vpcId}" }`,
|
|
14
|
-
backup: { tier: "${
|
|
15
|
-
${
|
|
12
|
+
`;const n=e.backup&&typeof e.backup=="object"?e.backup:void 0,i=e.tunnel&&typeof e.tunnel=="object"?e.tunnel:void 0,o=i?i.instanceType?`tunnel: { instanceType: "${i.instanceType}" }`:"tunnel: true":void 0;if(e.vpcId)t+=`const app = App.getApp(appName, {
|
|
13
|
+
network: { useExisting: "${e.vpcId}" }`,n&&(t+=`,
|
|
14
|
+
backup: { tier: "${n.tier}" }`),o&&(t+=`,
|
|
15
|
+
${o}`),t+=`
|
|
16
16
|
});
|
|
17
|
-
`;else if(e.network){const c=
|
|
18
|
-
network: ${
|
|
19
|
-
backup: { tier: "${
|
|
20
|
-
${
|
|
17
|
+
`;else if(e.network){const c=l(e.network);t+=`const app = App.getApp(appName, {
|
|
18
|
+
network: ${f(c," ")}`,n&&(t+=`,
|
|
19
|
+
backup: { tier: "${n.tier}" }`),o&&(t+=`,
|
|
20
|
+
${o}`),t+=`
|
|
21
21
|
});
|
|
22
|
-
`}else t+="const app = App.getApp(appName, { network: false",
|
|
22
|
+
`}else t+="const app = App.getApp(appName, { network: false",n&&(t+=`, backup: { tier: "${n.tier}" }`),o&&(t+=`, ${o}`),t+=` });
|
|
23
23
|
`;return t+=`
|
|
24
|
-
`,t}
|
|
24
|
+
`,t}r(M,"generateAppInit");function j(e){const t=[],n=r(i=>{for(const o of i)t.includes(o)||t.push(o)},"add");for(const i of e.compute)if(i.type===g.LAMBDA&&n(A($(i))),i.type===g.ECS)for(const o of i.services??[])typeof o.scaling=="object"&&o.scaling.scalingType&&n(b(o.scaling.scalingType)?.imports??[]);return t}r(j,"collectComputeImports");function H(e){const t=[];if(e.patternConfig)t.push(I.factory);else{e.database.length>0&&t.push(d.factory),e.s3.length>0&&t.push(w.factory),e.compute.length>0&&t.push(O.factory),(e.compute.length>0||e.database.length>0||e.sqs!==void 0&&e.sqs.length>0)&&t.push("getConfig"),e.dynamodb&&e.dynamodb.length>0&&e.database.length===0&&t.push(d.factory),e.clickhouse&&e.clickhouse.length>0&&e.database.length===0&&!(e.dynamodb&&e.dynamodb.length>0)&&t.push(d.factory),e.sqs&&e.sqs.length>0&&t.push(C.factory),e.cdn&&t.push(s.factory);for(const o of j(e))t.includes(o)||t.push(o)}if(e.additionalNetworks&&e.additionalNetworks.length>0&&t.push(u.factory),e.additionalManagedImports){for(const o of e.additionalManagedImports)if(o.moduleSpecifier==="@fjall/components-infrastructure"||o.moduleSpecifier==="@fjall/infrastructure")for(const c of o.namedImports)t.includes(c)||t.push(c)}let i=`#!/usr/bin/env node
|
|
25
25
|
|
|
26
26
|
import { App${t.length>0?`, ${t.join(", ")}`:""} } from "@fjall/components-infrastructure";
|
|
27
|
-
`;if(e.additionalManagedImports)for(const
|
|
28
|
-
`)}return i}
|
|
29
|
-
app.
|
|
30
|
-
|
|
27
|
+
`;if(e.additionalManagedImports)for(const o of e.additionalManagedImports){if(o.moduleSpecifier==="@fjall/components-infrastructure"||o.moduleSpecifier==="@fjall/infrastructure")continue;const c=o.namedImports.length>0?`{ ${o.namedImports.join(", ")} }`:"",m=[o.defaultImport??"",c].filter(Boolean).join(", ");m&&(i+=`import ${m} from "${o.moduleSpecifier}";
|
|
28
|
+
`)}return i}r(H,"generateImports");function E(e){if(!e.cdn)return!1;const t=e.compute.find(o=>o.name===e.cdn?.defaultOriginRef);if(t===void 0||t.type!=="ecs")return!1;const n=t.cluster;return n?.domain!==void 0?!1:!(n?.extraProperties??[]).some(o=>o.key==="domainConfig")}r(E,"cdnDefaultOriginNeedsAlbLane");function B(e){if(!e.cdn)return"";const t=p(e,e.cdn.defaultOriginRef);let n=E(e)?`
|
|
29
|
+
app.${s.appMethod}(
|
|
30
|
+
${s.factory}.build("${e.cdn.name}", {
|
|
31
31
|
// Plain-HTTP origin fetch: the compute has no domain, so no TLS-valid
|
|
32
32
|
// origin hostname exists. Give the cluster a domain and switch to
|
|
33
33
|
// originType "auto" for HTTPS between CloudFront and the origin.
|
|
34
34
|
originType: "alb",
|
|
35
35
|
loadBalancer: ${t},
|
|
36
36
|
protocolPolicy: "HTTP_ONLY"`:`
|
|
37
|
-
app.
|
|
38
|
-
|
|
37
|
+
app.${s.appMethod}(
|
|
38
|
+
${s.factory}.build("${e.cdn.name}", {
|
|
39
39
|
originType: "auto",
|
|
40
|
-
origin: ${t}`;if(e.cdn.behaviours&&e.cdn.behaviours.length>0){const i=e.cdn.behaviours.map(
|
|
41
|
-
pathPattern: "${
|
|
42
|
-
origin: ${c},`;return
|
|
43
|
-
cachePolicy: "${
|
|
40
|
+
origin: ${t}`;if(e.cdn.behaviours&&e.cdn.behaviours.length>0){const i=e.cdn.behaviours.map(o=>{const c=p(e,o.originRef);let a=`{
|
|
41
|
+
pathPattern: "${o.pathPattern}",
|
|
42
|
+
origin: ${c},`;return o.cachePolicy&&(a+=`
|
|
43
|
+
cachePolicy: "${o.cachePolicy}",`),a+=`
|
|
44
44
|
}`,a}).join(`,
|
|
45
|
-
`);
|
|
45
|
+
`);n+=`,
|
|
46
46
|
behaviours: [
|
|
47
47
|
${i}
|
|
48
|
-
]`}return e.cdn.customDomain&&(
|
|
49
|
-
domainNames: ["${e.cdn.customDomain}"]`),e.cdn.domain&&(
|
|
50
|
-
domainConfig: { domainName: "${e.cdn.domain}" }`),e.cdn.certificateArn&&(
|
|
51
|
-
certificateArn: "${e.cdn.certificateArn}"`),e.cdn.originHostname&&(
|
|
52
|
-
originHostname: "${e.cdn.originHostname}"`),e.cdn.accessGate!==void 0&&(e.cdn.accessGate===!1?
|
|
53
|
-
accessGate: false`:
|
|
54
|
-
accessGate: ${
|
|
48
|
+
]`}return e.cdn.customDomain&&(n+=`,
|
|
49
|
+
domainNames: ["${e.cdn.customDomain}"]`),e.cdn.domain&&(n+=`,
|
|
50
|
+
domainConfig: { domainName: "${e.cdn.domain}" }`),e.cdn.certificateArn&&(n+=`,
|
|
51
|
+
certificateArn: "${e.cdn.certificateArn}"`),e.cdn.originHostname&&(n+=`,
|
|
52
|
+
originHostname: "${e.cdn.originHostname}"`),e.cdn.accessGate!==void 0&&(e.cdn.accessGate===!1?n+=`,
|
|
53
|
+
accessGate: false`:n+=`,
|
|
54
|
+
accessGate: ${f(e.cdn.accessGate," ")}`),n+=T(e.cdn.extraProperties),n+=`
|
|
55
55
|
})
|
|
56
56
|
);
|
|
57
|
-
`,
|
|
57
|
+
`,n}r(B,"generateCDNCode");function q(e){const t=new Set;if(e.cdn&&(e.cdn.defaultOriginRef&&t.add(e.cdn.defaultOriginRef),e.cdn.behaviours))for(const n of e.cdn.behaviours)t.add(n.originRef);return t}r(q,"collectCdnReferencedResources");function U(e){return e.patternConfig!==void 0}r(U,"usesPatternApproach");export{h as COST_ALLOCATION_TAG,P as DEFAULT_COST_ALLOCATION_OWNER,W as OPENNEXT_DEFAULTS,E as cdnDefaultOriginNeedsAlbLane,q as collectCdnReferencedResources,M as generateAppInit,B as generateCDNCode,H as generateImports,V as generateNetworkCode,Y as generatePatternCodeWithComments,D as generateTags,U as usesPatternApproach};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Construct-call vocabulary for the scaffold's emitters — the factory
|
|
3
|
+
* identifier and the `app.<method>` wrapper each statement type is written
|
|
4
|
+
* with.
|
|
5
|
+
*
|
|
6
|
+
* Both are already declared once, for the codemod lane, in
|
|
7
|
+
* `codemod/registry.ts` (`FACTORY_IDENTIFIERS` and each entry's
|
|
8
|
+
* `emitWrapper.appMethod`). The scaffold used to repeat them as string
|
|
9
|
+
* literals inside its template strings, which made the pair a TWO-inventory
|
|
10
|
+
* fact: renaming `DatabaseFactory` or `addDatabase` in the registry left the
|
|
11
|
+
* scaffold emitting an identifier the barrel no longer exports, and the
|
|
12
|
+
* regenerated file would not compile. Reading them from the registry makes
|
|
13
|
+
* the rename a one-line edit again.
|
|
14
|
+
*
|
|
15
|
+
* Zero output change: every constant below resolves to exactly the literal
|
|
16
|
+
* the emitter used to inline.
|
|
17
|
+
*/
|
|
18
|
+
export interface StatementInvocation {
|
|
19
|
+
/** Barrel export the statement calls `.build(...)` on. */
|
|
20
|
+
readonly factory: string;
|
|
21
|
+
/** `App` method the factory thunk is handed to. */
|
|
22
|
+
readonly appMethod: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const DATABASE_INVOCATION: StatementInvocation;
|
|
25
|
+
export declare const STORAGE_INVOCATION: StatementInvocation;
|
|
26
|
+
export declare const COMPUTE_INVOCATION: StatementInvocation;
|
|
27
|
+
export declare const MESSAGING_INVOCATION: StatementInvocation;
|
|
28
|
+
export declare const CDN_INVOCATION: StatementInvocation;
|
|
29
|
+
export declare const NETWORK_INVOCATION: StatementInvocation;
|
|
30
|
+
export declare const PATTERN_INVOCATION: StatementInvocation;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.defineProperty;var n=(e,o)=>p(e,"name",{value:o,configurable:!0});import{STATEMENT_REGISTRY as a}from"../codemod/registry.js";function t(e){const o=a[e],r=o.emitWrapper?.appMethod;if(r===void 0)throw new Error(`Statement type "${e}" declares no emitWrapper.appMethod \u2014 the scaffold emits wrapped statements only.`);return{factory:o.factoryIdentifier,appMethod:r}}n(t,"invocationOf");const O=t("database"),c=t("storage"),I=t("compute"),T=t("messaging"),A=t("cdn"),i=t("network"),d=t("pattern");export{A as CDN_INVOCATION,I as COMPUTE_INVOCATION,O as DATABASE_INVOCATION,T as MESSAGING_INVOCATION,i as NETWORK_INVOCATION,d as PATTERN_INVOCATION,c as STORAGE_INVOCATION};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var
|
|
2
|
-
`:"",
|
|
3
|
-
|
|
1
|
+
var P=Object.defineProperty;var a=(e,t)=>P(e,"name",{value:t,configurable:!0});import{projectPlanToConstructProps as x}from"../projection/index.js";import{buildProperty as i,getVariableName as m,emitExtraProperties as u,emitProductionAlertsTopicSpread as N,escapeStringLiteral as o}from"./common.js";import{emitProjectedProps as A}from"./structuredSource.js";import{DATABASE_INVOCATION as g,MESSAGING_INVOCATION as b,STORAGE_INVOCATION as p}from"./statementInvocation.js";function K(e){let t="";return t+=i(e.bucketName!==void 0,"bucketName",e.bucketName,"string"),t+=i(e.stackPlacement!==void 0&&e.stackPlacement!=="storage","stackPlacement",e.stackPlacement,"string"),t+=i(e.publicReadAccess===!0,"publicReadAccess",!0),t+=i(e.websiteHosting!==void 0,"websiteHosting",e.websiteHosting,"object"),t+=i(e.backupVaultTier!==void 0,"backupVaultTier",e.backupVaultTier,"string"),t+=i(e.versioned!==void 0,"versioned",e.versioned),t+=i(e.encryption!==void 0,"encryption",e.encryption,"string"),t+=i(e.kmsKeyArn!==void 0,"kmsKeyArn",e.kmsKeyArn,"string"),t+=i(e.cors!==void 0&&e.cors.length>0,"cors",e.cors,"object"),t+=i(e.deployment!==void 0,"deployment",e.deployment,"object"),t+=i(e.retain===!0,"retain",!0),t}a(K,"generateS3BucketProps");function S(e,t){return!!(t.compute.some(r=>r.connectedStorage?.includes(e.name))||t.cdn&&(t.cdn.defaultOriginRef===e.name||t.cdn.behaviours?.some(r=>r.originRef===e.name)))}a(S,"s3NeedsVariable");function v(e){if(e.s3.length===0)return"";let t="";for(let n=0;n<e.s3.length;n++){const r=e.s3[n],c=m(r),s=S(r,e),l=e.database.length>0||n>0?`
|
|
2
|
+
`:"",f=K(r),y=s?`const ${c} = `:"",$=u(r.extraProperties);f||$?t+=`${l}${y}app.${p.appMethod}(
|
|
3
|
+
${p.factory}.build(${o(r.name)}, {${f}${$}
|
|
4
4
|
})
|
|
5
5
|
);
|
|
6
|
-
`:t+=`${l}${y}app.
|
|
7
|
-
|
|
6
|
+
`:t+=`${l}${y}app.${p.appMethod}(
|
|
7
|
+
${p.factory}.build(${o(r.name)}, {})
|
|
8
8
|
);
|
|
9
|
-
`}return t}
|
|
10
|
-
const ${r} = app.
|
|
11
|
-
|
|
9
|
+
`}return t}a(v,"generateS3Code");function C(e){if(!e.dynamodb||e.dynamodb.length===0)return"";let t="";for(const n of e.dynamodb){const r=m(n);if(t+=`
|
|
10
|
+
const ${r} = app.${g.appMethod}(
|
|
11
|
+
${g.factory}.build(${o(n.name)}, {
|
|
12
12
|
type: "DynamoDB",
|
|
13
13
|
partitionKey: {
|
|
14
14
|
name: ${o(n.partitionKey.name)},
|
|
@@ -17,15 +17,15 @@ const ${r} = app.addDatabase(
|
|
|
17
17
|
sortKey: {
|
|
18
18
|
name: ${o(n.sortKey.name)},
|
|
19
19
|
type: ${o(n.sortKey.type)},
|
|
20
|
-
}`),n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0){const c=n.globalSecondaryIndexes.map(
|
|
21
|
-
indexName: ${o(
|
|
20
|
+
}`),n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0){const c=n.globalSecondaryIndexes.map(s=>{let d=`{
|
|
21
|
+
indexName: ${o(s.indexName)},
|
|
22
22
|
partitionKey: {
|
|
23
|
-
name: ${o(
|
|
24
|
-
type: ${o(
|
|
25
|
-
},`;return
|
|
23
|
+
name: ${o(s.partitionKey.name)},
|
|
24
|
+
type: ${o(s.partitionKey.type)},
|
|
25
|
+
},`;return s.sortKey&&(d+=`
|
|
26
26
|
sortKey: {
|
|
27
|
-
name: ${o(
|
|
28
|
-
type: ${o(
|
|
27
|
+
name: ${o(s.sortKey.name)},
|
|
28
|
+
type: ${o(s.sortKey.type)},
|
|
29
29
|
},`),d+=`
|
|
30
30
|
}`,d}).join(`,
|
|
31
31
|
`);t+=`,
|
|
@@ -36,9 +36,9 @@ const ${r} = app.addDatabase(
|
|
|
36
36
|
stream: true`),t+=u(n.extraProperties),t+=`
|
|
37
37
|
})
|
|
38
38
|
);
|
|
39
|
-
`}return t}
|
|
40
|
-
${
|
|
41
|
-
|
|
39
|
+
`}return t}a(C,"generateDynamoDBCode");function h(e,t){return t.compute.some(n=>n.connectedMessaging?.includes(e.name))}a(h,"sqsNeedsVariable");function O(e){if(!e.sqs||e.sqs.length===0)return"";let t="";for(const n of e.sqs){const r=m(n),s=h(n,e)?`const ${r} = `:"",{props:d}=x("messaging",{queueType:n.queueType,visibilityTimeout:n.visibilityTimeout,retentionPeriod:n.retentionPeriod,...n.contentBasedDeduplication===!0&&{contentBasedDeduplication:!0},removalPolicy:n.removalPolicy});t+=`
|
|
40
|
+
${s}app.${b.appMethod}(
|
|
41
|
+
${b.factory}.build(${o(n.name)}, {${A(d)}`,t+=",",t+=u(n.extraProperties),t+=N(),t+=`
|
|
42
42
|
})
|
|
43
43
|
);
|
|
44
|
-
`}return t}
|
|
44
|
+
`}return t}a(O,"generateSQSCode");export{C as generateDynamoDBCode,v as generateS3Code,O as generateSQSCode,S as s3NeedsVariable,h as sqsNeedsVariable};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StructuredValue → TypeScript source — the scaffold lane's printer for the
|
|
3
|
+
* projection's validated expression trees.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the codemod's AST serialiser (`codemod/edits/addResource/
|
|
6
|
+
* propertyBuilder.ts § buildStructuredValue`) SEMANTICALLY, not mechanically:
|
|
7
|
+
* the same identifier-segment validation (pattern + reserved-word set, both
|
|
8
|
+
* imported from the serialiser so the two printers refuse the same set), the
|
|
9
|
+
* same literal value domain, string output instead of ast-types nodes. The
|
|
10
|
+
* scaffold's string renderer exists because the scaffold controls a whole
|
|
11
|
+
* file's bytes and must not reflow it through recast; the codemod's AST
|
|
12
|
+
* serialiser exists because a surgical edit must never splice free text.
|
|
13
|
+
* `structuredSource.test.ts` pins renderer output ≡ buildStructuredValue +
|
|
14
|
+
* recast for every StructuredValue kind, so the two cannot drift silently.
|
|
15
|
+
*
|
|
16
|
+
* Failures here THROW rather than return a Result: every input reaches this
|
|
17
|
+
* renderer from a projection table over a schema-validated plan, so a
|
|
18
|
+
* non-printable segment is a table regression the scaffold must surface
|
|
19
|
+
* loudly — the same posture `emitProjectedProps` took when it refused
|
|
20
|
+
* structured values outright.
|
|
21
|
+
*/
|
|
22
|
+
import type { ProjectedProp, StructuredValue } from "../projection/types.js";
|
|
23
|
+
export interface StructuredRenderOptions {
|
|
24
|
+
/** Base indentation of the line the rendered value starts on. */
|
|
25
|
+
indent?: string;
|
|
26
|
+
/**
|
|
27
|
+
* The identifier substituted for a `primary-binding` marker (the sibling
|
|
28
|
+
* engine's placeholder for the primary statement's construct). Absent =
|
|
29
|
+
* fail closed, exactly as the AST serialiser refuses an unsubstituted
|
|
30
|
+
* marker.
|
|
31
|
+
*/
|
|
32
|
+
primaryBinding?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Render a {@link StructuredValue} as TypeScript source. Formatting follows
|
|
36
|
+
* the scaffold's `formatValue` policy: arrays inline, empty objects `{}`,
|
|
37
|
+
* single-entry objects compact when their value renders on one line,
|
|
38
|
+
* multi-entry objects one entry per line at `indent + 2`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function renderStructuredValueSource(key: string, value: StructuredValue, options?: StructuredRenderOptions): string;
|
|
41
|
+
/**
|
|
42
|
+
* Render one projected prop's VALUE as source — the per-prop twin of
|
|
43
|
+
* {@link emitProjectedProps} for emitters that interleave scaffold-only
|
|
44
|
+
* props (an `ecrRepository` app binding, an `ENVIRONMENT` env block) between
|
|
45
|
+
* projected ones.
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderProjectedValueSource(prop: ProjectedProp, options?: StructuredRenderOptions): string;
|
|
48
|
+
/**
|
|
49
|
+
* Render projected construct props as the body of an object literal —
|
|
50
|
+
* `\n<indent>key: value` per prop, comma-separated, no trailing comma. The
|
|
51
|
+
* caller supplies the surrounding braces and whatever it appends after.
|
|
52
|
+
*/
|
|
53
|
+
export declare function emitProjectedProps(props: ReadonlyArray<ProjectedProp>, indent?: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Every components-barrel specifier the projected props need, deduplicated
|
|
56
|
+
* in first-appearance order — the scaffold's twin of the codemod's
|
|
57
|
+
* `collectImportSpecifiers`, over {@link ProjectedProp}s instead of emitted
|
|
58
|
+
* ones. The scaffold merges these into `generateImports`' components import
|
|
59
|
+
* line.
|
|
60
|
+
*/
|
|
61
|
+
export declare function collectProjectedPropImports(props: ReadonlyArray<ProjectedProp>): string[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
var p=Object.defineProperty;var s=(r,e)=>p(r,"name",{value:e,configurable:!0});import{IDENTIFIER_SOURCE_PATTERN as $,RESERVED_IDENTIFIER_NAMES as b}from"../codemod/edits/addResource/propertyBuilder.js";import{isValidIdentifier as g}from"../codemod/fileRewriter/builders.js";function m(r){return g(r)?r:JSON.stringify(r)}s(m,"renderObjectKey");function l(r,e){if(!$.test(e))throw new Error(`Cannot render "${r}": expression segment \`${e}\` is not a bare identifier \u2014 structured expressions emit validated identifier segments only.`);if(b.has(e))throw new Error(`Cannot render "${r}": expression segment \`${e}\` is a JavaScript reserved word \u2014 emitting it would write a file that does not parse.`)}s(l,"assertIdentifierSegment");function j(r){const e=Object.entries(r);return e.length===0?!0:e.length>1?!1:e.every(([,n])=>typeof n=="string"||typeof n=="number"||typeof n=="boolean"||n===null)}s(j,"isSimpleLiteralObject");function d(r,e,n){if(typeof e=="string")return JSON.stringify(e);if(typeof e=="number"&&Number.isFinite(e)||typeof e=="boolean")return String(e);if(e===null)return"null";if(Array.isArray(e))return`[${e.map(i=>d(r,i,n)).join(", ")}]`;if(typeof e=="object"){const i=Object.entries(e).filter(([,t])=>t!==void 0);if(j(e)){const t=i.map(([f,u])=>`${m(f)}: ${d(r,u,n)}`).join(", ");return t?`{ ${t} }`:"{}"}const c=n+" ",o=i.map(([t,f])=>`${c}${m(t)}: ${d(r,f,c)}`).join(`,
|
|
2
|
+
`);return o?`{
|
|
3
|
+
${o}
|
|
4
|
+
${n}}`:"{}"}throw new Error(`Cannot render "${r}": unsupported literal value (accepts string/number/boolean/null/array/object of the same).`)}s(d,"renderLiteralSource");function y(r,e,n){return e.kind==="identifier"?(l(r,e.name),e.name):d(r,e.value,n.indent??" ")}s(y,"renderCallArgument");function a(r,e,n={}){const i=n.indent??" ";switch(e.kind){case"primary-binding":{if(n.primaryBinding===void 0)throw new Error(`Cannot render "${r}": unsubstituted primary-binding marker \u2014 only a sibling statement's props may reference the primary construct, and the caller must supply the binding identifier.`);return l(r,n.primaryBinding),n.primaryBinding}case"literal":return d(r,e.value,i);case"identifier":return l(r,e.name),e.name;case"member":return l(r,e.property),`${a(r,e.object,n)}.${e.property}`;case"call":{const c=a(r,e.callee,n),o=e.args.map(t=>y(r,t,n)).join(", ");return`${c}(${o})`}case"object":{if(e.entries.length===0)return"{}";const c=i+" ",o=e.entries.map(u=>({key:u.key,source:a(r,u.value,{...n,indent:c})})),[t]=o;return o.length===1&&t!==void 0&&!t.source.includes(`
|
|
5
|
+
`)?`{ ${m(t.key)}: ${t.source} }`:`{
|
|
6
|
+
${o.map(u=>`${c}${m(u.key)}: ${u.source}`).join(`,
|
|
7
|
+
`)}
|
|
8
|
+
${i}}`}case"array":return`[${e.elements.map(o=>a(r,o,n)).join(", ")}]`}}s(a,"renderStructuredValueSource");function h(r,e={}){switch(r.value.kind){case"expression":return r.value.source;case"structured":return a(r.key,r.value.expression,e);case"literal":return d(r.key,r.value.value,e.indent??" ")}}s(h,"renderProjectedValueSource");function I(r,e=" "){return r.map(n=>`
|
|
9
|
+
${e}${n.key}: ${h(n,{indent:e})}`).join(",")}s(I,"emitProjectedProps");function x(r){const e=new Set;for(const n of r)if(!(n.value.kind!=="structured"||n.value.imports===void 0))for(const i of n.value.imports)e.add(i);return[...e]}s(x,"collectProjectedPropImports");export{x as collectProjectedPropImports,I as emitProjectedProps,h as renderProjectedValueSource,a as renderStructuredValueSource};
|
|
@@ -2,6 +2,7 @@ import { type TierEcsServiceConfig, type UserServiceConfig, type AppType } from
|
|
|
2
2
|
import { type Result } from "../types/Result.js";
|
|
3
3
|
import type { ApplicationResourcePlan, EcsServiceConfig } from "../schemas/resourceSchemas.js";
|
|
4
4
|
import type { ApplicationServiceConfig } from "../schemas/computeSchemas.js";
|
|
5
|
+
import { type PendingDeclaration } from "../codemod/edits/siblingBindingResolution.js";
|
|
5
6
|
/**
|
|
6
7
|
* Adapt the wire-level service config (`ApplicationServiceConfig`, validated by
|
|
7
8
|
* `ApplicationServiceConfigSchema`) into the planner's `UserServiceConfig`. The
|
|
@@ -30,4 +31,23 @@ export interface GenerationOptions {
|
|
|
30
31
|
/** Resource name mapping from old names to new names (for custom code repositioning) */
|
|
31
32
|
resourceMapping?: Map<string, string>;
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Every module-scope `const` the scaffold WILL declare for `plan`, in
|
|
36
|
+
* emission order, mirroring each emitter's own wrap predicate (a resource
|
|
37
|
+
* that emits as a bare `app.addX(...)` statement declares nothing and cannot
|
|
38
|
+
* collide). Feeds {@link findPendingWrapCollision} — the same collision
|
|
39
|
+
* oracle the codemod's sibling-wrap path uses — so two resources whose names
|
|
40
|
+
* collapse to one variable (`"Uploads"` and `"uploads"`) are refused before
|
|
41
|
+
* a file is written that does not parse.
|
|
42
|
+
*/
|
|
43
|
+
export declare function collectPlannedDeclarations(plan: ApplicationResourcePlan): PendingDeclaration[];
|
|
44
|
+
/**
|
|
45
|
+
* The module-scope consts the PRELUDE itself declares (`const appName = …`,
|
|
46
|
+
* `const app = App.getApp(…)`), DERIVED from the emitter's actual output so
|
|
47
|
+
* a new prelude binding joins the collision oracle without a hand-list going
|
|
48
|
+
* stale. Negative statement indexes keep every prelude entry distinct from
|
|
49
|
+
* the planned resource declarations and from each other (same-index pairs
|
|
50
|
+
* read as idempotent re-plans, not collisions).
|
|
51
|
+
*/
|
|
52
|
+
export declare function collectPreludeDeclarations(plan: ApplicationResourcePlan): PendingDeclaration[];
|
|
33
53
|
export declare function generateInfrastructureFromPlan(plan: ApplicationResourcePlan, options?: GenerationOptions): Result<string, Error>;
|