@fjall/generator 0.89.5 → 0.89.6

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 (168) hide show
  1. package/LICENSE +50 -21
  2. package/README.md +28 -0
  3. package/dist/.minified +1 -0
  4. package/dist/src/ast/astCdnParser.d.ts +5 -0
  5. package/dist/src/ast/astCdnParser.js +1 -114
  6. package/dist/src/ast/astCommonParser.d.ts +6 -17
  7. package/dist/src/ast/astCommonParser.js +1 -351
  8. package/dist/src/ast/astComputeConnectionParser.d.ts +18 -0
  9. package/dist/src/ast/astComputeConnectionParser.js +1 -0
  10. package/dist/src/ast/astComputeParser.d.ts +6 -0
  11. package/dist/src/ast/astComputeParser.js +1 -473
  12. package/dist/src/ast/astComputeParserHelpers.d.ts +21 -0
  13. package/dist/src/ast/astComputeParserHelpers.js +1 -0
  14. package/dist/src/ast/astDatabaseParser.d.ts +9 -24
  15. package/dist/src/ast/astDatabaseParser.js +1 -275
  16. package/dist/src/ast/astDomainParser.d.ts +139 -0
  17. package/dist/src/ast/astDomainParser.js +1 -0
  18. package/dist/src/ast/astDynamoDBParser.d.ts +35 -0
  19. package/dist/src/ast/astDynamoDBParser.js +1 -0
  20. package/dist/src/ast/astExpressionEvaluator.d.ts +23 -0
  21. package/dist/src/ast/astExpressionEvaluator.js +1 -0
  22. package/dist/src/ast/astInfrastructureParser.d.ts +12 -49
  23. package/dist/src/ast/astInfrastructureParser.js +1 -552
  24. package/dist/src/ast/astMessagingParser.d.ts +5 -0
  25. package/dist/src/ast/astMessagingParser.js +1 -78
  26. package/dist/src/ast/astNetworkParser.d.ts +6 -0
  27. package/dist/src/ast/astNetworkParser.js +1 -219
  28. package/dist/src/ast/astPatternParser.d.ts +6 -0
  29. package/dist/src/ast/astPatternParser.js +1 -155
  30. package/dist/src/ast/astPlanConverter.d.ts +11 -0
  31. package/dist/src/ast/astPlanConverter.js +2 -0
  32. package/dist/src/ast/astStatementClassifier.d.ts +24 -0
  33. package/dist/src/ast/astStatementClassifier.js +1 -0
  34. package/dist/src/ast/astStatementQueries.d.ts +21 -0
  35. package/dist/src/ast/astStatementQueries.js +3 -0
  36. package/dist/src/ast/astStorageParser.d.ts +5 -0
  37. package/dist/src/ast/astStorageParser.js +1 -164
  38. package/dist/src/ast/astSurgicalModification.js +19 -400
  39. package/dist/src/ast/astTestHelpers.d.ts +635 -0
  40. package/dist/src/ast/astTestHelpers.js +1 -0
  41. package/dist/src/ast/index.d.ts +1 -0
  42. package/dist/src/ast/index.js +1 -6
  43. package/dist/src/aws/regions.js +1 -254
  44. package/dist/src/codemod/_internal.d.ts +12 -0
  45. package/dist/src/codemod/_internal.js +1 -0
  46. package/dist/src/codemod/edits/addResource/bodyIndex.d.ts +34 -0
  47. package/dist/src/codemod/edits/addResource/bodyIndex.js +1 -0
  48. package/dist/src/codemod/edits/addResource/propertyBuilder.d.ts +7 -0
  49. package/dist/src/codemod/edits/addResource/propertyBuilder.js +1 -0
  50. package/dist/src/codemod/edits/addResource.d.ts +9 -0
  51. package/dist/src/codemod/edits/addResource.js +1 -0
  52. package/dist/src/codemod/edits/ensureImports.d.ts +26 -0
  53. package/dist/src/codemod/edits/ensureImports.js +1 -0
  54. package/dist/src/codemod/edits/findInsertionPosition.d.ts +39 -0
  55. package/dist/src/codemod/edits/findInsertionPosition.js +1 -0
  56. package/dist/src/codemod/edits/index.d.ts +6 -0
  57. package/dist/src/codemod/edits/index.js +1 -0
  58. package/dist/src/codemod/edits/modifyResource/literalConversion.d.ts +37 -0
  59. package/dist/src/codemod/edits/modifyResource/literalConversion.js +1 -0
  60. package/dist/src/codemod/edits/modifyResource.d.ts +9 -0
  61. package/dist/src/codemod/edits/modifyResource.js +1 -0
  62. package/dist/src/codemod/edits/removeResource/commentHeuristic.d.ts +31 -0
  63. package/dist/src/codemod/edits/removeResource/commentHeuristic.js +1 -0
  64. package/dist/src/codemod/edits/removeResource/importPruning.d.ts +8 -0
  65. package/dist/src/codemod/edits/removeResource/importPruning.js +1 -0
  66. package/dist/src/codemod/edits/removeResource.d.ts +10 -0
  67. package/dist/src/codemod/edits/removeResource.js +1 -0
  68. package/dist/src/codemod/edits/schemaFragments.d.ts +9 -0
  69. package/dist/src/codemod/edits/schemaFragments.js +1 -0
  70. package/dist/src/codemod/fileRewriter/builders.d.ts +57 -0
  71. package/dist/src/codemod/fileRewriter/builders.js +1 -0
  72. package/dist/src/codemod/fileRewriter/index.d.ts +4 -0
  73. package/dist/src/codemod/fileRewriter/index.js +1 -0
  74. package/dist/src/codemod/fileRewriter/locateByRange.d.ts +65 -0
  75. package/dist/src/codemod/fileRewriter/locateByRange.js +1 -0
  76. package/dist/src/codemod/fileRewriter/parse.d.ts +18 -0
  77. package/dist/src/codemod/fileRewriter/parse.js +2 -0
  78. package/dist/src/codemod/fileRewriter/print.d.ts +46 -0
  79. package/dist/src/codemod/fileRewriter/print.js +4 -0
  80. package/dist/src/codemod/historyPaths.d.ts +2 -0
  81. package/dist/src/codemod/historyPaths.js +1 -0
  82. package/dist/src/codemod/index.d.ts +7 -0
  83. package/dist/src/codemod/index.js +1 -0
  84. package/dist/src/codemod/listResources.d.ts +4 -0
  85. package/dist/src/codemod/listResources.js +1 -0
  86. package/dist/src/codemod/semanticIndex/findReferences.d.ts +15 -0
  87. package/dist/src/codemod/semanticIndex/findReferences.js +2 -0
  88. package/dist/src/codemod/semanticIndex/index.d.ts +4 -0
  89. package/dist/src/codemod/semanticIndex/index.js +1 -0
  90. package/dist/src/codemod/semanticIndex/listImports.d.ts +24 -0
  91. package/dist/src/codemod/semanticIndex/listImports.js +1 -0
  92. package/dist/src/codemod/semanticIndex/locateByShape.d.ts +28 -0
  93. package/dist/src/codemod/semanticIndex/locateByShape.js +1 -0
  94. package/dist/src/codemod/semanticIndex/projectCache.d.ts +14 -0
  95. package/dist/src/codemod/semanticIndex/projectCache.js +1 -0
  96. package/dist/src/codemod/types.d.ts +172 -0
  97. package/dist/src/codemod/types.js +1 -0
  98. package/dist/src/dns/bindParser.js +2 -224
  99. package/dist/src/dns/bindWriter.js +3 -52
  100. package/dist/src/dns/domainFileGenerator.d.ts +20 -0
  101. package/dist/src/dns/domainFileGenerator.js +207 -0
  102. package/dist/src/dns/domainRecords.d.ts +164 -0
  103. package/dist/src/dns/domainRecords.js +1 -0
  104. package/dist/src/dns/index.d.ts +2 -1
  105. package/dist/src/dns/index.js +1 -4
  106. package/dist/src/dns/types.js +1 -52
  107. package/dist/src/generation/common.js +6 -161
  108. package/dist/src/generation/compute.js +82 -590
  109. package/dist/src/generation/database.js +12 -198
  110. package/dist/src/generation/generatePatternCode.d.ts +58 -0
  111. package/dist/src/generation/generatePatternCode.js +33 -0
  112. package/dist/src/generation/index.js +1 -20
  113. package/dist/src/generation/infrastructure.d.ts +1 -5
  114. package/dist/src/generation/infrastructure.js +35 -377
  115. package/dist/src/generation/messagingConnections.js +1 -73
  116. package/dist/src/generation/storage.d.ts +0 -15
  117. package/dist/src/generation/storage.js +35 -168
  118. package/dist/src/generation/storageConnections.js +1 -75
  119. package/dist/src/planning/generateResourceChange.d.ts +21 -0
  120. package/dist/src/planning/generateResourceChange.js +1 -0
  121. package/dist/src/planning/index.d.ts +3 -0
  122. package/dist/src/planning/index.js +1 -1
  123. package/dist/src/planning/resourceAddition.d.ts +154 -0
  124. package/dist/src/planning/resourceAddition.js +1 -0
  125. package/dist/src/planning/resourceConnections.d.ts +19 -0
  126. package/dist/src/planning/resourceConnections.js +1 -0
  127. package/dist/src/planning/resourcePlanning.js +1 -214
  128. package/dist/src/presets/index.js +1 -3
  129. package/dist/src/presets/patternTierPresets.js +1 -131
  130. package/dist/src/presets/storagePresets.js +1 -36
  131. package/dist/src/presets/tierPresets.d.ts +5 -8
  132. package/dist/src/presets/tierPresets.js +1 -384
  133. package/dist/src/presets/tierTypes.d.ts +1 -1
  134. package/dist/src/presets/tierTypes.js +0 -7
  135. package/dist/src/schemas/alarmSchemas.d.ts +19 -0
  136. package/dist/src/schemas/alarmSchemas.js +1 -0
  137. package/dist/src/schemas/applicationSchemas.d.ts +22 -6
  138. package/dist/src/schemas/applicationSchemas.js +1 -80
  139. package/dist/src/schemas/baseSchemas.d.ts +8 -3
  140. package/dist/src/schemas/baseSchemas.js +2 -248
  141. package/dist/src/schemas/cdnSchemas.js +1 -62
  142. package/dist/src/schemas/computeSchemas.d.ts +25 -3
  143. package/dist/src/schemas/computeSchemas.js +1 -727
  144. package/dist/src/schemas/constants.d.ts +5 -7
  145. package/dist/src/schemas/constants.js +1 -218
  146. package/dist/src/schemas/databaseSchemas.d.ts +6 -1
  147. package/dist/src/schemas/databaseSchemas.js +1 -366
  148. package/dist/src/schemas/index.js +1 -3
  149. package/dist/src/schemas/instanceTypeArchitecture.js +1 -75
  150. package/dist/src/schemas/messagingSchemas.js +1 -29
  151. package/dist/src/schemas/networkSchemas.js +1 -125
  152. package/dist/src/schemas/patternSchemas.d.ts +1 -1
  153. package/dist/src/schemas/patternSchemas.js +1 -294
  154. package/dist/src/schemas/resourceSchemas.d.ts +1 -0
  155. package/dist/src/schemas/resourceSchemas.js +1 -28
  156. package/dist/src/schemas/sharedTypes.d.ts +18 -0
  157. package/dist/src/schemas/sharedTypes.js +1 -0
  158. package/dist/src/schemas/storageSchemas.d.ts +1 -0
  159. package/dist/src/schemas/storageSchemas.js +1 -119
  160. package/dist/src/types/Result.js +1 -31
  161. package/dist/src/util/errorUtils.js +1 -1
  162. package/dist/src/validation/patterns.d.ts +9 -0
  163. package/dist/src/validation/patterns.js +1 -369
  164. package/dist/src/version.d.ts +1 -1
  165. package/dist/src/version.js +1 -1
  166. package/package.json +29 -9
  167. package/dist/src/dns/infrastructureWriter.d.ts +0 -2
  168. package/dist/src/dns/infrastructureWriter.js +0 -58
@@ -1,596 +1,88 @@
1
- import { formatValue, getVariableName, emitExtraProperties } from "./common.js";
2
- import { DATABASE_ENV_VARS, getConnectedDatabases, generateDatabaseEnvVarEntries, buildDatabaseEnvVars, } from "./database.js";
3
- import { STORAGE_ENV_VARS, getConnectedStorage, generateStorageEnvVarEntries, buildStorageEnvVars, formatAllConnectionsCode, } from "./storageConnections.js";
4
- import { MESSAGING_ENV_VARS, getConnectedMessaging, generateMessagingEnvVarEntries, buildMessagingEnvVars, } from "./messagingConnections.js";
5
- import { COMPUTE_TYPE, DEPLOYMENT_TYPE, DEFAULT_COMPUTE_ARCHITECTURE, } from "../schemas/constants.js";
6
- /** Check if a compute resource has database connections */
7
- function computeHasDatabaseConnections(compute) {
8
- return Boolean(compute.needsConnection && compute.connectedDatabase?.length);
9
- }
10
- /** Check if a compute resource has storage connections */
11
- function computeHasStorageConnections(compute) {
12
- return Boolean(compute.connectedStorage?.length);
13
- }
14
- /** Check if a compute resource has messaging connections */
15
- function computeHasMessagingConnections(compute) {
16
- return Boolean(compute.connectedMessaging?.length);
17
- }
18
- /** Check if a compute resource has any connections (database, storage, or messaging) */
19
- function computeHasConnections(compute) {
20
- return (computeHasDatabaseConnections(compute) ||
21
- computeHasStorageConnections(compute) ||
22
- computeHasMessagingConnections(compute));
23
- }
24
- const BASE_ENVIRONMENT_VARS = {
25
- ENVIRONMENT: { __expression: "getConfig().environment" },
26
- };
27
- function formatEnvBlock(vars, indent) {
28
- return Object.entries(vars)
29
- .map(([key, value]) => `${indent}${key}: ${formatValue(value)},`)
30
- .join("\n");
31
- }
32
- export function generateLambdaCode(compute, _plan) {
33
- let code = "";
34
- if (compute.deployment === DEPLOYMENT_TYPE.CODE && compute.codePath) {
35
- code += `
36
- deployment: "${DEPLOYMENT_TYPE.CODE}",
37
- code: Code.fromAsset("${compute.codePath}"),`;
38
- if (compute.handler) {
39
- code += `
40
- handler: "${compute.handler}",`;
41
- }
42
- if (compute.runtime) {
43
- code += `
44
- runtime: Runtime.${compute.runtime},`;
45
- }
46
- }
47
- else {
48
- code += `
49
- deployment: "${DEPLOYMENT_TYPE.CONTAINER}",
50
- ecrRepository: app.getDefaultContainerRegistry(),`;
51
- }
52
- if (compute.timeout !== undefined) {
53
- code += `
54
- timeout: ${compute.timeout},`;
55
- }
56
- if (compute.memory !== undefined) {
57
- code += `
58
- memorySize: ${compute.memory},`;
59
- }
60
- if (compute.functionUrl) {
61
- code += `
62
- functionUrl: { authType: FunctionUrlAuthType.${compute.functionUrl.authType} },`;
63
- }
64
- if (compute.description) {
65
- code += `
66
- lambdaDescription: "${compute.description}",`;
67
- }
68
- if (compute.scheduleExpression) {
69
- code += `
70
- scheduleExpression: "${compute.scheduleExpression}",`;
71
- }
72
- if (compute.architecture ||
73
- compute.deployment === DEPLOYMENT_TYPE.CONTAINER) {
74
- const arch = compute.architecture ?? DEFAULT_COMPUTE_ARCHITECTURE;
75
- code += `
76
- architecture: Architecture.${arch},`;
77
- }
78
- if (compute.ephemeralStorageSize !== undefined) {
79
- code += `
80
- ephemeralStorageSize: ${compute.ephemeralStorageSize},`;
81
- }
82
- if (compute.functionName) {
83
- code += `
84
- functionName: "${compute.functionName}",`;
85
- }
86
- if (compute.ssmSecretsPath) {
87
- code += `
88
- ssmSecretsPath: "${compute.ssmSecretsPath}",`;
89
- }
90
- if (compute.ssmSecrets && compute.ssmSecrets.length > 0) {
91
- const secretsList = compute.ssmSecrets.map((s) => `"${s}"`).join(", ");
92
- code += `
93
- secrets: [${secretsList}],`;
94
- }
95
- // When there are connections, generateLambdaConnectionsCode handles env vars.
96
- // Otherwise, emit environment block here with base + user env vars.
97
- if (!computeHasConnections(compute)) {
98
- const allEnv = {
99
- ...BASE_ENVIRONMENT_VARS,
100
- ...compute.environment,
101
- };
102
- code += `
1
+ import{formatValue as $,getVariableName as _,emitExtraProperties as y}from"./common.js";import{DATABASE_ENV_VARS as m,getConnectedDatabases as x,generateDatabaseEnvVarEntries as j,buildDatabaseEnvVars as B}from"./database.js";import{STORAGE_ENV_VARS as L,getConnectedStorage as M,generateStorageEnvVarEntries as I,buildStorageEnvVars as U,formatAllConnectionsCode as T}from"./storageConnections.js";import{MESSAGING_ENV_VARS as N,getConnectedMessaging as O,generateMessagingEnvVarEntries as H,buildMessagingEnvVars as z}from"./messagingConnections.js";import{COMPUTE_TYPE as E,DEPLOYMENT_TYPE as C,DEFAULT_COMPUTE_ARCHITECTURE as w}from"../schemas/constants.js";function v(e){return!!(e.needsConnection&&e.connectedDatabase?.length)}function p(e){return!!e.connectedStorage?.length}function b(e){return!!e.connectedMessaging?.length}function D(e){return v(e)||p(e)||b(e)}const A={ENVIRONMENT:{__expression:"getConfig().environment"}};function P(e,n){return Object.entries(e).map(([t,a])=>`${n}${t}: ${$(a)},`).join(`
2
+ `)}function F(e,n){let t="";if(e.deployment===C.CODE&&e.codePath?(t+=`
3
+ deployment: "${C.CODE}",
4
+ code: Code.fromAsset("${e.codePath}"),`,e.handler&&(t+=`
5
+ handler: "${e.handler}",`),e.runtime&&(t+=`
6
+ runtime: Runtime.${e.runtime},`)):t+=`
7
+ deployment: "${C.CONTAINER}",
8
+ ecrRepository: app.getDefaultContainerRegistry(),`,e.timeout!==void 0&&(t+=`
9
+ timeout: ${e.timeout},`),e.memory!==void 0&&(t+=`
10
+ memorySize: ${e.memory},`),e.functionUrl&&(t+=`
11
+ functionUrl: { authType: FunctionUrlAuthType.${e.functionUrl.authType} },`),e.description&&(t+=`
12
+ lambdaDescription: "${e.description}",`),e.scheduleExpression&&(t+=`
13
+ scheduleExpression: "${e.scheduleExpression}",`),e.architecture||e.deployment===C.CONTAINER){const a=e.architecture??w;t+=`
14
+ architecture: Architecture.${a},`}if(e.ephemeralStorageSize!==void 0&&(t+=`
15
+ ephemeralStorageSize: ${e.ephemeralStorageSize},`),e.functionName&&(t+=`
16
+ functionName: "${e.functionName}",`),e.ssmSecretsPath&&(t+=`
17
+ ssmSecretsPath: "${e.ssmSecretsPath}",`),e.ssmSecrets&&e.ssmSecrets.length>0){const a=e.ssmSecrets.map(o=>`"${o}"`).join(", ");t+=`
18
+ secrets: [${a}],`}if(!D(e)){const a={...A,...e.environment};t+=`
103
19
  environment: {
104
- ${formatEnvBlock(allEnv, " ")}
105
- },`;
106
- }
107
- code += emitExtraProperties(compute.extraProperties);
108
- return code;
109
- }
110
- export function generateLambdaConnectionsCode(compute, plan) {
111
- if (compute.type !== COMPUTE_TYPE.LAMBDA)
112
- return "";
113
- const hasDatabaseConnections = computeHasDatabaseConnections(compute);
114
- const hasStorageConns = computeHasStorageConnections(compute);
115
- const hasMessagingConns = computeHasMessagingConnections(compute);
116
- if (!hasDatabaseConnections && !hasStorageConns && !hasMessagingConns)
117
- return "";
118
- const connectedDatabases = hasDatabaseConnections
119
- ? getConnectedDatabases(plan, compute)
120
- : [];
121
- const connectedStorage = hasStorageConns
122
- ? getConnectedStorage(plan, compute)
123
- : [];
124
- const connectedMessaging = hasMessagingConns
125
- ? getConnectedMessaging(plan, compute)
126
- : [];
127
- if (connectedDatabases.length === 0 &&
128
- connectedStorage.length === 0 &&
129
- connectedMessaging.length === 0) {
130
- return "";
131
- }
132
- // All env/secret values are stored as typed objects so formatValue handles
133
- // them uniformly: __expression objects emit raw code, strings get JSON-quoted.
134
- const envVars = {
135
- ...BASE_ENVIRONMENT_VARS,
136
- };
137
- const secretVars = {};
138
- // Database env vars
139
- if (connectedDatabases.length > 0) {
140
- const entries = generateDatabaseEnvVarEntries(connectedDatabases);
141
- for (const entry of entries) {
142
- // "true" is a literal string value (DATABASE_SSL); expressions are code refs
143
- const value = entry.expression === `"true"`
144
- ? "true"
145
- : { __expression: entry.expression };
146
- if (entry.isSecret) {
147
- secretVars[entry.key] = { __expression: entry.expression };
148
- }
149
- else {
150
- envVars[entry.key] = value;
151
- }
152
- }
153
- }
154
- // Storage env vars (no secrets — S3 uses IAM)
155
- if (connectedStorage.length > 0) {
156
- const entries = generateStorageEnvVarEntries(connectedStorage);
157
- for (const entry of entries) {
158
- envVars[entry.key] = { __expression: entry.expression };
159
- }
160
- }
161
- // Messaging env vars (no secrets — SQS uses IAM)
162
- if (connectedMessaging.length > 0) {
163
- const entries = generateMessagingEnvVarEntries(connectedMessaging);
164
- for (const entry of entries) {
165
- envVars[entry.key] = { __expression: entry.expression };
166
- }
167
- }
168
- // Merge compute.environment values directly — formatValue handles all types
169
- if (compute.environment) {
170
- for (const [key, value] of Object.entries(compute.environment)) {
171
- envVars[key] = value;
172
- }
173
- }
174
- let code = "";
175
- // containerSecretsImport for database credentials (resolved at deploy time)
176
- if (Object.keys(secretVars).length > 0) {
177
- code += `
178
- containerSecretsImport: {`;
179
- for (const [key, value] of Object.entries(secretVars)) {
180
- code += `
181
- ${key}: ${formatValue(value)},`;
182
- }
183
- code += `
184
- },`;
185
- }
186
- if (Object.keys(envVars).length > 0) {
187
- code += `
188
- environment: {`;
189
- for (const [key, value] of Object.entries(envVars)) {
190
- code += `
191
- ${key}: ${formatValue(value)},`;
192
- }
193
- code += `
194
- },`;
195
- }
196
- code += `
197
- ${formatAllConnectionsCode(connectedDatabases, connectedStorage, connectedMessaging)}`;
198
- return code;
199
- }
200
- export function generateEc2Code(compute) {
201
- let code = "";
202
- if (compute.instanceType) {
203
- code += `
204
- instanceType: "${compute.instanceType}",`;
205
- }
206
- if (compute.enableSSH !== undefined) {
207
- code += compute.enableSSH
208
- ? `
209
- ssh: {},`
210
- : `
211
- ssh: false,`;
212
- }
213
- code += emitExtraProperties(compute.extraProperties);
214
- return code;
215
- }
216
- function generateEcsClusterCode(compute) {
217
- if (!compute.cluster)
218
- return "";
219
- const parts = [];
220
- if (compute.cluster.directAccess) {
221
- parts.push(`directAccess: true`);
222
- }
223
- if (compute.cluster.domain) {
224
- parts.push(`domain: "${compute.cluster.domain}"`);
225
- }
226
- if (compute.cluster.loadBalancer !== undefined) {
227
- parts.push(compute.cluster.loadBalancer === false
228
- ? `loadBalancer: false`
229
- : `loadBalancer: "${compute.cluster.loadBalancer}"`);
230
- }
231
- if (parts.length <= 1) {
232
- return `
233
- cluster: { ${parts[0] || ""} },`;
234
- }
235
- const inner = parts.map((p) => `\n ${p},`).join("");
236
- return `
237
- cluster: {${inner}
238
- },`;
239
- }
240
- function generateEcsContainerCode(containerConfig, shouldAddConnectionEnv, dbEnvVars, storageEnvVars, messagingEnvVars, baseEnvVars) {
241
- let code = "";
242
- if (containerConfig.name) {
243
- code += `
244
- name: "${containerConfig.name}",`;
245
- }
246
- if (containerConfig.image) {
247
- code += `
248
- image: "${containerConfig.image}",`;
249
- }
250
- if (containerConfig.port !== undefined) {
251
- code += `
252
- port: ${containerConfig.port},`;
253
- }
254
- if (containerConfig.essential !== undefined) {
255
- code += `
256
- essential: ${containerConfig.essential},`;
257
- }
258
- if (containerConfig.command?.length) {
259
- code += `
260
- command: ${JSON.stringify(containerConfig.command)},`;
261
- }
262
- if (containerConfig.entryPoint?.length) {
263
- code += `
264
- entryPoint: ${JSON.stringify(containerConfig.entryPoint)},`;
265
- }
266
- const connectionEnvKeys = [
267
- DATABASE_ENV_VARS.HOST,
268
- DATABASE_ENV_VARS.PORT,
269
- DATABASE_ENV_VARS.NAME,
270
- DATABASE_ENV_VARS.SSL,
271
- DATABASE_ENV_VARS.USERNAME,
272
- DATABASE_ENV_VARS.PASSWORD,
273
- STORAGE_ENV_VARS.NAME,
274
- MESSAGING_ENV_VARS.URL,
275
- MESSAGING_ENV_VARS.ARN,
276
- ];
277
- const stripConnectionEnv = (env) => {
278
- if (!env)
279
- return env;
280
- const filtered = {};
281
- for (const [key, value] of Object.entries(env)) {
282
- const isConnectionKey = connectionEnvKeys.some((connKey) => key === connKey || key.startsWith(`${connKey}_`));
283
- if (!isConnectionKey) {
284
- filtered[key] = value;
285
- }
286
- }
287
- return Object.keys(filtered).length > 0 ? filtered : undefined;
288
- };
289
- // Base env vars (e.g. ENVIRONMENT) are always injected into every container.
290
- // Connection env vars are only added to the first container of the service that needs them.
291
- const containerEnv = shouldAddConnectionEnv
292
- ? {
293
- ...baseEnvVars,
294
- ...dbEnvVars.env,
295
- ...storageEnvVars.env,
296
- ...messagingEnvVars.env,
297
- ...containerConfig.environment,
298
- }
299
- : { ...baseEnvVars, ...stripConnectionEnv(containerConfig.environment) };
300
- const containerSecrets = shouldAddConnectionEnv
301
- ? { ...dbEnvVars.secrets, ...containerConfig.secretsImport }
302
- : stripConnectionEnv(containerConfig.secretsImport);
303
- if (containerEnv && Object.keys(containerEnv).length > 0) {
304
- code += `
20
+ ${P(a," ")}
21
+ },`}return t+=y(e.extraProperties),t}function G(e,n){if(e.type!==E.LAMBDA)return"";const t=v(e),a=p(e),o=b(e);if(!t&&!a&&!o)return"";const g=t?x(n,e):[],d=a?M(n,e):[],f=o?O(n,e):[];if(g.length===0&&d.length===0&&f.length===0)return"";const c={...A},l={};if(g.length>0){const i=j(g);for(const r of i){const h=r.expression==='"true"'?"true":{__expression:r.expression};r.isSecret?l[r.key]={__expression:r.expression}:c[r.key]=h}}if(d.length>0){const i=I(d);for(const r of i)c[r.key]={__expression:r.expression}}if(f.length>0){const i=H(f);for(const r of i)c[r.key]={__expression:r.expression}}if(e.environment)for(const[i,r]of Object.entries(e.environment))c[i]=r;let s="";if(Object.keys(l).length>0){s+=`
22
+ containerSecretsImport: {`;for(const[i,r]of Object.entries(l))s+=`
23
+ ${i}: ${$(r)},`;s+=`
24
+ },`}if(Object.keys(c).length>0){s+=`
25
+ environment: {`;for(const[i,r]of Object.entries(c))s+=`
26
+ ${i}: ${$(r)},`;s+=`
27
+ },`}return s+=`
28
+ ${T(g,d,f)}`,s}function Y(e){let n="";return e.instanceType&&(n+=`
29
+ instanceType: "${e.instanceType}",`),e.enableSSH!==void 0&&(n+=e.enableSSH?`
30
+ ssh: {},`:`
31
+ ssh: false,`),n+=y(e.extraProperties),n}function J(e){if(!e.cluster)return"";const n=[];return e.cluster.directAccess&&n.push("directAccess: true"),e.cluster.domain&&n.push(`domain: "${e.cluster.domain}"`),e.cluster.loadBalancer!==void 0&&n.push(e.cluster.loadBalancer===!1?"loadBalancer: false":`loadBalancer: "${e.cluster.loadBalancer}"`),n.length<=1?`
32
+ cluster: { ${n[0]||""} },`:`
33
+ cluster: {${n.map(a=>`
34
+ ${a},`).join("")}
35
+ },`}function K(e,n,t,a,o,g){let d="";e.name&&(d+=`
36
+ name: "${e.name}",`),e.image&&(d+=`
37
+ image: "${e.image}",`),e.port!==void 0&&(d+=`
38
+ port: ${e.port},`),e.essential!==void 0&&(d+=`
39
+ essential: ${e.essential},`),e.command?.length&&(d+=`
40
+ command: ${JSON.stringify(e.command)},`),e.entryPoint?.length&&(d+=`
41
+ entryPoint: ${JSON.stringify(e.entryPoint)},`);const f=[m.HOST,m.PORT,m.NAME,m.SSL,m.USERNAME,m.PASSWORD,L.NAME,N.URL,N.ARN],c=i=>{if(!i)return i;const r={};for(const[h,u]of Object.entries(i))f.some(S=>h===S||h.startsWith(`${S}_`))||(r[h]=u);return Object.keys(r).length>0?r:void 0},l=n?{...g,...t.env,...a.env,...o.env,...e.environment}:{...g,...c(e.environment)},s=n?{...t.secrets,...e.secretsImport}:c(e.secretsImport);if(l&&Object.keys(l).length>0&&(d+=`
305
42
  environment: {
306
- ${formatEnvBlock(containerEnv, " ")}
307
- },`;
308
- }
309
- if (containerSecrets && Object.keys(containerSecrets).length > 0) {
310
- code += `
43
+ ${P(l," ")}
44
+ },`),s&&Object.keys(s).length>0&&(d+=`
311
45
  secretsImport: {
312
- ${formatEnvBlock(containerSecrets, " ")}
313
- },`;
314
- }
315
- if (containerConfig.ssmSecrets && containerConfig.ssmSecrets.length > 0) {
316
- const secretsList = containerConfig.ssmSecrets
317
- .map((s) => `"${s}"`)
318
- .join(", ");
319
- code += `
320
- secrets: [${secretsList}],`;
321
- }
322
- if (containerConfig.healthCheck) {
323
- code += `
324
- healthCheck: ${formatValue(containerConfig.healthCheck, " ")},`;
325
- }
326
- code += emitExtraProperties(containerConfig.extraProperties, " ");
327
- return code;
328
- }
329
- function formatRoutingRule(rule, indent) {
330
- const parts = [];
331
- if (rule.path)
332
- parts.push(`path: "${rule.path}"`);
333
- if (rule.host)
334
- parts.push(`host: "${rule.host}"`);
335
- if (rule.priority !== undefined)
336
- parts.push(`priority: ${rule.priority}`);
337
- if (rule.healthCheckPath)
338
- parts.push(`healthCheckPath: "${rule.healthCheckPath}"`);
339
- if (parts.length <= 1) {
340
- return `{ ${parts[0] || ""} }`;
341
- }
342
- const inner = parts.map((p) => `\n${indent} ${p},`).join("");
343
- return `{${inner}\n${indent}}`;
344
- }
345
- function generateEcsServiceRoutingCode(routing) {
346
- const rules = Array.isArray(routing) ? routing : [routing];
347
- if (rules.length === 1) {
348
- const formatted = formatRoutingRule(rules[0], " ");
349
- return `
350
- routing: ${formatted},`;
351
- }
352
- const entries = rules.map((r) => formatRoutingRule(r, " "));
353
- return `
46
+ ${P(s," ")}
47
+ },`),e.ssmSecrets&&e.ssmSecrets.length>0){const i=e.ssmSecrets.map(r=>`"${r}"`).join(", ");d+=`
48
+ secrets: [${i}],`}return e.healthCheck&&(d+=`
49
+ healthCheck: ${$(e.healthCheck," ")},`),d+=y(e.extraProperties," "),d}function k(e,n){const t=[];return e.path&&t.push(`path: "${e.path}"`),e.host&&t.push(`host: "${e.host}"`),e.priority!==void 0&&t.push(`priority: ${e.priority}`),e.healthCheckPath&&t.push(`healthCheckPath: "${e.healthCheckPath}"`),t.length<=1?`{ ${t[0]||""} }`:`{${t.map(o=>`
50
+ ${n} ${o},`).join("")}
51
+ ${n}}`}function W(e){const n=Array.isArray(e)?e:[e];return n.length===1?`
52
+ routing: ${k(n[0]," ")},`:`
354
53
  routing: [
355
- ${entries.join(",\n ")},
356
- ],`;
357
- }
358
- function generateEcsServiceScalingCode(scaling) {
359
- if (scaling === false) {
360
- return `
361
- scaling: false,`;
362
- }
363
- if (typeof scaling !== "object")
364
- return "";
365
- const hasScalingConfig = scaling.minCapacity !== undefined ||
366
- scaling.maxCapacity !== undefined ||
367
- scaling.desiredCount !== undefined ||
368
- scaling.scalingType !== undefined;
369
- if (!hasScalingConfig)
370
- return "";
371
- const scalingParts = [];
372
- if (scaling.minCapacity !== undefined)
373
- scalingParts.push(`minCapacity: ${scaling.minCapacity}`);
374
- if (scaling.maxCapacity !== undefined)
375
- scalingParts.push(`maxCapacity: ${scaling.maxCapacity}`);
376
- if (scaling.desiredCount !== undefined)
377
- scalingParts.push(`desiredCount: ${scaling.desiredCount}`);
378
- if (scaling.scalingType)
379
- scalingParts.push(`scalingType: "${scaling.scalingType}"`);
380
- if (scalingParts.length <= 1) {
381
- return `
382
- scaling: { ${scalingParts[0] || ""} },`;
383
- }
384
- const inner = scalingParts.map((p) => `\n ${p},`).join("");
385
- return `
386
- scaling: {${inner}
387
- },`;
388
- }
389
- /** Derive which connection types a service needs (DRY — used for both container env and service-level connections) */
390
- function deriveServiceConnectionNeeds(service, isFirstService, compute) {
391
- return {
392
- needsDb: service.needsDatabaseConnection !== undefined
393
- ? service.needsDatabaseConnection
394
- : isFirstService && computeHasDatabaseConnections(compute),
395
- needsStorage: service.needsStorageConnection !== undefined
396
- ? service.needsStorageConnection
397
- : isFirstService && computeHasStorageConnections(compute),
398
- needsMessaging: service.needsMessagingConnection !== undefined
399
- ? service.needsMessagingConnection
400
- : isFirstService && computeHasMessagingConnections(compute),
401
- };
402
- }
403
- function generateEcsServiceCode(options) {
404
- const { service, isFirstService, hasConnections, dbEnvVars, storageEnvVars, messagingEnvVars, baseEnvVars, plan, compute, } = options;
405
- let code = `
406
- name: "${service.name}",`;
407
- code += `
408
- capacityProvider: "${service.capacityProvider}",`;
409
- if (service.ec2Config) {
410
- code += `
411
- ec2Config: ${formatValue(service.ec2Config, " ")},`;
412
- }
413
- if (service.dockerfilePath) {
414
- code += `
415
- dockerfilePath: "${service.dockerfilePath}",`;
416
- }
417
- if (service.dockerTarget) {
418
- code += `
419
- dockerTarget: "${service.dockerTarget}",`;
420
- }
421
- if (service.image) {
422
- code += `
423
- image: "${service.image}",`;
424
- }
425
- if (service.ssmSecretsPath) {
426
- code += `
427
- ssmSecretsPath: "${service.ssmSecretsPath}",`;
428
- }
429
- const connectionNeeds = deriveServiceConnectionNeeds(service, isFirstService, compute);
430
- if (service.containers?.length) {
431
- code += `
432
- containers: [{`;
433
- for (let i = 0; i < service.containers.length; i++) {
434
- const container = service.containers[i];
435
- if (!container)
436
- continue;
437
- const shouldAddConnectionEnv = i === 0 &&
438
- (connectionNeeds.needsDb ||
439
- connectionNeeds.needsStorage ||
440
- connectionNeeds.needsMessaging) &&
441
- hasConnections;
442
- // Build per-container env vars: only include the connection types this service needs
443
- const containerDbEnvVars = connectionNeeds.needsDb
444
- ? dbEnvVars
445
- : { env: {}, secrets: {} };
446
- const containerStorageEnvVars = connectionNeeds.needsStorage
447
- ? storageEnvVars
448
- : { env: {}, secrets: {} };
449
- const containerMessagingEnvVars = connectionNeeds.needsMessaging
450
- ? messagingEnvVars
451
- : { env: {}, secrets: {} };
452
- if (i > 0) {
453
- code += `
454
- }, {`;
455
- }
456
- code += generateEcsContainerCode(container, shouldAddConnectionEnv, containerDbEnvVars, containerStorageEnvVars, containerMessagingEnvVars, baseEnvVars);
457
- }
458
- code += `
459
- }],`;
460
- }
461
- if (service.routing) {
462
- code += generateEcsServiceRoutingCode(service.routing);
463
- }
464
- if (service.cpu !== undefined) {
465
- code += `
466
- cpu: ${service.cpu},`;
467
- }
468
- if (service.memoryLimitMiB !== undefined) {
469
- code += `
470
- memoryLimitMiB: ${service.memoryLimitMiB},`;
471
- }
472
- if (service.desiredCount !== undefined) {
473
- code += `
474
- desiredCount: ${service.desiredCount},`;
475
- }
476
- if (service.scaling !== undefined) {
477
- code += generateEcsServiceScalingCode(service.scaling);
478
- }
479
- code += emitExtraProperties(service.extraProperties, " ");
480
- if (connectionNeeds.needsDb ||
481
- connectionNeeds.needsStorage ||
482
- connectionNeeds.needsMessaging) {
483
- const connectedDatabases = connectionNeeds.needsDb
484
- ? getConnectedDatabases(plan, compute)
485
- : [];
486
- const connectedStorage = connectionNeeds.needsStorage
487
- ? getConnectedStorage(plan, compute)
488
- : [];
489
- const connectedMessaging = connectionNeeds.needsMessaging
490
- ? getConnectedMessaging(plan, compute)
491
- : [];
492
- if (connectedDatabases.length > 0 ||
493
- connectedStorage.length > 0 ||
494
- connectedMessaging.length > 0) {
495
- code += `
496
- ${formatAllConnectionsCode(connectedDatabases, connectedStorage, connectedMessaging)}`;
497
- }
498
- }
499
- return code;
500
- }
501
- export function generateEcsCode(compute, plan) {
502
- const hasConnections = computeHasConnections(compute);
503
- const baseEnvVars = {
504
- ...BASE_ENVIRONMENT_VARS,
505
- };
506
- // Database env vars only injected into containers with database connections
507
- const dbEnvVars = {
508
- env: {},
509
- secrets: {},
510
- };
511
- if (computeHasDatabaseConnections(compute)) {
512
- const builtEnvVars = buildDatabaseEnvVars(plan, compute);
513
- Object.assign(dbEnvVars.env, builtEnvVars.env);
514
- Object.assign(dbEnvVars.secrets, builtEnvVars.secrets);
515
- }
516
- // Storage env vars (no secrets — S3 uses IAM)
517
- const storageEnvVars = {
518
- env: {},
519
- secrets: {},
520
- };
521
- if (computeHasStorageConnections(compute)) {
522
- const builtStorageEnvVars = buildStorageEnvVars(plan, compute);
523
- Object.assign(storageEnvVars.env, builtStorageEnvVars.env);
524
- }
525
- // Messaging env vars (no secrets — SQS uses IAM)
526
- const messagingEnvVars = {
527
- env: {},
528
- secrets: {},
529
- };
530
- if (computeHasMessagingConnections(compute)) {
531
- const builtMessagingEnvVars = buildMessagingEnvVars(plan, compute);
532
- Object.assign(messagingEnvVars.env, builtMessagingEnvVars.env);
533
- }
534
- let code = `
535
- ecrRepository: app.getDefaultContainerRegistry(),`;
536
- code += generateEcsClusterCode(compute);
537
- if (compute.services?.length) {
538
- code += `
539
- services: [{`;
540
- for (let serviceIndex = 0; serviceIndex < compute.services.length; serviceIndex++) {
541
- const service = compute.services[serviceIndex];
542
- if (!service)
543
- continue;
544
- if (serviceIndex > 0) {
545
- code += `
546
- }, {`;
547
- }
548
- code += generateEcsServiceCode({
549
- service,
550
- isFirstService: serviceIndex === 0,
551
- hasConnections: !!hasConnections,
552
- dbEnvVars,
553
- storageEnvVars,
554
- messagingEnvVars,
555
- baseEnvVars,
556
- plan,
557
- compute,
558
- });
559
- }
560
- code += `
561
- }],`;
562
- }
563
- code += emitExtraProperties(compute.extraProperties);
564
- return code;
565
- }
566
- export function generateComputeCode(plan, cdnReferencedResources) {
567
- if (plan.compute.length === 0)
568
- return "";
569
- let code = "";
570
- for (let computeIndex = 0; computeIndex < plan.compute.length; computeIndex++) {
571
- const compute = plan.compute[computeIndex];
572
- const needsVariable = cdnReferencedResources.has(compute.name);
573
- const computeVariable = getVariableName(compute);
574
- const needsLeadingNewline = plan.database.length > 0 || plan.s3.length > 0 || computeIndex > 0;
575
- const prefix = needsVariable ? `const ${computeVariable} = ` : "";
576
- const leadingNewline = needsLeadingNewline ? "\n" : "";
577
- code += `${leadingNewline}${prefix}app.addCompute(
578
- ComputeFactory.build("${compute.name}", {
579
- type: "${compute.type}",`;
580
- if (compute.type === COMPUTE_TYPE.LAMBDA) {
581
- code += generateLambdaCode(compute, plan);
582
- }
583
- else if (compute.type === COMPUTE_TYPE.EC2) {
584
- code += generateEc2Code(compute);
585
- }
586
- else if (compute.type === COMPUTE_TYPE.ECS) {
587
- code += generateEcsCode(compute, plan);
588
- }
589
- code += generateLambdaConnectionsCode(compute, plan);
590
- code += `
54
+ ${n.map(a=>k(a," ")).join(`,
55
+ `)},
56
+ ],`}function q(e){if(e===!1)return`
57
+ scaling: false,`;if(typeof e!="object"||!(e.minCapacity!==void 0||e.maxCapacity!==void 0||e.desiredCount!==void 0||e.scalingType!==void 0))return"";const t=[];return e.minCapacity!==void 0&&t.push(`minCapacity: ${e.minCapacity}`),e.maxCapacity!==void 0&&t.push(`maxCapacity: ${e.maxCapacity}`),e.desiredCount!==void 0&&t.push(`desiredCount: ${e.desiredCount}`),e.scalingType&&t.push(`scalingType: "${e.scalingType}"`),t.length<=1?`
58
+ scaling: { ${t[0]||""} },`:`
59
+ scaling: {${t.map(o=>`
60
+ ${o},`).join("")}
61
+ },`}function Q(e,n,t){return{needsDb:e.needsDatabaseConnection!==void 0?e.needsDatabaseConnection:n&&v(t),needsStorage:e.needsStorageConnection!==void 0?e.needsStorageConnection:n&&p(t),needsMessaging:e.needsMessagingConnection!==void 0?e.needsMessagingConnection:n&&b(t)}}function X(e){const{service:n,isFirstService:t,hasConnections:a,dbEnvVars:o,storageEnvVars:g,messagingEnvVars:d,baseEnvVars:f,plan:c,compute:l}=e;let s=`
62
+ name: "${n.name}",`;s+=`
63
+ capacityProvider: "${n.capacityProvider}",`,n.ec2Config&&(s+=`
64
+ ec2Config: ${$(n.ec2Config," ")},`),n.dockerfilePath&&(s+=`
65
+ dockerfilePath: "${n.dockerfilePath}",`),n.dockerTarget&&(s+=`
66
+ dockerTarget: "${n.dockerTarget}",`),n.image&&(s+=`
67
+ image: "${n.image}",`),n.ssmSecretsPath&&(s+=`
68
+ ssmSecretsPath: "${n.ssmSecretsPath}",`);const i=Q(n,t,l);if(n.containers?.length){s+=`
69
+ containers: [{`;for(let r=0;r<n.containers.length;r++){const h=n.containers[r];if(!h)continue;const u=r===0&&(i.needsDb||i.needsStorage||i.needsMessaging)&&a,V=i.needsDb?o:{env:{},secrets:{}},S=i.needsStorage?g:{env:{},secrets:{}},R=i.needsMessaging?d:{env:{},secrets:{}};r>0&&(s+=`
70
+ }, {`),s+=K(h,u,V,S,R,f)}s+=`
71
+ }],`}if(n.routing&&(s+=W(n.routing)),n.cpu!==void 0&&(s+=`
72
+ cpu: ${n.cpu},`),n.memoryLimitMiB!==void 0&&(s+=`
73
+ memoryLimitMiB: ${n.memoryLimitMiB},`),n.desiredCount!==void 0&&(s+=`
74
+ desiredCount: ${n.desiredCount},`),n.scaling!==void 0&&(s+=q(n.scaling)),n.alarms===!1?s+=`
75
+ alarms: false,`:typeof n.alarms=="object"&&(s+=`
76
+ alarms: ${$(n.alarms," ")},`),s+=y(n.extraProperties," "),i.needsDb||i.needsStorage||i.needsMessaging){const r=i.needsDb?x(c,l):[],h=i.needsStorage?M(c,l):[],u=i.needsMessaging?O(c,l):[];(r.length>0||h.length>0||u.length>0)&&(s+=`
77
+ ${T(r,h,u)}`)}return s}function Z(e,n){const t=D(e),a={...A},o={env:{},secrets:{}};if(v(e)){const c=B(n,e);Object.assign(o.env,c.env),Object.assign(o.secrets,c.secrets)}const g={env:{},secrets:{}};if(p(e)){const c=U(n,e);Object.assign(g.env,c.env)}const d={env:{},secrets:{}};if(b(e)){const c=z(n,e);Object.assign(d.env,c.env)}let f=`
78
+ ecrRepository: app.getDefaultContainerRegistry(),`;if(f+=J(e),e.services?.length){f+=`
79
+ services: [{`;for(let c=0;c<e.services.length;c++){const l=e.services[c];l&&(c>0&&(f+=`
80
+ }, {`),f+=X({service:l,isFirstService:c===0,hasConnections:!!t,dbEnvVars:o,storageEnvVars:g,messagingEnvVars:d,baseEnvVars:a,plan:n,compute:e}))}f+=`
81
+ }],`}return f+=y(e.extraProperties),f+=`
82
+ ...(getConfig().environment === "production" ? { alertsTopic: "import:SharedAlarmTopicArn" } : {}),`,f}function ie(e,n){if(e.compute.length===0)return"";let t="";for(let a=0;a<e.compute.length;a++){const o=e.compute[a],g=n.has(o.name),d=_(o),f=e.database.length>0||e.s3.length>0||a>0,c=g?`const ${d} = `:"";t+=`${f?`
83
+ `:""}${c}app.addCompute(
84
+ ComputeFactory.build("${o.name}", {
85
+ type: "${o.type}",`,o.type===E.LAMBDA?t+=F(o,e):o.type===E.EC2?t+=Y(o):o.type===E.ECS&&(t+=Z(o,e)),t+=G(o,e),t+=`
591
86
  })
592
87
  );
593
- `;
594
- }
595
- return code;
596
- }
88
+ `}return t}export{ie as generateComputeCode,Y as generateEc2Code,Z as generateEcsCode,F as generateLambdaCode,G as generateLambdaConnectionsCode};