fjall 0.89.6 → 0.94.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 (107) hide show
  1. package/bin/.bundled +3 -0
  2. package/bin/.metafile.json +39155 -0
  3. package/bin/assets/generators/account/files/infrastructure.ts +17 -0
  4. package/bin/assets/generators/account/generator.d.ts +8 -0
  5. package/bin/assets/generators/account/generator.js +2 -0
  6. package/bin/assets/generators/account/index.d.ts +1 -0
  7. package/bin/assets/generators/account/index.js +1 -0
  8. package/bin/assets/generators/application/generator.d.ts +4 -0
  9. package/bin/assets/generators/application/generator.js +28 -0
  10. package/bin/assets/generators/application/index.d.ts +1 -0
  11. package/bin/assets/generators/application/index.js +1 -0
  12. package/bin/assets/generators/cdn/generator.d.ts +4 -0
  13. package/bin/assets/generators/cdn/generator.js +4 -0
  14. package/bin/assets/generators/cdn/index.d.ts +1 -0
  15. package/bin/assets/generators/cdn/index.js +1 -0
  16. package/bin/assets/generators/compute/computeIntegrationHelpers.d.ts +134 -0
  17. package/bin/assets/generators/compute/computeIntegrationHelpers.js +1 -0
  18. package/bin/assets/generators/compute/generator.d.ts +4 -0
  19. package/bin/assets/generators/compute/generator.js +1 -0
  20. package/bin/assets/generators/compute/index.d.ts +1 -0
  21. package/bin/assets/generators/compute/index.js +1 -0
  22. package/bin/assets/generators/compute/service/generator.d.ts +4 -0
  23. package/bin/assets/generators/compute/service/generator.js +1 -0
  24. package/bin/assets/generators/compute/service/index.d.ts +1 -0
  25. package/bin/assets/generators/compute/service/index.js +1 -0
  26. package/bin/assets/generators/database/databaseIntegrationTestUtils.d.ts +134 -0
  27. package/bin/assets/generators/database/databaseIntegrationTestUtils.js +1 -0
  28. package/bin/assets/generators/database/generator.d.ts +4 -0
  29. package/bin/assets/generators/database/generator.js +1 -0
  30. package/bin/assets/generators/database/index.d.ts +1 -0
  31. package/bin/assets/generators/database/index.js +1 -0
  32. package/bin/assets/generators/database/proxy/generator.d.ts +4 -0
  33. package/bin/assets/generators/database/proxy/generator.js +1 -0
  34. package/bin/assets/generators/database/proxy/index.d.ts +1 -0
  35. package/bin/assets/generators/database/proxy/index.js +1 -0
  36. package/bin/assets/generators/domain/files/infrastructure.ts.ejs +22 -0
  37. package/bin/assets/generators/domain/files/zone.bind.ejs +14 -0
  38. package/bin/assets/generators/domain/generator.d.ts +10 -0
  39. package/bin/assets/generators/domain/generator.js +2 -0
  40. package/bin/assets/generators/domain/index.d.ts +1 -0
  41. package/bin/assets/generators/domain/index.js +1 -0
  42. package/bin/assets/generators/messaging/index.d.ts +1 -0
  43. package/bin/assets/generators/messaging/index.js +0 -0
  44. package/bin/assets/generators/network/generator.d.ts +4 -0
  45. package/bin/assets/generators/network/generator.js +1 -0
  46. package/bin/assets/generators/network/index.d.ts +1 -0
  47. package/bin/assets/generators/network/index.js +1 -0
  48. package/bin/assets/generators/organisation/files/account/infrastructure.ts +25 -0
  49. package/bin/assets/generators/organisation/files/organisation/infrastructure.ts +46 -0
  50. package/bin/assets/generators/organisation/files/platform/infrastructure.ts +16 -0
  51. package/bin/assets/generators/organisation/generator.d.ts +4 -0
  52. package/bin/assets/generators/organisation/generator.js +2 -0
  53. package/bin/assets/generators/organisation/index.d.ts +1 -0
  54. package/bin/assets/generators/organisation/index.js +1 -0
  55. package/bin/assets/generators/shared/files/cdk.context.json +3 -0
  56. package/bin/assets/generators/shared/files/cdk.json +55 -0
  57. package/bin/assets/generators/shared/files/package.json +15 -0
  58. package/bin/assets/generators/shared/files/tsconfig.json +23 -0
  59. package/bin/assets/generators/storage/index.d.ts +1 -0
  60. package/bin/assets/generators/storage/index.js +1 -0
  61. package/bin/assets/generators/storage/s3/generator.d.ts +4 -0
  62. package/bin/assets/generators/storage/s3/generator.js +1 -0
  63. package/bin/assets/generators/tunnel/generator.d.ts +4 -0
  64. package/bin/assets/generators/tunnel/generator.js +1 -0
  65. package/bin/assets/generators/tunnel/index.d.ts +1 -0
  66. package/bin/assets/generators/tunnel/index.js +1 -0
  67. package/bin/assets/generators/utils/ast/astCodeModification.d.ts +23 -0
  68. package/bin/assets/generators/utils/ast/astCodeModification.js +1 -0
  69. package/bin/assets/generators/utils/ast/astDomainRewriter.d.ts +65 -0
  70. package/bin/assets/generators/utils/ast/astDomainRewriter.js +1 -0
  71. package/bin/assets/generators/utils/ast/astSurgicalModification.d.ts +2 -0
  72. package/bin/assets/generators/utils/ast/astSurgicalModification.js +1 -0
  73. package/bin/assets/generators/utils/ast/index.d.ts +3 -0
  74. package/bin/assets/generators/utils/ast/index.js +1 -0
  75. package/bin/assets/generators/utils/copySharedFiles.d.ts +10 -0
  76. package/bin/assets/generators/utils/copySharedFiles.js +1 -0
  77. package/bin/assets/generators/utils/index.d.ts +8 -0
  78. package/bin/assets/generators/utils/index.js +1 -0
  79. package/bin/assets/generators/utils/integrationTestUtils.d.ts +129 -0
  80. package/bin/assets/generators/utils/integrationTestUtils.js +2 -0
  81. package/bin/assets/generators/utils/mockTree.d.ts +30 -0
  82. package/bin/assets/generators/utils/mockTree.js +1 -0
  83. package/bin/assets/generators/utils/planning/generatorHelpers.d.ts +35 -0
  84. package/bin/assets/generators/utils/planning/generatorHelpers.js +2 -0
  85. package/bin/assets/generators/utils/planning/index.d.ts +1 -0
  86. package/bin/assets/generators/utils/planning/index.js +1 -0
  87. package/bin/assets/generators/utils/prompts.d.ts +4 -0
  88. package/bin/assets/generators/utils/prompts.js +6 -0
  89. package/bin/assets/generators/utils/renderEjs.d.ts +24 -0
  90. package/bin/assets/generators/utils/renderEjs.js +1 -0
  91. package/bin/assets/generators/utils/resources/connectionHelpers.d.ts +19 -0
  92. package/bin/assets/generators/utils/resources/connectionHelpers.js +1 -0
  93. package/bin/assets/generators/utils/resources/index.d.ts +4 -0
  94. package/bin/assets/generators/utils/resources/index.js +1 -0
  95. package/bin/assets/generators/utils/resources/promptValidation.d.ts +42 -0
  96. package/bin/assets/generators/utils/resources/promptValidation.js +1 -0
  97. package/bin/assets/generators/utils/resources/resourceDetection.d.ts +12 -0
  98. package/bin/assets/generators/utils/resources/resourceDetection.js +1 -0
  99. package/bin/assets/generators/utils/resources/resourceNaming.d.ts +6 -0
  100. package/bin/assets/generators/utils/resources/resourceNaming.js +1 -0
  101. package/bin/assets/generators/utils/tree.d.ts +25 -0
  102. package/bin/assets/generators/utils/tree.js +1 -0
  103. package/bin/assets/proto/buildkit.proto +126 -0
  104. package/bin/assets/proto/proto/buildkit.proto +126 -0
  105. package/bin/fjall.bundle.js +1138 -0
  106. package/bin/fjall.js +5 -1
  107. package/package.json +41 -4
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ App,
5
+ OrganisationFactory,
6
+ getConfig
7
+ } from "@fjall/components-infrastructure";
8
+
9
+ const config = getConfig();
10
+
11
+ if (config.environment !== "platform" && config.environment !== "root") {
12
+ const app = App.getInstance();
13
+ const buildAccount = OrganisationFactory.build("Account", {
14
+ type: "account"
15
+ });
16
+ buildAccount(app);
17
+ }
@@ -0,0 +1,8 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { z } from "zod";
3
+ export declare const AccountGeneratorSchema: z.ZodObject<{
4
+ primaryRegion: z.ZodDefault<z.ZodOptional<z.ZodString>>;
5
+ }, z.core.$strict>;
6
+ export type AccountGeneratorOptions = z.infer<typeof AccountGeneratorSchema>;
7
+ export declare function accountGenerator(tree: Tree, options: AccountGeneratorOptions): Promise<void>;
8
+ export default accountGenerator;
@@ -0,0 +1,2 @@
1
+ import{join as i}from"path";import{renderEjsTemplates as m}from"../utils/renderEjs.js";import{copySharedCdkFiles as s}from"../utils/copySharedFiles.js";import{getOrganisationComponentPath as p}from"../../src/util/pathHelpers.js";import{z as a}from"zod";import{getZodErrorMessage as c,DEFAULT_REGION as f}from"@fjall/generator";const g=import.meta.dirname,d=a.object({primaryRegion:a.string().optional().default(f)}).strict();async function l(o,n){const r=d.safeParse(n);if(!r.success)throw new Error(`Invalid account generator options:
2
+ ${c(r.error)}`);const t=p("account"),e={primaryRegion:r.data.primaryRegion};m(o,i(g,"files"),t,e),s(o,t,{...e,packageName:"infra-app"})}var x=l;export{d as AccountGeneratorSchema,l as accountGenerator,x as default};
@@ -0,0 +1 @@
1
+ export { accountGenerator, AccountGeneratorSchema, type AccountGeneratorOptions } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{accountGenerator as r,AccountGeneratorSchema as c}from"./generator.js";export{c as AccountGeneratorSchema,r as accountGenerator};
@@ -0,0 +1,4 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { type ApplicationGeneratorOptions } from "@fjall/generator";
3
+ export declare function applicationGenerator(tree: Tree, options: ApplicationGeneratorOptions): Promise<void>;
4
+ export default applicationGenerator;
@@ -0,0 +1,28 @@
1
+ import{join as m}from"path";import{copySharedCdkFiles as u}from"../utils/copySharedFiles.js";import{getInfrastructurePath as d,getAppPath as l}from"../../src/util/pathHelpers.js";import{planApplicationResources as f,planOpenNextResources as g,generateInfrastructureFromPlan as b,ApplicationGeneratorSchema as w,getZodErrorMessage as h}from"@fjall/generator";import{z as y}from"zod";async function C(n,r){let e;try{e=w.parse(r)}catch(t){throw t instanceof y.ZodError?new Error(`Invalid application generator options:
2
+ ${h(t)}`):t}let o;if(e.pattern){const t=e.includeDatabase??!0,a=e.patternTier||"standard",c=t?a==="custom"&&e.customDatabase?{type:e.customDatabase.type,instanceType:e.customDatabase.instanceType,databaseName:e.databaseName,backupRetention:e.customDatabase.backupRetention,deletionProtection:e.customDatabase.deletionProtection,encryption:e.customDatabase.encryption}:{databaseName:e.databaseName}:void 0,p=a==="custom"&&e.customCompute?{memorySize:e.customCompute.memorySize,timeout:e.customCompute.timeout}:void 0,i=g(e.name,e.pattern,{tier:a,domain:e.patternDomain,database:c,compute:p});if(!i.success)throw new Error(i.error.message);o=i.data}else if(e.type==="custom")o=await k(e);else{const t=e.services?.map(a=>({name:a.name,dockerfilePath:a.dockerfilePath,containerPort:a.containerPort,needsDatabaseConnection:a.needsDatabaseConnection,routing:a.routing}));o=f(e.name,e.type,e.includeDatabase??!0,t,{snapshotIdentifier:e.snapshotIdentifier,snapshotUsername:e.snapshotUsername})}e.owner&&(o.owner=e.owner),e.vpcId&&(o.vpcId=e.vpcId),e.network!==void 0&&(o.network=e.network===!1?void 0:e.network);const s=b(o);if(!s.success)throw new Error(s.error.message);if(n.write(d(e.name),s.data),e.pattern==="payload"||e.pattern==="nextjs"){const t=m(l(e.name),"open-next.config.ts");n.write(t,D())}u(n,e.name,{name:e.name,type:e.type,packageName:e.name})}async function k(n){const r=n.network||void 0;return{appName:n.name,type:"custom",owner:n.owner,network:r,database:[],s3:[],compute:[]}}function D(){return`// OpenNext configuration - Generated by Fjall CLI
3
+ const sharpInstallConfig = {
4
+ packages: ["sharp@0.34.2", "typescript@5.7.3"],
5
+ arch: "arm64" as const,
6
+ nodeVersion: "20.0.0",
7
+ libc: "glibc" as const,
8
+ };
9
+
10
+ const config = {
11
+ default: {
12
+ install: sharpInstallConfig,
13
+ override: {
14
+ wrapper: "aws-lambda-streaming",
15
+ converter: "aws-apigw-v2",
16
+ incrementalCache: "s3-lite",
17
+ tagCache: "dynamodb-lite",
18
+ queue: "sqs-lite",
19
+ },
20
+ },
21
+ imageOptimization: {
22
+ loader: "s3",
23
+ install: sharpInstallConfig,
24
+ },
25
+ };
26
+
27
+ export default config;
28
+ `}var R=C;export{C as applicationGenerator,R as default};
@@ -0,0 +1 @@
1
+ export { applicationGenerator } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{applicationGenerator as a}from"./generator.js";export{a as applicationGenerator};
@@ -0,0 +1,4 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { type CdnGeneratorOptions } from "@fjall/generator";
3
+ export declare function cdnGenerator(tree: Tree, options: CdnGeneratorOptions): Promise<void>;
4
+ export default cdnGenerator;
@@ -0,0 +1,4 @@
1
+ import{withInfrastructurePlan as g}from"../utils/planning/generatorHelpers.js";import{CdnGeneratorSchema as p,toPascalCase as w}from"@fjall/generator";import{promptForConnection as b}from"../utils/prompts.js";import s from"prompts";function R(o){const n=[];for(const e of o.s3)n.push({name:e.name,description:"S3 Storage"});for(const e of o.compute)e.type==="lambda"?e.functionUrl&&n.push({name:e.name,description:"Lambda"}):e.type==="ecs"&&n.push({name:e.name,description:"ECS with ALB"});return n}function d(o,n){if(!n.some(i=>i.name===o)){const i=n.map(t=>t.name).join(", ");throw new Error(`Origin "${o}" not found in infrastructure. Available origins: ${i}`)}}async function y(o,n){const e=R(o);if(e.length===0)throw new Error("No available CDN origins found. Add an S3 bucket or compute resource with ALB/function URL first.");if(n.defaultOriginRef){if(d(n.defaultOriginRef,e),n.behaviours)for(const r of n.behaviours)d(r.originRef,e);return{defaultOriginRef:n.defaultOriginRef,behaviours:n.behaviours,...n.customDomain&&{customDomain:n.customDomain}}}if(n.nameProvidedByFlag)throw new Error("Default origin must be specified in non-interactive mode");let i;if(e.length===1)i=e[0].name,process.stdout.write(`
2
+ Auto-selected origin: ${i}
3
+ `);else if(i=(await s([{type:"select",name:"origin",message:"Select the default origin:",choices:e.map(c=>({title:`${c.name} (${c.description})`,value:c.name}))}])).origin,!i)throw new Error("Origin selection cancelled");let t;const a=e.filter(r=>r.name!==i);if(a.length>0&&await b(a.length,"origin","Add path-based routing to another origin?","Add path-based routing to other origins?")){t=[];let c=!0;for(;c&&a.length>0;){const h=(await s([{type:"text",name:"pathPattern",message:"Path pattern (e.g., /static/*):"}])).pathPattern;if(!h)break;let m;if(a.length===1)m=a[0].name,process.stdout.write(` Auto-selected origin: ${m}
4
+ `);else if(m=(await s([{type:"select",name:"origin",message:"Origin for this path:",choices:a.map(f=>({title:`${f.name} (${f.description})`,value:f.name}))}])).origin,!m)break;const l=(await s([{type:"select",name:"cachePolicy",message:"Cache policy:",choices:[{title:"Caching Optimised",value:"CACHING_OPTIMIZED",description:"Best for static assets"},{title:"Caching Disabled",value:"CACHING_DISABLED",description:"Best for dynamic APIs"}]}])).cachePolicy;t.push({pathPattern:h,originRef:m,...l!==void 0&&{cachePolicy:l}}),c=(await s([{type:"confirm",name:"addMore",message:"Add another path route?",initial:!1}])).addMore}t.length===0&&(t=void 0)}let u;return(await s([{type:"confirm",name:"wantDomain",message:"Add a custom domain?",initial:!1}])).wantDomain&&(u=(await s([{type:"text",name:"domain",message:"Enter custom domain:"}])).domain||void 0),{defaultOriginRef:i,behaviours:t,...u!==void 0&&{customDomain:u}}}async function A(o,n){await g(o,p,n,"CDN",async({validated:e,plan:i})=>{if(i.cdn)throw new Error("A CDN is already configured for this application. Remove the existing CDN first.");const t=await y(i,e),a=e.name??`${w(e.appName)}Cdn`;return{...i,cdn:{name:a,defaultOriginRef:t.defaultOriginRef,...t.behaviours&&t.behaviours.length>0&&{behaviours:t.behaviours},...t.customDomain!==void 0&&{customDomain:t.customDomain},...e.certificateArn!==void 0&&{certificateArn:e.certificateArn},...e.accessGate!==void 0&&{accessGate:e.accessGate}}}})}var S=A;export{A as cdnGenerator,S as default};
@@ -0,0 +1 @@
1
+ export { cdnGenerator } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{cdnGenerator as o}from"./generator.js";export{o as cdnGenerator};
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Shared helpers for compute integration tests.
3
+ *
4
+ * Extracted to allow splitting compute tests across multiple files
5
+ * for parallel execution without duplicating helper functions.
6
+ */
7
+ import { type TierName, type EC2InstanceType, type EnvironmentValue } from "@fjall/generator";
8
+ import { FileSystemTree } from "../utils/tree.js";
9
+ import { type CfnTemplate, type ResourceEntry } from "../utils/integrationTestUtils.js";
10
+ export { CLI_ROOT } from "../utils/integrationTestUtils.js";
11
+ export declare function createTree(): FileSystemTree;
12
+ /**
13
+ * Create a test app with the application generator
14
+ */
15
+ export declare function createTestApp(tree: FileSystemTree, appName: string, tier: TierName | "custom"): Promise<void>;
16
+ /**
17
+ * Add ECS compute to an existing app
18
+ */
19
+ export declare function addEcsCompute(tree: FileSystemTree, appName: string, options: {
20
+ computeName: string;
21
+ capacityProvider?: "FARGATE" | "FARGATE_SPOT" | "EC2";
22
+ containerPort?: number;
23
+ containers?: Array<{
24
+ name: string;
25
+ image?: string;
26
+ port?: number;
27
+ environment?: Record<string, EnvironmentValue>;
28
+ essential?: boolean;
29
+ }>;
30
+ desiredCount?: number;
31
+ cpu?: number;
32
+ memoryLimitMiB?: number;
33
+ ec2Config?: {
34
+ instanceType?: string;
35
+ amiHardwareType?: "ARM" | "STANDARD";
36
+ minCapacity?: number;
37
+ maxCapacity?: number;
38
+ memoryLimitMiB?: number;
39
+ };
40
+ }): Promise<void>;
41
+ /**
42
+ * Add Lambda compute to an existing app
43
+ */
44
+ export declare function addLambdaCompute(tree: FileSystemTree, appName: string, options: {
45
+ computeName: string;
46
+ timeout?: number;
47
+ memory?: number;
48
+ handler?: string;
49
+ runtime?: string;
50
+ }): Promise<void>;
51
+ /**
52
+ * Add ECS compute with multiple services to an existing app
53
+ */
54
+ export declare function addMultiServiceEcsCompute(tree: FileSystemTree, appName: string, options: {
55
+ computeName: string;
56
+ capacityProvider?: "FARGATE" | "FARGATE_SPOT" | "EC2";
57
+ cluster?: {
58
+ domain?: string;
59
+ loadBalancer?: false | "public" | "internal";
60
+ directAccess?: boolean;
61
+ };
62
+ ec2Config?: {
63
+ instanceType?: string;
64
+ amiHardwareType?: "ARM" | "STANDARD";
65
+ minCapacity?: number;
66
+ maxCapacity?: number;
67
+ memoryLimitMiB?: number;
68
+ };
69
+ services: Array<{
70
+ name: string;
71
+ containers?: Array<{
72
+ name?: string;
73
+ port?: number;
74
+ image?: string;
75
+ ssmSecrets?: string[];
76
+ }>;
77
+ routing?: {
78
+ path?: string;
79
+ host?: string;
80
+ priority?: number;
81
+ } | Array<{
82
+ path?: string;
83
+ host?: string;
84
+ priority?: number;
85
+ }>;
86
+ cpu?: number;
87
+ memoryLimitMiB?: number;
88
+ desiredCount?: number;
89
+ ssmSecretsPath?: string;
90
+ capacityProvider?: "FARGATE" | "FARGATE_SPOT" | "EC2";
91
+ ec2Config?: {
92
+ instanceType?: string;
93
+ amiHardwareType?: "ARM" | "STANDARD";
94
+ minCapacity?: number;
95
+ maxCapacity?: number;
96
+ memoryLimitMiB?: number;
97
+ };
98
+ }>;
99
+ }): Promise<void>;
100
+ /**
101
+ * Add EC2 compute to an existing app
102
+ */
103
+ export declare function addEc2Compute(tree: FileSystemTree, appName: string, options: {
104
+ computeName: string;
105
+ instanceType?: EC2InstanceType;
106
+ enableSSH?: boolean;
107
+ }): Promise<void>;
108
+ /**
109
+ * Expected configuration derived from tier preset
110
+ */
111
+ export interface ExpectedEcsConfig {
112
+ capacityProvider: "FARGATE" | "FARGATE_SPOT" | "EC2";
113
+ cpu: string;
114
+ memory: string;
115
+ desiredCount: number;
116
+ isEc2Based: boolean;
117
+ }
118
+ /**
119
+ * Derive expected ECS configuration from tier preset
120
+ */
121
+ export declare function getExpectedComputeConfigFromPreset(tier: TierName): ExpectedEcsConfig;
122
+ /**
123
+ * ECS tiers - all tiers support ECS
124
+ */
125
+ export declare const ECS_TIER_SUPPORT: TierName[];
126
+ export declare function findEcsCluster(template: CfnTemplate): ResourceEntry | undefined;
127
+ export declare function findEcsService(template: CfnTemplate): ResourceEntry | undefined;
128
+ export declare function findEcsTaskDefinition(template: CfnTemplate): ResourceEntry | undefined;
129
+ export declare function findLoadBalancer(template: CfnTemplate): ResourceEntry | undefined;
130
+ export declare function findLambdaFunction(template: CfnTemplate): ResourceEntry | undefined;
131
+ export declare function findAutoScalingGroup(template: CfnTemplate): ResourceEntry | undefined;
132
+ export declare function findSecurityGroups(template: CfnTemplate): ResourceEntry[];
133
+ export declare function findTargetGroups(template: CfnTemplate): ResourceEntry[];
134
+ export declare function findListenerRules(template: CfnTemplate): ResourceEntry[];
@@ -0,0 +1 @@
1
+ import{applicationGenerator as u}from"../application/generator.js";import{computeGenerator as o}from"./generator.js";import{getEcsPreset as m}from"@fjall/generator";import{FileSystemTree as d}from"../utils/tree.js";import{CLI_ROOT as p,findResourcesByType as n}from"../utils/integrationTestUtils.js";import{CLI_ROOT as h}from"../utils/integrationTestUtils.js";function g(){return new d(p)}async function S(t,r,e){await u(t,{name:r,type:e,includeDatabase:!1,network:{maxAzs:2,natGateways:{count:1},flowLogs:!1}})}async function v(t,r,e){const a=e.capacityProvider??"FARGATE";let c;e.containers?c=[{name:"TestService",capacityProvider:a,ec2Config:e.ec2Config,containers:e.containers,cpu:e.cpu,memoryLimitMiB:e.memoryLimitMiB,desiredCount:e.desiredCount}]:e.containerPort?c=[{name:"TestService",capacityProvider:a,ec2Config:e.ec2Config,containers:[{port:e.containerPort}],cpu:e.cpu,memoryLimitMiB:e.memoryLimitMiB,desiredCount:e.desiredCount}]:c=[{name:"TestService",capacityProvider:a,ec2Config:e.ec2Config}],await o(t,{appName:r,computeName:e.computeName,type:"ecs",nameProvidedByFlag:!0,connectionConfig:{connectToDatabase:[]},services:c})}async function E(t,r,e){await o(t,{appName:r,computeName:e.computeName,type:"lambda",nameProvidedByFlag:!0,connectionConfig:{connectToDatabase:[]},timeout:e.timeout,memory:e.memory,handler:e.handler,runtime:e.runtime})}async function T(t,r,e){const a=e.capacityProvider??"FARGATE",c=e.services.map(i=>({...i,capacityProvider:i.capacityProvider??a,ec2Config:i.ec2Config??(i.capacityProvider==="EC2"||!i.capacityProvider&&a==="EC2"?e.ec2Config:void 0)}));await o(t,{appName:r,computeName:e.computeName,type:"ecs",nameProvidedByFlag:!0,connectionConfig:{connectToDatabase:[]},cluster:e.cluster,services:c})}async function P(t,r,e){await o(t,{appName:r,computeName:e.computeName,type:"ec2",nameProvidedByFlag:!0,connectionConfig:{connectToDatabase:[]},instanceType:e.instanceType,enableSSH:e.enableSSH})}function x(t){const e=m(t).services[0];return{capacityProvider:e.capacityProvider,cpu:String(e.cpu??256),memory:String(e.memoryLimitMiB??512),desiredCount:e.desiredCount??1,isEc2Based:e.capacityProvider==="EC2"}}const A=["tinkerer","lightweight","standard","resilient","enterprise"];function L(t){return n(t,"AWS::ECS::Cluster")[0]}function B(t){return n(t,"AWS::ECS::Service")[0]}function b(t){return n(t,"AWS::ECS::TaskDefinition")[0]}function G(t){return n(t,"AWS::ElasticLoadBalancingV2::LoadBalancer")[0]}function w(t){return n(t,"AWS::Lambda::Function")[0]}function F(t){return n(t,"AWS::AutoScaling::AutoScalingGroup")[0]}function W(t){return n(t,"AWS::EC2::SecurityGroup")}function R(t){return n(t,"AWS::ElasticLoadBalancingV2::TargetGroup")}function N(t){return n(t,"AWS::ElasticLoadBalancingV2::ListenerRule")}export{h as CLI_ROOT,A as ECS_TIER_SUPPORT,P as addEc2Compute,v as addEcsCompute,E as addLambdaCompute,T as addMultiServiceEcsCompute,S as createTestApp,g as createTree,F as findAutoScalingGroup,L as findEcsCluster,B as findEcsService,b as findEcsTaskDefinition,w as findLambdaFunction,N as findListenerRules,G as findLoadBalancer,W as findSecurityGroups,R as findTargetGroups,x as getExpectedComputeConfigFromPreset};
@@ -0,0 +1,4 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { type ComputeGeneratorOptions } from "@fjall/generator";
3
+ export declare function computeGenerator(tree: Tree, options: ComputeGeneratorOptions): Promise<void>;
4
+ export default computeGenerator;
@@ -0,0 +1 @@
1
+ import{assertResourceNameUnique as o}from"../utils/resources/resourceDetection.js";import{withInfrastructurePlan as s}from"../utils/planning/generatorHelpers.js";import{ComputeGeneratorSchema as i}from"@fjall/generator";import{ensureUniqueResourceName as f}from"../utils/resources/resourceNaming.js";import{promptForConnection as y,selectResources as h}from"../utils/prompts.js";function p(r,e,n){const t=n.length>0;switch(e.type){case"ecs":return{name:r,type:"ecs",needsConnection:t,connectedDatabase:n,cluster:e.cluster,services:e.services,dockerfilePath:e.dockerfilePath};case"lambda":return{name:r,type:"lambda",needsConnection:t,connectedDatabase:n,timeout:e.timeout,memory:e.memory,handler:e.handler,runtime:e.runtime,environment:e.environment,secrets:e.secrets};case"ec2":return{name:r,type:"ec2",needsConnection:t,connectedDatabase:n,instanceType:e.instanceType,enableSSH:e.enableSSH,keyName:e.keyName,userData:e.userData,securityGroups:e.securityGroups};default:return e}}async function C(r,e){await s(r,i,e,"compute",async({tree:n,validated:t,plan:a})=>{t.nameProvidedByFlag||o(n,t.appName,t.computeName);const c=t.nameProvidedByFlag?f(n,t.appName,t.computeName):t.computeName,m=await b(t,a),u=p(c,t,m);return{...a,compute:[...a.compute,u]}})}async function b(r,e){return r.connectionConfig?r.connectionConfig.connectToDatabase??[]:e.database.length>0&&!r.nameProvidedByFlag&&await y(e.database.length,"database","Connect to existing database?","Found {count} databases. Configure connections?")?h(e.database,"Select databases to connect:",t=>`${t.type} - ${t.databaseName}`):[]}var w=C;export{C as computeGenerator,w as default};
@@ -0,0 +1 @@
1
+ export { computeGenerator } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{computeGenerator as r}from"./generator.js";export{r as computeGenerator};
@@ -0,0 +1,4 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { type AddServiceGeneratorOptions } from "@fjall/generator";
3
+ export declare function serviceGenerator(tree: Tree, options: AddServiceGeneratorOptions): Promise<void>;
4
+ export default serviceGenerator;
@@ -0,0 +1 @@
1
+ import{AddServiceGeneratorSchema as g}from"@fjall/generator";import{withInfrastructurePlan as p,pickDefined as h}from"../../utils/planning/generatorHelpers.js";async function l(m,f){await p(m,g,f,"service",({validated:n,plan:o})=>{const t=o.compute.find(e=>e.name===n.clusterName&&e.type==="ecs");if(!t)throw new Error(`ECS cluster '${n.clusterName}' not found. Available clusters: ${o.compute.filter(e=>e.type==="ecs").map(e=>e.name).join(", ")||"none"}`);const c=t.services||[];if(c.some(e=>e.name===n.serviceName))throw new Error(`Service '${n.serviceName}' already exists in cluster '${n.clusterName}'`);const i={name:n.serviceName,capacityProvider:n.capacityProvider,...h(n,"dockerfilePath","dockerTarget","cpu","memoryLimitMiB","desiredCount","ec2Config","routing")};if(n.containerPort&&(i.containers=[{port:n.containerPort}]),n.connectionConfig?.connectToDatabase?.length){i.needsDatabaseConnection=!0;const e=t.connectedDatabase||[],r=n.connectionConfig.connectToDatabase.filter(a=>!e.includes(a));r.length>0&&(t.connectedDatabase=[...e,...r],t.needsConnection=!0)}t.services=[...c,i];const s=t.services.filter(e=>e.containers?.some(r=>r.port));if(s.length>1){const e=s.filter(r=>!(Array.isArray(r.routing)?r.routing:r.routing?[r.routing]:[]).some(u=>u.path||u.host));if(e.length>0)throw new Error(`Multiple services have container ports \u2014 all must have routing configuration. Services missing routing: ${e.map(r=>r.name).join(", ")}`)}return o})}var y=l;export{y as default,l as serviceGenerator};
@@ -0,0 +1 @@
1
+ export { serviceGenerator, serviceGenerator as default } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{serviceGenerator as a,serviceGenerator as o}from"./generator.js";export{o as default,a as serviceGenerator};
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Database Integration Test Utilities
3
+ *
4
+ * Shared utilities for database integration tests.
5
+ * Extracted to enable parallel test execution across split test files.
6
+ *
7
+ * @see aiDocs/architecture/TESTING_STRATEGY.md
8
+ */
9
+ import { type TierName } from "@fjall/generator";
10
+ import type { FileSystemTree } from "../utils/tree.js";
11
+ import { type CfnTemplate, type ResourceEntry } from "../utils/integrationTestUtils.js";
12
+ export { CLI_ROOT, findSecurityGroupByDescription } from "../utils/integrationTestUtils.js";
13
+ export type { TierName } from "@fjall/generator";
14
+ /**
15
+ * Assert that a security group has a self-referencing ingress rule,
16
+ * optionally checking the port matches.
17
+ */
18
+ export declare function expectSecurityGroupSelfReferencing(template: CfnTemplate, description: string, options?: {
19
+ port?: number;
20
+ checkToPort?: boolean;
21
+ }): void;
22
+ /**
23
+ * Create a test app with the application generator
24
+ */
25
+ export declare function createTestApp(tree: FileSystemTree, appName: string, tier: TierName | "custom"): Promise<void>;
26
+ /**
27
+ * Database options for addDatabase helper
28
+ */
29
+ export interface AddDatabaseOptions {
30
+ databaseName: string;
31
+ databaseType: "Instance" | "Aurora" | "GlobalAurora";
32
+ resourceName: string;
33
+ tier?: TierName;
34
+ instanceType?: string;
35
+ multiAz?: boolean;
36
+ readReplica?: {
37
+ instanceType?: string;
38
+ } | false;
39
+ publiclyAccessible?: boolean;
40
+ readers?: {
41
+ count: number;
42
+ } | false;
43
+ backupRetention?: number;
44
+ primaryRegion?: string;
45
+ secondaryRegions?: string[];
46
+ enableGlobalWriteForwarding?: boolean;
47
+ port?: number;
48
+ proxy?: {
49
+ requireTLS?: boolean;
50
+ maxConnections?: number;
51
+ } | false;
52
+ credentials?: {
53
+ username?: string;
54
+ secretRotation?: {
55
+ automaticallyAfterDays?: number;
56
+ } | false;
57
+ };
58
+ databaseInsights?: {
59
+ mode?: "standard" | "advanced";
60
+ encryptionKey?: {
61
+ useCMK: true;
62
+ } | {
63
+ awsManaged: true;
64
+ };
65
+ } | false;
66
+ encryption?: {
67
+ storageKey?: {
68
+ useCMK: true;
69
+ } | {
70
+ awsManaged: true;
71
+ };
72
+ };
73
+ }
74
+ /**
75
+ * Add a database to an existing app
76
+ */
77
+ export declare function addDatabase(tree: FileSystemTree, appName: string, options: AddDatabaseOptions): Promise<void>;
78
+ /**
79
+ * Find the primary RDS Instance (not a read replica)
80
+ */
81
+ export declare function findPrimaryDbInstance(template: CfnTemplate): ResourceEntry | undefined;
82
+ /**
83
+ * Find read replica RDS Instances
84
+ */
85
+ export declare function findReadReplicas(template: CfnTemplate): ResourceEntry[];
86
+ /**
87
+ * Find Aurora DB Cluster
88
+ */
89
+ export declare function findAuroraCluster(template: CfnTemplate): ResourceEntry | undefined;
90
+ /**
91
+ * Find Aurora DB Instances (writer + readers)
92
+ */
93
+ export declare function findAuroraInstances(template: CfnTemplate): ResourceEntry[];
94
+ /**
95
+ * Find RDS Proxy resources
96
+ */
97
+ export declare function findRdsProxy(template: CfnTemplate): ResourceEntry | undefined;
98
+ /**
99
+ * Find KMS Keys (for encryption validation)
100
+ */
101
+ export declare function findKmsKeys(template: CfnTemplate): ResourceEntry[];
102
+ /**
103
+ * Find Security Groups
104
+ */
105
+ export declare function findSecurityGroups(template: CfnTemplate): ResourceEntry[];
106
+ /**
107
+ * Extract security group logical ID from a CloudFormation reference
108
+ * Handles both { Ref: logicalId } and { "Fn::GetAtt": [logicalId, "GroupId"] }
109
+ */
110
+ export declare function extractSecurityGroupRef(ref: unknown): string | undefined;
111
+ /**
112
+ * Find Security Group Ingress rules
113
+ * Returns rules that reference the given security group (self-referencing)
114
+ */
115
+ export declare function findSelfReferencingIngressRules(template: CfnTemplate, securityGroupLogicalId: string): ResourceEntry[];
116
+ /**
117
+ * Expected database configuration interface
118
+ */
119
+ export interface ExpectedDatabaseConfig {
120
+ port: number;
121
+ deletionProtection: boolean;
122
+ hasProxy: boolean;
123
+ proxyRequireTLS: boolean;
124
+ hasReadReplica: boolean;
125
+ multiAz: boolean;
126
+ storageEncrypted: boolean;
127
+ databaseInsightsEnabled: boolean;
128
+ backupRetentionPeriod: number;
129
+ }
130
+ /**
131
+ * Derive expected configuration from tier preset
132
+ * This ensures tests validate against the same source of truth as production code
133
+ */
134
+ export declare function getExpectedConfigFromPreset(tier: TierName, databaseType: "Instance" | "Aurora" | "GlobalAurora"): ExpectedDatabaseConfig;
@@ -0,0 +1 @@
1
+ import{applicationGenerator as R}from"../application/generator.js";import{databaseGenerator as x}from"./generator.js";import{DEFAULT_DATABASE_PORT as S,getDatabasePreset as u}from"@fjall/generator";import{expect as a}from"vitest";import{findResourcesByType as s,findSecurityGroupByDescription as A}from"../utils/integrationTestUtils.js";import{CLI_ROOT as K,findSecurityGroupByDescription as L}from"../utils/integrationTestUtils.js";function T(t,r,e){const n=b(t),i=A(n,r);a(i).toBeDefined();const o=m(t,i.logicalId);a(o.length).toBeGreaterThan(0),e?.port!==void 0&&(a(Number(o[0].properties.FromPort)).toBe(e.port),e.checkToPort&&a(Number(o[0].properties.ToPort)).toBe(e.port))}async function P(t,r,e){await R(t,{name:r,type:e,includeDatabase:!1,network:{maxAzs:2,natGateways:{count:1},flowLogs:!1}})}async function h(t,r,e){const n=e.tier?u(e.tier,e.databaseType):void 0,{tier:i,databaseName:o,databaseType:c,resourceName:f,...d}=e,l=n?{port:n.port,proxy:n.proxy,databaseInsights:n.databaseInsights,encryption:n.encryption,backupRetention:n.backupRetention,...c==="Instance"&&{instanceType:n.instanceType,multiAz:n.multiAz,readReplica:n.readReplica,publiclyAccessible:n.publiclyAccessible},...(c==="Aurora"||c==="GlobalAurora")&&{readers:n.readers}}:{},y={appName:r,databaseName:o,databaseType:c,resourceName:f,nameProvidedByFlag:!0,connectionConfig:{connectToCompute:[]},...l,...d};await x(t,y)}function C(t){return s(t,"AWS::RDS::DBInstance").find(e=>!e.properties.SourceDBInstanceIdentifier)}function E(t){return s(t,"AWS::RDS::DBInstance").filter(e=>e.properties.SourceDBInstanceIdentifier)}function W(t){return s(t,"AWS::RDS::DBCluster")[0]}function w(t){return s(t,"AWS::RDS::DBInstance").filter(e=>e.properties.DBClusterIdentifier)}function k(t){return s(t,"AWS::RDS::DBProxy")[0]}function F(t){return s(t,"AWS::KMS::Key")}function b(t){return s(t,"AWS::EC2::SecurityGroup")}function p(t){if(!t||typeof t!="object")return;const r=t;if(typeof r.Ref=="string")return r.Ref;const e=r["Fn::GetAtt"];if(Array.isArray(e)&&typeof e[0]=="string")return e[0]}function m(t,r){return s(t,"AWS::EC2::SecurityGroupIngress").filter(n=>{const i=p(n.properties.SourceSecurityGroupId),o=p(n.properties.GroupId);return i===r&&o===r})}function O(t,r){const e=u(t,r);if(!e)throw new Error(`No preset found for ${t}/${r}`);const n=e.port??S,i=e.proxy!==!1&&e.proxy!==void 0,o=i&&typeof e.proxy=="object"?e.proxy.requireTLS??!0:!0;return{port:n,deletionProtection:!0,hasProxy:i,proxyRequireTLS:o,hasReadReplica:r==="Instance"&&e.readReplica!==!1&&e.readReplica!==void 0,multiAz:e.multiAz!==!1,storageEncrypted:!0,databaseInsightsEnabled:e.databaseInsights!==!1,backupRetentionPeriod:e.backupRetention??14}}export{K as CLI_ROOT,h as addDatabase,P as createTestApp,T as expectSecurityGroupSelfReferencing,p as extractSecurityGroupRef,W as findAuroraCluster,w as findAuroraInstances,F as findKmsKeys,C as findPrimaryDbInstance,k as findRdsProxy,E as findReadReplicas,L as findSecurityGroupByDescription,b as findSecurityGroups,m as findSelfReferencingIngressRules,O as getExpectedConfigFromPreset};
@@ -0,0 +1,4 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { type DatabaseGeneratorOptions } from "@fjall/generator";
3
+ export declare function databaseGenerator(tree: Tree, options: DatabaseGeneratorOptions): Promise<void>;
4
+ export default databaseGenerator;
@@ -0,0 +1 @@
1
+ import{assertResourceNameUnique as u,databaseExists as m}from"../utils/resources/resourceDetection.js";import{pickDefined as s,withInfrastructurePlan as b}from"../utils/planning/generatorHelpers.js";import{DatabaseGeneratorSchema as p}from"@fjall/generator";import{handleResourceConnections as d}from"../utils/resources/connectionHelpers.js";function f(t,e){const r={name:t,type:e.databaseType,databaseName:e.databaseName,...s(e,"databaseInsights","port","proxy","credentials","encryption","deletionProtection")};switch(e.databaseType){case"Instance":return{...r,...s(e,"instanceType","multiAz","readReplica","publiclyAccessible","backupRetention","snapshotIdentifier","snapshotUsername")};case"Aurora":return{...r,...s(e,"writer","readers","backupRetention","preferredMaintenanceWindow","snapshotIdentifier","snapshotUsername")};case"GlobalAurora":return{...r,primaryRegion:e.primaryRegion,...e.secondaryRegions&&e.secondaryRegions.length>0&&{secondaryRegions:e.secondaryRegions},...s(e,"globalClusterIdentifier","enableGlobalWriteForwarding","writer","readers","backupRetention","preferredMaintenanceWindow","snapshotIdentifier","snapshotUsername")};default:return e}}async function l(t,e){await b(t,p,e,"database",async({tree:r,validated:a,plan:o})=>{const n=a.resourceName||`${a.appName}Database`;if(u(r,a.appName,n),m(r,a.appName,a.databaseName))throw new Error(`Database name '${a.databaseName}' already exists in ${a.appName}. Please choose a different database name.`);const i=f(n,a),c={...o,database:[...o.database,i]};return await d(c,a,n,"database",{singularPrompt:"Found an existing compute resource. Configure database access for it?",pluralPrompt:"Found {count} compute resources. Configure database access for them?"}),c})}var w=l;export{l as databaseGenerator,w as default};
@@ -0,0 +1 @@
1
+ export { databaseGenerator } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{databaseGenerator as r}from"./generator.js";export{r as databaseGenerator};
@@ -0,0 +1,4 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { type AddProxyGeneratorOptions } from "@fjall/generator";
3
+ export declare function proxyGenerator(tree: Tree, options: AddProxyGeneratorOptions): Promise<void>;
4
+ export default proxyGenerator;
@@ -0,0 +1 @@
1
+ import{AddProxyGeneratorSchema as i}from"@fjall/generator";import{withInfrastructurePlan as m,pickDefined as b}from"../../utils/planning/generatorHelpers.js";async function f(t,s){await m(t,i,s,"proxy",({validated:e,plan:r})=>{const a=r.database.find(o=>o.name===e.databaseName||o.databaseName===e.databaseName);if(!a)throw new Error(`Database '${e.databaseName}' not found. Available databases: ${r.database.map(o=>o.name).join(", ")||"none"}`);if(a.proxy!==void 0&&a.proxy!==!1)throw new Error(`Database '${a.name}' already has RDS Proxy enabled.`);const n=b(e,"maxConnections","maxIdleConnections","connectionBorrowTimeout","requireTLS");return a.proxy=Object.keys(n).length>0?n:{},r})}var x=f;export{x as default,f as proxyGenerator};
@@ -0,0 +1 @@
1
+ export { proxyGenerator, proxyGenerator as default } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{proxyGenerator as o,proxyGenerator as a}from"./generator.js";export{a as default,o as proxyGenerator};
@@ -0,0 +1,22 @@
1
+ import {
2
+ App,
3
+ Domain,
4
+ } from "@fjall/components-infrastructure";
5
+
6
+ // Fjall-managed domain — edit this file to add or change records.
7
+ // See docs/domains.md for the Domain construct API.
8
+
9
+ const app = App.getApp("<%= safeZoneName %>Domain");
10
+
11
+ new Domain(app, "<%= safeZoneName %>", {
12
+ registrar: "route53",
13
+ zoneName: "<%= domainName %>",
14
+ <% if (hostedZoneId) { -%>
15
+ hostedZoneId: "<%= hostedZoneId %>",
16
+ <% } -%>
17
+ certificates: [
18
+ { domainName: "<%= domainName %>" },
19
+ ],
20
+ records: [],
21
+ delegations: [],
22
+ });
@@ -0,0 +1,14 @@
1
+ ; zone.bind — managed by fjall
2
+ ; Edit this file and run 'fjall deploy domain' to apply changes
3
+ $ORIGIN <%= domainName %>.
4
+ $TTL 300
5
+
6
+ ; Certificate for this domain
7
+ $FJALL-CERT <%= domainName %>
8
+
9
+ ; Add your DNS records below
10
+ ; Examples:
11
+ ; @ IN A ALIAS fjall:cdn:my-app
12
+ ; www IN CNAME <%= domainName %>.
13
+ ; api IN A ALIAS fjall:ecs:my-api
14
+ ; @ IN MX 10 mail.<%= domainName %>.
@@ -0,0 +1,10 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { z } from "zod";
3
+ export declare const DomainGeneratorSchema: z.ZodObject<{
4
+ domainName: z.ZodString;
5
+ hostedZoneId: z.ZodOptional<z.ZodString>;
6
+ infrastructureTs: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strict>;
8
+ export type DomainGeneratorOptions = z.infer<typeof DomainGeneratorSchema>;
9
+ export declare function domainGenerator(tree: Tree, options: DomainGeneratorOptions): Promise<void>;
10
+ export default domainGenerator;
@@ -0,0 +1,2 @@
1
+ import{join as i}from"path";import{renderEjsTemplates as d}from"../utils/renderEjs.js";import{copySharedCdkFiles as p}from"../utils/copySharedFiles.js";import{getDomainComponentPath as c}from"../../src/util/pathHelpers.js";import{z as e}from"zod";import{VALIDATION_PATTERNS as f,VALIDATION_MESSAGES as l,getZodErrorMessage as u}from"@fjall/generator";import{toPascalCase as N}from"../../src/util/caseConversion.js";const g=import.meta.dirname,I=e.object({domainName:e.string().regex(f.DOMAIN,l.DOMAIN),hostedZoneId:e.string().optional(),infrastructureTs:e.string().optional()}).strict();async function h(t,s){const r=I.safeParse(s);if(!r.success)throw new Error(`Invalid domain generator options:
2
+ ${u(r.error)}`);const o=r.data,m=N(o.domainName.split(".").join("")),a=c(o.domainName),n={domainName:o.domainName,safeZoneName:m,hostedZoneId:o.hostedZoneId??""};d(t,i(g,"files"),a,n),o.infrastructureTs!==void 0&&t.write(i(a,"infrastructure.ts"),o.infrastructureTs),p(t,a,{...n,packageName:`domain-${o.domainName}`})}var Z=h;export{I as DomainGeneratorSchema,Z as default,h as domainGenerator};
@@ -0,0 +1 @@
1
+ export { domainGenerator, DomainGeneratorSchema, type DomainGeneratorOptions } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{domainGenerator as r,DomainGeneratorSchema as a}from"./generator.js";export{a as DomainGeneratorSchema,r as domainGenerator};
@@ -0,0 +1 @@
1
+ export {};
File without changes
@@ -0,0 +1,4 @@
1
+ import { type Tree } from "@nx/devkit";
2
+ import { type NetworkGeneratorOptions } from "@fjall/generator";
3
+ export declare function networkGenerator(tree: Tree, options: NetworkGeneratorOptions): Promise<void>;
4
+ export default networkGenerator;
@@ -0,0 +1 @@
1
+ import{pickDefined as a,withInfrastructurePlan as w}from"../utils/planning/generatorHelpers.js";import{NetworkGeneratorSchema as k}from"@fjall/generator";async function i(r,n){await w(r,k,n,"network",({validated:t,plan:o})=>{const e=a(t,"maxAzs","natGateways","flowLogs","vpcEndpoints");return t.networkName?{...o,additionalNetworks:[...o.additionalNetworks??[],{name:t.networkName,...e}]}:{...o,network:{...o.network??{},...e}}})}var c=i;export{c as default,i as networkGenerator};
@@ -0,0 +1 @@
1
+ export { networkGenerator } from "./generator.js";
@@ -0,0 +1 @@
1
+ import{networkGenerator as o}from"./generator.js";export{o as networkGenerator};
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { App, OrganisationFactory, getConfig } from "@fjall/components-infrastructure";
4
+
5
+ const config = getConfig();
6
+
7
+ if (config.environment !== "platform" && config.environment !== "root") {
8
+ const app = App.getInstance();
9
+ const account = OrganisationFactory.build("Account", { type: "account" })(app);
10
+ <% if (security === "foundation" || security === "compliance" || security === "hardened") { -%>
11
+
12
+ account.enableGuardDuty();
13
+ account.enableSecurityHub();
14
+ account.enableConfigRecorder();
15
+ account.enableAccessAnalyser();
16
+ <% } -%>
17
+ <% if (security === "compliance") { -%>
18
+ account.enableInspector();
19
+ account.enableConfigRules({ preset: "essential" });
20
+ <% } -%>
21
+ <% if (security === "hardened") { -%>
22
+ account.enableInspector();
23
+ account.enableConfigRules({ preset: "production" });
24
+ <% } -%>
25
+ }
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { OrganisationFactory, getConfig, env } from "@fjall/components-infrastructure";
4
+
5
+ export const ACCOUNTS = {
6
+ security: [],
7
+ workloads: {
8
+ production: ["Production"],
9
+ staging: ["Staging"],
10
+ development: ["Development"],
11
+ compliance: ["BusinessContinuity"]
12
+ },
13
+ platform: "Platform",
14
+ suspended: []
15
+ };
16
+
17
+ const config = getConfig();
18
+
19
+ const ALLOWED_REGIONS = env({
20
+ default: [] as string[]
21
+ });
22
+
23
+ if (config.environment === "root") {
24
+ const organisation = OrganisationFactory.build("Organisation", {
25
+ type: "organisation",
26
+ accounts: ACCOUNTS,
27
+ organisationName: "<%= name %>",
28
+ orgEmail: "<%= email %>"
29
+ });
30
+ <% if (security === "compliance") { -%>
31
+
32
+ organisation.enableScps({
33
+ preset: "standard",
34
+ rootId: organisation.node.tryGetContext("rootId"),
35
+ allowedRegions: ALLOWED_REGIONS
36
+ });
37
+ <% } -%>
38
+ <% if (security === "hardened") { -%>
39
+
40
+ organisation.enableScps({
41
+ preset: "hardened",
42
+ rootId: organisation.node.tryGetContext("rootId"),
43
+ allowedRegions: ALLOWED_REGIONS
44
+ });
45
+ <% } -%>
46
+ }