@fjall/generator 7.2.0 → 8.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 +30 -21
- package/dist/.minified +1 -1
- package/dist/src/ast/domain/astDomainParser.d.ts +2 -0
- package/dist/src/ast/domain/astDomainParser.js +1 -1
- package/dist/src/codemod/drift/snapshot.js +1 -1
- package/dist/src/codemod/edits/addResource/propertyBuilder.d.ts +8 -1
- package/dist/src/codemod/edits/addResource/propertyBuilder.js +1 -1
- package/dist/src/codemod/edits/addResource.js +1 -1
- package/dist/src/codemod/edits/appendAccountToStage.js +1 -1
- package/dist/src/codemod/edits/modifyResource.js +1 -1
- package/dist/src/codemod/edits/moduleConstResolver.d.ts +24 -0
- package/dist/src/codemod/edits/moduleConstResolver.js +1 -0
- package/dist/src/codemod/edits/objectGraph.d.ts +28 -0
- package/dist/src/codemod/edits/objectGraph.js +1 -0
- package/dist/src/codemod/edits/secretsProvability.d.ts +48 -0
- package/dist/src/codemod/edits/secretsProvability.js +1 -0
- package/dist/src/codemod/edits/setContainerSecrets.d.ts +55 -0
- package/dist/src/codemod/edits/setContainerSecrets.js +1 -0
- package/dist/src/codemod/emitProjection.d.ts +29 -0
- package/dist/src/codemod/emitProjection.js +1 -0
- package/dist/src/codemod/index.d.ts +1 -0
- package/dist/src/codemod/index.js +1 -1
- package/dist/src/codemod/registry.d.ts +15 -10
- package/dist/src/codemod/registry.js +1 -1
- package/dist/src/dns/bindParser.js +2 -2
- package/dist/src/dns/bindWriter.js +2 -2
- package/dist/src/dns/domainRecords.d.ts +4 -0
- package/dist/src/dns/domainRecords.js +1 -1
- package/dist/src/generation/common.d.ts +7 -0
- package/dist/src/generation/common.js +6 -5
- package/dist/src/generation/storage.js +27 -33
- package/dist/src/planning/index.d.ts +1 -1
- package/dist/src/planning/index.js +1 -1
- package/dist/src/planning/resourcePlanning.d.ts +14 -2
- package/dist/src/planning/resourcePlanning.js +1 -1
- package/dist/src/projection/index.d.ts +3 -0
- package/dist/src/projection/index.js +1 -0
- package/dist/src/projection/project.d.ts +22 -0
- package/dist/src/projection/project.js +1 -0
- package/dist/src/projection/tables.d.ts +32 -0
- package/dist/src/projection/tables.js +1 -0
- package/dist/src/projection/types.d.ts +108 -0
- package/dist/src/projection/types.js +0 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{addResource as o}from"./edits/addResource.js";import{removeResource as c}from"./edits/removeResource.js";import{modifyResource as m}from"./edits/modifyResource.js";import{appendAccountToStage as s}from"./edits/appendAccountToStage.js";import{addVpcPeer as
|
|
1
|
+
import{addResource as o}from"./edits/addResource.js";import{removeResource as c}from"./edits/removeResource.js";import{modifyResource as m}from"./edits/modifyResource.js";import{appendAccountToStage as s}from"./edits/appendAccountToStage.js";import{setContainerSecrets as d}from"./edits/setContainerSecrets.js";import{addVpcPeer as i,modifyVpcPeer as l,removeVpcPeer as f}from"./edits/vpcPeer.js";import{addVpcPeerAccepter as P,modifyVpcPeerAccepter as x,removeVpcPeerAccepter as R}from"./edits/vpcPeerAccepter.js";import{addCrossPlanConnection as T,modifyCrossPlanConnection as v,removeCrossPlanConnection as A}from"./edits/crossPlanConnection.js";import{resolveDriftPolicy as V}from"./edits/driftPolicy.js";import{listResources as y}from"./listResources.js";import{resolveConstructByLiteralProperty as D}from"./semanticIndex/index.js";import{parse as N}from"./fileRewriter/parse.js";import{CrossPlanConnectionResourcePlanSchema as F,VpcPeerAccepterResourcePlanSchema as L,VpcPeerResourcePlanSchema as I}from"../schemas/index.js";import{detectDrift as O,mergeProperties as g,snapshotProperties as k}from"./drift/index.js";import{computeLinesDelta as U}from"./_internal.js";import{ResourceNameSchema as Y,StatementTypeSchema as j}from"./types.js";import{REGISTERED_STATEMENT_TYPES as w,STATEMENT_REGISTRY as z}from"./registry.js";import{evaluateEmitGuard as J,UNRESOLVED as Q}from"./emitGuard.js";import{CODEMOD_ERROR_KINDS as X}from"./telemetry/errorKinds.js";import{buildEgressBlockedEvent as $,buildFiredEvent as ee,buildGateFailedEvent as re,buildGatePassedEvent as oe,buildRejectedEvent as te,buildSucceededEvent as ce,buildTimeoutEvent as pe,estimateCostUsd as me,FALLBACK_EVENTS as ae,GATE_EVENTS as se,PARSE_GATE as ne,RUNTIME_GATE as de,runFallback as Ee,shouldTryFallback as ie}from"./llmFallback/index.js";export{X as CODEMOD_ERROR_KINDS,F as CrossPlanConnectionResourcePlanSchema,ae as FALLBACK_EVENTS,se as GATE_EVENTS,ne as PARSE_GATE,w as REGISTERED_STATEMENT_TYPES,de as RUNTIME_GATE,Y as ResourceNameSchema,z as STATEMENT_REGISTRY,j as StatementTypeSchema,Q as UNRESOLVED,L as VpcPeerAccepterResourcePlanSchema,I as VpcPeerResourcePlanSchema,T as addCrossPlanConnection,o as addResource,i as addVpcPeer,P as addVpcPeerAccepter,s as appendAccountToStage,$ as buildEgressBlockedEvent,ee as buildFiredEvent,re as buildGateFailedEvent,oe as buildGatePassedEvent,te as buildRejectedEvent,ce as buildSucceededEvent,pe as buildTimeoutEvent,U as computeLinesDelta,O as detectDrift,me as estimateCostUsd,J as evaluateEmitGuard,y as listResources,g as mergeProperties,v as modifyCrossPlanConnection,m as modifyResource,l as modifyVpcPeer,x as modifyVpcPeerAccepter,N as parse,A as removeCrossPlanConnection,c as removeResource,f as removeVpcPeer,R as removeVpcPeerAccepter,D as resolveConstructByLiteralProperty,V as resolveDriftPolicy,Ee as runFallback,d as setContainerSecrets,ie as shouldTryFallback,k as snapshotProperties};
|
|
@@ -61,13 +61,16 @@ export interface StatementTypeEntry {
|
|
|
61
61
|
* Property shapes the ADD and MODIFY paths must REFUSE to write, checked
|
|
62
62
|
* before any file is touched. Declared here, beside `emitWrapper`, because
|
|
63
63
|
* `emitWrapper` is precisely what creates the hazard: wrapping makes the
|
|
64
|
-
* emitted props load-bearing at synth, and the
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* `
|
|
69
|
-
*
|
|
70
|
-
*
|
|
64
|
+
* emitted props load-bearing at synth, and the plan and construct
|
|
65
|
+
* vocabularies disagree.
|
|
66
|
+
*
|
|
67
|
+
* ONLY for types the plan→construct projection cannot describe. Where it
|
|
68
|
+
* can (`src/projection/tables.ts`), the disagreement is TRANSLATED at
|
|
69
|
+
* emission and no rule belongs here — `emitProjection.ts` reports what is
|
|
70
|
+
* left from the projection's own `unprojectable` list. What survives is
|
|
71
|
+
* props needing a live sibling construct (`cdn`'s origin, `compute`'s
|
|
72
|
+
* connection expansion) and cross-key conditions no per-key table can
|
|
73
|
+
* state.
|
|
71
74
|
*
|
|
72
75
|
* Rules cover exactly two classes, and nothing else:
|
|
73
76
|
*
|
|
@@ -88,9 +91,11 @@ export interface StatementTypeEntry {
|
|
|
88
91
|
* through (a separate, recorded gap).
|
|
89
92
|
*
|
|
90
93
|
* Absent = every expressible property shape for this type reaches a
|
|
91
|
-
* synthesising statement. That is a claim, not an oversight
|
|
92
|
-
* `
|
|
93
|
-
*
|
|
94
|
+
* synthesising statement. That is a claim, not an oversight, and it is now
|
|
95
|
+
* true two ways: `network` and `buildkite` have outright plan/construct
|
|
96
|
+
* parity, while `database`, `storage` and `messaging` reach it through the
|
|
97
|
+
* projection. The components-infrastructure materialisation contract pins
|
|
98
|
+
* both.
|
|
94
99
|
*/
|
|
95
100
|
emitGuard?: ReadonlyArray<EmitGuardRule>;
|
|
96
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C=Object.defineProperty;var n=(e,t)=>C(e,"name",{value:t,configurable:!0});import{z as d}from"zod";import{BuildkitePropsObjectSchema as v,CDNResourcePlanSchema as R,ComputeResourcePlanSchema as k,CrossPlanConnectionResourcePlanSchema as T,DatabaseResourcePlanSchema as A,NetworkResourcePlanSchema as E,NextJSPatternConfigSchema as w,OrganisationResourcePlanSchema as F,PayloadPatternConfigSchema as N,S3ResourcePlanSchema as M,SQSResourcePlanSchema as D,StaticSitePatternConfigSchema as _,VpcPeerAccepterResourcePlanSchema as O,VpcPeerResourcePlanSchema as W}from"../schemas/index.js";import{failure as x}from"../types/Result.js";import{isRecord as G}from"./_internal.js";import{AUTHOR_BY_HAND as c,requiresLiveValue as g,silentlyDropped as a,UNRESOLVED as m,whenAbsent as p}from"./emitGuard.js";const r={database:"DatabaseFactory",storage:"StorageFactory",compute:"ComputeFactory",messaging:"MessagingFactory",cdn:"CdnFactory",network:"NetworkFactory",pattern:"PatternFactory","vpc-peer":"VpcPeerFactory","vpc-peer-accepter":"VpcPeerAccepterFactory","cross-plan-connection":"CrossPlanConnectionFactory",organisation:"OrganisationFactory",buildkite:"BuildkiteFactory"};function s(e){const{name:t,...i}=e.shape;return d.object(i).partial().strict()}n(s,"fragmentOf");const I=s(A),B=s(M),j=(()=>{const{name:e,...t}=k.shape;return d.object(t).partial().strict()})(),L=s(D),V=s(R),Y=s(E),q=(()=>{const{name:e,type:t,cdn:i,...f}=N.shape,{name:ae,type:re,cdn:oe,...b}=w.shape,{name:se,type:ie,domain:ce,cdn:S,...P}=_.shape;return d.object({...f,...b,...P,cdn:d.union([i,S])}).partial().strict()})(),K=s(W),U=s(O),z=s(T),H=s(F),Q=s(v);function l(e,t){return x({kind:"SemanticQueryError",reason:`StatementTypeEntry.${e} for ${t} is not wired; existing types dispatch through the shared locator/generator.`})}n(l,"notWiredError");function $(e){return{factoryIdentifier:e,findByShape:n(()=>l("locator.findByShape",e),"findByShape"),validateContext:n(()=>l("locator.validateContext",e),"validateContext")}}n($,"createLocator");function J(e){return{build:n(()=>{const t=l("generator.build",e);throw new Error(t.success?"unreachable":t.error.reason)},"build")}}n(J,"createGenerator");const X=a("variableName","`variableName` is a plan-only round-trip key naming the `const <var> =` binding the scaffold emits; no construct reads it."),y=a("extraProperties","`extraProperties` is a plan-only round-trip key: the scaffold flattens each `{ key, sourceText }` entry into a sibling property, and no construct reads the array."),u="the connection keys are scaffold inputs, not construct props: the scaffold expands them into environment variables and a `connections: [...]` array, and the compute constructs read none of them.",Z=[{property:"deployment",refuseWhen:n(e=>(e.type==="lambda"||e.deployment!==void 0)&&e.deployment!=="container"&&e.code!==m,"refuseWhen"),reason:"a code-deployed Lambda requires `code: Code`, a CDK object built by `Code.fromAsset(...)` that no flag value can carry, so the statement takes the whole app's synth down with `Cannot read properties of undefined (reading 'bind')` \u2014 naming no resource. Use `--deployment container`, which is fully expressible, or write this compute in infrastructure.ts by hand."},a("codePath","`codePath` is the scaffold's input to `Code.fromAsset(...)`; no compute construct reads it, and a container Lambda takes its code from the image."),g("runtime","the construct expects a CDK `Runtime`, not a version string, and a container Lambda takes its runtime from the image (`Runtime.FROM_IMAGE`) regardless."),g("architecture","the construct expects a CDK `Architecture`, not a string: `--architecture ARM_64` emits an EMPTY `Architectures` list, whereas omitting the flag emits the correct default."),a("memory","the Lambda construct reads `memorySize`, so `--memory 1024` deploys a function at the 128 MB default."),a("ssmSecrets","the Lambda construct reads `secrets`, so `--ssmSecrets` deploys a function with no SSM wiring and no secrets environment at all."),a("scheduleExpression","`scheduleExpression` is not a compute prop: the scaffold turns it into a SEPARATE `app.addSchedule(...)` statement, which this command cannot emit."),a("needsConnection",u),a("connectedDatabase",u),a("connectedStorage",u),a("connectedMessaging",u),X,y],ee=[{property:"originType",refuseWhen:p("originType"),reason:"`Cdn` selects its origin implementation from an `originType` discriminator that the CDN vocabulary does not carry, so a distribution built from CDN properties throws `Unsupported CDN origin type: undefined` the moment `app.addCdn` materialises it. "+c},{property:"originType",refuseWhen:n(e=>e.originType==="s3"&&e.bucket!==m,"refuseWhen"),reason:"an s3 origin needs `bucket` to be an `IBucket` or a Fjall `Storage` \u2014 a live construct, not a name, and not a string; omitting it throws `Cannot read properties of undefined (reading 'bucketRegionalDomainName')` at synth. "+c},{property:"originType",refuseWhen:n(e=>e.originType==="alb"&&e.loadBalancer!==m,"refuseWhen"),reason:'an alb origin needs `loadBalancer` to be an `IApplicationLoadBalancer` or an ECS compute \u2014 a live construct, not a name, and not a string; a string reaches CloudFormation as `Supplied properties not correct for "OriginProperty"`. '+c},{property:"behaviours",refuseWhen:n(e=>Array.isArray(e.behaviours)&&e.behaviours.some(t=>G(t)&&t.originRef!==void 0),"refuseWhen"),reason:"the plan's `behaviours[].originRef` names another planned resource, while the construct's behaviour takes a live origin object; the plan shape throws `Cannot read properties of undefined (reading 'computeType')` at synth. "+c},a("customDomain","the distribution reads `domainNames`, so `--customDomain` deploys a distribution with no alias."),a("defaultOriginRef","`defaultOriginRef` names another planned resource for the scaffold to resolve into a live origin; no CDN construct reads it."),y],te=[{property:"name",refuseWhen:p("name"),reason:"every pattern construct requires a `name` PROPERTY in addition to its construct id, and `fjall add --name` binds the construct id, so no invocation can deliver it \u2014 `toPascalCase(props.name)` throws at synth and takes the whole app down. "+c},{property:"type",refuseWhen:p("type"),reason:"`PatternFactory.build` reads `PATTERN_REGISTRY[props.type]` before it even returns the thunk, and the pattern vocabulary carries no `type` discriminator. "+c}],ne=[{property:"peerAppName",refuseWhen:p("peerAppName"),reason:"`peerAppName` is required: it is the SSM prefix every remote lookup is built from, and omitting it does NOT fail \u2014 synth succeeds and the app deploys a peering connection pointed at `/fjall/default/undefined/vpc-id`. Pass `--peerAppName <remote app>`."},{property:"peerAccountId",refuseWhen:p("peerAccountId"),reason:"`peerAccountId` is required: omitting it does NOT fail, it deploys a VPC peering connection with no `PeerOwnerId`. Pass `--peerAccountId <12-digit account>`."}];function o(e,t,i={}){return{factoryIdentifier:e,locator:$(e),generator:J(e),schemaFragment:t,...i}}n(o,"createEntry");const h={database:o(r.database,I,{emitWrapper:{appMethod:"addDatabase"}}),storage:o(r.storage,B,{emitWrapper:{appMethod:"addStorage"}}),compute:o(r.compute,j,{emitWrapper:{appMethod:"addCompute"},emitGuard:Z}),messaging:o(r.messaging,L,{emitWrapper:{appMethod:"addMessaging"}}),cdn:o(r.cdn,V,{emitWrapper:{appMethod:"addCdn"},emitGuard:ee}),network:o(r.network,Y,{emitWrapper:{appMethod:"addNetwork"}}),pattern:o(r.pattern,q,{emitWrapper:{appMethod:"addPattern"},emitGuard:te}),"vpc-peer":o(r["vpc-peer"],K,{emitWrapper:{appMethod:"addVpcPeer"},emitGuard:ne}),"vpc-peer-accepter":o(r["vpc-peer-accepter"],U,{emitWrapper:{appMethod:"addVpcPeerAccepter"}}),"cross-plan-connection":o(r["cross-plan-connection"],z),organisation:o(r.organisation,H),buildkite:o(r.buildkite,Q,{emitWrapper:{appMethod:"addBuildkite",propsOverloadConstructId:"Buildkite"}})},ge=Object.keys(h);function ye(e){const t=Object.keys(h);for(const i of t)if(h[i].factoryIdentifier===e)return i}n(ye,"findTypeByIdentifier");export{ge as REGISTERED_STATEMENT_TYPES,h as STATEMENT_REGISTRY,ye as findTypeByIdentifier};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var m=Object.defineProperty;var c=(e,n)=>m(e,"name",{value:n,configurable:!0});import{success as
|
|
2
|
-
`);let t,s=300;const i=[],r=[],o=[];for(const f of n){const l=f.trim();if(l===""||l.startsWith(";"))continue;if(l.toUpperCase().startsWith(d.FJALL_DELEGATE)){const a=$(l);a&&r.push(a);continue}const p=R(l);if(p==="")continue;const u=j(p);if(u.length===0)continue;const h=u[0].toUpperCase();if(h===d.ORIGIN){if(u.length<2)continue;t=C(u[1]);continue}if(h===d.TTL){if(u.length<2)continue;s=parseInt(u[1],10);continue}if(h===d.FJALL_CERT){const a=S(u);a&&o.push(a);continue}const g=w(u);g&&i.push(g)}return t?
|
|
1
|
+
var m=Object.defineProperty;var c=(e,n)=>m(e,"name",{value:n,configurable:!0});import{success as A,failure as I}from"../types/Result.js";import{DnsRecordTypeSchema as T,BIND_DIRECTIVES as d,ALIAS_PREFIX as E}from"./types.js";const v=new Set(T.options);function L(e){return v.has(e.toUpperCase())}c(L,"isRecordType");function C(e){return e.endsWith(".")?e.slice(0,-1):e}c(C,"stripTrailingDot");function R(e){let n=!1;for(let t=0;t<e.length;t++)if(e[t]==='"')n=!n;else if(e[t]===";"&&!n)return e.slice(0,t).trimEnd();return e}c(R,"stripInlineComment");function D(e,n){const t=e.slice(n).join(" "),s=[];let i="",r=!1;for(const o of t)o==='"'?(r&&(s.push(i),i=""),r=!r):r&&(i+=o);return s.join(" ")}c(D,"parseTxtValue");function $(e){const n=/;\s*auto\s*$/.test(e),s=e.replace(/;\s*auto\s*$/,"").trim().match(/^\$FJALL-DELEGATE\s+(\S+)\s+TO\s+(\S+)$/i);if(s)return{subdomain:s[1],targetAccount:s[2],auto:n}}c($,"parseDelegateDirective");function S(e){if(e.length<2)return;const n=e[1],t=e.slice(2);return{domainName:n,subjectAlternativeNames:t}}c(S,"parseCertDirective");function j(e){const n=[];let t="",s=!1;for(const i of e)i==='"'?(s=!s,t+=i):/\s/.test(i)&&!s?t.length>0&&(n.push(t),t=""):t+=i;return t.length>0&&n.push(t),n}c(j,"tokenise");function w(e){if(e.length<2)return;let n=0;const t=e[n++];let s,i;for(;n<e.length&&i===void 0;){const o=e[n].toUpperCase();if(o==="IN")n++;else if(L(o))i=o,n++;else if(/^\d+$/.test(e[n]))s=parseInt(e[n],10),n++;else return}if(!i)return;const r=e.slice(n);switch(i){case"MX":{if(r.length<2)return;const o=parseInt(r[0],10),f=r.slice(1).join(" ");return{name:t,type:i,ttl:s,value:f,priority:o}}case"SRV":{if(r.length<4)return;const o=parseInt(r[0],10),f=parseInt(r[1],10),l=parseInt(r[2],10),p=r[3];return{name:t,type:i,ttl:s,value:p,priority:o,weight:f,port:l}}case"TXT":{const o=D(e,n);return{name:t,type:i,ttl:s,value:o}}case"CAA":{const o=r.join(" ");return{name:t,type:i,ttl:s,value:o}}case"A":case"AAAA":{if(r.length===0)return;if(r[0].toUpperCase()==="ALIAS"){if(r.length<2)return;const f=r.slice(1).join(" ");return{name:t,type:i,ttl:s,value:`${E}${f}`}}return{name:t,type:i,ttl:s,value:r[0]}}default:return r.length===0?void 0:{name:t,type:i,ttl:s,value:r[0]}}}c(w,"parseRecord");function U(e){const n=e.split(`
|
|
2
|
+
`);let t,s=300;const i=[],r=[],o=[];for(const f of n){const l=f.trim();if(l===""||l.startsWith(";"))continue;if(l.toUpperCase().startsWith(d.FJALL_DELEGATE)){const a=$(l);a&&r.push(a);continue}const p=R(l);if(p==="")continue;const u=j(p);if(u.length===0)continue;const h=u[0].toUpperCase();if(h===d.ORIGIN){if(u.length<2)continue;t=C(u[1]);continue}if(h===d.TTL){if(u.length<2)continue;s=parseInt(u[1],10);continue}if(h===d.FJALL_CERT){const a=S(u);a&&o.push(a);continue}const g=w(u);g&&i.push(g)}return t?A({origin:t,ttl:s,records:i,delegations:r,certificates:o}):I(new Error("Missing $ORIGIN directive"))}c(U,"parseZoneFile");function _(e,n){if(!e.startsWith("fjall:"))return;const t=e.split(":");if(t.length<3)return;const s=t[1],i=t[2],r=`${s}:${i}`;return n.get(r)??n.get(e)}c(_,"resolveAlias");export{U as parseZoneFile,_ as resolveAlias};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var u=Object.defineProperty;var
|
|
1
|
+
var u=Object.defineProperty;var i=(t,n)=>u(t,"name",{value:n,configurable:!0});import{BIND_DIRECTIVES as $}from"./types.js";function l(t,n){return t.length>=n?t:t+" ".repeat(n-t.length)}i(l,"padRight");function o(t,n){const s=l(t.name,24),e=t.ttl!==void 0&&t.ttl!==n?`${t.ttl} `:"";switch(t.type){case"MX":return`${s} ${e}IN MX ${t.priority??10} ${t.value}`;case"SRV":return`${s} ${e}IN SRV ${t.priority??0} ${t.weight??0} ${t.port??0} ${t.value}`;case"TXT":return`${s} ${e}IN TXT "${t.value}"`;case"CAA":return`${s} ${e}IN CAA ${t.value}`;default:return`${s} ${e}IN ${t.type} ${t.value}`}}i(o,"formatRecord");function h(t){const n=[];if(n.push("; zone.bind \u2014 managed by fjall"),n.push(`${$.ORIGIN} ${t.origin}.`),n.push(`${$.TTL} ${t.ttl}`),n.push(""),t.certificates.length>0){for(const s of t.certificates){const a=[s.domainName,...s.subjectAlternativeNames];n.push(`${$.FJALL_CERT} ${a.join(" ")}`)}n.push("")}if(t.delegations.length>0){for(const s of t.delegations){const a=s.auto?" ; auto":"";n.push(`${$.FJALL_DELEGATE} ${s.subdomain} TO ${s.targetAccount}${a}`)}n.push("")}for(const s of t.records)n.push(o(s,t.ttl));return n.join(`
|
|
2
2
|
`)+`
|
|
3
|
-
`}
|
|
3
|
+
`}i(h,"generateZoneFile");export{h as generateZoneFile};
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
export declare const TypedFjallTargetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3
3
|
kind: z.ZodLiteral<"ecs">;
|
|
4
4
|
appName: z.ZodString;
|
|
5
|
+
computeName: z.ZodOptional<z.ZodString>;
|
|
5
6
|
}, z.core.$strict>, z.ZodObject<{
|
|
6
7
|
kind: z.ZodLiteral<"cdn">;
|
|
7
8
|
appName: z.ZodString;
|
|
@@ -65,6 +66,7 @@ export declare const ParsedAliasRecordSchema: z.ZodObject<{
|
|
|
65
66
|
target: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
66
67
|
kind: z.ZodLiteral<"ecs">;
|
|
67
68
|
appName: z.ZodString;
|
|
69
|
+
computeName: z.ZodOptional<z.ZodString>;
|
|
68
70
|
}, z.core.$strict>, z.ZodObject<{
|
|
69
71
|
kind: z.ZodLiteral<"cdn">;
|
|
70
72
|
appName: z.ZodString;
|
|
@@ -102,6 +104,7 @@ export declare const ParsedDnsRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
102
104
|
target: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
103
105
|
kind: z.ZodLiteral<"ecs">;
|
|
104
106
|
appName: z.ZodString;
|
|
107
|
+
computeName: z.ZodOptional<z.ZodString>;
|
|
105
108
|
}, z.core.$strict>, z.ZodObject<{
|
|
106
109
|
kind: z.ZodLiteral<"cdn">;
|
|
107
110
|
appName: z.ZodString;
|
|
@@ -160,6 +163,7 @@ export declare const ParsedDomainRecordsSchema: z.ZodObject<{
|
|
|
160
163
|
target: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
161
164
|
kind: z.ZodLiteral<"ecs">;
|
|
162
165
|
appName: z.ZodString;
|
|
166
|
+
computeName: z.ZodOptional<z.ZodString>;
|
|
163
167
|
}, z.core.$strict>, z.ZodObject<{
|
|
164
168
|
kind: z.ZodLiteral<"cdn">;
|
|
165
169
|
appName: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as e}from"zod";const r=e.discriminatedUnion("kind",[e.object({kind:e.literal("ecs"),appName:e.string()}).strict(),e.object({kind:e.literal("cdn"),appName:e.string()}).strict(),e.object({kind:e.literal("bucket"),bucketName:e.string()}).strict(),e.object({kind:e.literal("custom"),dnsName:e.string(),hostedZoneId:e.string()}).strict()]),m=r.options.map(t=>t.shape.kind.value),a=e.enum(["A","AAAA"]),n=e.enum(["route53","external-delegated","external-records"]),g=e.enum(["zone","full"]),o=e.object({kind:e.literal("standard"),type:e.enum(["A","AAAA","CNAME","MX","TXT","NS","SRV","CAA"]),name:e.string(),value:e.union([e.string(),e.array(e.string())]),ttl:e.number().int().positive().optional()}).strict(),i=e.object({kind:e.literal("alias"),type:a,name:e.string(),target:r}).strict(),s=e.discriminatedUnion("kind",[o,i]),d=e.object({domainName:e.string(),subjectAlternativeNames:e.array(e.string()).optional(),transparencyLogging:e.boolean().optional(),cloudFront:e.boolean().optional()}).strict(),c=e.object({subdomain:e.string(),toAccount:e.string(),auto:e.boolean().optional()}).strict(),p=e.object({zoneName:e.string(),registrar:n,hostedZoneId:e.string().optional(),delegatedSubdomain:e.string().optional(),adoptedNameServers:e.array(e.string().min(1)).min(1).optional(),records:e.array(s),certificates:e.array(d),delegations:e.array(c)}).strict().refine(t=>t.registrar!=="external-delegated"||t.delegatedSubdomain!==void 0,{message:"external-delegated requires delegatedSubdomain"}).refine(t=>t.registrar!=="external-records"||t.delegations.length===0,{message:"external-records forbids delegations"}).refine(t=>t.registrar==="external-delegated"||t.adoptedNameServers===void 0,{message:"adoptedNameServers requires registrar external-delegated"}).refine(t=>t.registrar!=="external-delegated"||t.hostedZoneId===void 0==(t.adoptedNameServers===void 0),{message:"external-delegated adoption requires hostedZoneId and adoptedNameServers together (both-or-neither)"});export{a as AliasRecordTypeSchema,g as DomainDeployPhaseSchema,n as DomainRegistrarSchema,i as ParsedAliasRecordSchema,d as ParsedCertificateSchema,s as ParsedDnsRecordSchema,p as ParsedDomainRecordsSchema,o as ParsedStandardRecordSchema,c as ParsedSubdomainDelegationSchema,m as TYPED_FJALL_TARGET_KINDS,r as TypedFjallTargetSchema};
|
|
1
|
+
import{z as e}from"zod";const r=e.discriminatedUnion("kind",[e.object({kind:e.literal("ecs"),appName:e.string(),computeName:e.string().min(1).optional()}).strict(),e.object({kind:e.literal("cdn"),appName:e.string()}).strict(),e.object({kind:e.literal("bucket"),bucketName:e.string()}).strict(),e.object({kind:e.literal("custom"),dnsName:e.string(),hostedZoneId:e.string()}).strict()]),m=r.options.map(t=>t.shape.kind.value),a=e.enum(["A","AAAA"]),n=e.enum(["route53","external-delegated","external-records"]),g=e.enum(["zone","full"]),o=e.object({kind:e.literal("standard"),type:e.enum(["A","AAAA","CNAME","MX","TXT","NS","SRV","CAA"]),name:e.string(),value:e.union([e.string(),e.array(e.string())]),ttl:e.number().int().positive().optional()}).strict(),i=e.object({kind:e.literal("alias"),type:a,name:e.string(),target:r}).strict(),s=e.discriminatedUnion("kind",[o,i]),d=e.object({domainName:e.string(),subjectAlternativeNames:e.array(e.string()).optional(),transparencyLogging:e.boolean().optional(),cloudFront:e.boolean().optional()}).strict(),c=e.object({subdomain:e.string(),toAccount:e.string(),auto:e.boolean().optional()}).strict(),p=e.object({zoneName:e.string(),registrar:n,hostedZoneId:e.string().optional(),delegatedSubdomain:e.string().optional(),adoptedNameServers:e.array(e.string().min(1)).min(1).optional(),records:e.array(s),certificates:e.array(d),delegations:e.array(c)}).strict().refine(t=>t.registrar!=="external-delegated"||t.delegatedSubdomain!==void 0,{message:"external-delegated requires delegatedSubdomain"}).refine(t=>t.registrar!=="external-records"||t.delegations.length===0,{message:"external-records forbids delegations"}).refine(t=>t.registrar==="external-delegated"||t.adoptedNameServers===void 0,{message:"adoptedNameServers requires registrar external-delegated"}).refine(t=>t.registrar!=="external-delegated"||t.hostedZoneId===void 0==(t.adoptedNameServers===void 0),{message:"external-delegated adoption requires hostedZoneId and adoptedNameServers together (both-or-neither)"});export{a as AliasRecordTypeSchema,g as DomainDeployPhaseSchema,n as DomainRegistrarSchema,i as ParsedAliasRecordSchema,d as ParsedCertificateSchema,s as ParsedDnsRecordSchema,p as ParsedDomainRecordsSchema,o as ParsedStandardRecordSchema,c as ParsedSubdomainDelegationSchema,m as TYPED_FJALL_TARGET_KINDS,r as TypedFjallTargetSchema};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Shared helper functions used across all generation modules.
|
|
5
5
|
*/
|
|
6
|
+
import type { ProjectedProp } from "../projection/types.js";
|
|
6
7
|
import type { IdentifierValue, ExpressionValue, CallValue, SpecialValue } from "../schemas/resourceSchemas.js";
|
|
7
8
|
export type { IdentifierValue, ExpressionValue, CallValue, SpecialValue };
|
|
8
9
|
export { toPascalCase, toKebab, toValidDatabaseName } from "@fjall/util";
|
|
@@ -76,6 +77,12 @@ export declare function resolveResourceVariable(plan: {
|
|
|
76
77
|
* Simple objects (few primitive values) are kept on one line.
|
|
77
78
|
*/
|
|
78
79
|
export declare function formatValue(value: unknown, baseIndent?: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Render projected construct props as the body of an object literal —
|
|
82
|
+
* `\n<indent>key: value` per prop, comma-separated, no trailing comma. The
|
|
83
|
+
* caller supplies the surrounding braces and whatever it appends after.
|
|
84
|
+
*/
|
|
85
|
+
export declare function emitProjectedProps(props: ReadonlyArray<ProjectedProp>, indent?: string): string;
|
|
79
86
|
type PropertyFormat = "raw" | "string" | "object" | "boolean-or-object";
|
|
80
87
|
/**
|
|
81
88
|
* Build a property string for code generation.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
${
|
|
1
|
+
var u=Object.defineProperty;var n=(e,t)=>u(e,"name",{value:t,configurable:!0});import{toPascalCase as P,toKebab as T,toValidDatabaseName as h}from"@fjall/util";function c(e){return JSON.stringify(e)}n(c,"escapeStringLiteral");function g(e){return e.map(c).join(", ")}n(g,"formatStringArray");const b="import:SharedAlarmTopicArn";function _(e=" "){return`
|
|
2
|
+
${e}...(getConfig().environment === "production" ? { alertsTopic: ${c(b)} } : {}),`}n(_,"emitProductionAlertsTopicSpread");function l(e){if(typeof e!="object"||e===null)return!1;const t=e;return typeof t.__identifier=="string"||typeof t.__expression=="string"||typeof t.__call=="string"}n(l,"isSpecialValue");function m(e){return e.replace(/[^a-zA-Z0-9]/g," ").split(" ").map((t,r)=>r===0?t.charAt(0).toLowerCase()+t.slice(1):t.charAt(0).toUpperCase()+t.slice(1)).join("")}n(m,"toVariableName");function $(e){return e.variableName??m(e.name)}n($,"getVariableName");function x(e,t){for(const r of e.database)if(r.name===t&&r.variableName)return r.variableName;for(const r of e.s3)if(r.name===t&&r.variableName)return r.variableName;for(const r of e.compute)if(r.name===t&&r.variableName)return r.variableName;for(const r of e.dynamodb??[])if(r.name===t&&r.variableName)return r.variableName;for(const r of e.sqs??[])if(r.name===t&&r.variableName)return r.variableName;return m(t)}n(x,"resolveResourceVariable");function d(e){const t=Object.entries(e);return t.length===0?!0:t.length>1?!1:t.every(([,r])=>typeof r=="string"||typeof r=="number"||typeof r=="boolean"||r===null)}n(d,"isSimpleObject");function f(e,t=" "){if(e==null)return"undefined";if(typeof e=="string")return JSON.stringify(e);if(typeof e=="number"||typeof e=="boolean")return String(e);if(l(e)){if("__identifier"in e)return e.__identifier;if("__expression"in e)return e.__expression;if("__call"in e)return e.__call}if(Array.isArray(e))return`[${e.map(r=>f(r,t)).join(", ")}]`;if(typeof e=="object"){const r=Object.entries(e).filter(([,a])=>a!==void 0);if(d(e)){const a=r.map(([s,p])=>`${s}: ${f(p,t)}`).join(", ");return a?`{ ${a} }`:"{}"}const o=t+" ",i=r.map(([a,s])=>`${o}${a}: ${f(s,o)}`).join(`,
|
|
3
3
|
`);return i?`{
|
|
4
4
|
${i}
|
|
5
|
-
${
|
|
6
|
-
|
|
7
|
-
${
|
|
5
|
+
${t}}`:"{}"}return JSON.stringify(e)}n(f,"formatValue");function j(e,t=" "){return e.map(r=>{const o=r.value.kind==="expression"?r.value.source:f(r.value.value,t);return`
|
|
6
|
+
${t}${r.key}: ${o}`}).join(",")}n(j,"emitProjectedProps");function N(e,t,r,o="raw"){if(!e)return"";let i;switch(o){case"string":i=c(String(r));break;case"object":i=f(r);break;case"boolean-or-object":i=r===!1?"false":f(r);break;default:i=String(r)}return`
|
|
7
|
+
${t}: ${i},`}n(N,"buildProperty");function S(e,t=" "){return e?.length?e.map(r=>`
|
|
8
|
+
${t}${r.key}: ${r.sourceText},`).join(""):""}n(S,"emitExtraProperties");export{b as PRODUCTION_ALERTS_TOPIC_IMPORT,N as buildProperty,S as emitExtraProperties,_ as emitProductionAlertsTopicSpread,j as emitProjectedProps,c as escapeStringLiteral,g as formatStringArray,f as formatValue,$ as getVariableName,l as isSpecialValue,x as resolveResourceVariable,T as toKebab,P as toPascalCase,h as toValidDatabaseName,m as toVariableName};
|
|
@@ -1,50 +1,44 @@
|
|
|
1
|
-
var g=Object.defineProperty;var s=(e,t)=>g(e,"name",{value:t,configurable:!0});import{buildProperty as
|
|
2
|
-
`:"",
|
|
3
|
-
StorageFactory.build(${r
|
|
1
|
+
var g=Object.defineProperty;var s=(e,t)=>g(e,"name",{value:t,configurable:!0});import{projectPlanToConstructProps as $}from"../projection/index.js";import{buildProperty as i,getVariableName as m,emitExtraProperties as u,emitProductionAlertsTopicSpread as b,emitProjectedProps as P,escapeStringLiteral as o}from"./common.js";function x(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}s(x,"generateS3BucketProps");function K(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)))}s(K,"s3NeedsVariable");function R(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),a=K(r,e),l=e.database.length>0||n>0?`
|
|
2
|
+
`:"",p=x(r),y=a?`const ${c} = `:"",f=u(r.extraProperties);p||f?t+=`${l}${y}app.addStorage(
|
|
3
|
+
StorageFactory.build(${o(r.name)}, {${p}${f}
|
|
4
4
|
})
|
|
5
5
|
);
|
|
6
|
-
`:t+=`${
|
|
7
|
-
StorageFactory.build(${r
|
|
6
|
+
`:t+=`${l}${y}app.addStorage(
|
|
7
|
+
StorageFactory.build(${o(r.name)}, {})
|
|
8
8
|
);
|
|
9
|
-
`}return t}s(
|
|
10
|
-
const ${
|
|
11
|
-
DatabaseFactory.build(${
|
|
9
|
+
`}return t}s(R,"generateS3Code");function T(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.addDatabase(
|
|
11
|
+
DatabaseFactory.build(${o(n.name)}, {
|
|
12
12
|
type: "DynamoDB",
|
|
13
13
|
partitionKey: {
|
|
14
|
-
name: ${
|
|
15
|
-
type: ${
|
|
14
|
+
name: ${o(n.partitionKey.name)},
|
|
15
|
+
type: ${o(n.partitionKey.type)},
|
|
16
16
|
}`,n.sortKey&&(t+=`,
|
|
17
17
|
sortKey: {
|
|
18
|
-
name: ${
|
|
19
|
-
type: ${
|
|
20
|
-
}`),n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0){const
|
|
21
|
-
indexName: ${
|
|
18
|
+
name: ${o(n.sortKey.name)},
|
|
19
|
+
type: ${o(n.sortKey.type)},
|
|
20
|
+
}`),n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0){const c=n.globalSecondaryIndexes.map(a=>{let d=`{
|
|
21
|
+
indexName: ${o(a.indexName)},
|
|
22
22
|
partitionKey: {
|
|
23
|
-
name: ${
|
|
24
|
-
type: ${
|
|
25
|
-
},`;return a.sortKey&&(
|
|
23
|
+
name: ${o(a.partitionKey.name)},
|
|
24
|
+
type: ${o(a.partitionKey.type)},
|
|
25
|
+
},`;return a.sortKey&&(d+=`
|
|
26
26
|
sortKey: {
|
|
27
|
-
name: ${
|
|
28
|
-
type: ${
|
|
29
|
-
},`),
|
|
30
|
-
}`,
|
|
27
|
+
name: ${o(a.sortKey.name)},
|
|
28
|
+
type: ${o(a.sortKey.type)},
|
|
29
|
+
},`),d+=`
|
|
30
|
+
}`,d}).join(`,
|
|
31
31
|
`);t+=`,
|
|
32
32
|
globalSecondaryIndexes: [
|
|
33
|
-
${
|
|
33
|
+
${c}
|
|
34
34
|
]`}n.ttlAttribute&&(t+=`,
|
|
35
|
-
ttlAttribute: ${
|
|
36
|
-
stream: true`),t+=
|
|
35
|
+
ttlAttribute: ${o(n.ttlAttribute)}`),n.stream&&(t+=`,
|
|
36
|
+
stream: true`),t+=u(n.extraProperties),t+=`
|
|
37
37
|
})
|
|
38
38
|
);
|
|
39
|
-
`}return t}s(
|
|
39
|
+
`}return t}s(T,"generateDynamoDBCode");function S(e,t){return t.compute.some(n=>n.connectedMessaging?.includes(e.name))}s(S,"sqsNeedsVariable");function V(e){if(!e.sqs||e.sqs.length===0)return"";let t="";for(const n of e.sqs){const r=m(n),a=S(n,e)?`const ${r} = `:"",{props:d}=$("messaging",{queueType:n.queueType,visibilityTimeout:n.visibilityTimeout,retentionPeriod:n.retentionPeriod,...n.contentBasedDeduplication===!0&&{contentBasedDeduplication:!0},removalPolicy:n.removalPolicy});t+=`
|
|
40
40
|
${a}app.addMessaging(
|
|
41
|
-
MessagingFactory.build(${
|
|
42
|
-
type: "queue",
|
|
43
|
-
queueType: ${r(n.queueType)}`,n.visibilityTimeout!==void 0&&(t+=`,
|
|
44
|
-
visibilityTimeout: ${n.visibilityTimeout}`),n.retentionPeriod!==void 0&&(t+=`,
|
|
45
|
-
messageRetentionPeriod: ${n.retentionPeriod}`),n.contentBasedDeduplication&&(t+=`,
|
|
46
|
-
contentBasedDeduplication: true`),n.removalPolicy!==void 0&&(t+=`,
|
|
47
|
-
removalPolicy: ${r(n.removalPolicy)}`),t+=",",t+=l(n.extraProperties),t+=$(),t+=`
|
|
41
|
+
MessagingFactory.build(${o(n.name)}, {${P(d)}`,t+=",",t+=u(n.extraProperties),t+=b(),t+=`
|
|
48
42
|
})
|
|
49
43
|
);
|
|
50
|
-
`}return t}s(
|
|
44
|
+
`}return t}s(V,"generateSQSCode");export{T as generateDynamoDBCode,R as generateS3Code,V as generateSQSCode,K as s3NeedsVariable,S as sqsNeedsVariable};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { planApplicationResources, toUserServiceConfigs, type GenerationOptions, generateInfrastructureFromPlan, } from "./resourcePlanning.js";
|
|
1
|
+
export { planApplicationResources, planServiceFromTierPreset, toUserServiceConfigs, type GenerationOptions, generateInfrastructureFromPlan, } from "./resourcePlanning.js";
|
|
2
2
|
export { type OpenNextResourceOptions, planOpenNextResources, } from "./openNextPlanning.js";
|
|
3
3
|
export { type StaticSiteResourceOptions, planStaticSiteResources, } from "./staticSitePlanning.js";
|
|
4
4
|
export { type ConnectionType, applyComputeConnections, applyServiceConnections, } from "./resourceConnections.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{planApplicationResources as
|
|
1
|
+
import{planApplicationResources as o,planServiceFromTierPreset as t,toUserServiceConfigs as n,generateInfrastructureFromPlan as a}from"./resourcePlanning.js";import{planOpenNextResources as s}from"./openNextPlanning.js";import{planStaticSiteResources as c}from"./staticSitePlanning.js";import{applyComputeConnections as u,applyServiceConnections as m}from"./resourceConnections.js";import{addResourceToPlan as x,validateResourceAddition as R,listAvailableResources as d}from"./resourceAddition.js";import{generateResourceChange as C}from"./generateResourceChange.js";export{x as addResourceToPlan,u as applyComputeConnections,m as applyServiceConnections,a as generateInfrastructureFromPlan,C as generateResourceChange,d as listAvailableResources,o as planApplicationResources,s as planOpenNextResources,t as planServiceFromTierPreset,c as planStaticSiteResources,n as toUserServiceConfigs,R as validateResourceAddition};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type UserServiceConfig, type AppType } from "../presets/tierPresets.js";
|
|
1
|
+
import { type TierEcsServiceConfig, type UserServiceConfig, type AppType } from "../presets/tierPresets.js";
|
|
2
2
|
import { type Result } from "../types/Result.js";
|
|
3
|
-
import type { ApplicationResourcePlan } from "../schemas/resourceSchemas.js";
|
|
3
|
+
import type { ApplicationResourcePlan, EcsServiceConfig } from "../schemas/resourceSchemas.js";
|
|
4
4
|
import type { ApplicationServiceConfig } from "../schemas/computeSchemas.js";
|
|
5
5
|
/**
|
|
6
6
|
* Adapt the wire-level service config (`ApplicationServiceConfig`, validated by
|
|
@@ -14,6 +14,18 @@ export declare function planApplicationResources(appName: string, appType: AppTy
|
|
|
14
14
|
snapshotIdentifier?: string;
|
|
15
15
|
snapshotUsername?: string;
|
|
16
16
|
}): ApplicationResourcePlan;
|
|
17
|
+
/**
|
|
18
|
+
* The one translation from a tier preset's service entry to the plan shape.
|
|
19
|
+
*
|
|
20
|
+
* The two differ in exactly one place: the preset carries `minCapacity` /
|
|
21
|
+
* `maxCapacity` flat, the plan nests them under `scaling`. Every other key
|
|
22
|
+
* passes through, so a new preset field reaches the plan without touching this
|
|
23
|
+
* function. Exported because anything deriving a plan from a tier — the app
|
|
24
|
+
* planner below, the dogfood deploy-test suites — must apply the same rule, and
|
|
25
|
+
* a second copy of it would drift silently: an unnested `minCapacity` is an
|
|
26
|
+
* excess property the plan schema rejects only at parse time.
|
|
27
|
+
*/
|
|
28
|
+
export declare function planServiceFromTierPreset(tierService: TierEcsServiceConfig): EcsServiceConfig;
|
|
17
29
|
export interface GenerationOptions {
|
|
18
30
|
/** Resource name mapping from old names to new names (for custom code repositioning) */
|
|
19
31
|
resourceMapping?: Map<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var b=Object.defineProperty;var
|
|
1
|
+
var b=Object.defineProperty;var i=(e,n)=>b(e,"name",{value:n,configurable:!0});import{TIER_PRESETS as l,getDefaultDatabaseTypeForTier as P,applyTierDefaultsToServices as k}from"../presets/tierPresets.js";import{COMPUTE_TYPE as D,DEFAULT_CONTAINER_PORT as T}from"../schemas/constants.js";import{success as f,failure as h}from"../types/Result.js";import{injectCustomCodeBlocks as p}from"../ast/mutation/astCodeInjection.js";import{toVariableName as m,toValidDatabaseName as v,generateImports as S,generateAppInit as E,generateTags as R,generateNetworkCode as C,generateDatabaseCode as y,generateClickHouseCode as I,generateS3Code as w,generateDynamoDBCode as x,generateSQSCode as A,generateComputeCode as B,generateCDNCode as U,collectCdnReferencedResources as j,usesPatternApproach as F,generatePatternCodeWithComments as _}from"../generation/index.js";function J(e){return e?.map(n=>({name:n.name,...n.serviceType!==void 0&&{serviceType:n.serviceType},...n.docker!==void 0&&{docker:n.docker},...n.containerPort!==void 0&&{containerPort:n.containerPort},...n.needsDatabaseConnection!==void 0&&{needsDatabaseConnection:n.needsDatabaseConnection},...n.routing!==void 0&&{routing:n.routing}}))}i(J,"toUserServiceConfigs");function K(e,n,r=!0,c,t){const o={appName:e,type:n,database:[],s3:[],compute:[]};if(n==="custom")return o;const s=n,a=l[s];return{...o,database:$(e,a,s,r,t),compute:W(e,a,s,r,c),network:a.network,backup:a.backup}}i(K,"planApplicationResources");function $(e,n,r,c,t){const o=P(r),s=n.database[o];return!c||s===null?[]:[{name:e,type:o,databaseName:v(e),variableName:`${m(e)}Database`,...s,...t?.snapshotIdentifier!==void 0&&{snapshotIdentifier:t.snapshotIdentifier},...t?.snapshotUsername!==void 0&&{snapshotUsername:t.snapshotUsername}}]}i($,"buildDatabasePlan");function N(e,n){if(!(e===void 0&&n===void 0))return{scaling:{...e!==void 0&&{minCapacity:e},...n!==void 0&&{maxCapacity:n}}}}i(N,"buildScalingConfig");function H(e){const{minCapacity:n,maxCapacity:r,...c}=e;return{...c,...N(n,r)}}i(H,"planServiceFromTierPreset");function M(e,n){const r=H(e),c=n?.serviceType==="worker",t=n?.containerPort??T,o=n?.docker;return{...r,...o?.path!==void 0&&{docker:{path:o.path,...o.context!==void 0&&{context:o.context},...o.target!==void 0&&{target:o.target}}},...n?.needsDatabaseConnection!==void 0&&{needsDatabaseConnection:n.needsDatabaseConnection},containers:c?[{}]:[{port:t}]}}i(M,"buildServiceEntry");function V(e,n){return n||e?.directAccess===!0?e:{...e,loadBalancer:!1}}i(V,"resolveClusterConfig");function W(e,n,r,c,t){const o=n.compute.ecs,a=(t&&t.length>0?k(r,t):o.services.map((u,d)=>({...u,name:d===0?"api":`service-${d+1}`}))).map((u,d)=>M(u,t?.[d])),g=a.some(u=>u.containers?.some(d=>d.port!==void 0));return[{name:e,type:D.ECS,needsConnection:c,connectedDatabase:c?[e]:void 0,variableName:`${m(e)}Compute`,cluster:V(o.cluster,g),services:a}]}i(W,"buildComputePlan");function O(e,n){const r=[S(e),E(e),R(e)];if(F(e))r.push(_(e),C(e));else{const t=j(e);r.push(C(e),y(e),I(e),w(e),x(e),A(e),B(e,t),U(e))}const c=r.join("");if(e.customCodeBlocks&&e.customCodeBlocks.length>0){const t=p(c,e.customCodeBlocks,n?.resourceMapping);return t.success?f(t.content):h(new Error(`Custom code injection failed: ${t.error??"unknown error"}`))}return f(c)}i(O,"generateInfrastructureFromPlan");export{O as generateInfrastructureFromPlan,K as planApplicationResources,H as planServiceFromTierPreset,J as toUserServiceConfigs};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { projectPlanToConstructProps } from "./project.js";
|
|
2
|
+
export { isProjectableType, TYPE_PROJECTIONS, type ProjectableType, } from "./tables.js";
|
|
3
|
+
export type { PlanKeyRule, Projection, ProjectionContext, ProjectedProp, ProjectedValue, TypeProjection, UnprojectableProp, } from "./types.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{projectPlanToConstructProps as e}from"./project.js";import{isProjectableType as p,TYPE_PROJECTIONS as P}from"./tables.js";export{P as TYPE_PROJECTIONS,p as isProjectableType,e as projectPlanToConstructProps};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ProjectableType } from "./tables.js";
|
|
2
|
+
import type { Projection, ProjectionContext } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Project a resource-plan fragment onto its construct's props.
|
|
5
|
+
*
|
|
6
|
+
* Keys with no rule pass through under their own name — the two vocabularies
|
|
7
|
+
* agree far more often than they disagree, and enumerating the agreements
|
|
8
|
+
* would be a second inventory to keep in step with the schemas.
|
|
9
|
+
*
|
|
10
|
+
* `undefined` values are skipped rather than emitted: a construct prop
|
|
11
|
+
* explicitly set to `undefined` is not the same as an absent one for a
|
|
12
|
+
* `.strict()` Zod props schema, and the plan's optional keys arrive as
|
|
13
|
+
* `undefined` routinely.
|
|
14
|
+
*
|
|
15
|
+
* A fragment key landing on a constant's construct key REPLACES it, in the
|
|
16
|
+
* constant's position. Constants exist to supply what the plan vocabulary
|
|
17
|
+
* cannot say; a caller who says it anyway (a hand-written `type: "queue"`,
|
|
18
|
+
* a round-tripped statement) is not disagreeing with the projection, and
|
|
19
|
+
* emitting the key twice would be a syntax-level duplicate that the last
|
|
20
|
+
* writer silently wins.
|
|
21
|
+
*/
|
|
22
|
+
export declare function projectPlanToConstructProps(type: ProjectableType, fragment: Readonly<Record<string, unknown>>, context?: ProjectionContext): Projection;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var k=Object.defineProperty;var f=(o,s)=>k(o,"name",{value:s,configurable:!0});import{TYPE_PROJECTIONS as y}from"./tables.js";function O(o,s,r={}){const u=y[o],l=r.editingExisting===!0?[]:u.constants??[],t=new Map(l.map(n=>[n.key,n])),i=[];for(const[n,c]of Object.entries(s)){if(c===void 0)continue;const e=u.keys?.[n];if(e===void 0||e.kind==="prop"){const d=e?.as??n;t.set(d,{key:d,value:{kind:"literal",value:c}});continue}if(e.kind==="planOnly"){i.push({key:n,reason:e.reason});continue}const a=e.bind(c,r);if(a===void 0){i.push({key:n,reason:e.reason});continue}const p=e.as??n;t.set(p,{key:p,value:{kind:"expression",source:a}})}return{props:[...t.values()],unprojectable:i}}f(O,"projectPlanToConstructProps");export{O as projectPlanToConstructProps};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-type plan→construct projections.
|
|
3
|
+
*
|
|
4
|
+
* Every entry here was, before this module, a `silentlyDropped` /
|
|
5
|
+
* `requiresLiveValue` rule in `codemod/registry.ts` describing a translation
|
|
6
|
+
* the scaffold generator performed and the codemod could not. The reasons are
|
|
7
|
+
* carried over verbatim where they still apply, because they record what was
|
|
8
|
+
* actually observed to happen at synth — not what the vocabulary suggests.
|
|
9
|
+
*
|
|
10
|
+
* Two plan keys recur on nearly every type and are declared once:
|
|
11
|
+
* `variableName` (the `const <var> =` binding the scaffold emits) and
|
|
12
|
+
* `extraProperties` (round-trip preservation the scaffold flattens into
|
|
13
|
+
* sibling properties). Neither is a construct prop anywhere.
|
|
14
|
+
*
|
|
15
|
+
* `compute`, `cdn`, `pattern` and `vpc-peer` are deliberately ABSENT. Their
|
|
16
|
+
* disagreements are not renames: a CDN origin needs the live `IBucket` or
|
|
17
|
+
* load balancer its sibling resource became, and a compute's four connection
|
|
18
|
+
* keys expand into environment variables plus a whole second statement
|
|
19
|
+
* (`app.addSchedule(...)`). Both need a projection that can carry bindings
|
|
20
|
+
* and emit more than one statement, which is the next increment; until then
|
|
21
|
+
* they keep their `emitGuard` tables and a type is projected or guarded,
|
|
22
|
+
* never both.
|
|
23
|
+
*/
|
|
24
|
+
import type { TypeProjection } from "./types.js";
|
|
25
|
+
export declare const TYPE_PROJECTIONS: {
|
|
26
|
+
readonly messaging: TypeProjection;
|
|
27
|
+
readonly storage: TypeProjection;
|
|
28
|
+
readonly database: TypeProjection;
|
|
29
|
+
readonly network: TypeProjection;
|
|
30
|
+
};
|
|
31
|
+
export type ProjectableType = keyof typeof TYPE_PROJECTIONS;
|
|
32
|
+
export declare function isProjectableType(value: string): value is ProjectableType;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s=Object.defineProperty;var a=(n,t)=>s(n,"name",{value:t,configurable:!0});const r={kind:"planOnly",reason:"`variableName` is a plan-only round-trip key naming the `const <var> =` binding the scaffold emits; no construct reads it."},o={kind:"planOnly",reason:"`extraProperties` is a plan-only round-trip key: the scaffold flattens each `{ key, sourceText }` entry into a sibling property, and no construct reads the array."},e={variableName:r,extraProperties:o},i={constants:[{key:"type",value:{kind:"literal",value:"queue"}}],keys:{retentionPeriod:{kind:"prop",as:"messageRetentionPeriod"},...e}},l={keys:{...e}},p={keys:{engineExpression:{kind:"planOnly",reason:"`engineExpression` carries a raw CDK engine expression for the scaffold to inline; the construct reads `databaseEngine` instead, so a cluster pinned to `DatabaseClusterEngine.auroraMysql(...)` still deploys as aurora-postgresql."},...e}},c={keys:{...e}},y={messaging:i,storage:l,database:p,network:c};function u(n){return Object.prototype.hasOwnProperty.call(y,n)}a(u,"isProjectableType");export{y as TYPE_PROJECTIONS,u as isProjectableType};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plan→construct projection vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* A resource PLAN and a CDK construct's PROPS are two different vocabularies
|
|
5
|
+
* for the same resource. They agree on most keys and disagree on a handful,
|
|
6
|
+
* and every disagreement has been, until now, encoded twice: once in the
|
|
7
|
+
* scaffold generator (which translates on the way out) and once in the
|
|
8
|
+
* codemod's `emitGuard` tables (which refuse what they cannot translate).
|
|
9
|
+
* Two encodings of one fact is drift waiting to happen — and it happened, in
|
|
10
|
+
* the direction that hurts: the guards are what stop `fjall add messaging`
|
|
11
|
+
* and `fjall add cdn` working at all.
|
|
12
|
+
*
|
|
13
|
+
* This module is that encoding, and the codemod reads it for every type in
|
|
14
|
+
* TYPE_PROJECTIONS. The scaffold does NOT yet, except for `messaging`
|
|
15
|
+
* (generation/storage.ts) — storage, database and network still emit their
|
|
16
|
+
* props by hand there, so for those three this is one of two encodings still.
|
|
17
|
+
* Converging the scaffold's remaining emitters is what makes the "single"
|
|
18
|
+
* claim true; until then, a table entry proves the codemod's behaviour and
|
|
19
|
+
* only documents the scaffold's.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* A construct prop's value. `literal` is a plain JS value the emitter
|
|
23
|
+
* serialises; `expression` is TypeScript source spliced in verbatim, which
|
|
24
|
+
* only a caller that can supply live bindings may ask for.
|
|
25
|
+
*/
|
|
26
|
+
export type ProjectedValue = {
|
|
27
|
+
kind: "literal";
|
|
28
|
+
value: unknown;
|
|
29
|
+
} | {
|
|
30
|
+
kind: "expression";
|
|
31
|
+
source: string;
|
|
32
|
+
};
|
|
33
|
+
/** One construct prop, in construct vocabulary. */
|
|
34
|
+
export interface ProjectedProp {
|
|
35
|
+
key: string;
|
|
36
|
+
value: ProjectedValue;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A plan key this context cannot turn into a construct prop, and why. The
|
|
40
|
+
* scaffold ignores these — it consumes such keys through its own paths. The
|
|
41
|
+
* codemod refuses the whole statement, because writing the key would either
|
|
42
|
+
* take synth down or deploy something other than what was asked for.
|
|
43
|
+
*/
|
|
44
|
+
export interface UnprojectableProp {
|
|
45
|
+
key: string;
|
|
46
|
+
reason: string;
|
|
47
|
+
}
|
|
48
|
+
export interface Projection {
|
|
49
|
+
props: ProjectedProp[];
|
|
50
|
+
unprojectable: UnprojectableProp[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* What the caller can offer beyond the plan fragment itself.
|
|
54
|
+
*
|
|
55
|
+
* `resolveBinding` is the whole difference between the two emission paths: the
|
|
56
|
+
* scaffold knows the identifier it bound each planned resource to, so it can
|
|
57
|
+
* answer; a codemod appending to a file someone else wrote generally cannot,
|
|
58
|
+
* and a key needing a live sibling is unprojectable for it.
|
|
59
|
+
*/
|
|
60
|
+
export interface ProjectionContext {
|
|
61
|
+
resolveBinding?: (planResourceName: string) => string | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* The fragment is an EDIT to an existing statement rather than a whole
|
|
64
|
+
* resource. Constants describe the statement, so an edit must not carry
|
|
65
|
+
* them: `fjall modify messaging --retentionPeriod` asked to change the
|
|
66
|
+
* retention, not to write a `type` discriminator its author never mentioned.
|
|
67
|
+
*/
|
|
68
|
+
editingExisting?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* How one plan key becomes (or fails to become) a construct prop.
|
|
72
|
+
*
|
|
73
|
+
* - `prop` — carried through as a literal, under `as` when the two
|
|
74
|
+
* vocabularies name it differently.
|
|
75
|
+
* - `planOnly` — never a construct prop. The scaffold consumes it (a
|
|
76
|
+
* `const <var> =` binding, flattened extra properties); anywhere else it is
|
|
77
|
+
* inert, so it is reported rather than silently dropped.
|
|
78
|
+
* - `live` — the construct wants an object, not a value. `bind` gets the plan
|
|
79
|
+
* value and the context and returns the source text of an expression, or
|
|
80
|
+
* undefined when this context cannot produce one.
|
|
81
|
+
*/
|
|
82
|
+
export type PlanKeyRule = {
|
|
83
|
+
kind: "prop";
|
|
84
|
+
as?: string;
|
|
85
|
+
} | {
|
|
86
|
+
kind: "planOnly";
|
|
87
|
+
reason: string;
|
|
88
|
+
} | {
|
|
89
|
+
kind: "live";
|
|
90
|
+
as?: string;
|
|
91
|
+
reason: string;
|
|
92
|
+
bind: (value: unknown, context: ProjectionContext) => string | undefined;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* One resource type's projection.
|
|
96
|
+
*
|
|
97
|
+
* `constants` are props every statement of the type carries no matter what
|
|
98
|
+
* the plan says — the discriminators the constructs switch on and the plan
|
|
99
|
+
* vocabulary never carried.
|
|
100
|
+
*
|
|
101
|
+
* `keys` is consulted per plan key; a key with no entry passes through under
|
|
102
|
+
* its own name, which is the common case and is why the tables stay short
|
|
103
|
+
* enough to read as the specification they are.
|
|
104
|
+
*/
|
|
105
|
+
export interface TypeProjection {
|
|
106
|
+
constants?: ProjectedProp[];
|
|
107
|
+
keys?: Record<string, PlanKeyRule>;
|
|
108
|
+
}
|
|
File without changes
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const GENERATOR_VERSION = "
|
|
1
|
+
export declare const GENERATOR_VERSION = "8.0.0";
|
package/dist/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const E="
|
|
1
|
+
const E="8.0.0";export{E as GENERATOR_VERSION};
|