@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.
Files changed (46) hide show
  1. package/dist/.build-source-hash +30 -21
  2. package/dist/.minified +1 -1
  3. package/dist/src/ast/domain/astDomainParser.d.ts +2 -0
  4. package/dist/src/ast/domain/astDomainParser.js +1 -1
  5. package/dist/src/codemod/drift/snapshot.js +1 -1
  6. package/dist/src/codemod/edits/addResource/propertyBuilder.d.ts +8 -1
  7. package/dist/src/codemod/edits/addResource/propertyBuilder.js +1 -1
  8. package/dist/src/codemod/edits/addResource.js +1 -1
  9. package/dist/src/codemod/edits/appendAccountToStage.js +1 -1
  10. package/dist/src/codemod/edits/modifyResource.js +1 -1
  11. package/dist/src/codemod/edits/moduleConstResolver.d.ts +24 -0
  12. package/dist/src/codemod/edits/moduleConstResolver.js +1 -0
  13. package/dist/src/codemod/edits/objectGraph.d.ts +28 -0
  14. package/dist/src/codemod/edits/objectGraph.js +1 -0
  15. package/dist/src/codemod/edits/secretsProvability.d.ts +48 -0
  16. package/dist/src/codemod/edits/secretsProvability.js +1 -0
  17. package/dist/src/codemod/edits/setContainerSecrets.d.ts +55 -0
  18. package/dist/src/codemod/edits/setContainerSecrets.js +1 -0
  19. package/dist/src/codemod/emitProjection.d.ts +29 -0
  20. package/dist/src/codemod/emitProjection.js +1 -0
  21. package/dist/src/codemod/index.d.ts +1 -0
  22. package/dist/src/codemod/index.js +1 -1
  23. package/dist/src/codemod/registry.d.ts +15 -10
  24. package/dist/src/codemod/registry.js +1 -1
  25. package/dist/src/dns/bindParser.js +2 -2
  26. package/dist/src/dns/bindWriter.js +2 -2
  27. package/dist/src/dns/domainRecords.d.ts +4 -0
  28. package/dist/src/dns/domainRecords.js +1 -1
  29. package/dist/src/generation/common.d.ts +7 -0
  30. package/dist/src/generation/common.js +6 -5
  31. package/dist/src/generation/storage.js +27 -33
  32. package/dist/src/planning/index.d.ts +1 -1
  33. package/dist/src/planning/index.js +1 -1
  34. package/dist/src/planning/resourcePlanning.d.ts +14 -2
  35. package/dist/src/planning/resourcePlanning.js +1 -1
  36. package/dist/src/projection/index.d.ts +3 -0
  37. package/dist/src/projection/index.js +1 -0
  38. package/dist/src/projection/project.d.ts +22 -0
  39. package/dist/src/projection/project.js +1 -0
  40. package/dist/src/projection/tables.d.ts +32 -0
  41. package/dist/src/projection/tables.js +1 -0
  42. package/dist/src/projection/types.d.ts +108 -0
  43. package/dist/src/projection/types.js +0 -0
  44. package/dist/src/version.d.ts +1 -1
  45. package/dist/src/version.js +1 -1
  46. package/package.json +2 -2
@@ -9,10 +9,10 @@
9
9
  "package.json",
10
10
  "tsconfig.json"
11
11
  ],
12
- "hash": "0baa26e2a704915b32867832ebb1fd741502646d6d1466be1ea84a7a685d901a",
12
+ "hash": "74a0bb134e5609fe93c1b79a77239f6b6d70c8db41fba13d0416c41d87bb28b0",
13
13
  "files": {
14
14
  "src/ast/astTestHelpers.ts": "026cac849eb88bdb",
15
- "src/ast/domain/astDomainParser.ts": "bac0b16eb2e62552",
15
+ "src/ast/domain/astDomainParser.ts": "940ce5742507477d",
16
16
  "src/ast/index.ts": "502a507c3764acbf",
17
17
  "src/ast/mutation/astCodeInjection.ts": "c1ebf483fb1e2332",
18
18
  "src/ast/mutation/astExpressionEvaluator.ts": "6082789268b91212",
@@ -39,35 +39,40 @@
39
39
  "src/codemod/drift/detect.ts": "af3fb518a9d7165d",
40
40
  "src/codemod/drift/index.ts": "e87e1ced35eefa44",
41
41
  "src/codemod/drift/merge.ts": "29093929befa9abd",
42
- "src/codemod/drift/snapshot.ts": "f8ef6b4097aa3d10",
42
+ "src/codemod/drift/snapshot.ts": "d3c70df4f8537237",
43
43
  "src/codemod/drift/types.ts": "7f1d7899e420e4d7",
44
- "src/codemod/edits/addResource.ts": "bad55550ecff2f72",
44
+ "src/codemod/edits/addResource.ts": "c8fe476d5ef589fe",
45
45
  "src/codemod/edits/addResource/appBinding.ts": "3553fdb30fe06335",
46
46
  "src/codemod/edits/addResource/bodyIndex.ts": "3e179eac10d7bcf4",
47
- "src/codemod/edits/addResource/propertyBuilder.ts": "18022f8899ba4b38",
48
- "src/codemod/edits/appendAccountToStage.ts": "2b92f93734497303",
47
+ "src/codemod/edits/addResource/propertyBuilder.ts": "9102dff7e9fab376",
48
+ "src/codemod/edits/appendAccountToStage.ts": "8c01227ad85021f2",
49
49
  "src/codemod/edits/controlFlowPolicy.ts": "e32bbe2894f76c65",
50
50
  "src/codemod/edits/crossPlanConnection.ts": "54a4ecb7b3368160",
51
51
  "src/codemod/edits/driftPolicy.ts": "5d9b7bb3505f987d",
52
52
  "src/codemod/edits/ensureImports.ts": "3ca0b6d446c4333c",
53
53
  "src/codemod/edits/findInsertionPosition.ts": "20cd34fdcf781017",
54
54
  "src/codemod/edits/index.ts": "bea5ed7c3983342b",
55
- "src/codemod/edits/modifyResource.ts": "578412079d63ab60",
55
+ "src/codemod/edits/modifyResource.ts": "c27380cf9dae5dfc",
56
56
  "src/codemod/edits/modifyResource/literalConversion.ts": "31295cccd59131b7",
57
+ "src/codemod/edits/moduleConstResolver.ts": "33f3e7ccac89b325",
58
+ "src/codemod/edits/objectGraph.ts": "beb4025daf6525d5",
57
59
  "src/codemod/edits/removeResource.ts": "2c7c8fe67bc3a866",
58
60
  "src/codemod/edits/removeResource/commentHeuristic.ts": "90b6ce7ba5aa2a48",
59
61
  "src/codemod/edits/removeResource/importPruning.ts": "f22783108b40f6cb",
62
+ "src/codemod/edits/secretsProvability.ts": "d723283918e31efd",
63
+ "src/codemod/edits/setContainerSecrets.ts": "07cbfac49b5329be",
60
64
  "src/codemod/edits/unmanagedShapeErrors.ts": "47a2644913c8e619",
61
65
  "src/codemod/edits/vpcPeer.ts": "0bcf90c2e6d16ca4",
62
66
  "src/codemod/edits/vpcPeerAccepter.ts": "c9eace933e9e2345",
63
- "src/codemod/emitGuard.ts": "cbe270e04e1fea1a",
67
+ "src/codemod/emitGuard.ts": "652d9b188276acf8",
68
+ "src/codemod/emitProjection.ts": "9a47ef44995be65f",
64
69
  "src/codemod/fileRewriter/builders.ts": "46a0d43240ff0818",
65
70
  "src/codemod/fileRewriter/index.ts": "fd715b41176a7999",
66
71
  "src/codemod/fileRewriter/locateByRange.ts": "889ee6256201c1fe",
67
72
  "src/codemod/fileRewriter/parse.ts": "b12026c31562a13c",
68
73
  "src/codemod/fileRewriter/print.ts": "f5ff7afb5b7786bf",
69
74
  "src/codemod/historyPaths.ts": "ef8084013146db57",
70
- "src/codemod/index.ts": "6d786ef76a61fdc6",
75
+ "src/codemod/index.ts": "71ebede4ab133f9c",
71
76
  "src/codemod/listResources.ts": "97f206a50edbea20",
72
77
  "src/codemod/llmFallback/apply.ts": "2e656a6e55b3b4e3",
73
78
  "src/codemod/llmFallback/claudeTier.ts": "0a37fe782c85f75b",
@@ -82,7 +87,7 @@
82
87
  "src/codemod/llmFallback/telemetryEvents.ts": "33a85939739693ab",
83
88
  "src/codemod/llmFallback/tierRunner.ts": "a26094accd78cf15",
84
89
  "src/codemod/llmFallback/types.ts": "14af8d2bd9afae12",
85
- "src/codemod/registry.ts": "ab1869907bcb957b",
90
+ "src/codemod/registry.ts": "bb0d629f33e5bf59",
86
91
  "src/codemod/semanticIndex/classifyControlFlow.ts": "ed96215d91a3cae3",
87
92
  "src/codemod/semanticIndex/findReferences.ts": "96aea37418d1e91a",
88
93
  "src/codemod/semanticIndex/index.ts": "cfcd212d34ab20fb",
@@ -100,13 +105,13 @@
100
105
  "src/codemod/validationGate/index.ts": "df5754bea9070410",
101
106
  "src/codemod/validationGate/types.ts": "af466ee5f3433042",
102
107
  "src/detection/index.ts": "b4ad9a935564cb3e",
103
- "src/dns/bindParser.ts": "a5371cd1fa781ce6",
104
- "src/dns/bindWriter.ts": "634b96dd15ee94b2",
108
+ "src/dns/bindParser.ts": "376d274bf9e4bf9f",
109
+ "src/dns/bindWriter.ts": "c296911ce5aef77c",
105
110
  "src/dns/domainFileGenerator.ts": "83451c031d3ed79c",
106
- "src/dns/domainRecords.ts": "17f895ff9a7b719b",
111
+ "src/dns/domainRecords.ts": "ab917006b92ae916",
107
112
  "src/dns/index.ts": "b476ef3d7b381dc8",
108
113
  "src/dns/types.ts": "82d6db9d7d26dbc2",
109
- "src/generation/common.ts": "4b63724600c726de",
114
+ "src/generation/common.ts": "73fa0ad5ffeeeed4",
110
115
  "src/generation/compute.ts": "4029a0d8e3197686",
111
116
  "src/generation/compute/ec2.ts": "4d8187d293a57fb1",
112
117
  "src/generation/compute/ecs.ts": "72190132fdaa1847",
@@ -117,15 +122,15 @@
117
122
  "src/generation/index.ts": "fd58a833e13bcf07",
118
123
  "src/generation/infrastructure.ts": "6381d502f4733926",
119
124
  "src/generation/messagingConnections.ts": "1f070088c39e9749",
120
- "src/generation/storage.ts": "68fa78401bbcf8a5",
125
+ "src/generation/storage.ts": "2c0171aeeec3d79e",
121
126
  "src/generation/storageConnections.ts": "db1ab6ccdc19afab",
122
127
  "src/index.ts": "fc8f27b8ffade9ef",
123
128
  "src/planning/generateResourceChange.ts": "1c6411f9a12e7acb",
124
- "src/planning/index.ts": "5caacb699eed31ba",
129
+ "src/planning/index.ts": "64c4a88a38e9956d",
125
130
  "src/planning/openNextPlanning.ts": "4af9cb9061f7d21e",
126
131
  "src/planning/resourceAddition.ts": "45b010d2eaf96522",
127
132
  "src/planning/resourceConnections.ts": "a6b7db8f733e560f",
128
- "src/planning/resourcePlanning.ts": "85038ad65bda976f",
133
+ "src/planning/resourcePlanning.ts": "6c966fe586fff080",
129
134
  "src/planning/staticSitePlanning.ts": "242af1e9618821ab",
130
135
  "src/presets/clickhouseTierPreset.ts": "72b2b8a8caf4bdb4",
131
136
  "src/presets/index.ts": "8332c0198b2a6fe9",
@@ -133,6 +138,10 @@
133
138
  "src/presets/storagePresets.ts": "5df2d4d7d21a66d8",
134
139
  "src/presets/tierPresets.ts": "c0148771bffbef9b",
135
140
  "src/presets/tierTypes.ts": "96d33201ebddf6e6",
141
+ "src/projection/index.ts": "f46e0e482bb33565",
142
+ "src/projection/project.ts": "2104026f10a27264",
143
+ "src/projection/tables.ts": "00904da382c06cf5",
144
+ "src/projection/types.ts": "da0845cb34bfd12b",
136
145
  "src/schemas/alarmSchemas.ts": "9016095d8031f006",
137
146
  "src/schemas/applicationSchemas.ts": "d85771a4607cf2da",
138
147
  "src/schemas/baseSchemas.ts": "93d9bd1c0adfcaa0",
@@ -157,11 +166,11 @@
157
166
  "src/validation/patterns.ts": "f9629eafdad7ac3e",
158
167
  "src/validation/validationMessages.ts": "c727ade4690274f4",
159
168
  "src/validation/validationPatterns.ts": "865f3d688975b7c8",
160
- "src/version.ts": "0e8c8d5ddae4f56f",
169
+ "src/version.ts": "d2ac361c506b072c",
161
170
  "../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
162
- "package.json": "f4b1c9b80d0dbdc7",
171
+ "package.json": "175b4806c4526e18",
163
172
  "tsconfig.json": "1929cf3f99fe9b1e"
164
173
  },
165
- "outputHash": "f4cd7140916d1965092b898aae1c66a849628b3d65177ab511f1207b09329c8f",
166
- "outputFileCount": 295
174
+ "outputHash": "328c5bda6ca2ae851022ef763790754a86c127a24c8de327ca3ed6ab00291f65",
175
+ "outputFileCount": 313
167
176
  }
package/dist/.minified CHANGED
@@ -1 +1 @@
1
- 147 files minified at 2026-08-06T02:33:58.009Z
1
+ 156 files minified at 2026-08-09T06:27:43.898Z
@@ -27,6 +27,8 @@ export interface DomainCallMatch {
27
27
  export type ParsedFjallTarget = {
28
28
  readonly kind: "ecs";
29
29
  readonly appName: string;
30
+ /** Second `fjallApp` argument — present only for a multi-ALB app. */
31
+ readonly computeName?: string;
30
32
  } | {
31
33
  readonly kind: "cdn";
32
34
  readonly appName: string;
@@ -1 +1 @@
1
- var R=Object.defineProperty;var u=(n,e)=>R(n,"name",{value:e,configurable:!0});import*as m from"typescript";import{parseObjectLiteral as T,asString as c,asStringUnion as _,asStringArray as y,asBoolean as b,asNumber as $,isCallRef as E,isParsedObject as g}from"../parsers/common/astCommonParser.js";import{success as l,failure as a}from"../../types/Result.js";import{DnsRecordTypeSchema as L}from"../../dns/types.js";import{DomainRegistrarSchema as j,DomainDeployPhaseSchema as Z,AliasRecordTypeSchema as O,TYPED_FJALL_TARGET_KINDS as C}from"../../dns/domainRecords.js";const N=j.options,x=Z.options,P=L.options,V=O.options;function ie(n){const e=[],t=u(i=>{if(m.isNewExpression(i)&&z(i.expression)){const d=F(i);d!==void 0&&e.push(d)}m.forEachChild(i,t)},"visit");if(t(n),e.length===0)return l(void 0);if(e.length>1)return a(new Error(`Expected exactly one 'new Domain(...)' call per infrastructure file, found ${e.length}`));const r=e[0];return r?l(r):l(void 0)}u(ie,"findDomainConstructCall");function z(n){return m.isIdentifier(n)&&n.text==="Domain"}u(z,"isDomainIdentifier");function F(n){const e=n.arguments;if(!e||e.length<3)return;const t=e[0],r=e[1],i=e[2];if(!t||!r||!i||!m.isObjectLiteralExpression(i))return;const d=M(n);if(d===void 0)return;const o=q(n),s=m.isStringLiteral(r)?r.text:void 0;return{callExpression:n,containingStatement:d,propsObjectLiteral:i,domainVarId:o,scopeArgumentText:t.getText(),constructIdLiteral:s}}u(F,"buildMatch");function M(n){let e=n;for(;e!==void 0;){if(m.isExpressionStatement(e)||m.isVariableStatement(e))return e;e=e.parent}}u(M,"findContainingTopLevelStatement");function q(n){let e=n.parent;for(;e!==void 0;){if(m.isVariableDeclaration(e)&&m.isIdentifier(e.name)&&e.initializer===n)return e.name.text;e=e.parent}}u(q,"extractDomainVarId");function B(n){switch(n.kind){case"registrar_required":return"'registrar' property is required";case"registrar_unsupported":return`'registrar' must be one of ${N.join(", ")}, got ${JSON.stringify(n.value)}`;case"missing_field":return`'${n.field}' property is required`;case"invalid_literal":return`'${n.field}' ${n.reason}`;case"removed_field":return`'${n.field}' was removed from the Domain API \u2014 ${n.cure}`}}u(B,"errorMessage");const J="declare the delegated child as its own Domain with registrar: 'external-delegated' and set 'parentDelegationRoleArn' (the CLI injects it via ManagedDomainBinding.delegationRoleArn); the child UPSERTs its NS records into the parent zone";function re(n){const e=T(n),t=_(e.registrar,N);if(t===void 0){const s=e.registrar;if(s===void 0)return a({kind:"registrar_required"});const f=typeof s=="string"?s:k(s);return a({kind:"registrar_unsupported",value:f})}const r=c(e.zoneName);if(r===void 0)return a({kind:"missing_field",field:"zoneName"});const i=U(e.records);if(!i.success)return i;const d=Q(e.certificates);if(!d.success)return d;if(e.delegations!==void 0)return a({kind:"removed_field",field:"delegations",cure:J});const o={zoneName:r,description:c(e.description),costAllocationEnvironment:c(e.costAllocationEnvironment),tags:W(e.tags),records:i.data,certificates:d.data};switch(t){case"route53":return l({...o,registrar:t,hostedZoneId:c(e.hostedZoneId)});case"external-delegated":{const s=c(e.delegatedSubdomain);if(s===void 0)return a({kind:"missing_field",field:"delegatedSubdomain"});const f=c(e.hostedZoneId);if(e.hostedZoneId!==void 0&&f===void 0)return a({kind:"invalid_literal",field:"hostedZoneId",reason:"must be a literal string zone id on external-delegated \u2014 dynamic expressions cannot be round-tripped"});const h=y(e.adoptedNameServers);if(e.adoptedNameServers!==void 0&&h===void 0)return a({kind:"invalid_literal",field:"adoptedNameServers",reason:"must be an array of literal NS hostname strings \u2014 the parent NS UPSERT writes them verbatim"});if(f===void 0!=(h===void 0))return a({kind:"invalid_literal",field:f===void 0?"hostedZoneId":"adoptedNameServers",reason:"adopting an existing child zone requires hostedZoneId and adoptedNameServers together (both-or-neither) \u2014 an imported zone exposes no name-server attribute at synth"});const S=c(e.parentDelegationRoleArn);if(e.parentDelegationRoleArn!==void 0&&S===void 0)return a({kind:"invalid_literal",field:"parentDelegationRoleArn",reason:"must be a literal string ARN (VD2-a) \u2014 the CLI injects it via ManagedDomainBinding.delegationRoleArn; dynamic expressions such as Fn.importValue are not supported"});const A=_(e.phase,x);return e.phase!==void 0&&A===void 0?a({kind:"invalid_literal",field:"phase",reason:`must be one of ${x.map(I=>`'${I}'`).join(", ")}`}):l({...o,registrar:t,delegatedSubdomain:s,hostedZoneId:f,adoptedNameServers:h,parentDelegationRoleArn:S,phase:A})}case"external-records":return l({...o,registrar:t})}}u(re,"parseDomainProps");function se(n){return B(n)}u(se,"parseDomainErrorMessage");function U(n){if(n===void 0)return l([]);if(!Array.isArray(n))return a({kind:"invalid_literal",field:"records",reason:"must be an array"});const e=[];for(let t=0;t<n.length;t++){const r=n[t];if(!g(r))return a({kind:"invalid_literal",field:`records[${t}]`,reason:"must be an object literal"});const i=G(r,t);if(!i.success)return i;e.push(i.data)}return l(e)}u(U,"parseRecordsArray");function G(n,e){const t=c(n.type),r=c(n.name);if(t===void 0)return a({kind:"missing_field",field:`records[${e}].type`});if(r===void 0)return a({kind:"missing_field",field:`records[${e}].name`});if(n.target!==void 0){if(!V.some(f=>f===t))return a({kind:"invalid_literal",field:`records[${e}]`,reason:`alias records must have type 'A' or 'AAAA', got '${t}'`});const s=H(n.target);return l({kind:"alias",type:t,name:r,target:s})}if(!P.some(s=>s===t))return a({kind:"invalid_literal",field:`records[${e}]`,reason:`unsupported record type '${t}'`});const i=Y(n.value);if(i===void 0)return a({kind:"invalid_literal",field:`records[${e}].value`,reason:`must be a string or array of strings (got ${JSON.stringify(n.value)})`});const d=$(n.ttl),o={kind:"standard",type:t,name:r,value:i,...d!==void 0?{ttl:d}:{}};return l(o)}u(G,"parseRecord");function Y(n){if(n===void 0)return;if(typeof n=="string")return n;const e=y(n);if(e!==void 0)return e}u(Y,"parseRecordValue");function H(n){if(E(n))return K(n);if(g(n)){const e=_(n.kind,C);if(e==="ecs"||e==="cdn"){const t=c(n.appName);if(t!==void 0)return{kind:e,appName:t}}if(e==="bucket"){const t=c(n.bucketName);if(t!==void 0)return{kind:e,bucketName:t}}if(e==="custom"){const t=c(n.dnsName),r=c(n.hostedZoneId);if(t!==void 0&&r!==void 0)return{kind:e,dnsName:t,hostedZoneId:r}}}return{kind:"unresolved",sourceText:k(n)}}u(H,"parseTarget");function K(n){const e=n.__call.trim(),t=e.match(/^([A-Za-z_][\w$]*)\s*\(([\s\S]*)\)\s*$/);if(!t)return{kind:"unresolved",sourceText:e};const r=t[1],i=t[2]??"",d=v(i);switch(r){case"fjallApp":{const o=p(d,0);return o===void 0?{kind:"dynamic",sourceText:e}:{kind:"ecs",appName:o}}case"fjallCdn":{const o=p(d,0);return o===void 0?{kind:"dynamic",sourceText:e}:{kind:"cdn",appName:o}}case"fjallBucket":{const o=p(d,0);return o===void 0?{kind:"dynamic",sourceText:e}:{kind:"bucket",bucketName:o}}case"aliasTo":{if(d.length>=2){const o=p(d,0),s=p(d,1);return o!==void 0&&s!==void 0?{kind:"custom",dnsName:o,hostedZoneId:s}:{kind:"dynamic",sourceText:e}}if(d.length===1){const o=d[0]?.trim()??"",s=D(o,"dnsName"),f=D(o,"hostedZoneId");return s!==void 0&&f!==void 0?{kind:"custom",dnsName:s,hostedZoneId:f}:{kind:"dynamic",sourceText:e}}return{kind:"unresolved",sourceText:e}}default:return{kind:"unresolved",sourceText:e}}}u(K,"resolveCallRefTarget");function v(n){const e=[];let t=0,r=null,i="";for(let o=0;o<n.length;o++){const s=n[o];if(r!==null){if(i+=s,s==="\\"&&o+1<n.length){const f=n[o+1];f!==void 0&&(i+=f,o+=1);continue}s===r&&(r=null);continue}if(s==='"'||s==="'"||s==="`"){r=s,i+=s;continue}if(s==="("||s==="{"||s==="["){t+=1,i+=s;continue}if(s===")"||s==="}"||s==="]"){t-=1,i+=s;continue}if(s===","&&t===0){e.push(i.trim()),i="";continue}i+=s}const d=i.trim();return d.length>0&&e.push(d),e}u(v,"splitTopLevelArgs");function p(n,e){const t=n[e];if(t===void 0)return;const r=t.trim();if(r.length<2)return;const i=r[0],d=r[r.length-1];if(i===d&&!(i!=='"'&&i!=="'"&&i!=="`"))return r.slice(1,-1)}u(p,"extractStringLiteralArg");function D(n,e){const t=n.trim().replace(/^\{|\}$/g,""),r=v(t);for(const i of r){const d=i.indexOf(":");if(d<0||i.slice(0,d).trim().replace(/["'`]/g,"")!==e)continue;const s=i.slice(d+1).trim();return p([s],0)}}u(D,"extractObjectFieldString");function Q(n){if(n===void 0)return l([]);if(!Array.isArray(n))return a({kind:"invalid_literal",field:"certificates",reason:"must be an array"});const e=[];for(let t=0;t<n.length;t++){const r=n[t];if(typeof r=="string"){e.push({domainName:r});continue}if(!g(r))return a({kind:"invalid_literal",field:`certificates[${t}]`,reason:"must be a string or object literal"});const i=c(r.domainName);if(i===void 0)return a({kind:"missing_field",field:`certificates[${t}].domainName`});const d=y(r.subjectAlternativeNames),o=b(r.transparencyLogging),s=b(r.cloudFront);if(r.cloudFront!==void 0&&s===void 0)return a({kind:"invalid_literal",field:`certificates[${t}].cloudFront`,reason:"must be a boolean literal \u2014 the CloudFront designation drives the zone-level us-east-1 export contract and cannot be round-tripped from a dynamic expression"});e.push({domainName:i,...d!==void 0?{subjectAlternativeNames:d}:{},...o!==void 0?{transparencyLogging:o}:{},...s!==void 0?{cloudFront:s}:{}})}return l(e)}u(Q,"parseCertificatesArray");function W(n){if(n===void 0||!g(n))return;const e={};for(const[t,r]of Object.entries(n)){const i=c(r);i!==void 0&&(e[t]=i)}return Object.keys(e).length===0?void 0:e}u(W,"parseStringRecord");function k(n){if(n===void 0)return"undefined";if(n===null)return"null";if(typeof n=="string")return JSON.stringify(n);if(typeof n=="number"||typeof n=="boolean")return String(n);if(Array.isArray(n))return`[${n.map(e=>k(e)).join(", ")}]`;if(typeof n=="object"){if("__call"in n)return String(n.__call);if("__identifier"in n)return String(n.__identifier);if("__expression"in n)return String(n.__expression);if("__unknown"in n)return String(n.__unknown)}return String(n)}u(k,"stringifyParsedValue");export{ie as findDomainConstructCall,se as parseDomainErrorMessage,re as parseDomainProps,v as splitTopLevelArgs};
1
+ var R=Object.defineProperty;var u=(n,e)=>R(n,"name",{value:e,configurable:!0});import*as m from"typescript";import{parseObjectLiteral as T,asString as c,asStringUnion as k,asStringArray as y,asBoolean as b,asNumber as $,isCallRef as E,isParsedObject as g}from"../parsers/common/astCommonParser.js";import{success as l,failure as a}from"../../types/Result.js";import{DnsRecordTypeSchema as L}from"../../dns/types.js";import{DomainRegistrarSchema as j,DomainDeployPhaseSchema as Z,AliasRecordTypeSchema as O,TYPED_FJALL_TARGET_KINDS as C}from"../../dns/domainRecords.js";const N=j.options,x=Z.options,P=L.options,V=O.options;function ie(n){const e=[],t=u(r=>{if(m.isNewExpression(r)&&z(r.expression)){const d=F(r);d!==void 0&&e.push(d)}m.forEachChild(r,t)},"visit");if(t(n),e.length===0)return l(void 0);if(e.length>1)return a(new Error(`Expected exactly one 'new Domain(...)' call per infrastructure file, found ${e.length}`));const s=e[0];return s?l(s):l(void 0)}u(ie,"findDomainConstructCall");function z(n){return m.isIdentifier(n)&&n.text==="Domain"}u(z,"isDomainIdentifier");function F(n){const e=n.arguments;if(!e||e.length<3)return;const t=e[0],s=e[1],r=e[2];if(!t||!s||!r||!m.isObjectLiteralExpression(r))return;const d=M(n);if(d===void 0)return;const o=q(n),i=m.isStringLiteral(s)?s.text:void 0;return{callExpression:n,containingStatement:d,propsObjectLiteral:r,domainVarId:o,scopeArgumentText:t.getText(),constructIdLiteral:i}}u(F,"buildMatch");function M(n){let e=n;for(;e!==void 0;){if(m.isExpressionStatement(e)||m.isVariableStatement(e))return e;e=e.parent}}u(M,"findContainingTopLevelStatement");function q(n){let e=n.parent;for(;e!==void 0;){if(m.isVariableDeclaration(e)&&m.isIdentifier(e.name)&&e.initializer===n)return e.name.text;e=e.parent}}u(q,"extractDomainVarId");function B(n){switch(n.kind){case"registrar_required":return"'registrar' property is required";case"registrar_unsupported":return`'registrar' must be one of ${N.join(", ")}, got ${JSON.stringify(n.value)}`;case"missing_field":return`'${n.field}' property is required`;case"invalid_literal":return`'${n.field}' ${n.reason}`;case"removed_field":return`'${n.field}' was removed from the Domain API \u2014 ${n.cure}`}}u(B,"errorMessage");const J="declare the delegated child as its own Domain with registrar: 'external-delegated' and set 'parentDelegationRoleArn' (the CLI injects it via ManagedDomainBinding.delegationRoleArn); the child UPSERTs its NS records into the parent zone";function re(n){const e=T(n),t=k(e.registrar,N);if(t===void 0){const i=e.registrar;if(i===void 0)return a({kind:"registrar_required"});const f=typeof i=="string"?i:_(i);return a({kind:"registrar_unsupported",value:f})}const s=c(e.zoneName);if(s===void 0)return a({kind:"missing_field",field:"zoneName"});const r=U(e.records);if(!r.success)return r;const d=Q(e.certificates);if(!d.success)return d;if(e.delegations!==void 0)return a({kind:"removed_field",field:"delegations",cure:J});const o={zoneName:s,description:c(e.description),costAllocationEnvironment:c(e.costAllocationEnvironment),tags:W(e.tags),records:r.data,certificates:d.data};switch(t){case"route53":return l({...o,registrar:t,hostedZoneId:c(e.hostedZoneId)});case"external-delegated":{const i=c(e.delegatedSubdomain);if(i===void 0)return a({kind:"missing_field",field:"delegatedSubdomain"});const f=c(e.hostedZoneId);if(e.hostedZoneId!==void 0&&f===void 0)return a({kind:"invalid_literal",field:"hostedZoneId",reason:"must be a literal string zone id on external-delegated \u2014 dynamic expressions cannot be round-tripped"});const h=y(e.adoptedNameServers);if(e.adoptedNameServers!==void 0&&h===void 0)return a({kind:"invalid_literal",field:"adoptedNameServers",reason:"must be an array of literal NS hostname strings \u2014 the parent NS UPSERT writes them verbatim"});if(f===void 0!=(h===void 0))return a({kind:"invalid_literal",field:f===void 0?"hostedZoneId":"adoptedNameServers",reason:"adopting an existing child zone requires hostedZoneId and adoptedNameServers together (both-or-neither) \u2014 an imported zone exposes no name-server attribute at synth"});const S=c(e.parentDelegationRoleArn);if(e.parentDelegationRoleArn!==void 0&&S===void 0)return a({kind:"invalid_literal",field:"parentDelegationRoleArn",reason:"must be a literal string ARN (VD2-a) \u2014 the CLI injects it via ManagedDomainBinding.delegationRoleArn; dynamic expressions such as Fn.importValue are not supported"});const A=k(e.phase,x);return e.phase!==void 0&&A===void 0?a({kind:"invalid_literal",field:"phase",reason:`must be one of ${x.map(I=>`'${I}'`).join(", ")}`}):l({...o,registrar:t,delegatedSubdomain:i,hostedZoneId:f,adoptedNameServers:h,parentDelegationRoleArn:S,phase:A})}case"external-records":return l({...o,registrar:t})}}u(re,"parseDomainProps");function se(n){return B(n)}u(se,"parseDomainErrorMessage");function U(n){if(n===void 0)return l([]);if(!Array.isArray(n))return a({kind:"invalid_literal",field:"records",reason:"must be an array"});const e=[];for(let t=0;t<n.length;t++){const s=n[t];if(!g(s))return a({kind:"invalid_literal",field:`records[${t}]`,reason:"must be an object literal"});const r=G(s,t);if(!r.success)return r;e.push(r.data)}return l(e)}u(U,"parseRecordsArray");function G(n,e){const t=c(n.type),s=c(n.name);if(t===void 0)return a({kind:"missing_field",field:`records[${e}].type`});if(s===void 0)return a({kind:"missing_field",field:`records[${e}].name`});if(n.target!==void 0){if(!V.some(f=>f===t))return a({kind:"invalid_literal",field:`records[${e}]`,reason:`alias records must have type 'A' or 'AAAA', got '${t}'`});const i=H(n.target);return l({kind:"alias",type:t,name:s,target:i})}if(!P.some(i=>i===t))return a({kind:"invalid_literal",field:`records[${e}]`,reason:`unsupported record type '${t}'`});const r=Y(n.value);if(r===void 0)return a({kind:"invalid_literal",field:`records[${e}].value`,reason:`must be a string or array of strings (got ${JSON.stringify(n.value)})`});const d=$(n.ttl),o={kind:"standard",type:t,name:s,value:r,...d!==void 0?{ttl:d}:{}};return l(o)}u(G,"parseRecord");function Y(n){if(n===void 0)return;if(typeof n=="string")return n;const e=y(n);if(e!==void 0)return e}u(Y,"parseRecordValue");function H(n){if(E(n))return K(n);if(g(n)){const e=k(n.kind,C);if(e==="ecs"||e==="cdn"){const t=c(n.appName);if(t!==void 0)return{kind:e,appName:t}}if(e==="bucket"){const t=c(n.bucketName);if(t!==void 0)return{kind:e,bucketName:t}}if(e==="custom"){const t=c(n.dnsName),s=c(n.hostedZoneId);if(t!==void 0&&s!==void 0)return{kind:e,dnsName:t,hostedZoneId:s}}}return{kind:"unresolved",sourceText:_(n)}}u(H,"parseTarget");function K(n){const e=n.__call.trim(),t=e.match(/^([A-Za-z_][\w$]*)\s*\(([\s\S]*)\)\s*$/);if(!t)return{kind:"unresolved",sourceText:e};const s=t[1],r=t[2]??"",d=v(r);switch(s){case"fjallApp":{const o=p(d,0);if(o===void 0)return{kind:"dynamic",sourceText:e};if(d.length<2)return{kind:"ecs",appName:o};const i=p(d,1);return i===void 0?{kind:"dynamic",sourceText:e}:{kind:"ecs",appName:o,computeName:i}}case"fjallCdn":{const o=p(d,0);return o===void 0?{kind:"dynamic",sourceText:e}:{kind:"cdn",appName:o}}case"fjallBucket":{const o=p(d,0);return o===void 0?{kind:"dynamic",sourceText:e}:{kind:"bucket",bucketName:o}}case"aliasTo":{if(d.length>=2){const o=p(d,0),i=p(d,1);return o!==void 0&&i!==void 0?{kind:"custom",dnsName:o,hostedZoneId:i}:{kind:"dynamic",sourceText:e}}if(d.length===1){const o=d[0]?.trim()??"",i=D(o,"dnsName"),f=D(o,"hostedZoneId");return i!==void 0&&f!==void 0?{kind:"custom",dnsName:i,hostedZoneId:f}:{kind:"dynamic",sourceText:e}}return{kind:"unresolved",sourceText:e}}default:return{kind:"unresolved",sourceText:e}}}u(K,"resolveCallRefTarget");function v(n){const e=[];let t=0,s=null,r="";for(let o=0;o<n.length;o++){const i=n[o];if(s!==null){if(r+=i,i==="\\"&&o+1<n.length){const f=n[o+1];f!==void 0&&(r+=f,o+=1);continue}i===s&&(s=null);continue}if(i==='"'||i==="'"||i==="`"){s=i,r+=i;continue}if(i==="("||i==="{"||i==="["){t+=1,r+=i;continue}if(i===")"||i==="}"||i==="]"){t-=1,r+=i;continue}if(i===","&&t===0){e.push(r.trim()),r="";continue}r+=i}const d=r.trim();return d.length>0&&e.push(d),e}u(v,"splitTopLevelArgs");function p(n,e){const t=n[e];if(t===void 0)return;const s=t.trim();if(s.length<2)return;const r=s[0],d=s[s.length-1];if(r===d&&!(r!=='"'&&r!=="'"&&r!=="`"))return s.slice(1,-1)}u(p,"extractStringLiteralArg");function D(n,e){const t=n.trim().replace(/^\{|\}$/g,""),s=v(t);for(const r of s){const d=r.indexOf(":");if(d<0||r.slice(0,d).trim().replace(/["'`]/g,"")!==e)continue;const i=r.slice(d+1).trim();return p([i],0)}}u(D,"extractObjectFieldString");function Q(n){if(n===void 0)return l([]);if(!Array.isArray(n))return a({kind:"invalid_literal",field:"certificates",reason:"must be an array"});const e=[];for(let t=0;t<n.length;t++){const s=n[t];if(typeof s=="string"){e.push({domainName:s});continue}if(!g(s))return a({kind:"invalid_literal",field:`certificates[${t}]`,reason:"must be a string or object literal"});const r=c(s.domainName);if(r===void 0)return a({kind:"missing_field",field:`certificates[${t}].domainName`});const d=y(s.subjectAlternativeNames),o=b(s.transparencyLogging),i=b(s.cloudFront);if(s.cloudFront!==void 0&&i===void 0)return a({kind:"invalid_literal",field:`certificates[${t}].cloudFront`,reason:"must be a boolean literal \u2014 the CloudFront designation drives the zone-level us-east-1 export contract and cannot be round-tripped from a dynamic expression"});e.push({domainName:r,...d!==void 0?{subjectAlternativeNames:d}:{},...o!==void 0?{transparencyLogging:o}:{},...i!==void 0?{cloudFront:i}:{}})}return l(e)}u(Q,"parseCertificatesArray");function W(n){if(n===void 0||!g(n))return;const e={};for(const[t,s]of Object.entries(n)){const r=c(s);r!==void 0&&(e[t]=r)}return Object.keys(e).length===0?void 0:e}u(W,"parseStringRecord");function _(n){if(n===void 0)return"undefined";if(n===null)return"null";if(typeof n=="string")return JSON.stringify(n);if(typeof n=="number"||typeof n=="boolean")return String(n);if(Array.isArray(n))return`[${n.map(e=>_(e)).join(", ")}]`;if(typeof n=="object"){if("__call"in n)return String(n.__call);if("__identifier"in n)return String(n.__identifier);if("__expression"in n)return String(n.__expression);if("__unknown"in n)return String(n.__unknown)}return String(n)}u(_,"stringifyParsedValue");export{ie as findDomainConstructCall,se as parseDomainErrorMessage,re as parseDomainProps,v as splitTopLevelArgs};
@@ -1 +1 @@
1
- var h=Object.defineProperty;var u=(r,t)=>h(r,"name",{value:t,configurable:!0});import{failure as d,success as g}from"../../types/Result.js";import{extractProgramBody as k,isRecord as m}from"../_internal.js";import{astToLiteral as b,isNodeShape as y,NON_LITERAL as E,readKeyName as x}from"../edits/modifyResource/literalConversion.js";import{parse as N}from"../fileRewriter/index.js";import{listResources as O}from"../listResources.js";import{STATEMENT_REGISTRY as j}from"../registry.js";function I(r,t,n){const e=O(r);if(!e.success)return d(e.error);const i=e.data.resources.find(o=>o.type===t&&o.name===n);if(i===void 0)return d({kind:"ResourceNotFoundError",type:t,name:n,knownNames:e.data.resources.filter(o=>o.type===t).map(o=>o.name)});const s=N(r,i.filePath);if(!s.success)return d(s.error);const c=k(s.data);if(c===void 0)return d({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const f=S(c,i);if(f===void 0)return d({kind:"SemanticQueryError",reason:"Unable to resolve config ObjectExpression for the located resource."});const a=new Set(Object.keys(j[t].schemaFragment.shape)),l={};for(const o of f.properties){if(o.type!=="Property"&&o.type!=="ObjectProperty"||o.shorthand===!0||o.computed===!0)continue;const p=x(o.key);p===void 0||!a.has(p)||o.value!==void 0&&(l[p]=v(o.value,r))}return g({type:t,name:n,properties:l,schemaVersion:1})}u(I,"snapshotProperties");function S(r,t){const n=t.start+t.length;let e;const i=u(s=>{if(e!==void 0||s.type!=="CallExpression")return;const c=s.arguments;if(!Array.isArray(c)||c.length<2)return;const f=c[0];if(!y(f)||f.type!=="StringLiteral"||f.start!==t.start||f.end!==n)return;const a=c[1];y(a)&&a.type==="ObjectExpression"&&(e=a)},"visitor");for(const s of r)if(P(s,i),e!==void 0)break;return e}u(S,"findConfigObject");function v(r,t){const n=b(r);return n!==E?n:A(r,t)}u(v,"extractPropertyValue");function A(r,t){const n=typeof r.start=="number"?r.start:void 0,e=typeof r.end=="number"?r.end:void 0;return{kind:"expression",text:n!==void 0&&e!==void 0&&n<e?t.slice(n,e):""}}u(A,"toExpressionValue");function P(r,t){const n=[r];for(;n.length>0;){const e=n.pop();if(m(e)){typeof e.type=="string"&&t(e);for(const i of Object.keys(e)){if(i==="loc"||i==="comments"||i==="tokens")continue;const s=e[i];if(Array.isArray(s))for(const c of s)m(c)&&n.push(c);else m(s)&&n.push(s)}}}}u(P,"visit");export{I as snapshotProperties};
1
+ var y=Object.defineProperty;var u=(e,r)=>y(e,"name",{value:r,configurable:!0});import{failure as d,success as h}from"../../types/Result.js";import{extractProgramBody as b}from"../_internal.js";import{astToLiteral as g,isNodeShape as l,NON_LITERAL as E,readKeyName as k}from"../edits/modifyResource/literalConversion.js";import{visit as x}from"../edits/objectGraph.js";import{parse as N}from"../fileRewriter/index.js";import{listResources as O}from"../listResources.js";import{STATEMENT_REGISTRY as S}from"../registry.js";function I(e,r,o){const n=O(e);if(!n.success)return d(n.error);const f=n.data.resources.find(t=>t.type===r&&t.name===o);if(f===void 0)return d({kind:"ResourceNotFoundError",type:r,name:o,knownNames:n.data.resources.filter(t=>t.type===r).map(t=>t.name)});const s=N(e,f.filePath);if(!s.success)return d(s.error);const i=b(s.data);if(i===void 0)return d({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const c=j(i,f);if(c===void 0)return d({kind:"SemanticQueryError",reason:"Unable to resolve config ObjectExpression for the located resource."});const a=new Set(Object.keys(S[r].schemaFragment.shape)),m={};for(const t of c.properties){if(t.type!=="Property"&&t.type!=="ObjectProperty"||t.shorthand===!0||t.computed===!0)continue;const p=k(t.key);p===void 0||!a.has(p)||t.value!==void 0&&(m[p]=P(t.value,e))}return h({type:r,name:o,properties:m,schemaVersion:1})}u(I,"snapshotProperties");function j(e,r){const o=r.start+r.length;let n;const f=u(s=>{if(n!==void 0||s.type!=="CallExpression")return;const i=s.arguments;if(!Array.isArray(i)||i.length<2)return;const c=i[0];if(!l(c)||c.type!=="StringLiteral"||c.start!==r.start||c.end!==o)return;const a=i[1];l(a)&&a.type==="ObjectExpression"&&(n=a)},"visitor");for(const s of e)if(x(s,f),n!==void 0)break;return n}u(j,"findConfigObject");function P(e,r){const o=g(e);return o!==E?o:T(e,r)}u(P,"extractPropertyValue");function T(e,r){const o=typeof e.start=="number"?e.start:void 0,n=typeof e.end=="number"?e.end:void 0;return{kind:"expression",text:o!==void 0&&n!==void 0&&o<n?r.slice(o,n):""}}u(T,"toExpressionValue");export{I as snapshotProperties};
@@ -1,7 +1,14 @@
1
1
  import { type namedTypes as n } from "ast-types";
2
2
  import { type Result } from "../../../types/Result.js";
3
3
  import { type ObjectPropertyInput, type QuoteStyle } from "../../fileRewriter/index.js";
4
+ import type { LiteralProp } from "../../emitProjection.js";
4
5
  import type { InvalidPropertyError } from "../../types.js";
5
- export declare function buildPropertyInputs(properties: Record<string, unknown>, quoteStyle: QuoteStyle): Result<ObjectPropertyInput[], InvalidPropertyError>;
6
+ /**
7
+ * Build the emitted object literal from CONSTRUCT-vocabulary props.
8
+ *
9
+ * The caller has already run the plan fragment through the projection, so
10
+ * every key here is one a construct reads, in emission order.
11
+ */
12
+ export declare function buildPropertyInputs(properties: ReadonlyArray<LiteralProp>, quoteStyle: QuoteStyle): Result<ObjectPropertyInput[], InvalidPropertyError>;
6
13
  export declare function toAstValue(value: unknown, quoteStyle: QuoteStyle): n.Property["value"] | undefined;
7
14
  export declare function makeStringLiteral(value: string, quote: QuoteStyle): n.StringLiteral;
@@ -1 +1 @@
1
- var c=Object.defineProperty;var f=(r,e)=>c(r,"name",{value:e,configurable:!0});import{builders as i}from"ast-types";import{failure as u,success as a}from"../../../types/Result.js";import{buildObjectProperty as d}from"../../fileRewriter/index.js";function j(r,e){const n=[];for(const[t,o]of Object.entries(r)){const s=p(o,e);if(s===void 0)return u({kind:"InvalidPropertyError",property:t,reason:`Unsupported property value for "${t}" (accepts string/number/boolean/null/array/object of the same).`});n.push({key:t,value:s})}return a(n)}f(j,"buildPropertyInputs");function p(r,e){if(typeof r=="string")return l(r,e);if(typeof r=="number"&&Number.isFinite(r))return i.numericLiteral(r);if(typeof r=="boolean")return i.booleanLiteral(r);if(r===null)return i.nullLiteral();if(Array.isArray(r)){const n=[];for(const t of r){const o=p(t,e);if(o===void 0)return;n.push(o)}return i.arrayExpression(n)}if(typeof r=="object"&&r!==null){const n=[];for(const[t,o]of Object.entries(r)){const s=p(o,e);if(s===void 0)return;n.push(d(t,s,e))}return i.objectExpression(n)}}f(p,"toAstValue");function l(r,e){const n=e==="single"?"'":'"',t=e==="single"?r.replace(/\\/g,"\\\\").replace(/'/g,"\\'"):r.replace(/\\/g,"\\\\").replace(/"/g,'\\"'),o=`${n}${t}${n}`;return i.stringLiteral.from({value:r,extra:{rawValue:r,raw:o}})}f(l,"makeStringLiteral");export{j as buildPropertyInputs,l as makeStringLiteral,p as toAstValue};
1
+ var c=Object.defineProperty;var f=(r,e)=>c(r,"name",{value:e,configurable:!0});import{builders as i}from"ast-types";import{failure as u,success as a}from"../../../types/Result.js";import{buildObjectProperty as d}from"../../fileRewriter/index.js";function x(r,e){const n=[];for(const{key:t,value:o}of r){const s=p(o,e);if(s===void 0)return u({kind:"InvalidPropertyError",property:t,reason:`Unsupported property value for "${t}" (accepts string/number/boolean/null/array/object of the same).`});n.push({key:t,value:s})}return a(n)}f(x,"buildPropertyInputs");function p(r,e){if(typeof r=="string")return l(r,e);if(typeof r=="number"&&Number.isFinite(r))return i.numericLiteral(r);if(typeof r=="boolean")return i.booleanLiteral(r);if(r===null)return i.nullLiteral();if(Array.isArray(r)){const n=[];for(const t of r){const o=p(t,e);if(o===void 0)return;n.push(o)}return i.arrayExpression(n)}if(typeof r=="object"&&r!==null){const n=[];for(const[t,o]of Object.entries(r)){const s=p(o,e);if(s===void 0)return;n.push(d(t,s,e))}return i.objectExpression(n)}}f(p,"toAstValue");function l(r,e){const n=e==="single"?"'":'"',t=e==="single"?r.replace(/\\/g,"\\\\").replace(/'/g,"\\'"):r.replace(/\\/g,"\\\\").replace(/"/g,'\\"'),o=`${n}${t}${n}`;return i.stringLiteral.from({value:r,extra:{rawValue:r,raw:o}})}f(l,"makeStringLiteral");export{x as buildPropertyInputs,l as makeStringLiteral,p as toAstValue};
@@ -1 +1 @@
1
- var A=Object.defineProperty;var u=(r,e)=>A(r,"name",{value:e,configurable:!0});import{failure as a,success as g}from"../../types/Result.js";import{DEFAULT_FILE_PATH as D,computeLinesDelta as F,extractProgramBody as M,isRecord as C}from"../_internal.js";import{evaluateEmitGuard as v}from"../emitGuard.js";import{appendSpecifier as x,buildAppMethodWrappedStatement as w,buildFactoryStatement as G,buildImportDeclaration as N,detectQuoteStyle as Q,parse as B,printFile as U}from"../fileRewriter/index.js";import{STATEMENT_REGISTRY as _}from"../registry.js";import{locateAllShapes as O,locateByShape as W}from"../semanticIndex/index.js";import{checkControlFlowPolicy as Y}from"./controlFlowPolicy.js";import{driftGate as j,runPipeline as q,schemaGate as H}from"../validationGate/index.js";import{resolveAppBindingName as $}from"./addResource/appBinding.js";import{buildUnmanagedDuplicateError as z}from"./unmanagedShapeErrors.js";import{buildResourceLocations as J,indexBody as K,orderByEndPos as V,resolveInsertIndex as X}from"./addResource/bodyIndex.js";import{buildPropertyInputs as Z}from"./addResource/propertyBuilder.js";import{findInsertionPosition as ee}from"./findInsertionPosition.js";const k="@fjall/components-infrastructure";function he(r,e,m={}){const s=e.filePath??D,n=B(r,s);if(!n.success)return a(n.error);const t=W(r,{type:e.type,name:e.name},s);if(!t.success)return t.error.kind==="TemplateLiteralNameError"?a(t.error):a({kind:"SemanticQueryError",reason:t.error.reason,cause:t.error.cause});if(t.data!==void 0){if(t.data.managed===!1)return a(z(e.type,t.data.symbolName));const d=Y({ast:n.data,target:t.data,resource:{type:e.type,name:e.name},op:"add"});if(d.refusal!==void 0)return a(d.refusal);const E=q([H,j],{content:r,plan:{type:e.type,name:e.name,properties:e.properties,op:"add"},baseline:m.baseline,policy:e.driftPolicy});return E.success?E.data.action==="skip"?g({content:r,linesChanged:{added:0,removed:0},skipped:!0}):a({kind:"DuplicateResourceError",type:e.type,name:e.name}):a(re(E.error))}const l=Q(n.data),f=Z(e.properties,l);if(!f.success)return a(f.error);const c=M(n.data);if(c===void 0)return a({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const o=_[e.type],h=v(o.emitGuard,e.properties);if(h!==void 0)return a(h);const I={factory:o.factoryIdentifier,name:e.name,properties:f.data,quoteStyle:l};let y;if(o.emitWrapper!==void 0){const d=$(c);if(d===void 0)return a({kind:"MissingAppInitError",type:e.type,appMethod:o.emitWrapper.appMethod});y=w({...I,appIdentifier:d,appMethod:o.emitWrapper.appMethod})}else y=G(I);const p=K(c,r),i=O(r,s);if(!i.success)return i.error.kind==="TemplateLiteralNameError"?a(i.error):a({kind:"SemanticQueryError",reason:i.error.reason,cause:i.error.cause});const P=J(p.anchors,i.data),L=V([...p.appInitLocations,...P]),R=ee(p.importInfos,L,e.type,p.programEnd),b=X(p.anchors,R);c.splice(b,0,y),te(c,o.factoryIdentifier,l);const S=U(n.data,r),T=F(r,S);return g({content:S,linesChanged:T})}u(he,"addResource");function re(r){switch(r.kind){case"ParseError":case"TemplateLiteralNameError":case"DuplicateResourceError":case"InvalidPropertyError":case"SemanticQueryError":case"MissingAppInitError":case"DriftConflictError":case"ControlFlowClassifierError":return r;default:return{kind:"SemanticQueryError",reason:`Unexpected codemod error in validation-gate pipeline: ${r.kind}`}}}u(re,"narrowGateError");function te(r,e,m){for(const n of r){if(n.type!=="ImportDeclaration")continue;const t=n.source;if(!(!C(t)||t.type!=="StringLiteral")&&t.value===k){x(n,e);return}}const s=N([e],k,m);r.unshift(s)}u(te,"ensureFactoryImport");export{he as addResource};
1
+ var D=Object.defineProperty;var u=(r,e)=>D(r,"name",{value:e,configurable:!0});import{failure as t,success as P}from"../../types/Result.js";import{DEFAULT_FILE_PATH as F,computeLinesDelta as M,extractProgramBody as C,isRecord as v}from"../_internal.js";import{evaluateEmitGuard as x}from"../emitGuard.js";import{projectEmittedProperties as w}from"../emitProjection.js";import{appendSpecifier as G,buildAppMethodWrappedStatement as N,buildFactoryStatement as Q,buildImportDeclaration as B,detectQuoteStyle as U,parse as _,printFile as O}from"../fileRewriter/index.js";import{STATEMENT_REGISTRY as W}from"../registry.js";import{locateAllShapes as j,locateByShape as Y}from"../semanticIndex/index.js";import{checkControlFlowPolicy as q}from"./controlFlowPolicy.js";import{driftGate as H,runPipeline as $,schemaGate as z}from"../validationGate/index.js";import{resolveAppBindingName as J}from"./addResource/appBinding.js";import{buildUnmanagedDuplicateError as K}from"./unmanagedShapeErrors.js";import{buildResourceLocations as V,indexBody as X,orderByEndPos as Z,resolveInsertIndex as ee}from"./addResource/bodyIndex.js";import{buildPropertyInputs as re}from"./addResource/propertyBuilder.js";import{findInsertionPosition as te}from"./findInsertionPosition.js";const k="@fjall/components-infrastructure";function ge(r,e,m={}){const s=e.filePath??F,o=_(r,s);if(!o.success)return t(o.error);const a=Y(r,{type:e.type,name:e.name},s);if(!a.success)return a.error.kind==="TemplateLiteralNameError"?t(a.error):t({kind:"SemanticQueryError",reason:a.error.reason,cause:a.error.cause});if(a.data!==void 0){if(a.data.managed===!1)return t(K(e.type,a.data.symbolName));const d=q({ast:o.data,target:a.data,resource:{type:e.type,name:e.name},op:"add"});if(d.refusal!==void 0)return t(d.refusal);const h=$([z,H],{content:r,plan:{type:e.type,name:e.name,properties:e.properties,op:"add"},baseline:m.baseline,policy:e.driftPolicy});return h.success?h.data.action==="skip"?P({content:r,linesChanged:{added:0,removed:0},skipped:!0}):t({kind:"DuplicateResourceError",type:e.type,name:e.name}):t(ae(h.error))}const f=U(o.data),l=w(e.type,e.properties);if("refusal"in l)return t(l.refusal);const y=re(l.props,f);if(!y.success)return t(y.error);const c=C(o.data);if(c===void 0)return t({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const i=W[e.type],I=x(i.emitGuard,e.properties);if(I!==void 0)return t(I);const S={factory:i.factoryIdentifier,name:e.name,properties:y.data,quoteStyle:f};let E;if(i.emitWrapper!==void 0){const d=J(c);if(d===void 0)return t({kind:"MissingAppInitError",type:e.type,appMethod:i.emitWrapper.appMethod});E=N({...S,appIdentifier:d,appMethod:i.emitWrapper.appMethod})}else E=Q(S);const p=X(c,r),n=j(r,s);if(!n.success)return n.error.kind==="TemplateLiteralNameError"?t(n.error):t({kind:"SemanticQueryError",reason:n.error.reason,cause:n.error.cause});const L=V(p.anchors,n.data),R=Z([...p.appInitLocations,...L]),b=te(p.importInfos,R,e.type,p.programEnd),T=ee(p.anchors,b);c.splice(T,0,E),oe(c,i.factoryIdentifier,f);const g=O(o.data,r),A=M(r,g);return P({content:g,linesChanged:A})}u(ge,"addResource");function ae(r){switch(r.kind){case"ParseError":case"TemplateLiteralNameError":case"DuplicateResourceError":case"InvalidPropertyError":case"SemanticQueryError":case"MissingAppInitError":case"DriftConflictError":case"ControlFlowClassifierError":return r;default:return{kind:"SemanticQueryError",reason:`Unexpected codemod error in validation-gate pipeline: ${r.kind}`}}}u(ae,"narrowGateError");function oe(r,e,m){for(const o of r){if(o.type!=="ImportDeclaration")continue;const a=o.source;if(!(!v(a)||a.type!=="StringLiteral")&&a.value===k){G(o,e);return}}const s=B([e],k,m);r.unshift(s)}u(oe,"ensureFactoryImport");export{ge as addResource};
@@ -1 +1 @@
1
- var T=Object.defineProperty;var u=(e,r)=>T(e,"name",{value:r,configurable:!0});import{failure as d,success as y}from"../../types/Result.js";import{DEFAULT_FILE_PATH as x,computeLinesDelta as k,extractProgramBody as b}from"../_internal.js";import{buildObjectProperty as h,detectQuoteStyle as D,parse as C,printFile as F}from"../fileRewriter/index.js";import{makeStringLiteral as L,toAstValue as w}from"./addResource/propertyBuilder.js";import{astToLiteral as I,isNodeShape as f,readKeyName as g}from"./modifyResource/literalConversion.js";const K="ACCOUNTS",O="workloads";function J(e,r){const n=r.filePath??x,t=r.constName??K,a=r.nestedKey??O,{stage:i,displayName:o}=r,s=C(e,n);if(!s.success)return d(s.error);const l=b(s.data);if(l===void 0)return d({kind:"InvalidStageTargetError",stage:i,reason:"recast File is missing program.body"});const m=$(l,t);if(m===void 0)return d({kind:"ConstNotFoundError",constName:t});const p=D(s.data),c=V(m,{constName:t,stage:i,nestedKey:a,displayName:o,quoteStyle:p});if(!c.success)return d(c.error);if(c.data.created)return P(s.data,e);const v=c.data.array;return v.elements.some(N=>f(N)&&I(N)===o)?y({content:e,linesChanged:{added:0,removed:0},skipped:!0}):(v.elements.push(L(o,p)),P(s.data,e))}u(J,"appendAccountToStage");function P(e,r){const n=F(e,r);return y({content:n,linesChanged:k(r,n)})}u(P,"printSuccess");function V(e,r){const{constName:n,stage:t,nestedKey:a,displayName:i,quoteStyle:o}=r,s=E(e,t);if(s!==void 0)return A(s.value)?y({created:!1,array:s.value}):d({kind:"InvalidStageTargetError",stage:t,reason:`Top-level "${t}" is not an array literal.`});const l=E(e,a);if(l!==void 0&&S(l.value)){const m=l.value,p=E(m,t);if(p!==void 0)return A(p.value)?y({created:!1,array:p.value}):d({kind:"InvalidStageTargetError",stage:t,reason:`Nested "${a}.${t}" is not an array literal.`});const c=_(m,t,i,o);return c.success?y({created:!0}):d(c.error)}return d({kind:"StageNotFoundError",constName:n,stage:t,knownStages:B(e,a)})}u(V,"resolveStageArray");function _(e,r,n,t){const a=w([n],t);if(a===void 0)return d({kind:"InvalidStageTargetError",stage:r,reason:`Unable to build an array literal for "${r}".`});const i=h(r,a,t);return e.properties[e.properties.length-1]?.extra?.trailingComma===!0&&(i.extra={...i.extra??{},trailingComma:!0}),e.properties.push(i),y(void 0)}u(_,"appendStageProperty");function $(e,r){for(const n of e){const t=U(n);if(t===void 0)continue;const a=t.declarations;if(Array.isArray(a))for(const i of a){if(!f(i)||i.type!=="VariableDeclarator")continue;const o=i.id,s=j(i.init);if(f(o)&&o.type==="Identifier"&&o.name===r&&S(s))return s}}}u($,"findConstObjectExpression");function U(e){if(e.type==="VariableDeclaration")return e;if(e.type==="ExportNamedDeclaration"){const r=e.declaration;if(f(r)&&r.type==="VariableDeclaration")return r}}u(U,"unwrapVariableDeclaration");function j(e){let r=e;for(;f(r)&&(r.type==="TSAsExpression"||r.type==="TSSatisfiesExpression");)r=r.expression;return r}u(j,"unwrapExpression");function E(e,r){return e.properties.find(n=>(n.type==="Property"||n.type==="ObjectProperty")&&n.shorthand!==!0&&n.computed!==!0&&g(n.key)===r)}u(E,"findPropertyByKey");function B(e,r){const n=[];for(const t of e.properties){if(t.type!=="Property"&&t.type!=="ObjectProperty")continue;const a=g(t.key);if(a!==void 0)if(a===r&&S(t.value))for(const i of t.value.properties){const o=g(i.key);o!==void 0&&n.push(`${r}.${o}`)}else A(t.value)&&n.push(a)}return n}u(B,"collectStageKeys");function S(e){return f(e)&&e.type==="ObjectExpression"&&Array.isArray(e.properties)}u(S,"isObjectExpression");function A(e){return f(e)&&e.type==="ArrayExpression"&&Array.isArray(e.elements)}u(A,"isArrayExpression");export{J as appendAccountToStage};
1
+ var x=Object.defineProperty;var u=(e,r)=>x(e,"name",{value:r,configurable:!0});import{failure as d,success as y}from"../../types/Result.js";import{DEFAULT_FILE_PATH as P,computeLinesDelta as k,extractProgramBody as b}from"../_internal.js";import{buildObjectProperty as h,detectQuoteStyle as D,parse as C,printFile as F}from"../fileRewriter/index.js";import{makeStringLiteral as L,toAstValue as w}from"./addResource/propertyBuilder.js";import{astToLiteral as I,isNodeShape as l,readKeyName as N}from"./modifyResource/literalConversion.js";import{findPropertyByKey as g}from"./objectGraph.js";const K="ACCOUNTS",V="workloads";function R(e,r){const i=r.filePath??P,t=r.constName??K,n=r.nestedKey??V,{stage:a,displayName:o}=r,s=C(e,i);if(!s.success)return d(s.error);const f=b(s.data);if(f===void 0)return d({kind:"InvalidStageTargetError",stage:a,reason:"recast File is missing program.body"});const m=O(f,t);if(m===void 0)return d({kind:"ConstNotFoundError",constName:t});const p=D(s.data),c=_(m,{constName:t,stage:a,nestedKey:n,displayName:o,quoteStyle:p});if(!c.success)return d(c.error);if(c.data.created)return T(s.data,e);const A=c.data.array;return A.elements.some(v=>l(v)&&I(v)===o)?y({content:e,linesChanged:{added:0,removed:0},skipped:!0}):(A.elements.push(L(o,p)),T(s.data,e))}u(R,"appendAccountToStage");function T(e,r){const i=F(e,r);return y({content:i,linesChanged:k(r,i)})}u(T,"printSuccess");function _(e,r){const{constName:i,stage:t,nestedKey:n,displayName:a,quoteStyle:o}=r,s=g(e,t);if(s!==void 0)return S(s.value)?y({created:!1,array:s.value}):d({kind:"InvalidStageTargetError",stage:t,reason:`Top-level "${t}" is not an array literal.`});const f=g(e,n);if(f!==void 0&&E(f.value)){const m=f.value,p=g(m,t);if(p!==void 0)return S(p.value)?y({created:!1,array:p.value}):d({kind:"InvalidStageTargetError",stage:t,reason:`Nested "${n}.${t}" is not an array literal.`});const c=$(m,t,a,o);return c.success?y({created:!0}):d(c.error)}return d({kind:"StageNotFoundError",constName:i,stage:t,knownStages:B(e,n)})}u(_,"resolveStageArray");function $(e,r,i,t){const n=w([i],t);if(n===void 0)return d({kind:"InvalidStageTargetError",stage:r,reason:`Unable to build an array literal for "${r}".`});const a=h(r,n,t);return e.properties[e.properties.length-1]?.extra?.trailingComma===!0&&(a.extra={...a.extra??{},trailingComma:!0}),e.properties.push(a),y(void 0)}u($,"appendStageProperty");function O(e,r){for(const i of e){const t=U(i);if(t===void 0)continue;const n=t.declarations;if(Array.isArray(n))for(const a of n){if(!l(a)||a.type!=="VariableDeclarator")continue;const o=a.id,s=j(a.init);if(l(o)&&o.type==="Identifier"&&o.name===r&&E(s))return s}}}u(O,"findConstObjectExpression");function U(e){if(e.type==="VariableDeclaration")return e;if(e.type==="ExportNamedDeclaration"){const r=e.declaration;if(l(r)&&r.type==="VariableDeclaration")return r}}u(U,"unwrapVariableDeclaration");function j(e){let r=e;for(;l(r)&&(r.type==="TSAsExpression"||r.type==="TSSatisfiesExpression");)r=r.expression;return r}u(j,"unwrapExpression");function B(e,r){const i=[];for(const t of e.properties){if(t.type!=="Property"&&t.type!=="ObjectProperty")continue;const n=N(t.key);if(n!==void 0)if(n===r&&E(t.value))for(const a of t.value.properties){const o=N(a.key);o!==void 0&&i.push(`${r}.${o}`)}else S(t.value)&&i.push(n)}return i}u(B,"collectStageKeys");function E(e){return l(e)&&e.type==="ObjectExpression"&&Array.isArray(e.properties)}u(E,"isObjectExpression");function S(e){return l(e)&&e.type==="ArrayExpression"&&Array.isArray(e.elements)}u(S,"isArrayExpression");export{R as appendAccountToStage};
@@ -1 +1 @@
1
- var T=Object.defineProperty;var c=(r,e)=>T(r,"name",{value:e,configurable:!0});import{failure as s,success as m}from"../../types/Result.js";import{DEFAULT_FILE_PATH as A,computeLinesDelta as F,extractProgramBody as L,isRecord as y}from"../_internal.js";import{buildObjectProperty as j,detectQuoteStyle as G,parse as O,printFile as Q}from"../fileRewriter/index.js";import{STATEMENT_REGISTRY as P}from"../registry.js";import{locateAllShapes as U,locateByShape as I}from"../semanticIndex/index.js";import{buildUnmanagedEditRefusal as D}from"./unmanagedShapeErrors.js";import{checkControlFlowPolicy as K}from"./controlFlowPolicy.js";import{driftGate as V,runPipeline as B,schemaGate as _}from"../validationGate/index.js";import{toAstValue as M}from"./addResource/propertyBuilder.js";import{buildMergedLiteral as v,collectPropertyKeys as $,isNodeShape as S,readKeyName as H}from"./modifyResource/literalConversion.js";import{evaluateEmitGuard as w,UNRESOLVED as Y}from"../emitGuard.js";function pe(r,e,t={}){const n=e.filePath??A,a=O(r,n);if(!a.success)return s(a.error);const i=I(r,{type:e.type,name:e.name},n);if(!i.success)return i.error.kind==="TemplateLiteralNameError"?s(i.error):s({kind:"SemanticQueryError",reason:i.error.reason,cause:i.error.cause});if(i.data===void 0)return s({kind:"ResourceNotFoundError",type:e.type,name:e.name,knownNames:Z(r,e.type,n)});if(i.data.managed===!1)return s(D(e.type,"modify"));const o=K({ast:a.data,target:i.data,resource:{type:e.type,name:e.name},op:"modify"});if(o.refusal!==void 0)return s(o.refusal);const u=B([_,V],{content:r,plan:{type:e.type,name:e.name,properties:e.properties,op:"modify"},baseline:t.baseline,policy:e.driftPolicy});if(!u.success)return s(q(u.error));if(u.data.action==="skip")return m({content:r,linesChanged:{added:0,removed:0},skipped:!0});const d=L(a.data);if(d===void 0)return s({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const f=z(d,i.data);if(f===void 0)return s({kind:"SemanticQueryError",reason:"Unable to resolve config ObjectExpression for the located resource."});const N=G(a.data),g=v(f,e.properties),E=P[e.type].emitGuard,R=w(E,C(f,v(f,{}))),p=w(E,C(f,g));if(p!==void 0&&p.property!==R?.property)return s(p);const h=P[e.type].schemaFragment.safeParse(g);if(!h.success){const l=h.error.issues[0];return s({kind:"InvalidPropertyError",property:l!==void 0&&l.path.length>0?String(l.path[0]):Object.keys(e.properties)[0]??"<unknown>",reason:l?.message??"Schema validation failed"})}const k=J(f,e.properties,N);if(!k.success)return s(k.error);const b=Q(a.data,r),x=o.warning!==void 0?[o.warning.message]:void 0;return m({content:b,linesChanged:F(r,b),warnings:x})}c(pe,"modifyResource");function C(r,e){const t={...e};for(const n of $(r))n in t||(t[n]=Y);return t}c(C,"buildGuardView");function q(r){switch(r.kind){case"ParseError":case"ResourceNotFoundError":case"InvalidPropertyError":case"TemplateLiteralNameError":case"SemanticQueryError":case"DriftConflictError":case"ControlFlowClassifierError":return r;default:return{kind:"SemanticQueryError",reason:`Unexpected codemod error in validation-gate pipeline: ${r.kind}`}}}c(q,"narrowGateError");function z(r,e){const t=e.start+e.length;let n;const a=c(i=>{if(n!==void 0||i.type!=="CallExpression")return;const o=i.arguments;if(!Array.isArray(o)||o.length<2)return;const u=o[0];if(!S(u)||u.type!=="StringLiteral"||u.start!==e.start||u.end!==t)return;const d=o[1];S(d)&&d.type==="ObjectExpression"&&(n=d)},"visitor");for(const i of r)if(ee(i,a),n!==void 0)break;return n}c(z,"findConfigObject");function J(r,e,t){const n=X(r);for(const[a,i]of Object.entries(e)){const o=M(i,t);if(o===void 0)return s({kind:"InvalidPropertyError",property:a,reason:`Unsupported property value for "${a}" (accepts string/number/boolean/null/array/object of the same).`});const u=W(r,a);if(u!==void 0){u.value=o;continue}const d=j(a,o,t);n&&(d.extra={...d.extra??{},trailingComma:!0}),r.properties.push(d)}return m(void 0)}c(J,"applyPropertyEdits");function W(r,e){return r.properties.find(t=>(t.type==="Property"||t.type==="ObjectProperty")&&t.shorthand!==!0&&t.computed!==!0&&H(t.key)===e)}c(W,"findPropertyByKey");function X(r){return r.properties[r.properties.length-1]?.extra?.trailingComma===!0}c(X,"detectTrailingCommaStyle");function Z(r,e,t){const n=U(r,t);return n.success?n.data.filter(a=>a.type===e).map(a=>a.symbolName):[]}c(Z,"collectKnownNames");function ee(r,e){const t=[r];for(;t.length>0;){const n=t.pop();if(y(n)){typeof n.type=="string"&&e(n);for(const a of Object.keys(n)){if(a==="loc"||a==="comments"||a==="tokens")continue;const i=n[a];if(Array.isArray(i))for(const o of i)y(o)&&t.push(o);else y(i)&&t.push(i)}}}}c(ee,"visit");export{pe as modifyResource};
1
+ var T=Object.defineProperty;var d=(r,e)=>T(r,"name",{value:e,configurable:!0});import{failure as i,success as y}from"../../types/Result.js";import{DEFAULT_FILE_PATH as F,computeLinesDelta as L,extractProgramBody as j}from"../_internal.js";import{buildObjectProperty as A,detectQuoteStyle as G,parse as Q,printFile as U}from"../fileRewriter/index.js";import{STATEMENT_REGISTRY as P}from"../registry.js";import{locateAllShapes as I,locateByShape as D}from"../semanticIndex/index.js";import{buildUnmanagedEditRefusal as O}from"./unmanagedShapeErrors.js";import{checkControlFlowPolicy as V}from"./controlFlowPolicy.js";import{driftGate as B,runPipeline as K,schemaGate as _}from"../validationGate/index.js";import{toAstValue as M}from"./addResource/propertyBuilder.js";import{buildMergedLiteral as b,collectPropertyKeys as $,isNodeShape as S}from"./modifyResource/literalConversion.js";import{findPropertyByKey as H,visit as Y}from"./objectGraph.js";import{evaluateEmitGuard as q,UNRESOLVED as z}from"../emitGuard.js";import{projectEmittedProperties as J,projectionRefusal as W}from"../emitProjection.js";function Ee(r,e,s={}){const n=e.filePath??F,t=Q(r,n);if(!t.success)return i(t.error);const a=D(r,{type:e.type,name:e.name},n);if(!a.success)return a.error.kind==="TemplateLiteralNameError"?i(a.error):i({kind:"SemanticQueryError",reason:a.error.reason,cause:a.error.cause});if(a.data===void 0)return i({kind:"ResourceNotFoundError",type:e.type,name:e.name,knownNames:te(r,e.type,n)});if(a.data.managed===!1)return i(O(e.type,"modify"));const o=V({ast:t.data,target:a.data,resource:{type:e.type,name:e.name},op:"modify"});if(o.refusal!==void 0)return i(o.refusal);const u=K([_,B],{content:r,plan:{type:e.type,name:e.name,properties:e.properties,op:"modify"},baseline:s.baseline,policy:e.driftPolicy});if(!u.success)return i(X(u.error));if(u.data.action==="skip")return y({content:r,linesChanged:{added:0,removed:0},skipped:!0});const c=j(t.data);if(c===void 0)return i({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const f=Z(c,a.data);if(f===void 0)return i({kind:"SemanticQueryError",reason:"Unable to resolve config ObjectExpression for the located resource."});const w=G(t.data),x=b(f,e.properties),C=P[e.type].emitGuard,g=d(l=>q(C,l)??W(e.type,l),"judge"),R=g(v(f,b(f,{}))),p=g(v(f,x));if(p!==void 0&&p.property!==R?.property)return i(p);const E=P[e.type].schemaFragment.safeParse(e.properties);if(!E.success){const l=E.error.issues[0];return i({kind:"InvalidPropertyError",property:l!==void 0&&l.path.length>0?String(l.path[0]):Object.keys(e.properties)[0]??"<unknown>",reason:l?.message??"Schema validation failed"})}const m=J(e.type,e.properties,{editingExisting:!0});if("refusal"in m)return i(m.refusal);const h=ee(f,m.props,w);if(!h.success)return i(h.error);const k=U(t.data,r),N=o.warning!==void 0?[o.warning.message]:void 0;return y({content:k,linesChanged:L(r,k),warnings:N})}d(Ee,"modifyResource");function v(r,e){const s={...e};for(const n of $(r))n in s||(s[n]=z);return s}d(v,"buildGuardView");function X(r){switch(r.kind){case"ParseError":case"ResourceNotFoundError":case"InvalidPropertyError":case"TemplateLiteralNameError":case"SemanticQueryError":case"DriftConflictError":case"ControlFlowClassifierError":return r;default:return{kind:"SemanticQueryError",reason:`Unexpected codemod error in validation-gate pipeline: ${r.kind}`}}}d(X,"narrowGateError");function Z(r,e){const s=e.start+e.length;let n;const t=d(a=>{if(n!==void 0||a.type!=="CallExpression")return;const o=a.arguments;if(!Array.isArray(o)||o.length<2)return;const u=o[0];if(!S(u)||u.type!=="StringLiteral"||u.start!==e.start||u.end!==s)return;const c=o[1];S(c)&&c.type==="ObjectExpression"&&(n=c)},"visitor");for(const a of r)if(Y(a,t),n!==void 0)break;return n}d(Z,"findConfigObject");function ee(r,e,s){const n=re(r);for(const{key:t,value:a}of e){const o=M(a,s);if(o===void 0)return i({kind:"InvalidPropertyError",property:t,reason:`Unsupported property value for "${t}" (accepts string/number/boolean/null/array/object of the same).`});const u=H(r,t);if(u!==void 0){u.value=o;continue}const c=A(t,o,s);n&&(c.extra={...c.extra??{},trailingComma:!0}),r.properties.push(c)}return y(void 0)}d(ee,"applyPropertyEdits");function re(r){return r.properties[r.properties.length-1]?.extra?.trailingComma===!0}d(re,"detectTrailingCommaStyle");function te(r,e,s){const n=I(r,s);return n.success?n.data.filter(t=>t.type===e).map(t=>t.symbolName):[]}d(te,"collectKnownNames");export{Ee as modifyResource};
@@ -0,0 +1,24 @@
1
+ import { type NodeShapeLike } from "./modifyResource/literalConversion.js";
2
+ export interface ModuleConstResolver {
3
+ /**
4
+ * Strings of `const NAME = ["A", "B"] as const`. `undefined` when NAME is
5
+ * not a uniquely-bound module-scope const initialised to a flat array of
6
+ * string literals (nested spreads do not resolve).
7
+ */
8
+ resolveStringArray(name: string): readonly string[] | undefined;
9
+ /** Value of `const NAME = "A"`; `undefined` when not uniquely so bound. */
10
+ resolveString(name: string): string | undefined;
11
+ /**
12
+ * Statically-known keys of the object a node denotes: an object literal
13
+ * (following nested same-file spreads) or an identifier naming a
14
+ * uniquely-bound module-scope const object. `undefined` when any key is
15
+ * computed or any spread does not resolve.
16
+ */
17
+ objectKeysOf(node: NodeShapeLike): readonly string[] | undefined;
18
+ }
19
+ export declare function buildModuleConstResolver(body: NodeShapeLike[]): ModuleConstResolver;
20
+ /**
21
+ * The string a node statically denotes: a string literal or an
22
+ * expressionless template literal. `undefined` for anything else.
23
+ */
24
+ export declare function readStaticString(node: NodeShapeLike): string | undefined;
@@ -0,0 +1 @@
1
+ var b=Object.defineProperty;var f=(a,r)=>b(a,"name",{value:r,configurable:!0});import{isRecord as l}from"../_internal.js";import{isNodeShape as d,readKeyName as S}from"./modifyResource/literalConversion.js";function w(a){const r=k(a),s=x(a),t=f(n=>r.get(n)===1?s.get(n):void 0,"initFor");return{resolveString(n){const e=t(n);return e===void 0?void 0:g(e)},resolveStringArray(n){const e=t(n);if(e===void 0)return;const i=y(e);if(i.type!=="ArrayExpression")return;const o=i.elements;if(!Array.isArray(o))return;const u=[];for(const p of o){if(!d(p))return;const A=g(p);if(A===void 0)return;u.push(A)}return u},objectKeysOf:f(n=>m(n,t,new Set),"objectKeysOf")}}f(w,"buildModuleConstResolver");function g(a){const r=y(a);if(r.type==="StringLiteral"){const s=r.value;return typeof s=="string"?s:void 0}if(r.type==="TemplateLiteral"){const s=r.expressions,t=r.quasis;if(!Array.isArray(s)||s.length!==0||!Array.isArray(t)||t.length!==1)return;const[c]=t;return!l(c)||!l(c.value)?void 0:typeof c.value.cooked=="string"?c.value.cooked:void 0}}f(g,"readStaticString");const h=new Set(["TSAsExpression","TSSatisfiesExpression","TSTypeAssertion","TSNonNullExpression","ParenthesizedExpression"]);function y(a){let r=a;for(;h.has(r.type);){const s=r.expression;if(!d(s))return r;r=s}return r}f(y,"unwrapTsWrappers");function m(a,r,s){const t=y(a);if(t.type==="Identifier"){const e=t.name;if(typeof e!="string"||s.has(e))return;s.add(e);const i=r(e);return i===void 0?void 0:m(i,r,s)}if(t.type!=="ObjectExpression")return;const c=t.properties;if(!Array.isArray(c))return;const n=[];for(const e of c){if(!d(e))return;if(e.type==="SpreadElement"||e.type==="SpreadProperty"){const u=e.argument;if(!d(u))return;const p=m(u,r,s);if(p===void 0)return;n.push(...p);continue}if(e.type!=="Property"&&e.type!=="ObjectProperty"&&e.type!=="ObjectMethod"||e.computed===!0)return;const i=e.key;if(!d(i))return;const o=S(i);if(o===void 0)return;n.push(o)}return n}f(m,"objectKeysOfNode");function k(a){const r=new Map,s=f(n=>{r.set(n,(r.get(n)??0)+1)},"bump"),t=f(n=>{if(d(n))switch(n.type){case"Identifier":{const e=n.name;typeof e=="string"&&s(e);return}case"ObjectPattern":{const e=n.properties;if(!Array.isArray(e))return;for(const i of e)d(i)&&(i.type==="RestElement"||i.type==="RestProperty"?t(i.argument):t(i.value));return}case"ArrayPattern":{const e=n.elements;if(!Array.isArray(e))return;for(const i of e)t(i);return}case"AssignmentPattern":t(n.left);return;case"RestElement":t(n.argument);return;case"TSParameterProperty":t(n.parameter);return;default:return}},"bumpPattern"),c=f(n=>{const e=[n];for(;e.length>0;){const i=e.pop();if(l(i)){if(typeof i.type=="string"){const o=i;switch(o.type){case"VariableDeclarator":t(o.id);break;case"FunctionDeclaration":case"FunctionExpression":case"ArrowFunctionExpression":{t(o.id);const u=o.params;if(Array.isArray(u))for(const p of u)t(p);break}case"ClassDeclaration":case"ClassExpression":t(o.id);break;case"ImportSpecifier":case"ImportDefaultSpecifier":case"ImportNamespaceSpecifier":t(o.local);break;case"CatchClause":t(o.param);break;default:break}}for(const o of Object.keys(i)){if(o==="loc"||o==="comments"||o==="tokens")continue;const u=i[o];if(Array.isArray(u))for(const p of u)l(p)&&e.push(p);else l(u)&&e.push(u)}}}},"visitForBindings");for(const n of a)c(n);return r}f(k,"countBindings");function x(a){const r=new Map;for(const s of a){const t=s.type==="ExportNamedDeclaration"?s.declaration:s;if(!d(t)||t.type!=="VariableDeclaration"||t.kind!=="const")continue;const c=t.declarations;if(Array.isArray(c))for(const n of c){if(!d(n)||n.type!=="VariableDeclarator")continue;const e=n.id,i=n.init;if(!d(e)||e.type!=="Identifier"||!d(i))continue;const o=e.name;typeof o=="string"&&r.set(o,i)}}return r}f(x,"collectTopLevelConstInits");export{w as buildModuleConstResolver,g as readStaticString};
@@ -0,0 +1,28 @@
1
+ import { type NodeShapeLike, type ObjectExpressionNodeLike, type PropertyNodeLike } from "./modifyResource/literalConversion.js";
2
+ /**
3
+ * Finds a plain (non-shorthand, non-computed) property by key name.
4
+ *
5
+ * `undefined` means "no plain property with that key" — NOT "the key is
6
+ * absent". A spread, a shorthand, or a computed key can still supply it.
7
+ * Callers that act on absence must gate on {@link objectAbsenceIsProvable}.
8
+ */
9
+ export declare function findPropertyByKey(obj: ObjectExpressionNodeLike, key: string): PropertyNodeLike | undefined;
10
+ /**
11
+ * True when a `findPropertyByKey(obj, key) === undefined` result may safely be
12
+ * read as "the key is absent from this object".
13
+ *
14
+ * False when the object carries a spread (which can supply any key), a
15
+ * computed property (whose key is not statically known), or a shorthand
16
+ * property named `key` — each of which makes the key present while
17
+ * {@link findPropertyByKey} reports nothing. Appending in those cases would
18
+ * emit a duplicate that silently overrides, or is overridden by, the invisible
19
+ * one depending on source order.
20
+ */
21
+ export declare function objectAbsenceIsProvable(obj: ObjectExpressionNodeLike, key: string): boolean;
22
+ /**
23
+ * Non-recursive depth-first walk over every typed node reachable from `root`.
24
+ *
25
+ * Skips `loc`, `comments` and `tokens` so large fixtures do not descend into
26
+ * parser bookkeeping.
27
+ */
28
+ export declare function visit(root: NodeShapeLike, visitor: (node: NodeShapeLike) => void): void;
@@ -0,0 +1 @@
1
+ var f=Object.defineProperty;var s=(t,r)=>f(t,"name",{value:r,configurable:!0});import{isRecord as u}from"../_internal.js";import{readKeyName as c}from"./modifyResource/literalConversion.js";function d(t,r){return t.properties.find(e=>(e.type==="Property"||e.type==="ObjectProperty")&&e.shorthand!==!0&&e.computed!==!0&&c(e.key)===r)}s(d,"findPropertyByKey");function h(t,r){return!t.properties.some(e=>e.type==="SpreadElement"||e.type==="SpreadProperty"?!0:e.type!=="Property"&&e.type!=="ObjectProperty"?!1:e.computed===!0?!0:e.shorthand===!0&&c(e.key)===r)}s(h,"objectAbsenceIsProvable");function l(t,r){const e=[t];for(;e.length>0;){const n=e.pop();if(u(n)){typeof n.type=="string"&&r(n);for(const o of Object.keys(n)){if(o==="loc"||o==="comments"||o==="tokens")continue;const i=n[o];if(Array.isArray(i))for(const y of i)u(y)&&e.push(y);else u(i)&&e.push(i)}}}}s(l,"visit");export{d as findPropertyByKey,h as objectAbsenceIsProvable,l as visit};
@@ -0,0 +1,48 @@
1
+ import { type ModuleConstResolver } from "./moduleConstResolver.js";
2
+ import { type ObjectExpressionNodeLike } from "./modifyResource/literalConversion.js";
3
+ /** One element of a `secrets` array, classified for provability. */
4
+ export type SecretsElement = {
5
+ kind: "literal";
6
+ name: string;
7
+ description: string;
8
+ } | {
9
+ kind: "identifier";
10
+ name: string;
11
+ description: string;
12
+ } | {
13
+ kind: "spread";
14
+ names: readonly string[];
15
+ description: string;
16
+ } | {
17
+ kind: "unresolvable";
18
+ description: string;
19
+ };
20
+ export type ProvabilityCheck = {
21
+ ok: true;
22
+ warnings: string[];
23
+ } | {
24
+ ok: false;
25
+ reason: string;
26
+ };
27
+ export declare function classifySecretsElement(element: unknown, resolver: ModuleConstResolver): SecretsElement;
28
+ export declare function describeElements(elements: readonly SecretsElement[]): string;
29
+ /**
30
+ * True when `key` is provably absent from the container object — either
31
+ * structurally (no spread/shorthand/computed at all) or because every spread
32
+ * resolves to a same-file const object whose keys are known not to include it.
33
+ */
34
+ export declare function keyProvablyAbsent(container: ObjectExpressionNodeLike, key: string, resolver: ModuleConstResolver): boolean;
35
+ /**
36
+ * A spread placed AFTER the `secrets` property overrides it at runtime when
37
+ * the spread object also carries a `secrets` key — the edit would mutate a
38
+ * dead literal while reporting success. Refuses unless every later spread is
39
+ * proven not to redefine `secrets`.
40
+ */
41
+ export declare function checkShadowingSpread(container: ObjectExpressionNodeLike, secretsPropIndex: number, resolver: ModuleConstResolver): ProvabilityCheck;
42
+ /**
43
+ * A name present in both `secrets` and `secretsImport` fails `fjall deploy`
44
+ * at synth (the construct rejects the overlap). Proven collisions refuse;
45
+ * an unenumerable `secretsImport` degrades to a warning because the
46
+ * construct's own validation is the authoritative, clearly-worded gate.
47
+ */
48
+ export declare function checkSecretsImportConflicts(container: ObjectExpressionNodeLike, namesToAdd: readonly string[], resolver: ModuleConstResolver): ProvabilityCheck;
@@ -0,0 +1 @@
1
+ var m=Object.defineProperty;var o=(t,r)=>m(t,"name",{value:r,configurable:!0});import{readStaticString as g}from"./moduleConstResolver.js";import{isNodeShape as c,readKeyName as h}from"./modifyResource/literalConversion.js";import{findPropertyByKey as d,objectAbsenceIsProvable as b}from"./objectGraph.js";const u="secretsImport";function w(t,r){if(!c(t))return{kind:"unresolvable",description:"an unrecognised element"};if(t.type==="SpreadElement"||t.type==="SpreadProperty"){const e=t.argument;if(c(e)&&e.type==="Identifier"){const n=e.name;if(typeof n=="string"){const s=r.resolveStringArray(n);return s!==void 0?{kind:"spread",names:s,description:`...${n}`}:{kind:"unresolvable",description:`...${n}`}}}return{kind:"unresolvable",description:"...<expression>"}}const i=g(t);if(i!==void 0)return{kind:"literal",name:i,description:JSON.stringify(i)};if(t.type==="Identifier"){const e=t.name;if(typeof e=="string"){const n=r.resolveString(e);return n!==void 0?{kind:"identifier",name:n,description:e}:{kind:"unresolvable",description:e}}}return{kind:"unresolvable",description:"an expression element"}}o(w,"classifySecretsElement");function $(t){const r=t.slice(0,3).map(e=>`\`${e.description}\``),i=t.length>3?", \u2026":"";return r.join(", ")+i}o($,"describeElements");function k(t,r,i){if(d(t,r)!==void 0)return!1;if(b(t,r))return!0;for(const e of t.properties){if(e.type==="SpreadElement"||e.type==="SpreadProperty"){const n=e.argument;if(!c(n))return!1;const s=i.objectKeysOf(n);if(s===void 0||s.includes(r))return!1;continue}if(!(e.type!=="Property"&&e.type!=="ObjectProperty")&&(e.computed===!0||e.shorthand===!0&&h(e.key)===r))return!1}return!0}o(k,"keyProvablyAbsent");function x(t,r,i){for(const e of t.properties.slice(r+1)){if(e.type!=="SpreadElement"&&e.type!=="SpreadProperty")continue;const n=e.argument,s=c(n)&&n.type==="Identifier"?n.name:void 0,a=typeof s=="string"?`...${s}`:"...<expression>";if(!c(n))return{ok:!1,reason:p(a,"cannot be resolved")};const f=i.objectKeysOf(n);if(f===void 0)return{ok:!1,reason:p(a,"does not resolve to a same-file const object")};if(f.includes("secrets"))return{ok:!1,reason:`The container spreads \`${a}\` after \`secrets\`, and it redefines \`secrets\` \u2014 the edit would be overridden at runtime. Edit that object, or move the spread above \`secrets\`.`}}return{ok:!0,warnings:[]}}o(x,"checkShadowingSpread");function p(t,r){return`The container spreads \`${t}\` after \`secrets\`, which ${r}, so the edit cannot be proven to take effect at runtime. Move the spread above \`secrets\` or edit the file by hand.`}o(p,"shadowingReason");function E(t,r,i){if(r.length===0)return{ok:!0,warnings:[]};const e=d(t,u);if(e===void 0)return k(t,u,i)?{ok:!0,warnings:[]}:{ok:!0,warnings:[l(r,"the container may supply `secretsImport` indirectly")]};const n=e.value!==void 0&&c(e.value)?i.objectKeysOf(e.value):void 0;if(n===void 0)return{ok:!0,warnings:[l(r,"`secretsImport` is not statically enumerable here")]};const s=r.filter(a=>n.includes(a));if(s.length>0){const a=s.map(y=>JSON.stringify(y)).join(", "),f=s.length===1?"is":"are";return{ok:!1,reason:`${a} ${f} already wired via \`secretsImport\`; declaring the same name in \`secrets\` fails \`fjall deploy\` at synth. Remove it from \`secretsImport\` first, or use a different name.`}}return{ok:!0,warnings:[]}}o(E,"checkSecretsImportConflicts");function l(t,r){return`Could not check ${t.map(e=>JSON.stringify(e)).join(", ")} against \`secretsImport\` (${r}); a name declared in both is rejected by \`fjall deploy\` at synth.`}o(l,"buildImportWarning");export{E as checkSecretsImportConflicts,x as checkShadowingSpread,w as classifySecretsElement,$ as describeElements,k as keyProvablyAbsent};
@@ -0,0 +1,55 @@
1
+ import { type Result } from "../../types/Result.js";
2
+ import type { LinesChanged, ParseError } from "../types.js";
3
+ export interface SetContainerSecretsOptions {
4
+ /** ECS service `name` to target, e.g. "api". */
5
+ serviceName: string;
6
+ /** Container within that service. Defaults to the first. */
7
+ containerIndex?: number;
8
+ /** Names to declare. Already-declared names are left alone. */
9
+ add?: readonly string[];
10
+ /** Names to undeclare. Names not declared are ignored. */
11
+ remove?: readonly string[];
12
+ /**
13
+ * Path the caller's namespace implies. Compared against an explicitly
14
+ * declared `ssmSecretsPath` to surface a mismatch; never written — an
15
+ * absent declaration is the construct's own `/<app>/<cluster>/<service>`
16
+ * derivation and writing it back would duplicate that derivation here.
17
+ */
18
+ expectedSsmSecretsPath?: string;
19
+ filePath?: string;
20
+ }
21
+ export interface SetContainerSecretsSuccess {
22
+ /** Byte-identical to the input when `skipped` is true. */
23
+ content: string;
24
+ linesChanged: LinesChanged;
25
+ added: string[];
26
+ removed: string[];
27
+ skipped: boolean;
28
+ warnings: string[];
29
+ }
30
+ export interface ServiceNotFoundError {
31
+ kind: "ServiceNotFoundError";
32
+ serviceName: string;
33
+ knownServices: string[];
34
+ }
35
+ export interface ContainerNotFoundError {
36
+ kind: "ContainerNotFoundError";
37
+ serviceName: string;
38
+ containerIndex: number;
39
+ containerCount: number;
40
+ }
41
+ /**
42
+ * `reason` is author-written text that may embed identifiers, property keys
43
+ * and secret NAMES read from the parsed source or CLI input — identifier-class
44
+ * data, never expression values (see security-standards § "Values, not
45
+ * identifiers"). It is never error-derived: interpolating a caught error's
46
+ * message here would silently make every consumer a leak. The CLI boundary
47
+ * masks defensively regardless.
48
+ */
49
+ export interface UnsupportedSecretsShapeError {
50
+ kind: "UnsupportedSecretsShapeError";
51
+ serviceName: string;
52
+ reason: string;
53
+ }
54
+ export type SetContainerSecretsError = ParseError | ServiceNotFoundError | ContainerNotFoundError | UnsupportedSecretsShapeError;
55
+ export declare function setContainerSecrets(content: string, options: SetContainerSecretsOptions): Result<SetContainerSecretsSuccess, SetContainerSecretsError>;
@@ -0,0 +1 @@
1
+ var I=Object.defineProperty;var d=(t,e)=>I(t,"name",{value:e,configurable:!0});import{failure as a,success as m}from"../../types/Result.js";import{DEFAULT_FILE_PATH as _,computeLinesDelta as D,extractProgramBody as M}from"../_internal.js";import{buildObjectProperty as R,detectQuoteStyle as B,parse as K,printFile as q}from"../fileRewriter/index.js";import{makeStringLiteral as H,toAstValue as J}from"./addResource/propertyBuilder.js";import{astToLiteral as W,isNodeShape as v,NON_LITERAL as Y,readKeyName as z}from"./modifyResource/literalConversion.js";import{buildModuleConstResolver as Q}from"./moduleConstResolver.js";import{findPropertyByKey as A,visit as V}from"./objectGraph.js";import{checkSecretsImportConflicts as j,checkShadowingSpread as G,classifySecretsElement as X,describeElements as F,keyProvablyAbsent as Z}from"./secretsProvability.js";const N="ComputeFactory",ee="build",x="secrets";function ve(t,e){const n=e.filePath??_,{serviceName:r}=e,o=e.containerIndex??0,i=e.add??[],u=e.remove??[],c=K(t,n);if(!c.success)return a(c.error);const p=M(c.data);if(p===void 0)return a({kind:"UnsupportedSecretsShapeError",serviceName:r,reason:"recast File is missing program.body"});const l=re(p,r);if(!l.success)return a(l.error);const{service:y}=l.data,h=oe(y,r,o);if(!h.success)return a(h.error);const g=ie(y,r,e.expectedSsmSecretsPath),k=Q(p),b=ae(h.data,r,k,{add:i,remove:u,quoteStyle:B(c.data)});if(!b.success)return a(b.error);const{added:w,removed:C}=b.data,P=[...g,...b.data.warnings];return w.length===0&&C.length===0?m({content:t,linesChanged:{added:0,removed:0},added:[],removed:[],skipped:!0,warnings:P}):m({...te(c.data,t),added:w,removed:C,skipped:!1,warnings:P})}d(ve,"setContainerSecrets");function te(t,e){const n=q(t,e);return{content:n,linesChanged:D(e,n)}}d(te,"printResult");function re(t,e){const n=[],r=[];for(const i of ne(t)){const u=A(i,"services");if(!(u===void 0||!$(u.value)))for(const c of u.value.elements){if(!v(c)||c.type!=="ObjectExpression")continue;const p=c,l=U(p,"name");l!==void 0&&(l===e?r.push(p):n.push(l))}}const[o]=r;return r.length>1?a(S(e,`${String(r.length)} services share the name "${e}" across ComputeFactory.build calls \u2014 the edit cannot be proven to target the right one. Edit the file by hand.`)):o!==void 0?m({service:o}):a({kind:"ServiceNotFoundError",serviceName:e,knownServices:n})}d(re,"locateService");function ne(t){const e=[];for(const n of t)V(n,r=>{if(r.type!=="CallExpression"||!se(r))return;const o=r.arguments;if(!Array.isArray(o))return;const i=o[1];v(i)&&i.type==="ObjectExpression"&&e.push(i)});return e}d(ne,"collectComputeConfigs");function se(t){const e=t.callee;if(!v(e)||e.type!=="MemberExpression"||e.computed===!0)return!1;const n=e.object,r=e.property;return v(n)&&n.type==="Identifier"&&n.name===N&&v(r)&&r.type==="Identifier"&&r.name===ee}d(se,"isComputeFactoryBuild");function oe(t,e,n){const r=A(t,"containers");if(r===void 0||!$(r.value))return a({kind:"UnsupportedSecretsShapeError",serviceName:e,reason:"Service has no `containers` array literal."});const o=r.value.elements,i=o[n];return i===void 0?a({kind:"ContainerNotFoundError",serviceName:e,containerIndex:n,containerCount:o.length}):!v(i)||i.type!=="ObjectExpression"?a({kind:"UnsupportedSecretsShapeError",serviceName:e,reason:`Container ${String(n)} is not an object literal.`}):m(i)}d(oe,"resolveContainer");function ie(t,e,n){if(n===void 0)return[];const r=U(t,"ssmSecretsPath");return r===void 0||r===n?[]:[`Service "${e}" declares ssmSecretsPath "${r}", but the secrets were written under "${n}". The task will read the declared path.`]}d(ie,"collectPathWarnings");function S(t,e){return{kind:"UnsupportedSecretsShapeError",serviceName:t,reason:e}}d(S,"unsupported");function ae(t,e,n,r){const{add:o,remove:i,quoteStyle:u}=r,c=ce(t,x);if(c===-1){if(!Z(t,x,n))return a(S(e,"Container carries a spread, shorthand or computed key that could supply `secrets` invisibly, so an absent property cannot be proven. Declare `secrets` explicitly first."));if(i.length>0&&o.length===0)return m({added:[],removed:[],warnings:[]});const h=O(o),g=j(t,h,n);if(!g.ok)return a(S(e,g.reason));const k=de(t,e,h,u);return k.success?m({...k.data,warnings:g.warnings}):k}const l=t.properties[c]?.value;if(!$(l))return a(S(e,"`secrets` is not an array literal."));const y=G(t,c,n);return y.ok?ue(l,t,e,n,r):a(S(e,y.reason))}d(ae,"applySecrets");function ce(t,e){for(let n=t.properties.length-1;n>=0;n--){const r=t.properties[n];if(r!==void 0&&(r.type==="Property"||r.type==="ObjectProperty")&&r.shorthand!==!0&&r.computed!==!0&&z(r.key)===e)return n}return-1}d(ce,"findLastPlainPropertyIndex");function de(t,e,n,r){const o=O(n);if(o.length===0)return m({added:[],removed:[]});const i=J(o,r);if(i===void 0)return a({kind:"UnsupportedSecretsShapeError",serviceName:e,reason:"Unable to build a `secrets` array literal."});const u=R(x,i,r);return t.properties[t.properties.length-1]?.extra?.trailingComma===!0&&(u.extra={...u.extra??{},trailingComma:!0}),t.properties.push(u),m({added:o,removed:[]})}d(de,"createSecretsArray");function ue(t,e,n,r,o){const{add:i,remove:u,quoteStyle:c}=o,p=t.elements.map(s=>X(s,r)),l=p.filter(s=>s.kind==="unresolvable"),y=new Set(u);if(y.size>0){if(l.length>0)return a(S(n,`\`secrets\` contains ${F(l)}, which cannot be resolved to string literals in this file, so a removed name cannot be proven gone. Edit the array by hand.`));for(const s of p){if(s.kind!=="spread")continue;const E=s.names.filter(f=>y.has(f));if(E.length>0){const f=E.map(T=>JSON.stringify(T)).join(", "),L=E.length===1?"is":"are";return a(S(n,`${f} ${L} supplied by \`${s.description}\`, so this edit cannot undeclare it \u2014 the shared array may feed other services. Edit \`${s.description.slice(3)}\` by hand.`))}}}const h=[],g=[];t.elements=t.elements.filter((s,E)=>{const f=p[E];return f!==void 0&&(f.kind==="literal"||f.kind==="identifier")&&y.has(f.name)?(h.push(f.name),!1):(f!==void 0&&g.push(f),!0)});const k=new Set(g.flatMap(s=>s.kind==="unresolvable"?[]:s.kind==="spread"?[...s.names]:[s.name])),b=O(i).filter(s=>!k.has(s));if(b.length===0)return m({added:[],removed:h,warnings:[]});const w=g.filter(s=>s.kind==="unresolvable");if(w.length>0){const s=b.map(E=>JSON.stringify(E)).join(", ");return a(S(n,`\`secrets\` contains ${F(w)}, which cannot be resolved in this file, so ${s} cannot be proven absent \u2014 a duplicate name breaks \`fjall deploy\` at synth. Add it by hand.`))}const C=j(e,b,r);if(!C.ok)return a(S(n,C.reason));const P=[];for(const s of b)t.elements.push(H(s,c)),P.push(s);return m({added:P,removed:h,warnings:C.warnings})}d(ue,"mutateSecretsArray");function U(t,e){const n=A(t,e);if(n===void 0||!v(n.value))return;const r=W(n.value);return r===Y||typeof r!="string"?void 0:r}d(U,"readStringProperty");function $(t){return v(t)&&t.type==="ArrayExpression"&&Array.isArray(t.elements)}d($,"isArrayExpression");function O(t){return[...new Set(t)]}d(O,"dedupe");export{ve as setContainerSecrets};
@@ -0,0 +1,29 @@
1
+ import { type ProjectionContext } from "../projection/index.js";
2
+ import { type EmitGuardProperties } from "./emitGuard.js";
3
+ import type { InvalidPropertyError, StatementType } from "./types.js";
4
+ /** One emitted construct prop, resolved to a serialisable value. */
5
+ export interface LiteralProp {
6
+ key: string;
7
+ value: unknown;
8
+ }
9
+ /**
10
+ * The first plan key in `properties` that this type cannot turn into a
11
+ * construct prop, as the codebase's actionable error shape.
12
+ *
13
+ * Values are passed through verbatim, `UNRESOLVED` included: a plan-only key
14
+ * is inert whatever it holds, which is exactly the presence test the
15
+ * `silentlyDropped` rules applied.
16
+ */
17
+ export declare function projectionRefusal(type: StatementType, properties: EmitGuardProperties): InvalidPropertyError | undefined;
18
+ /**
19
+ * The construct props to write for `properties`, or the refusal that stops
20
+ * the write.
21
+ *
22
+ * A non-projectable type is emitted as it always was — its plan keys go into
23
+ * the file verbatim and its `emitGuard` is what decides whether that is safe.
24
+ */
25
+ export declare function projectEmittedProperties(type: StatementType, properties: Readonly<Record<string, unknown>>, context?: ProjectionContext): {
26
+ props: LiteralProp[];
27
+ } | {
28
+ refusal: InvalidPropertyError;
29
+ };
@@ -0,0 +1 @@
1
+ var y=Object.defineProperty;var n=(e,r)=>y(e,"name",{value:r,configurable:!0});import{isProjectableType as u,projectPlanToConstructProps as a}from"../projection/index.js";import{AUTHOR_BY_HAND as p}from"./emitGuard.js";function l(e,r){return{kind:"InvalidPropertyError",property:e,reason:`${r} \`fjall add\` would write it into the factory call and the resource would deploy without it. ${p}`}}n(l,"unprojectableRefusal");function v(e,r){if(!u(e))return;const[t]=a(e,r).unprojectable;if(t!==void 0)return l(t.key,t.reason)}n(v,"projectionRefusal");function h(e,r,t={}){if(!u(e))return{props:Object.entries(r).map(([o,d])=>({key:o,value:d}))};const{props:c,unprojectable:f}=a(e,r,t),[i]=f;if(i!==void 0)return{refusal:l(i.key,i.reason)};const s=[];for(const o of c){if(o.value.kind==="expression")return{refusal:{kind:"InvalidPropertyError",property:o.key,reason:`\`${o.key}\` needs a live construct expression, which this command cannot resolve against a file it did not write. ${p}`}};s.push({key:o.key,value:o.value.value})}return{props:s}}n(h,"projectEmittedProperties");export{h as projectEmittedProperties,v as projectionRefusal};
@@ -2,6 +2,7 @@ export { addResource, type AddResourceCallContext, type AddResourceError, type A
2
2
  export { removeResource, type RemoveResourceError, type RemoveResourceSuccess, } from "./edits/removeResource.js";
3
3
  export { modifyResource, type ModifyResourceCallContext, type ModifyResourceError, type ModifyResourceSuccess, } from "./edits/modifyResource.js";
4
4
  export { appendAccountToStage, type AppendAccountToStageError, type AppendAccountToStageOptions, type AppendAccountToStageSuccess, } from "./edits/appendAccountToStage.js";
5
+ export { setContainerSecrets, type SetContainerSecretsError, type SetContainerSecretsOptions, type SetContainerSecretsSuccess, } from "./edits/setContainerSecrets.js";
5
6
  export { addVpcPeer, modifyVpcPeer, removeVpcPeer, type VpcPeerAddOptions, type VpcPeerModifyOptions, type VpcPeerOrchestratorSuccess, type VpcPeerRemoveOptions, } from "./edits/vpcPeer.js";
6
7
  export { addVpcPeerAccepter, modifyVpcPeerAccepter, removeVpcPeerAccepter, type VpcPeerAccepterAddOptions, type VpcPeerAccepterModifyOptions, type VpcPeerAccepterOrchestratorSuccess, type VpcPeerAccepterRemoveOptions, } from "./edits/vpcPeerAccepter.js";
7
8
  export { addCrossPlanConnection, modifyCrossPlanConnection, removeCrossPlanConnection, type CrossPlanConnectionAddOptions, type CrossPlanConnectionModifyOptions, type CrossPlanConnectionOrchestratorSuccess, type CrossPlanConnectionRemoveOptions, } from "./edits/crossPlanConnection.js";