@fjall/generator 0.88.4 → 0.89.4

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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/ast/astCdnParser.d.ts +15 -0
  3. package/dist/src/ast/astCdnParser.js +114 -0
  4. package/dist/src/ast/astCommonParser.d.ts +90 -0
  5. package/dist/src/ast/astCommonParser.js +351 -0
  6. package/dist/src/ast/astComputeParser.d.ts +14 -2
  7. package/dist/src/ast/astComputeParser.js +55 -9
  8. package/dist/src/ast/astDatabaseParser.d.ts +104 -0
  9. package/dist/src/ast/astDatabaseParser.js +275 -0
  10. package/dist/src/ast/astInfrastructureParser.d.ts +23 -277
  11. package/dist/src/ast/astInfrastructureParser.js +83 -1456
  12. package/dist/src/ast/astMessagingParser.d.ts +25 -0
  13. package/dist/src/ast/astMessagingParser.js +78 -0
  14. package/dist/src/ast/astNetworkParser.d.ts +70 -0
  15. package/dist/src/ast/astNetworkParser.js +219 -0
  16. package/dist/src/ast/astPatternParser.d.ts +80 -0
  17. package/dist/src/ast/astPatternParser.js +155 -0
  18. package/dist/src/ast/astStorageParser.d.ts +18 -0
  19. package/dist/src/ast/astStorageParser.js +164 -0
  20. package/dist/src/ast/index.d.ts +1 -0
  21. package/dist/src/ast/index.js +4 -0
  22. package/dist/src/dns/bindParser.d.ts +13 -0
  23. package/dist/src/dns/bindParser.js +224 -0
  24. package/dist/src/dns/bindWriter.d.ts +2 -0
  25. package/dist/src/dns/bindWriter.js +52 -0
  26. package/dist/src/dns/index.d.ts +4 -0
  27. package/dist/src/dns/index.js +4 -0
  28. package/dist/src/dns/infrastructureWriter.d.ts +2 -0
  29. package/dist/src/dns/infrastructureWriter.js +58 -0
  30. package/dist/src/dns/types.d.ts +82 -0
  31. package/dist/src/dns/types.js +52 -0
  32. package/dist/src/generation/common.d.ts +1 -16
  33. package/dist/src/generation/common.js +2 -28
  34. package/dist/src/generation/compute.js +77 -28
  35. package/dist/src/generation/index.d.ts +2 -1
  36. package/dist/src/generation/index.js +3 -1
  37. package/dist/src/generation/messagingConnections.d.ts +33 -0
  38. package/dist/src/generation/messagingConnections.js +73 -0
  39. package/dist/src/generation/storage.d.ts +5 -1
  40. package/dist/src/generation/storage.js +9 -1
  41. package/dist/src/generation/storageConnections.d.ts +3 -3
  42. package/dist/src/generation/storageConnections.js +8 -4
  43. package/dist/src/index.d.ts +1 -0
  44. package/dist/src/index.js +2 -0
  45. package/dist/src/planning/resourcePlanning.js +0 -2
  46. package/dist/src/presets/tierTypes.d.ts +4 -1
  47. package/dist/src/schemas/applicationSchemas.d.ts +854 -0
  48. package/dist/src/schemas/applicationSchemas.js +80 -0
  49. package/dist/src/schemas/baseSchemas.d.ts +206 -0
  50. package/dist/src/schemas/baseSchemas.js +248 -0
  51. package/dist/src/schemas/cdnSchemas.d.ts +61 -0
  52. package/dist/src/schemas/cdnSchemas.js +62 -0
  53. package/dist/src/schemas/computeSchemas.d.ts +723 -0
  54. package/dist/src/schemas/computeSchemas.js +727 -0
  55. package/dist/src/schemas/constants.d.ts +12 -8
  56. package/dist/src/schemas/constants.js +14 -4
  57. package/dist/src/schemas/databaseSchemas.d.ts +638 -0
  58. package/dist/src/schemas/databaseSchemas.js +366 -0
  59. package/dist/src/schemas/messagingSchemas.d.ts +20 -0
  60. package/dist/src/schemas/messagingSchemas.js +29 -0
  61. package/dist/src/schemas/networkSchemas.d.ts +246 -0
  62. package/dist/src/schemas/networkSchemas.js +125 -0
  63. package/dist/src/schemas/patternSchemas.d.ts +708 -0
  64. package/dist/src/schemas/patternSchemas.js +294 -0
  65. package/dist/src/schemas/resourceSchemas.d.ts +24 -3530
  66. package/dist/src/schemas/resourceSchemas.js +24 -2011
  67. package/dist/src/schemas/storageSchemas.d.ts +93 -0
  68. package/dist/src/schemas/storageSchemas.js +119 -0
  69. package/dist/src/util/errorUtils.d.ts +1 -2
  70. package/dist/src/util/errorUtils.js +1 -15
  71. package/dist/src/validation/patterns.d.ts +9 -0
  72. package/dist/src/validation/patterns.js +9 -0
  73. package/dist/src/version.d.ts +1 -1
  74. package/dist/src/version.js +1 -1
  75. package/package.json +5 -3
@@ -5,26 +5,11 @@
5
5
  */
6
6
  import type { IdentifierValue, ExpressionValue, CallValue, SpecialValue } from "../schemas/resourceSchemas.js";
7
7
  export type { IdentifierValue, ExpressionValue, CallValue, SpecialValue };
8
+ export { toPascalCase, toKebab, toValidDatabaseName } from "@fjall/util";
8
9
  /**
9
10
  * Type guard to check if a value is a special code generation value
10
11
  */
11
12
  export declare function isSpecialValue(value: unknown): value is SpecialValue;
12
- /**
13
- * Convert hyphenated/underscored names to PascalCase for resource names
14
- */
15
- export declare function toPascalCase(str: string): string;
16
- /**
17
- * Convert any case (PascalCase, camelCase, kebab-case, snake_case) to kebab-case.
18
- * Three-pass regex: split acronyms, split camel boundaries, replace separators.
19
- * e.g., "MyApp" -> "my-app", "AWSLambda" -> "aws-lambda", "myApp" -> "my-app"
20
- */
21
- export declare function toKebab(str: string): string;
22
- /**
23
- * Convert a name to a valid RDS database name (snake_case).
24
- * RDS API allows letters, numbers, and underscores for PostgreSQL/MySQL DatabaseName.
25
- * Hyphens are rejected, so convert them to underscores.
26
- */
27
- export declare function toValidDatabaseName(name: string): string;
28
13
  /**
29
14
  * Convert resource names to camelCase variable names
30
15
  */
@@ -3,6 +3,8 @@
3
3
  *
4
4
  * Shared helper functions used across all generation modules.
5
5
  */
6
+ // Re-export case conversion functions from @fjall/util for backwards compatibility
7
+ export { toPascalCase, toKebab, toValidDatabaseName } from "@fjall/util";
6
8
  /**
7
9
  * Type guard to check if a value is a special code generation value
8
10
  */
@@ -15,34 +17,6 @@ export function isSpecialValue(value) {
15
17
  typeof obj.__expression === "string" ||
16
18
  typeof obj.__call === "string");
17
19
  }
18
- /**
19
- * Convert hyphenated/underscored names to PascalCase for resource names
20
- */
21
- export function toPascalCase(str) {
22
- return str
23
- .replace(/[-_](.)/g, (_, c) => c.toUpperCase())
24
- .replace(/^./, (c) => c.toUpperCase());
25
- }
26
- /**
27
- * Convert any case (PascalCase, camelCase, kebab-case, snake_case) to kebab-case.
28
- * Three-pass regex: split acronyms, split camel boundaries, replace separators.
29
- * e.g., "MyApp" -> "my-app", "AWSLambda" -> "aws-lambda", "myApp" -> "my-app"
30
- */
31
- export function toKebab(str) {
32
- return str
33
- .replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
34
- .replace(/([a-z\d])([A-Z])/g, "$1-$2")
35
- .replace(/[\s_]+/g, "-")
36
- .toLowerCase();
37
- }
38
- /**
39
- * Convert a name to a valid RDS database name (snake_case).
40
- * RDS API allows letters, numbers, and underscores for PostgreSQL/MySQL DatabaseName.
41
- * Hyphens are rejected, so convert them to underscores.
42
- */
43
- export function toValidDatabaseName(name) {
44
- return toKebab(name).replace(/-/g, "_");
45
- }
46
20
  /**
47
21
  * Convert resource names to camelCase variable names
48
22
  */
@@ -1,6 +1,7 @@
1
1
  import { formatValue, getVariableName, emitExtraProperties } from "./common.js";
2
2
  import { DATABASE_ENV_VARS, getConnectedDatabases, generateDatabaseEnvVarEntries, buildDatabaseEnvVars, } from "./database.js";
3
3
  import { STORAGE_ENV_VARS, getConnectedStorage, generateStorageEnvVarEntries, buildStorageEnvVars, formatAllConnectionsCode, } from "./storageConnections.js";
4
+ import { MESSAGING_ENV_VARS, getConnectedMessaging, generateMessagingEnvVarEntries, buildMessagingEnvVars, } from "./messagingConnections.js";
4
5
  import { COMPUTE_TYPE, DEPLOYMENT_TYPE, DEFAULT_COMPUTE_ARCHITECTURE, } from "../schemas/constants.js";
5
6
  /** Check if a compute resource has database connections */
6
7
  function computeHasDatabaseConnections(compute) {
@@ -10,10 +11,15 @@ function computeHasDatabaseConnections(compute) {
10
11
  function computeHasStorageConnections(compute) {
11
12
  return Boolean(compute.connectedStorage?.length);
12
13
  }
13
- /** Check if a compute resource has any connections (database or storage) */
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) */
14
19
  function computeHasConnections(compute) {
15
20
  return (computeHasDatabaseConnections(compute) ||
16
- computeHasStorageConnections(compute));
21
+ computeHasStorageConnections(compute) ||
22
+ computeHasMessagingConnections(compute));
17
23
  }
18
24
  const BASE_ENVIRONMENT_VARS = {
19
25
  ENVIRONMENT: { __expression: "getConfig().environment" },
@@ -106,7 +112,8 @@ export function generateLambdaConnectionsCode(compute, plan) {
106
112
  return "";
107
113
  const hasDatabaseConnections = computeHasDatabaseConnections(compute);
108
114
  const hasStorageConns = computeHasStorageConnections(compute);
109
- if (!hasDatabaseConnections && !hasStorageConns)
115
+ const hasMessagingConns = computeHasMessagingConnections(compute);
116
+ if (!hasDatabaseConnections && !hasStorageConns && !hasMessagingConns)
110
117
  return "";
111
118
  const connectedDatabases = hasDatabaseConnections
112
119
  ? getConnectedDatabases(plan, compute)
@@ -114,7 +121,12 @@ export function generateLambdaConnectionsCode(compute, plan) {
114
121
  const connectedStorage = hasStorageConns
115
122
  ? getConnectedStorage(plan, compute)
116
123
  : [];
117
- if (connectedDatabases.length === 0 && connectedStorage.length === 0) {
124
+ const connectedMessaging = hasMessagingConns
125
+ ? getConnectedMessaging(plan, compute)
126
+ : [];
127
+ if (connectedDatabases.length === 0 &&
128
+ connectedStorage.length === 0 &&
129
+ connectedMessaging.length === 0) {
118
130
  return "";
119
131
  }
120
132
  // All env/secret values are stored as typed objects so formatValue handles
@@ -146,6 +158,13 @@ export function generateLambdaConnectionsCode(compute, plan) {
146
158
  envVars[entry.key] = { __expression: entry.expression };
147
159
  }
148
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
+ }
149
168
  // Merge compute.environment values directly — formatValue handles all types
150
169
  if (compute.environment) {
151
170
  for (const [key, value] of Object.entries(compute.environment)) {
@@ -175,7 +194,7 @@ export function generateLambdaConnectionsCode(compute, plan) {
175
194
  },`;
176
195
  }
177
196
  code += `
178
- ${formatAllConnectionsCode(connectedDatabases, connectedStorage)}`;
197
+ ${formatAllConnectionsCode(connectedDatabases, connectedStorage, connectedMessaging)}`;
179
198
  return code;
180
199
  }
181
200
  export function generateEc2Code(compute) {
@@ -218,7 +237,7 @@ function generateEcsClusterCode(compute) {
218
237
  cluster: {${inner}
219
238
  },`;
220
239
  }
221
- function generateEcsContainerCode(containerConfig, shouldAddConnectionEnv, dbEnvVars, storageEnvVars, baseEnvVars) {
240
+ function generateEcsContainerCode(containerConfig, shouldAddConnectionEnv, dbEnvVars, storageEnvVars, messagingEnvVars, baseEnvVars) {
222
241
  let code = "";
223
242
  if (containerConfig.name) {
224
243
  code += `
@@ -252,6 +271,8 @@ function generateEcsContainerCode(containerConfig, shouldAddConnectionEnv, dbEnv
252
271
  DATABASE_ENV_VARS.USERNAME,
253
272
  DATABASE_ENV_VARS.PASSWORD,
254
273
  STORAGE_ENV_VARS.NAME,
274
+ MESSAGING_ENV_VARS.URL,
275
+ MESSAGING_ENV_VARS.ARN,
255
276
  ];
256
277
  const stripConnectionEnv = (env) => {
257
278
  if (!env)
@@ -272,6 +293,7 @@ function generateEcsContainerCode(containerConfig, shouldAddConnectionEnv, dbEnv
272
293
  ...baseEnvVars,
273
294
  ...dbEnvVars.env,
274
295
  ...storageEnvVars.env,
296
+ ...messagingEnvVars.env,
275
297
  ...containerConfig.environment,
276
298
  }
277
299
  : { ...baseEnvVars, ...stripConnectionEnv(containerConfig.environment) };
@@ -364,8 +386,22 @@ function generateEcsServiceScalingCode(scaling) {
364
386
  scaling: {${inner}
365
387
  },`;
366
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
+ }
367
403
  function generateEcsServiceCode(options) {
368
- const { service, isFirstService, hasConnections, dbEnvVars, storageEnvVars, baseEnvVars, plan, compute, } = options;
404
+ const { service, isFirstService, hasConnections, dbEnvVars, storageEnvVars, messagingEnvVars, baseEnvVars, plan, compute, } = options;
369
405
  let code = `
370
406
  name: "${service.name}",`;
371
407
  code += `
@@ -390,6 +426,7 @@ function generateEcsServiceCode(options) {
390
426
  code += `
391
427
  ssmSecretsPath: "${service.ssmSecretsPath}",`;
392
428
  }
429
+ const connectionNeeds = deriveServiceConnectionNeeds(service, isFirstService, compute);
393
430
  if (service.containers?.length) {
394
431
  code += `
395
432
  containers: [{`;
@@ -397,25 +434,26 @@ function generateEcsServiceCode(options) {
397
434
  const container = service.containers[i];
398
435
  if (!container)
399
436
  continue;
400
- const serviceNeedsDb = service.needsDatabaseConnection !== undefined
401
- ? service.needsDatabaseConnection
402
- : isFirstService && computeHasDatabaseConnections(compute);
403
- const serviceNeedsStorage = service.needsStorageConnection !== undefined
404
- ? service.needsStorageConnection
405
- : isFirstService && computeHasStorageConnections(compute);
406
- const shouldAddConnectionEnv = i === 0 && (serviceNeedsDb || serviceNeedsStorage) && hasConnections;
437
+ const shouldAddConnectionEnv = i === 0 &&
438
+ (connectionNeeds.needsDb ||
439
+ connectionNeeds.needsStorage ||
440
+ connectionNeeds.needsMessaging) &&
441
+ hasConnections;
407
442
  // Build per-container env vars: only include the connection types this service needs
408
- const containerDbEnvVars = serviceNeedsDb
443
+ const containerDbEnvVars = connectionNeeds.needsDb
409
444
  ? dbEnvVars
410
445
  : { env: {}, secrets: {} };
411
- const containerStorageEnvVars = serviceNeedsStorage
446
+ const containerStorageEnvVars = connectionNeeds.needsStorage
412
447
  ? storageEnvVars
413
448
  : { env: {}, secrets: {} };
449
+ const containerMessagingEnvVars = connectionNeeds.needsMessaging
450
+ ? messagingEnvVars
451
+ : { env: {}, secrets: {} };
414
452
  if (i > 0) {
415
453
  code += `
416
454
  }, {`;
417
455
  }
418
- code += generateEcsContainerCode(container, shouldAddConnectionEnv, containerDbEnvVars, containerStorageEnvVars, baseEnvVars);
456
+ code += generateEcsContainerCode(container, shouldAddConnectionEnv, containerDbEnvVars, containerStorageEnvVars, containerMessagingEnvVars, baseEnvVars);
419
457
  }
420
458
  code += `
421
459
  }],`;
@@ -439,22 +477,23 @@ function generateEcsServiceCode(options) {
439
477
  code += generateEcsServiceScalingCode(service.scaling);
440
478
  }
441
479
  code += emitExtraProperties(service.extraProperties, " ");
442
- const serviceNeedsDbConnection = service.needsDatabaseConnection !== undefined
443
- ? service.needsDatabaseConnection
444
- : isFirstService && computeHasDatabaseConnections(compute);
445
- const serviceNeedsStorageConnection = service.needsStorageConnection !== undefined
446
- ? service.needsStorageConnection
447
- : isFirstService && computeHasStorageConnections(compute);
448
- if (serviceNeedsDbConnection || serviceNeedsStorageConnection) {
449
- const connectedDatabases = serviceNeedsDbConnection
480
+ if (connectionNeeds.needsDb ||
481
+ connectionNeeds.needsStorage ||
482
+ connectionNeeds.needsMessaging) {
483
+ const connectedDatabases = connectionNeeds.needsDb
450
484
  ? getConnectedDatabases(plan, compute)
451
485
  : [];
452
- const connectedStorage = serviceNeedsStorageConnection
486
+ const connectedStorage = connectionNeeds.needsStorage
453
487
  ? getConnectedStorage(plan, compute)
454
488
  : [];
455
- if (connectedDatabases.length > 0 || connectedStorage.length > 0) {
489
+ const connectedMessaging = connectionNeeds.needsMessaging
490
+ ? getConnectedMessaging(plan, compute)
491
+ : [];
492
+ if (connectedDatabases.length > 0 ||
493
+ connectedStorage.length > 0 ||
494
+ connectedMessaging.length > 0) {
456
495
  code += `
457
- ${formatAllConnectionsCode(connectedDatabases, connectedStorage)}`;
496
+ ${formatAllConnectionsCode(connectedDatabases, connectedStorage, connectedMessaging)}`;
458
497
  }
459
498
  }
460
499
  return code;
@@ -483,6 +522,15 @@ export function generateEcsCode(compute, plan) {
483
522
  const builtStorageEnvVars = buildStorageEnvVars(plan, compute);
484
523
  Object.assign(storageEnvVars.env, builtStorageEnvVars.env);
485
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
+ }
486
534
  let code = `
487
535
  ecrRepository: app.getDefaultContainerRegistry(),`;
488
536
  code += generateEcsClusterCode(compute);
@@ -503,6 +551,7 @@ export function generateEcsCode(compute, plan) {
503
551
  hasConnections: !!hasConnections,
504
552
  dbEnvVars,
505
553
  storageEnvVars,
554
+ messagingEnvVars,
506
555
  baseEnvVars,
507
556
  plan,
508
557
  compute,
@@ -7,6 +7,7 @@
7
7
  export { type IdentifierValue, type ExpressionValue, type CallValue, type SpecialValue, isSpecialValue, toPascalCase, toKebab, toValidDatabaseName, toVariableName, formatValue, buildProperty, getVariableName, resolveResourceVariable, emitExtraProperties, } from "./common.js";
8
8
  export { DATABASE_ENV_VARS, CREDENTIAL_KEYS, type DatabaseEnvVarEntry, type DatabaseEnvVars, getConnectedDatabases, generateDatabaseEnvVarEntries, formatConnectionsCode, buildDatabaseEnvVars, databaseNeedsVariable, generateDatabaseCode, } from "./database.js";
9
9
  export { STORAGE_ENV_VARS, type StorageEnvVarEntry, type StorageEnvVars, getConnectedStorage, generateStorageEnvVarEntries, buildStorageEnvVars, formatAllConnectionsCode, } from "./storageConnections.js";
10
+ export { MESSAGING_ENV_VARS, type MessagingEnvVarEntry, type MessagingEnvVars, getConnectedMessaging, generateMessagingEnvVarEntries, buildMessagingEnvVars, } from "./messagingConnections.js";
10
11
  export { generateLambdaCode, generateLambdaConnectionsCode, generateEc2Code, generateEcsCode, generateComputeCode, } from "./compute.js";
11
- export { generateS3Code, generateDynamoDBCode, generateSQSCode, s3NeedsVariable, } from "./storage.js";
12
+ export { generateS3Code, generateDynamoDBCode, generateSQSCode, s3NeedsVariable, sqsNeedsVariable, } from "./storage.js";
12
13
  export { generateNetworkCode, generateTags, generateAppInit, generateImports, generateCDNCode, collectCdnReferencedResources, usesPatternApproach, generatePatternCodeWithComments, } from "./infrastructure.js";
@@ -10,9 +10,11 @@ export { isSpecialValue, toPascalCase, toKebab, toValidDatabaseName, toVariableN
10
10
  export { DATABASE_ENV_VARS, CREDENTIAL_KEYS, getConnectedDatabases, generateDatabaseEnvVarEntries, formatConnectionsCode, buildDatabaseEnvVars, databaseNeedsVariable, generateDatabaseCode, } from "./database.js";
11
11
  // Storage connections
12
12
  export { STORAGE_ENV_VARS, getConnectedStorage, generateStorageEnvVarEntries, buildStorageEnvVars, formatAllConnectionsCode, } from "./storageConnections.js";
13
+ // Messaging connections
14
+ export { MESSAGING_ENV_VARS, getConnectedMessaging, generateMessagingEnvVarEntries, buildMessagingEnvVars, } from "./messagingConnections.js";
13
15
  // Compute generation
14
16
  export { generateLambdaCode, generateLambdaConnectionsCode, generateEc2Code, generateEcsCode, generateComputeCode, } from "./compute.js";
15
17
  // Storage generation
16
- export { generateS3Code, generateDynamoDBCode, generateSQSCode, s3NeedsVariable, } from "./storage.js";
18
+ export { generateS3Code, generateDynamoDBCode, generateSQSCode, s3NeedsVariable, sqsNeedsVariable, } from "./storage.js";
17
19
  // Infrastructure generation
18
20
  export { generateNetworkCode, generateTags, generateAppInit, generateImports, generateCDNCode, collectCdnReferencedResources, usesPatternApproach, generatePatternCodeWithComments, } from "./infrastructure.js";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Messaging Connection Code Generation
3
+ *
4
+ * Functions for generating messaging connection code (env vars, connections array)
5
+ * following the same pattern as database and storage connections.
6
+ */
7
+ import type { SQSResourcePlan, ApplicationResourcePlan, ComputeResourcePlan } from "../schemas/resourceSchemas.js";
8
+ export declare const MESSAGING_ENV_VARS: Readonly<{
9
+ readonly URL: "QUEUE_URL";
10
+ readonly ARN: "QUEUE_ARN";
11
+ }>;
12
+ export type MessagingEnvVarEntry = {
13
+ key: string;
14
+ expression: string;
15
+ };
16
+ export interface MessagingEnvVars {
17
+ env: Record<string, unknown>;
18
+ secrets: Record<string, unknown>;
19
+ }
20
+ /**
21
+ * Get SQS queues connected to a compute resource
22
+ */
23
+ export declare function getConnectedMessaging(plan: ApplicationResourcePlan, compute: ComputeResourcePlan): SQSResourcePlan[];
24
+ /**
25
+ * Generate messaging environment variable entries for a list of connected queues.
26
+ * SQS uses IAM-based access, so there are no secrets — only QUEUE_URL and QUEUE_ARN env vars.
27
+ */
28
+ export declare function generateMessagingEnvVarEntries(connectedMessaging: SQSResourcePlan[]): MessagingEnvVarEntry[];
29
+ /**
30
+ * Build messaging environment variables for a compute resource.
31
+ * SQS always uses IAM — secrets is always empty.
32
+ */
33
+ export declare function buildMessagingEnvVars(plan: ApplicationResourcePlan, compute: ComputeResourcePlan): MessagingEnvVars;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Messaging Connection Code Generation
3
+ *
4
+ * Functions for generating messaging connection code (env vars, connections array)
5
+ * following the same pattern as database and storage connections.
6
+ */
7
+ import { getVariableName } from "./common.js";
8
+ export const MESSAGING_ENV_VARS = Object.freeze({
9
+ URL: "QUEUE_URL",
10
+ ARN: "QUEUE_ARN",
11
+ });
12
+ /**
13
+ * Get SQS queues connected to a compute resource
14
+ */
15
+ export function getConnectedMessaging(plan, compute) {
16
+ const { connectedMessaging } = compute;
17
+ if (!connectedMessaging?.length)
18
+ return [];
19
+ return (plan.sqs ?? []).filter((queue) => connectedMessaging.includes(queue.name));
20
+ }
21
+ /**
22
+ * Generate messaging environment variable entries for a list of connected queues.
23
+ * SQS uses IAM-based access, so there are no secrets — only QUEUE_URL and QUEUE_ARN env vars.
24
+ */
25
+ export function generateMessagingEnvVarEntries(connectedMessaging) {
26
+ const entries = [];
27
+ if (connectedMessaging.length === 1) {
28
+ const queue = connectedMessaging[0];
29
+ if (!queue)
30
+ return entries;
31
+ const queueVar = getVariableName(queue);
32
+ entries.push({
33
+ key: MESSAGING_ENV_VARS.URL,
34
+ expression: `${queueVar}.getQueueUrl()`,
35
+ });
36
+ entries.push({
37
+ key: MESSAGING_ENV_VARS.ARN,
38
+ expression: `${queueVar}.getQueueArn()`,
39
+ });
40
+ }
41
+ else {
42
+ for (const [index, queue] of connectedMessaging.entries()) {
43
+ const queueVar = getVariableName(queue);
44
+ const suffix = index === 0 ? "" : `_${index + 1}`;
45
+ entries.push({
46
+ key: `${MESSAGING_ENV_VARS.URL}${suffix}`,
47
+ expression: `${queueVar}.getQueueUrl()`,
48
+ });
49
+ entries.push({
50
+ key: `${MESSAGING_ENV_VARS.ARN}${suffix}`,
51
+ expression: `${queueVar}.getQueueArn()`,
52
+ });
53
+ }
54
+ }
55
+ return entries;
56
+ }
57
+ /**
58
+ * Build messaging environment variables for a compute resource.
59
+ * SQS always uses IAM — secrets is always empty.
60
+ */
61
+ export function buildMessagingEnvVars(plan, compute) {
62
+ const env = {};
63
+ const secrets = {};
64
+ if (!compute.connectedMessaging?.length) {
65
+ return { env, secrets };
66
+ }
67
+ const connectedMessaging = getConnectedMessaging(plan, compute);
68
+ const entries = generateMessagingEnvVarEntries(connectedMessaging);
69
+ for (const entry of entries) {
70
+ env[entry.key] = { __expression: entry.expression };
71
+ }
72
+ return { env, secrets };
73
+ }
@@ -4,7 +4,7 @@
4
4
  * Functions for generating storage infrastructure code including
5
5
  * S3 buckets, DynamoDB tables, and SQS queues.
6
6
  */
7
- import type { ApplicationResourcePlan, S3ResourcePlan } from "../schemas/resourceSchemas.js";
7
+ import type { ApplicationResourcePlan, S3ResourcePlan, SQSResourcePlan } from "../schemas/resourceSchemas.js";
8
8
  /**
9
9
  * Check if an S3 bucket needs a variable assignment (referenced by compute or CDN)
10
10
  */
@@ -17,6 +17,10 @@ export declare function generateS3Code(plan: ApplicationResourcePlan): string;
17
17
  * Generate DynamoDB table infrastructure code
18
18
  */
19
19
  export declare function generateDynamoDBCode(plan: ApplicationResourcePlan): string;
20
+ /**
21
+ * Check if an SQS queue needs a variable assignment (referenced by compute)
22
+ */
23
+ export declare function sqsNeedsVariable(queue: SQSResourcePlan, plan: ApplicationResourcePlan): boolean;
20
24
  /**
21
25
  * Generate SQS queue infrastructure code
22
26
  */
@@ -138,6 +138,12 @@ const ${tableVariable} = app.addDatabase(
138
138
  }
139
139
  return code;
140
140
  }
141
+ /**
142
+ * Check if an SQS queue needs a variable assignment (referenced by compute)
143
+ */
144
+ export function sqsNeedsVariable(queue, plan) {
145
+ return plan.compute.some((compute) => compute.connectedMessaging?.includes(queue.name));
146
+ }
141
147
  /**
142
148
  * Generate SQS queue infrastructure code
143
149
  */
@@ -147,8 +153,10 @@ export function generateSQSCode(plan) {
147
153
  let code = "";
148
154
  for (const queue of plan.sqs) {
149
155
  const queueVariable = getVariableName(queue);
156
+ const hasReferences = sqsNeedsVariable(queue, plan);
157
+ const prefix = hasReferences ? `const ${queueVariable} = ` : "";
150
158
  code += `
151
- const ${queueVariable} = app.addMessaging(
159
+ ${prefix}app.addMessaging(
152
160
  MessagingFactory.build("${queue.name}", {
153
161
  type: "queue",
154
162
  queueType: "${queue.queueType}"`;
@@ -4,7 +4,7 @@
4
4
  * Functions for generating storage connection code (env vars, connections array)
5
5
  * following the same pattern as database connections.
6
6
  */
7
- import type { S3ResourcePlan, ApplicationResourcePlan, ComputeResourcePlan, DatabaseResourcePlan } from "../schemas/resourceSchemas.js";
7
+ import type { S3ResourcePlan, SQSResourcePlan, ApplicationResourcePlan, ComputeResourcePlan, DatabaseResourcePlan } from "../schemas/resourceSchemas.js";
8
8
  export declare const STORAGE_ENV_VARS: Readonly<{
9
9
  readonly NAME: "BUCKET_NAME";
10
10
  }>;
@@ -32,6 +32,6 @@ export declare function generateStorageEnvVarEntries(connectedStorage: S3Resourc
32
32
  export declare function buildStorageEnvVars(plan: ApplicationResourcePlan, compute: ComputeResourcePlan): StorageEnvVars;
33
33
  /**
34
34
  * Format combined connections array for generated infrastructure code.
35
- * Merges both database and storage variable names into a single connections line.
35
+ * Merges database, storage, and messaging variable names into a single connections line.
36
36
  */
37
- export declare function formatAllConnectionsCode(connectedDatabases: DatabaseResourcePlan[], connectedStorage: S3ResourcePlan[]): string;
37
+ export declare function formatAllConnectionsCode(connectedDatabases: DatabaseResourcePlan[], connectedStorage: S3ResourcePlan[], connectedMessaging?: SQSResourcePlan[]): string;
@@ -24,7 +24,10 @@ export function getConnectedStorage(plan, compute) {
24
24
  export function generateStorageEnvVarEntries(connectedStorage) {
25
25
  const entries = [];
26
26
  if (connectedStorage.length === 1) {
27
- const bucketVar = getVariableName(connectedStorage[0]);
27
+ const bucket = connectedStorage[0];
28
+ if (!bucket)
29
+ return entries;
30
+ const bucketVar = getVariableName(bucket);
28
31
  entries.push({
29
32
  key: STORAGE_ENV_VARS.NAME,
30
33
  expression: `${bucketVar}.getBucketName()`,
@@ -61,11 +64,12 @@ export function buildStorageEnvVars(plan, compute) {
61
64
  }
62
65
  /**
63
66
  * Format combined connections array for generated infrastructure code.
64
- * Merges both database and storage variable names into a single connections line.
67
+ * Merges database, storage, and messaging variable names into a single connections line.
65
68
  */
66
- export function formatAllConnectionsCode(connectedDatabases, connectedStorage) {
69
+ export function formatAllConnectionsCode(connectedDatabases, connectedStorage, connectedMessaging = []) {
67
70
  const dbVars = connectedDatabases.map((db) => getVariableName(db));
68
71
  const storageVars = connectedStorage.map((b) => getVariableName(b));
69
- const allVars = [...dbVars, ...storageVars].join(", ");
72
+ const messagingVars = connectedMessaging.map((q) => getVariableName(q));
73
+ const allVars = [...dbVars, ...storageVars, ...messagingVars].join(", ");
70
74
  return `connections: [${allVars}],`;
71
75
  }
@@ -8,3 +8,4 @@ export * from "./generation/index.js";
8
8
  export * from "./presets/index.js";
9
9
  export * from "./ast/index.js";
10
10
  export * from "./planning/index.js";
11
+ export * from "./dns/index.js";
package/dist/src/index.js CHANGED
@@ -17,3 +17,5 @@ export * from "./presets/index.js";
17
17
  export * from "./ast/index.js";
18
18
  // Resource planning
19
19
  export * from "./planning/index.js";
20
+ // DNS
21
+ export * from "./dns/index.js";
@@ -17,7 +17,6 @@ export function planApplicationResources(appName, appType, includeDatabase = tru
17
17
  database: [],
18
18
  s3: [],
19
19
  compute: [],
20
- importedResources: [],
21
20
  };
22
21
  if (appType === "custom") {
23
22
  return basePlan;
@@ -136,7 +135,6 @@ export function planOpenNextResources(appName, pattern, options) {
136
135
  s3: [],
137
136
  compute: [],
138
137
  tags: tags ?? {},
139
- importedResources: [],
140
138
  });
141
139
  }
142
140
  function mergeDatabaseConfig(database, tierPreset) {
@@ -5,6 +5,7 @@
5
5
  * consumers. Extracted from tierPresets.ts for maintainability.
6
6
  */
7
7
  import type { EcsCapacityProvider, BackupVaultTier } from "../schemas/constants.js";
8
+ import type { WarmPool } from "../schemas/computeSchemas.js";
8
9
  /**
9
10
  * Proxy configuration for tier presets
10
11
  * Presence = enabled. Use `false` to explicitly disable.
@@ -105,7 +106,7 @@ export interface DatabaseTierPreset {
105
106
  * Only applies when capacityProvider is "EC2".
106
107
  */
107
108
  export interface TierEc2CapacityConfig {
108
- /** EC2 instance type. Default: "t3.micro" */
109
+ /** EC2 instance type. Default: "t4g.micro" */
109
110
  instanceType?: string;
110
111
  /** AMI hardware type. Default: "ARM" for cost efficiency */
111
112
  amiHardwareType?: "ARM" | "STANDARD";
@@ -115,6 +116,8 @@ export interface TierEc2CapacityConfig {
115
116
  maxCapacity?: number;
116
117
  /** Memory limit for container in MiB. Default: 400 */
117
118
  memoryLimitMiB?: number;
119
+ /** Warm pool configuration for faster instance start times. */
120
+ warmPool?: WarmPool;
118
121
  }
119
122
  /**
120
123
  * Cluster configuration for ECS tier presets.