@fjall/deploy-core 0.89.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/src/aws/AwsProvider.d.ts +39 -0
- package/dist/src/aws/AwsProvider.js +1 -0
- package/dist/src/aws/SimpleAwsProvider.d.ts +22 -0
- package/dist/src/aws/SimpleAwsProvider.js +73 -0
- package/dist/src/aws/index.d.ts +4 -0
- package/dist/src/aws/index.js +3 -0
- package/dist/src/aws/organisations/accounts.d.ts +21 -0
- package/dist/src/aws/organisations/accounts.js +99 -0
- package/dist/src/aws/organisations/backup.d.ts +12 -0
- package/dist/src/aws/organisations/backup.js +28 -0
- package/dist/src/aws/organisations/costAllocation.d.ts +12 -0
- package/dist/src/aws/organisations/costAllocation.js +26 -0
- package/dist/src/aws/organisations/identityCentre.d.ts +8 -0
- package/dist/src/aws/organisations/identityCentre.js +19 -0
- package/dist/src/aws/organisations/index.d.ts +16 -0
- package/dist/src/aws/organisations/index.js +12 -0
- package/dist/src/aws/organisations/ipam.d.ts +7 -0
- package/dist/src/aws/organisations/ipam.js +18 -0
- package/dist/src/aws/organisations/organisation.d.ts +12 -0
- package/dist/src/aws/organisations/organisation.js +94 -0
- package/dist/src/aws/organisations/organisationalUnits.d.ts +19 -0
- package/dist/src/aws/organisations/organisationalUnits.js +125 -0
- package/dist/src/aws/organisations/policies.d.ts +7 -0
- package/dist/src/aws/organisations/policies.js +36 -0
- package/dist/src/aws/organisations/ram.d.ts +7 -0
- package/dist/src/aws/organisations/ram.js +15 -0
- package/dist/src/aws/organisations/serviceAccess.d.ts +7 -0
- package/dist/src/aws/organisations/serviceAccess.js +38 -0
- package/dist/src/aws/organisations/trustedAccess.d.ts +7 -0
- package/dist/src/aws/organisations/trustedAccess.js +15 -0
- package/dist/src/aws/organisations/types.d.ts +29 -0
- package/dist/src/aws/organisations/types.js +16 -0
- package/dist/src/aws/utils/CloudFormationFailureAnalyser.d.ts +32 -0
- package/dist/src/aws/utils/CloudFormationFailureAnalyser.js +228 -0
- package/dist/src/aws/utils/cloudformationEvents.d.ts +98 -0
- package/dist/src/aws/utils/cloudformationEvents.js +596 -0
- package/dist/src/aws/utils/errors.d.ts +26 -0
- package/dist/src/aws/utils/errors.js +59 -0
- package/dist/src/aws/utils/regions.d.ts +1 -0
- package/dist/src/aws/utils/regions.js +1 -0
- package/dist/src/aws/utils/stackStatus.d.ts +23 -0
- package/dist/src/aws/utils/stackStatus.js +90 -0
- package/dist/src/index.d.ts +35 -0
- package/dist/src/index.js +45 -0
- package/dist/src/orchestration/applicationDeploy.d.ts +11 -0
- package/dist/src/orchestration/applicationDeploy.js +327 -0
- package/dist/src/orchestration/contextHelpers.d.ts +9 -0
- package/dist/src/orchestration/contextHelpers.js +14 -0
- package/dist/src/orchestration/deploy.d.ts +10 -0
- package/dist/src/orchestration/deploy.js +42 -0
- package/dist/src/orchestration/detectionPipeline.d.ts +23 -0
- package/dist/src/orchestration/detectionPipeline.js +65 -0
- package/dist/src/orchestration/dockerInterface.d.ts +56 -0
- package/dist/src/orchestration/dockerInterface.js +1 -0
- package/dist/src/orchestration/domainInterface.d.ts +37 -0
- package/dist/src/orchestration/domainInterface.js +1 -0
- package/dist/src/orchestration/index.d.ts +8 -0
- package/dist/src/orchestration/index.js +3 -0
- package/dist/src/orchestration/organisationDeploy.d.ts +16 -0
- package/dist/src/orchestration/organisationDeploy.js +382 -0
- package/dist/src/orchestration/organisationSetup.d.ts +42 -0
- package/dist/src/orchestration/organisationSetup.js +227 -0
- package/dist/src/orchestration/resolveOperation.d.ts +10 -0
- package/dist/src/orchestration/resolveOperation.js +53 -0
- package/dist/src/orchestration/serviceFactory.d.ts +15 -0
- package/dist/src/orchestration/serviceFactory.js +16 -0
- package/dist/src/services/application/ApplicationStackService.d.ts +93 -0
- package/dist/src/services/application/ApplicationStackService.js +436 -0
- package/dist/src/services/application/index.d.ts +1 -0
- package/dist/src/services/application/index.js +1 -0
- package/dist/src/services/infrastructure/CdkArgumentBuilder.d.ts +12 -0
- package/dist/src/services/infrastructure/CdkArgumentBuilder.js +67 -0
- package/dist/src/services/infrastructure/CdkCommandRunner.d.ts +30 -0
- package/dist/src/services/infrastructure/CdkCommandRunner.js +241 -0
- package/dist/src/services/infrastructure/CdkErrorFormatter.d.ts +4 -0
- package/dist/src/services/infrastructure/CdkErrorFormatter.js +194 -0
- package/dist/src/services/infrastructure/CdkEventMonitoring.d.ts +19 -0
- package/dist/src/services/infrastructure/CdkEventMonitoring.js +41 -0
- package/dist/src/services/infrastructure/CdkOutputAnalyser.d.ts +43 -0
- package/dist/src/services/infrastructure/CdkOutputAnalyser.js +125 -0
- package/dist/src/services/infrastructure/CdkOutputParser.d.ts +8 -0
- package/dist/src/services/infrastructure/CdkOutputParser.js +33 -0
- package/dist/src/services/infrastructure/CdkProcessManager.d.ts +20 -0
- package/dist/src/services/infrastructure/CdkProcessManager.js +244 -0
- package/dist/src/services/infrastructure/CdkService.d.ts +71 -0
- package/dist/src/services/infrastructure/CdkService.js +254 -0
- package/dist/src/services/infrastructure/CloudFormationService.d.ts +79 -0
- package/dist/src/services/infrastructure/CloudFormationService.js +249 -0
- package/dist/src/services/infrastructure/index.d.ts +8 -0
- package/dist/src/services/infrastructure/index.js +7 -0
- package/dist/src/services/supporting/CdkContextBuilder.d.ts +49 -0
- package/dist/src/services/supporting/CdkContextBuilder.js +44 -0
- package/dist/src/services/supporting/TemplateHashService.d.ts +67 -0
- package/dist/src/services/supporting/TemplateHashService.js +152 -0
- package/dist/src/services/supporting/helpers.d.ts +46 -0
- package/dist/src/services/supporting/helpers.js +81 -0
- package/dist/src/services/supporting/index.d.ts +3 -0
- package/dist/src/services/supporting/index.js +3 -0
- package/dist/src/types/FjallState.d.ts +50 -0
- package/dist/src/types/FjallState.js +118 -0
- package/dist/src/types/ProgressEvent.d.ts +35 -0
- package/dist/src/types/ProgressEvent.js +48 -0
- package/dist/src/types/apiClient.d.ts +34 -0
- package/dist/src/types/apiClient.js +1 -0
- package/dist/src/types/application/ApplicationServiceTypes.d.ts +56 -0
- package/dist/src/types/application/ApplicationServiceTypes.js +30 -0
- package/dist/src/types/application/index.d.ts +1 -0
- package/dist/src/types/application/index.js +1 -0
- package/dist/src/types/callbacks.d.ts +36 -0
- package/dist/src/types/callbacks.js +1 -0
- package/dist/src/types/constants.d.ts +6 -0
- package/dist/src/types/constants.js +6 -0
- package/dist/src/types/credentials.d.ts +30 -0
- package/dist/src/types/credentials.js +1 -0
- package/dist/src/types/deployment/DeploymentServiceTypes.d.ts +23 -0
- package/dist/src/types/deployment/DeploymentServiceTypes.js +1 -0
- package/dist/src/types/deployment/DeploymentTypes.d.ts +29 -0
- package/dist/src/types/deployment/DeploymentTypes.js +1 -0
- package/dist/src/types/deployment/cloudformation.d.ts +14 -0
- package/dist/src/types/deployment/cloudformation.js +1 -0
- package/dist/src/types/deployment/index.d.ts +5 -0
- package/dist/src/types/deployment/index.js +1 -0
- package/dist/src/types/deployment/parallel.d.ts +46 -0
- package/dist/src/types/deployment/parallel.js +10 -0
- package/dist/src/types/errors/CdkError.d.ts +14 -0
- package/dist/src/types/errors/CdkError.js +20 -0
- package/dist/src/types/errors/ServiceError.d.ts +86 -0
- package/dist/src/types/errors/ServiceError.js +119 -0
- package/dist/src/types/events.d.ts +40 -0
- package/dist/src/types/events.js +5 -0
- package/dist/src/types/index.d.ts +20 -0
- package/dist/src/types/index.js +9 -0
- package/dist/src/types/operations.d.ts +193 -0
- package/dist/src/types/operations.js +285 -0
- package/dist/src/types/orgConfig.d.ts +28 -0
- package/dist/src/types/orgConfig.js +11 -0
- package/dist/src/types/params.d.ts +74 -0
- package/dist/src/types/params.js +1 -0
- package/dist/src/types/patternDetection.d.ts +43 -0
- package/dist/src/types/patternDetection.js +92 -0
- package/dist/src/types/validation.d.ts +12 -0
- package/dist/src/types/validation.js +1 -0
- package/dist/src/util/fsHelpers.d.ts +4 -0
- package/dist/src/util/fsHelpers.js +16 -0
- package/dist/src/util/index.d.ts +3 -0
- package/dist/src/util/index.js +3 -0
- package/dist/src/util/securityHelpers.d.ts +31 -0
- package/dist/src/util/securityHelpers.js +124 -0
- package/dist/src/util/singleton.d.ts +2 -0
- package/dist/src/util/singleton.js +9 -0
- package/dist/src/util/sleep.d.ts +4 -0
- package/dist/src/util/sleep.js +4 -0
- package/package.json +42 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { isOpenNextPattern } from "./patternDetection.js";
|
|
2
|
+
import { toPascalCase } from "@fjall/util";
|
|
3
|
+
/**
|
|
4
|
+
* Application infrastructure stacks
|
|
5
|
+
*/
|
|
6
|
+
export const APPLICATION_STACKS = {
|
|
7
|
+
NETWORK: "Network",
|
|
8
|
+
DATABASE: "Database",
|
|
9
|
+
STORAGE: "Storage",
|
|
10
|
+
COMPUTE: "Compute",
|
|
11
|
+
CDN: "Cdn",
|
|
12
|
+
MESSAGING: "Messaging"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Organisation infrastructure types
|
|
16
|
+
* Note: These are deployment types, not stacks - each maps to a single CDK stack
|
|
17
|
+
*/
|
|
18
|
+
export const ORGANISATION_TYPES = {
|
|
19
|
+
ORGANISATION: "organisation",
|
|
20
|
+
PLATFORM: "platform",
|
|
21
|
+
ACCOUNT: "account"
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Type guards for safe type narrowing
|
|
25
|
+
*/
|
|
26
|
+
export function isApplicationOperation(op) {
|
|
27
|
+
return op.kind === "application";
|
|
28
|
+
}
|
|
29
|
+
export function isOrganisationOperation(op) {
|
|
30
|
+
return op.kind === "organisation";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Stack ordering for application deployments
|
|
34
|
+
*/
|
|
35
|
+
export const APPLICATION_DEPLOY_ORDER = [
|
|
36
|
+
APPLICATION_STACKS.NETWORK,
|
|
37
|
+
APPLICATION_STACKS.DATABASE,
|
|
38
|
+
APPLICATION_STACKS.COMPUTE
|
|
39
|
+
];
|
|
40
|
+
export const APPLICATION_DESTROY_ORDER = [
|
|
41
|
+
APPLICATION_STACKS.COMPUTE,
|
|
42
|
+
APPLICATION_STACKS.DATABASE,
|
|
43
|
+
APPLICATION_STACKS.NETWORK
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Stack ordering for OpenNext (Next.js/Payload) deployments
|
|
47
|
+
* These patterns require additional infrastructure: S3, DynamoDB, SQS, CloudFront
|
|
48
|
+
*/
|
|
49
|
+
export const OPENNEXT_DEPLOY_ORDER = [
|
|
50
|
+
APPLICATION_STACKS.NETWORK,
|
|
51
|
+
APPLICATION_STACKS.STORAGE,
|
|
52
|
+
APPLICATION_STACKS.MESSAGING,
|
|
53
|
+
APPLICATION_STACKS.DATABASE,
|
|
54
|
+
APPLICATION_STACKS.COMPUTE,
|
|
55
|
+
APPLICATION_STACKS.CDN
|
|
56
|
+
];
|
|
57
|
+
/**
|
|
58
|
+
* Stack ordering for OpenNext destroy operations (reverse of deploy order)
|
|
59
|
+
* CDN must be destroyed first as it depends on Compute, then work backwards
|
|
60
|
+
*/
|
|
61
|
+
export const OPENNEXT_DESTROY_ORDER = [
|
|
62
|
+
APPLICATION_STACKS.CDN,
|
|
63
|
+
APPLICATION_STACKS.COMPUTE,
|
|
64
|
+
APPLICATION_STACKS.DATABASE,
|
|
65
|
+
APPLICATION_STACKS.MESSAGING,
|
|
66
|
+
APPLICATION_STACKS.STORAGE,
|
|
67
|
+
APPLICATION_STACKS.NETWORK
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* Parallel deployment groups for concurrent stack deployment
|
|
71
|
+
* Stacks within each phase can be deployed in parallel.
|
|
72
|
+
*
|
|
73
|
+
* Dependency structure:
|
|
74
|
+
* - Phase 1: Network (required by all other stacks)
|
|
75
|
+
* - Phase 2: Storage, Messaging, Database (independent of each other, only need Network)
|
|
76
|
+
* - Phase 3: Compute (needs Database outputs)
|
|
77
|
+
* - Phase 4: CDN (needs Compute outputs)
|
|
78
|
+
*/
|
|
79
|
+
export const PARALLEL_DEPLOY_GROUPS = {
|
|
80
|
+
PHASE_1: {
|
|
81
|
+
phase: 1,
|
|
82
|
+
stacks: [APPLICATION_STACKS.NETWORK],
|
|
83
|
+
description: "Network infrastructure"
|
|
84
|
+
},
|
|
85
|
+
PHASE_2: {
|
|
86
|
+
phase: 2,
|
|
87
|
+
stacks: [
|
|
88
|
+
APPLICATION_STACKS.STORAGE,
|
|
89
|
+
APPLICATION_STACKS.MESSAGING,
|
|
90
|
+
APPLICATION_STACKS.DATABASE
|
|
91
|
+
],
|
|
92
|
+
description: "Storage and database resources (parallel)"
|
|
93
|
+
},
|
|
94
|
+
PHASE_3: {
|
|
95
|
+
phase: 3,
|
|
96
|
+
stacks: [APPLICATION_STACKS.COMPUTE],
|
|
97
|
+
description: "Compute resources"
|
|
98
|
+
},
|
|
99
|
+
PHASE_4: {
|
|
100
|
+
phase: 4,
|
|
101
|
+
stacks: [APPLICATION_STACKS.CDN],
|
|
102
|
+
description: "CDN distribution"
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Parallel deployment groups for OpenNext (Next.js/Payload) deployments
|
|
107
|
+
* Optimised to run BUILD in parallel with infrastructure stacks.
|
|
108
|
+
*/
|
|
109
|
+
export const OPENNEXT_PARALLEL_GROUPS = {
|
|
110
|
+
/** Regular Next.js: BUILD + all Phase 2 stacks in parallel */
|
|
111
|
+
NEXTJS_PARALLEL: {
|
|
112
|
+
stacks: [
|
|
113
|
+
APPLICATION_STACKS.STORAGE,
|
|
114
|
+
APPLICATION_STACKS.MESSAGING,
|
|
115
|
+
APPLICATION_STACKS.DATABASE
|
|
116
|
+
],
|
|
117
|
+
includeBuild: true,
|
|
118
|
+
description: "Build + Storage/Messaging/Database (parallel)"
|
|
119
|
+
},
|
|
120
|
+
/** Payload: BUILD + remaining stacks (after Database + migrations) */
|
|
121
|
+
PAYLOAD_PARALLEL: {
|
|
122
|
+
stacks: [APPLICATION_STACKS.STORAGE, APPLICATION_STACKS.MESSAGING],
|
|
123
|
+
includeBuild: true,
|
|
124
|
+
description: "Build + Storage/Messaging (parallel)"
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Get all parallel deploy groups as an ordered array
|
|
129
|
+
*/
|
|
130
|
+
export function getParallelDeployGroups() {
|
|
131
|
+
return [
|
|
132
|
+
PARALLEL_DEPLOY_GROUPS.PHASE_1,
|
|
133
|
+
PARALLEL_DEPLOY_GROUPS.PHASE_2,
|
|
134
|
+
PARALLEL_DEPLOY_GROUPS.PHASE_3,
|
|
135
|
+
PARALLEL_DEPLOY_GROUPS.PHASE_4
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Parallel destroy groups for OpenNext destroy operations.
|
|
140
|
+
* Reverse of deploy order to respect dependencies.
|
|
141
|
+
*/
|
|
142
|
+
export const PARALLEL_DESTROY_GROUPS = {
|
|
143
|
+
PHASE_1: {
|
|
144
|
+
phase: 1,
|
|
145
|
+
stacks: [APPLICATION_STACKS.CDN],
|
|
146
|
+
description: "CDN distribution"
|
|
147
|
+
},
|
|
148
|
+
PHASE_2: {
|
|
149
|
+
phase: 2,
|
|
150
|
+
stacks: [APPLICATION_STACKS.COMPUTE],
|
|
151
|
+
description: "Compute resources"
|
|
152
|
+
},
|
|
153
|
+
PHASE_3: {
|
|
154
|
+
phase: 3,
|
|
155
|
+
stacks: [
|
|
156
|
+
APPLICATION_STACKS.DATABASE,
|
|
157
|
+
APPLICATION_STACKS.MESSAGING,
|
|
158
|
+
APPLICATION_STACKS.STORAGE
|
|
159
|
+
],
|
|
160
|
+
description: "Database, messaging, and storage (parallel)"
|
|
161
|
+
},
|
|
162
|
+
PHASE_4: {
|
|
163
|
+
phase: 4,
|
|
164
|
+
stacks: [APPLICATION_STACKS.NETWORK],
|
|
165
|
+
description: "Network infrastructure"
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Get all parallel destroy groups as an ordered array
|
|
170
|
+
*/
|
|
171
|
+
export function getParallelDestroyGroups() {
|
|
172
|
+
return [
|
|
173
|
+
PARALLEL_DESTROY_GROUPS.PHASE_1,
|
|
174
|
+
PARALLEL_DESTROY_GROUPS.PHASE_2,
|
|
175
|
+
PARALLEL_DESTROY_GROUPS.PHASE_3,
|
|
176
|
+
PARALLEL_DESTROY_GROUPS.PHASE_4
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Deploy tier priority — lower number deploys first, higher destroys first.
|
|
181
|
+
* Used for dynamic ordering based on manifest-detected resources.
|
|
182
|
+
*/
|
|
183
|
+
const STACK_DEPLOY_TIER = {
|
|
184
|
+
Network: 1,
|
|
185
|
+
Storage: 2,
|
|
186
|
+
Messaging: 2,
|
|
187
|
+
Database: 2,
|
|
188
|
+
Compute: 3,
|
|
189
|
+
Cdn: 4
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Get deployment order based on application configuration.
|
|
193
|
+
*
|
|
194
|
+
* Strategies:
|
|
195
|
+
* 1. OpenNext (pattern = "payload" or "nextjs"): Predefined order (build orchestration)
|
|
196
|
+
* 2. Dynamic: Include only detected stacks, ordered by tier
|
|
197
|
+
* 3. Fallback: Standard order (no manifest available)
|
|
198
|
+
*/
|
|
199
|
+
export function getApplicationDeployOrder(options) {
|
|
200
|
+
const { pattern, resources } = options ?? {};
|
|
201
|
+
if (isOpenNextPattern(pattern)) {
|
|
202
|
+
return OPENNEXT_DEPLOY_ORDER;
|
|
203
|
+
}
|
|
204
|
+
if (resources) {
|
|
205
|
+
return buildOrderFromResources(resources, "asc");
|
|
206
|
+
}
|
|
207
|
+
return APPLICATION_DEPLOY_ORDER;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get destroy order based on application configuration.
|
|
211
|
+
* Destroy order respects dependencies (reverse of deploy order).
|
|
212
|
+
*/
|
|
213
|
+
export function getApplicationDestroyOrder(options) {
|
|
214
|
+
const { pattern, resources } = options ?? {};
|
|
215
|
+
if (isOpenNextPattern(pattern)) {
|
|
216
|
+
return OPENNEXT_DESTROY_ORDER;
|
|
217
|
+
}
|
|
218
|
+
if (resources) {
|
|
219
|
+
return buildOrderFromResources(resources, "desc");
|
|
220
|
+
}
|
|
221
|
+
return APPLICATION_DESTROY_ORDER;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Build a stack order from resource flags, sorted by tier priority.
|
|
225
|
+
*/
|
|
226
|
+
function buildOrderFromResources(resources, direction) {
|
|
227
|
+
const stacks = [];
|
|
228
|
+
if (resources.hasNetwork)
|
|
229
|
+
stacks.push(APPLICATION_STACKS.NETWORK);
|
|
230
|
+
if (resources.hasStorage)
|
|
231
|
+
stacks.push(APPLICATION_STACKS.STORAGE);
|
|
232
|
+
if (resources.hasMessaging)
|
|
233
|
+
stacks.push(APPLICATION_STACKS.MESSAGING);
|
|
234
|
+
if (resources.hasDatabase)
|
|
235
|
+
stacks.push(APPLICATION_STACKS.DATABASE);
|
|
236
|
+
if (resources.hasCompute)
|
|
237
|
+
stacks.push(APPLICATION_STACKS.COMPUTE);
|
|
238
|
+
if (resources.hasCdn)
|
|
239
|
+
stacks.push(APPLICATION_STACKS.CDN);
|
|
240
|
+
return stacks.sort((a, b) => {
|
|
241
|
+
const diff = STACK_DEPLOY_TIER[a] - STACK_DEPLOY_TIER[b];
|
|
242
|
+
return direction === "asc" ? diff : -diff;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Helper functions for stack operations
|
|
247
|
+
*/
|
|
248
|
+
export { toPascalCase };
|
|
249
|
+
export function getApplicationStackName(appName, stack) {
|
|
250
|
+
return `${toPascalCase(appName)}${stack}`;
|
|
251
|
+
}
|
|
252
|
+
export function getOrganisationStackName(type) {
|
|
253
|
+
switch (type) {
|
|
254
|
+
case "organisation":
|
|
255
|
+
return "Organisation";
|
|
256
|
+
case "platform":
|
|
257
|
+
return "Platform";
|
|
258
|
+
case "account":
|
|
259
|
+
return "Account";
|
|
260
|
+
default: {
|
|
261
|
+
const _exhaustive = type;
|
|
262
|
+
throw new Error(`Unsupported organisation type: ${String(_exhaustive)}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Type guard for ApplicationStack
|
|
268
|
+
*/
|
|
269
|
+
export function isApplicationStack(value) {
|
|
270
|
+
return Object.values(APPLICATION_STACKS).includes(value);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Step name generators for UI display
|
|
274
|
+
*/
|
|
275
|
+
export function getApplicationStepName(stack, action) {
|
|
276
|
+
const verb = action === "deploy" ? "Deploying" : "Destroying";
|
|
277
|
+
return `${verb} ${stack.toLowerCase()} infrastructure`;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Step ID generators for tracking
|
|
281
|
+
*/
|
|
282
|
+
export function getApplicationStepId(stack, action) {
|
|
283
|
+
const suffix = action === "destroy" ? "-destroy" : "";
|
|
284
|
+
return `${stack.toLowerCase()}${suffix}`;
|
|
285
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organisation-level configuration.
|
|
3
|
+
*
|
|
4
|
+
* This config is injected by the caller, not read from disk:
|
|
5
|
+
* - CLI: fetches from GET /api/organisation-config (cached locally with TTL)
|
|
6
|
+
* - Worker: reads from DB (Organization + ConnectedAwsAccount models)
|
|
7
|
+
*
|
|
8
|
+
* Passed to CDK via -c orgConfig=<json> context at synthesis time.
|
|
9
|
+
* See: investigations/2026-03-16-config-split-investigation.md
|
|
10
|
+
*/
|
|
11
|
+
export interface OrgConfig {
|
|
12
|
+
providerAccounts: ProviderAccount[];
|
|
13
|
+
primaryRegion?: string;
|
|
14
|
+
secondaryRegions?: string[];
|
|
15
|
+
disasterRecoveryRegion?: string;
|
|
16
|
+
rootOidcRoleArn?: string;
|
|
17
|
+
ssoSessions?: Record<string, SSOSession>;
|
|
18
|
+
}
|
|
19
|
+
export interface ProviderAccount {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
environment: string;
|
|
23
|
+
managed?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface SSOSession {
|
|
26
|
+
ssoRegion: string;
|
|
27
|
+
ssoStartUrl: string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organisation-level configuration.
|
|
3
|
+
*
|
|
4
|
+
* This config is injected by the caller, not read from disk:
|
|
5
|
+
* - CLI: fetches from GET /api/organisation-config (cached locally with TTL)
|
|
6
|
+
* - Worker: reads from DB (Organization + ConnectedAwsAccount models)
|
|
7
|
+
*
|
|
8
|
+
* Passed to CDK via -c orgConfig=<json> context at synthesis time.
|
|
9
|
+
* See: investigations/2026-03-16-config-split-investigation.md
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Result } from "@fjall/generator";
|
|
2
|
+
import type { AwsCredentials, DeployIdentity } from "./credentials.js";
|
|
3
|
+
import type { DeployCallbacks } from "./callbacks.js";
|
|
4
|
+
import type { ApiClientInterface } from "./apiClient.js";
|
|
5
|
+
import type { OrgConfig } from "./orgConfig.js";
|
|
6
|
+
import type { DockerProvider } from "../orchestration/dockerInterface.js";
|
|
7
|
+
import type { DomainDeployProvider } from "../orchestration/domainInterface.js";
|
|
8
|
+
export interface DeployParams {
|
|
9
|
+
/** Deployment target name (e.g., "my-app", "organisation", "platform", "account-prod") */
|
|
10
|
+
target: string;
|
|
11
|
+
/** Absolute path to the repository root containing fjall-config.json */
|
|
12
|
+
workingDirectory: string;
|
|
13
|
+
/** AWS credentials for the deployment. deploy-core never resolves these itself. */
|
|
14
|
+
awsCredentials: AwsCredentials;
|
|
15
|
+
/** Typed callbacks for progress events. CLI and worker implement differently. */
|
|
16
|
+
callbacks: DeployCallbacks;
|
|
17
|
+
/** Deployment options */
|
|
18
|
+
options?: DeployOptions;
|
|
19
|
+
/**
|
|
20
|
+
* Org-level config (accounts, regions, OIDC).
|
|
21
|
+
* CLI: fetches from GET /api/organisation-config (cached locally with TTL).
|
|
22
|
+
* Worker: reads from DB (Organization + ConnectedAwsAccount models).
|
|
23
|
+
* Passed to CDK via -c orgConfig=<json> context.
|
|
24
|
+
* See: investigations/2026-03-16-config-split-investigation.md
|
|
25
|
+
*/
|
|
26
|
+
orgConfig?: OrgConfig;
|
|
27
|
+
/**
|
|
28
|
+
* Pre-fetched identity for org deployments.
|
|
29
|
+
* CLI: omit this, provide apiClient instead (fetches from API).
|
|
30
|
+
* Worker: provide this from DB, omit apiClient.
|
|
31
|
+
*/
|
|
32
|
+
identity?: DeployIdentity;
|
|
33
|
+
/**
|
|
34
|
+
* Optional API client for non-critical operations (app registration,
|
|
35
|
+
* account verification, config push). Worker omits this — those
|
|
36
|
+
* operations are handled by the webapp directly.
|
|
37
|
+
*/
|
|
38
|
+
apiClient?: ApiClientInterface;
|
|
39
|
+
/**
|
|
40
|
+
* Optional Docker provider for building and pushing container images.
|
|
41
|
+
* CLI and worker provide their own implementations.
|
|
42
|
+
* If omitted, Docker operations are skipped.
|
|
43
|
+
*/
|
|
44
|
+
dockerProvider?: DockerProvider;
|
|
45
|
+
/**
|
|
46
|
+
* Optional domain deployment provider for organisation cascade.
|
|
47
|
+
* CLI provides an implementation backed by DomainService + zone files.
|
|
48
|
+
* Worker omits this (domains managed via CLI only for now).
|
|
49
|
+
* If omitted, the domains cascade phase is skipped.
|
|
50
|
+
*/
|
|
51
|
+
domainProvider?: DomainDeployProvider;
|
|
52
|
+
}
|
|
53
|
+
export interface DeployOptions {
|
|
54
|
+
skipConfirmation?: boolean;
|
|
55
|
+
force?: boolean;
|
|
56
|
+
cascade?: boolean;
|
|
57
|
+
skipBuild?: boolean;
|
|
58
|
+
verbose?: boolean;
|
|
59
|
+
infraOnly?: boolean;
|
|
60
|
+
deployOnly?: boolean;
|
|
61
|
+
passThroughCDK?: boolean;
|
|
62
|
+
environment?: string;
|
|
63
|
+
}
|
|
64
|
+
export type DeploymentType = "application" | "organisation";
|
|
65
|
+
export interface DeployResult {
|
|
66
|
+
target: string;
|
|
67
|
+
deploymentType: DeploymentType;
|
|
68
|
+
/** Stack outputs (website URL, OIDC role ARN, etc.) */
|
|
69
|
+
outputs?: Record<string, string>;
|
|
70
|
+
/** Duration in milliseconds */
|
|
71
|
+
durationMs?: number;
|
|
72
|
+
}
|
|
73
|
+
/** Re-export Result from generator for consumers. */
|
|
74
|
+
export type { Result };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern detection types and functions.
|
|
3
|
+
*
|
|
4
|
+
* Contains both pure predicates used by operations.ts and
|
|
5
|
+
* filesystem-based detection functions used by orchestration services.
|
|
6
|
+
*/
|
|
7
|
+
import type { PatternType } from "@fjall/generator";
|
|
8
|
+
declare const OPENNEXT_PATTERNS_ARRAY: readonly ["payload", "nextjs"];
|
|
9
|
+
export type OpenNextPattern = (typeof OPENNEXT_PATTERNS_ARRAY)[number];
|
|
10
|
+
export declare const OPENNEXT_PATTERNS: Set<string>;
|
|
11
|
+
export declare function isOpenNextPattern(pattern: string | undefined | null): pattern is OpenNextPattern;
|
|
12
|
+
export interface AppResourceFlags {
|
|
13
|
+
hasNetwork: boolean;
|
|
14
|
+
hasCompute: boolean;
|
|
15
|
+
hasDatabase: boolean;
|
|
16
|
+
hasStorage: boolean;
|
|
17
|
+
hasMessaging: boolean;
|
|
18
|
+
hasCdn: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** Derive resource flags from manifest stack names (authoritative, post-synth) */
|
|
21
|
+
export declare function deriveResourcesFromManifestStacks(stackNames: string[]): AppResourceFlags;
|
|
22
|
+
/**
|
|
23
|
+
* Detect the application pattern (Payload, Next.js, or none) from infrastructure.ts.
|
|
24
|
+
*
|
|
25
|
+
* Pattern detection is based on the IaC file (infrastructure.ts), NOT on
|
|
26
|
+
* project files like package.json. This ensures accurate detection even
|
|
27
|
+
* when multiple apps coexist in the same project directory.
|
|
28
|
+
*
|
|
29
|
+
* @param appPath - The fjall app path (e.g., "fjall/app8" or absolute path)
|
|
30
|
+
*/
|
|
31
|
+
export declare function detectPattern(appPath: string): {
|
|
32
|
+
pattern: PatternType | null;
|
|
33
|
+
hasDatabase: boolean;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Detect if infrastructure.ts contains a Payload CMS pattern.
|
|
37
|
+
*/
|
|
38
|
+
export declare function detectPayloadPattern(appPath: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Detect if infrastructure.ts contains a database resource.
|
|
41
|
+
*/
|
|
42
|
+
export declare function detectDatabase(appPath: string): boolean;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern detection types and functions.
|
|
3
|
+
*
|
|
4
|
+
* Contains both pure predicates used by operations.ts and
|
|
5
|
+
* filesystem-based detection functions used by orchestration services.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { logger, getErrorMessage } from "@fjall/util";
|
|
10
|
+
import { APPLICATION_STACKS } from "./operations.js";
|
|
11
|
+
import { INFRASTRUCTURE_FILENAME } from "./constants.js";
|
|
12
|
+
const OPENNEXT_PATTERNS_ARRAY = ["payload", "nextjs"];
|
|
13
|
+
export const OPENNEXT_PATTERNS = new Set(OPENNEXT_PATTERNS_ARRAY);
|
|
14
|
+
export function isOpenNextPattern(pattern) {
|
|
15
|
+
return (pattern !== undefined && pattern !== null && OPENNEXT_PATTERNS.has(pattern));
|
|
16
|
+
}
|
|
17
|
+
/** Derive resource flags from manifest stack names (authoritative, post-synth) */
|
|
18
|
+
export function deriveResourcesFromManifestStacks(stackNames) {
|
|
19
|
+
const has = (suffix) => stackNames.some((s) => s.endsWith(suffix));
|
|
20
|
+
return {
|
|
21
|
+
hasNetwork: has(APPLICATION_STACKS.NETWORK),
|
|
22
|
+
hasCompute: has(APPLICATION_STACKS.COMPUTE),
|
|
23
|
+
hasDatabase: has(APPLICATION_STACKS.DATABASE),
|
|
24
|
+
hasStorage: has(APPLICATION_STACKS.STORAGE),
|
|
25
|
+
hasMessaging: has(APPLICATION_STACKS.MESSAGING),
|
|
26
|
+
hasCdn: has(APPLICATION_STACKS.CDN)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Read infrastructure.ts content from an app path.
|
|
31
|
+
* Returns null if file doesn't exist or can't be read.
|
|
32
|
+
*/
|
|
33
|
+
function readInfrastructureContent(appPath) {
|
|
34
|
+
try {
|
|
35
|
+
const filePath = join(appPath, INFRASTRUCTURE_FILENAME);
|
|
36
|
+
if (!existsSync(filePath))
|
|
37
|
+
return null;
|
|
38
|
+
return readFileSync(filePath, "utf-8");
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.debug("patternDetection", "Failed to read infrastructure file", {
|
|
42
|
+
appPath,
|
|
43
|
+
error: getErrorMessage(error)
|
|
44
|
+
});
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Detect the application pattern (Payload, Next.js, or none) from infrastructure.ts.
|
|
50
|
+
*
|
|
51
|
+
* Pattern detection is based on the IaC file (infrastructure.ts), NOT on
|
|
52
|
+
* project files like package.json. This ensures accurate detection even
|
|
53
|
+
* when multiple apps coexist in the same project directory.
|
|
54
|
+
*
|
|
55
|
+
* @param appPath - The fjall app path (e.g., "fjall/app8" or absolute path)
|
|
56
|
+
*/
|
|
57
|
+
export function detectPattern(appPath) {
|
|
58
|
+
const content = readInfrastructureContent(appPath);
|
|
59
|
+
if (!content) {
|
|
60
|
+
return { pattern: null, hasDatabase: false };
|
|
61
|
+
}
|
|
62
|
+
if (content.includes("PatternFactory")) {
|
|
63
|
+
if (content.includes('type: "payload"')) {
|
|
64
|
+
return { pattern: "payload", hasDatabase: true };
|
|
65
|
+
}
|
|
66
|
+
if (content.includes('type: "nextjs"')) {
|
|
67
|
+
const hasDatabase = content.includes("DatabaseFactory.build(") ||
|
|
68
|
+
content.includes("database:");
|
|
69
|
+
return { pattern: "nextjs", hasDatabase };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const hasDatabase = content.includes("DatabaseFactory.build(");
|
|
73
|
+
return { pattern: null, hasDatabase };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Detect if infrastructure.ts contains a Payload CMS pattern.
|
|
77
|
+
*/
|
|
78
|
+
export function detectPayloadPattern(appPath) {
|
|
79
|
+
const content = readInfrastructureContent(appPath);
|
|
80
|
+
if (!content)
|
|
81
|
+
return false;
|
|
82
|
+
return (content.includes("PatternFactory") && content.includes('type: "payload"'));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Detect if infrastructure.ts contains a database resource.
|
|
86
|
+
*/
|
|
87
|
+
export function detectDatabase(appPath) {
|
|
88
|
+
const content = readInfrastructureContent(appPath);
|
|
89
|
+
if (!content)
|
|
90
|
+
return false;
|
|
91
|
+
return content.includes("DatabaseFactory.build(");
|
|
92
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of a validation operation
|
|
3
|
+
* Used for form validation, input validation, etc.
|
|
4
|
+
*/
|
|
5
|
+
export interface ValidationResult {
|
|
6
|
+
/** Whether the validation passed */
|
|
7
|
+
valid: boolean;
|
|
8
|
+
/** Error messages if validation failed */
|
|
9
|
+
errors: string[];
|
|
10
|
+
/** Warning messages (non-blocking) */
|
|
11
|
+
warnings?: string[];
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async file system helpers.
|
|
3
|
+
*/
|
|
4
|
+
import { access, constants } from "fs/promises";
|
|
5
|
+
/**
|
|
6
|
+
* Async check for file existence. Replaces blocking existsSync().
|
|
7
|
+
*/
|
|
8
|
+
export async function fileExists(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
await access(filePath, constants.F_OK);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security helpers for spawn operations
|
|
3
|
+
*
|
|
4
|
+
* Provides environment variable filtering and credential masking
|
|
5
|
+
* to prevent command injection and credential leakage.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Environment variables that MUST NOT be passed from user input to spawned processes.
|
|
9
|
+
* These can be exploited for:
|
|
10
|
+
* - Code execution hijacking (PATH, NODE_OPTIONS)
|
|
11
|
+
* - Dynamic linker injection (LD_PRELOAD, DYLD_INSERT_LIBRARIES)
|
|
12
|
+
* - Interpreter code injection (PYTHONPATH, RUBYLIB)
|
|
13
|
+
* - Credential/identity hijacking (HOME, AWS_CONFIG_FILE)
|
|
14
|
+
* - Shell injection (BASH_ENV, ENV)
|
|
15
|
+
*/
|
|
16
|
+
export declare const DANGEROUS_ENV_VARS: Set<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Filter dangerous environment variables from a record.
|
|
19
|
+
* Returns a new object with only safe environment variables.
|
|
20
|
+
*/
|
|
21
|
+
export declare function filterDangerousEnvVars(env: Record<string, string | undefined>): Record<string, string | undefined>;
|
|
22
|
+
/**
|
|
23
|
+
* Mask sensitive information in output strings to prevent credential leakage.
|
|
24
|
+
* Patterns: postgres://user:pass@host, password=xxx, secret=xxx, apikey=xxx
|
|
25
|
+
*/
|
|
26
|
+
export declare function maskSensitiveOutput(output: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Parse a shell command string into an array of arguments.
|
|
29
|
+
* Handles single quotes, double quotes, and escaped characters.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseShellArgs(command: string): string[];
|