@awsless/awsless 0.0.13 → 0.0.15
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/dist/bin.cjs +2500 -1044
- package/dist/bin.js +2504 -1048
- package/dist/index.cjs +25 -21
- package/dist/index.d.ts +933 -804
- package/dist/index.js +20 -19
- package/package.json +4 -1
package/dist/bin.cjs
CHANGED
|
@@ -26,13 +26,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
// src/cli/program.ts
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
|
|
29
|
-
// src/app.ts
|
|
30
|
-
var import_aws_cdk_lib7 = require("aws-cdk-lib");
|
|
31
|
-
|
|
32
|
-
// src/stack.ts
|
|
33
|
-
var import_aws_cdk_lib = require("aws-cdk-lib");
|
|
34
|
-
var import_aws_iam = require("aws-cdk-lib/aws-iam");
|
|
35
|
-
|
|
36
29
|
// src/cli/style.ts
|
|
37
30
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
38
31
|
var symbol = {
|
|
@@ -84,7 +77,7 @@ var flushDebug = () => {
|
|
|
84
77
|
// src/util/param.ts
|
|
85
78
|
var import_client_ssm = require("@aws-sdk/client-ssm");
|
|
86
79
|
var configParameterPrefix = (config) => {
|
|
87
|
-
return
|
|
80
|
+
return `/awsless/${config.name}/${config.stage}`;
|
|
88
81
|
};
|
|
89
82
|
var Params = class {
|
|
90
83
|
constructor(config) {
|
|
@@ -165,81 +158,411 @@ var Params = class {
|
|
|
165
158
|
}
|
|
166
159
|
};
|
|
167
160
|
|
|
168
|
-
// src/
|
|
169
|
-
var
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
161
|
+
// src/formation/util.ts
|
|
162
|
+
var import_change_case = require("change-case");
|
|
163
|
+
var ref = (logicalId) => {
|
|
164
|
+
return { Ref: logicalId };
|
|
165
|
+
};
|
|
166
|
+
var sub = (value, params) => {
|
|
167
|
+
if (params) {
|
|
168
|
+
return { "Fn::Sub": [value, params] };
|
|
169
|
+
}
|
|
170
|
+
return { "Fn::Sub": value };
|
|
171
|
+
};
|
|
172
|
+
var getAtt = (logicalId, attr) => {
|
|
173
|
+
return { "Fn::GetAtt": [logicalId, attr] };
|
|
174
|
+
};
|
|
175
|
+
var importValue = (name) => {
|
|
176
|
+
return { "Fn::ImportValue": name };
|
|
177
|
+
};
|
|
178
|
+
var formatLogicalId = (id) => {
|
|
179
|
+
return (0, import_change_case.pascalCase)(id);
|
|
180
|
+
};
|
|
181
|
+
var formatName = (name) => {
|
|
182
|
+
return (0, import_change_case.paramCase)(name);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// src/formation/resource.ts
|
|
186
|
+
var Resource = class {
|
|
187
|
+
constructor(type, logicalId, children = []) {
|
|
188
|
+
this.type = type;
|
|
189
|
+
this.children = children;
|
|
190
|
+
this.logicalId = formatLogicalId(`${logicalId}-${type.replace(/^AWS::/, "")}`);
|
|
191
|
+
}
|
|
192
|
+
logicalId;
|
|
193
|
+
deps = /* @__PURE__ */ new Set();
|
|
194
|
+
dependsOn(...dependencies) {
|
|
195
|
+
for (const dependency of dependencies) {
|
|
196
|
+
this.deps.add(dependency);
|
|
177
197
|
}
|
|
178
|
-
|
|
179
|
-
|
|
198
|
+
return this;
|
|
199
|
+
}
|
|
200
|
+
attr(name, value) {
|
|
201
|
+
if (typeof value === "undefined") {
|
|
202
|
+
return {};
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
[name]: value
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
toJSON() {
|
|
209
|
+
return {
|
|
210
|
+
[this.logicalId]: {
|
|
211
|
+
Type: this.type,
|
|
212
|
+
DependsOn: [...this.deps].map((dep) => dep.logicalId),
|
|
213
|
+
Properties: this.properties()
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
var Group = class {
|
|
219
|
+
constructor(children) {
|
|
220
|
+
this.children = children;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// src/formation/resource/iam/inline-policy.ts
|
|
225
|
+
var InlinePolicy = class {
|
|
226
|
+
constructor(name, props = {}) {
|
|
227
|
+
this.name = name;
|
|
228
|
+
this.statements = props.statements || [];
|
|
229
|
+
}
|
|
230
|
+
statements;
|
|
231
|
+
addStatement(...statements) {
|
|
232
|
+
this.statements.push(...statements.flat());
|
|
233
|
+
return this;
|
|
234
|
+
}
|
|
235
|
+
toJSON() {
|
|
236
|
+
return {
|
|
237
|
+
PolicyName: this.name,
|
|
238
|
+
PolicyDocument: {
|
|
239
|
+
Version: "2012-10-17",
|
|
240
|
+
Statement: this.statements.map((statement) => ({
|
|
241
|
+
Effect: statement.effect || "Allow",
|
|
242
|
+
Action: statement.actions,
|
|
243
|
+
Resource: statement.resources
|
|
244
|
+
}))
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// src/formation/resource/iam/managed-policy.ts
|
|
251
|
+
var ManagedPolicy = class {
|
|
252
|
+
constructor(arn) {
|
|
253
|
+
this.arn = arn;
|
|
254
|
+
}
|
|
255
|
+
static fromAwsManagedPolicyName(name) {
|
|
256
|
+
const arn = sub("arn:${AWS::Partition}:iam::aws:policy/service-role/" + name);
|
|
257
|
+
return new ManagedPolicy(arn);
|
|
258
|
+
}
|
|
259
|
+
static fromManagedPolicyArn(arn) {
|
|
260
|
+
return new ManagedPolicy(arn);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// src/formation/resource/iam/role.ts
|
|
265
|
+
var Role = class extends Resource {
|
|
266
|
+
constructor(logicalId, props = {}) {
|
|
267
|
+
super("AWS::IAM::Role", logicalId);
|
|
268
|
+
this.props = props;
|
|
269
|
+
this.name = formatName(logicalId);
|
|
270
|
+
}
|
|
271
|
+
name;
|
|
272
|
+
inlinePolicies = /* @__PURE__ */ new Set();
|
|
273
|
+
managedPolicies = /* @__PURE__ */ new Set();
|
|
274
|
+
get arn() {
|
|
275
|
+
return getAtt(this.logicalId, "Arn");
|
|
276
|
+
}
|
|
277
|
+
addManagedPolicy(...policies) {
|
|
278
|
+
for (const policy of policies) {
|
|
279
|
+
this.managedPolicies.add(policy);
|
|
280
|
+
}
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
addInlinePolicy(...policies) {
|
|
284
|
+
for (const policy of policies) {
|
|
285
|
+
this.inlinePolicies.add(policy);
|
|
286
|
+
}
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
properties() {
|
|
290
|
+
return {
|
|
291
|
+
...this.props.assumedBy ? {
|
|
292
|
+
AssumeRolePolicyDocument: {
|
|
293
|
+
Version: "2012-10-17",
|
|
294
|
+
Statement: [{
|
|
295
|
+
Action: "sts:AssumeRole",
|
|
296
|
+
Effect: "Allow",
|
|
297
|
+
Principal: {
|
|
298
|
+
Service: this.props.assumedBy
|
|
299
|
+
}
|
|
300
|
+
}]
|
|
301
|
+
}
|
|
302
|
+
} : {},
|
|
303
|
+
ManagedPolicyArns: [...this.managedPolicies].map((policy) => policy.arn),
|
|
304
|
+
Policies: [...this.inlinePolicies].map((policy) => policy.toJSON())
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
// src/formation/resource/lambda/function.ts
|
|
310
|
+
var Function = class extends Resource {
|
|
311
|
+
constructor(logicalId, props) {
|
|
312
|
+
const policy = new InlinePolicy(logicalId);
|
|
313
|
+
const role = new Role(logicalId, {
|
|
314
|
+
assumedBy: "lambda.amazonaws.com"
|
|
315
|
+
});
|
|
316
|
+
role.addInlinePolicy(policy);
|
|
317
|
+
role.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName("AWSLambdaBasicExecutionRole"));
|
|
318
|
+
super("AWS::Lambda::Function", logicalId, [
|
|
319
|
+
role,
|
|
320
|
+
props.code
|
|
321
|
+
]);
|
|
322
|
+
this.props = props;
|
|
323
|
+
this.dependsOn(role);
|
|
324
|
+
this.role = role;
|
|
325
|
+
this.policy = policy;
|
|
326
|
+
this.name = formatName(this.props.name || logicalId);
|
|
327
|
+
this.environmentVariables = props.environment ? { ...props.environment } : {};
|
|
328
|
+
}
|
|
329
|
+
name;
|
|
330
|
+
role;
|
|
331
|
+
policy;
|
|
332
|
+
environmentVariables;
|
|
333
|
+
addPermissions(...permissions) {
|
|
334
|
+
this.policy.addStatement(...permissions);
|
|
335
|
+
return this;
|
|
336
|
+
}
|
|
337
|
+
addEnvironment(name, value) {
|
|
338
|
+
this.environmentVariables[name] = value;
|
|
339
|
+
return this;
|
|
340
|
+
}
|
|
341
|
+
get id() {
|
|
342
|
+
return ref(this.logicalId);
|
|
343
|
+
}
|
|
344
|
+
get arn() {
|
|
345
|
+
return getAtt(this.logicalId, "Arn");
|
|
346
|
+
}
|
|
347
|
+
get permissions() {
|
|
348
|
+
return {
|
|
349
|
+
actions: [
|
|
350
|
+
"lambda:InvokeFunction",
|
|
351
|
+
"lambda:InvokeAsync"
|
|
352
|
+
],
|
|
353
|
+
resources: [this.arn]
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
properties() {
|
|
357
|
+
return {
|
|
358
|
+
FunctionName: this.name,
|
|
359
|
+
MemorySize: this.props.memorySize?.toMegaBytes() ?? 128,
|
|
360
|
+
Runtime: this.props.runtime ?? "nodejs18.x",
|
|
361
|
+
Timeout: this.props.timeout?.toSeconds() ?? 10,
|
|
362
|
+
Architectures: [this.props.architecture ?? "arm64"],
|
|
363
|
+
Role: this.role.arn,
|
|
364
|
+
...this.props.code.toCodeJson(),
|
|
365
|
+
EphemeralStorage: {
|
|
366
|
+
Size: this.props.ephemeralStorageSize?.toMegaBytes() ?? 512
|
|
367
|
+
},
|
|
368
|
+
Environment: {
|
|
369
|
+
Variables: this.environmentVariables
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// src/formation/asset.ts
|
|
376
|
+
var import_change_case2 = require("change-case");
|
|
377
|
+
var Asset = class {
|
|
378
|
+
constructor(type, id) {
|
|
379
|
+
this.type = type;
|
|
380
|
+
this.id = (0, import_change_case2.paramCase)(id);
|
|
381
|
+
}
|
|
382
|
+
id;
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// src/formation/stack.ts
|
|
386
|
+
var Stack = class {
|
|
387
|
+
constructor(name, region) {
|
|
388
|
+
this.name = name;
|
|
389
|
+
this.region = region;
|
|
390
|
+
}
|
|
391
|
+
exports = /* @__PURE__ */ new Map();
|
|
392
|
+
resources = /* @__PURE__ */ new Set();
|
|
393
|
+
tags = /* @__PURE__ */ new Map();
|
|
394
|
+
assets = /* @__PURE__ */ new Set();
|
|
395
|
+
add(...resources) {
|
|
396
|
+
for (const item of resources) {
|
|
397
|
+
if (item instanceof Asset) {
|
|
398
|
+
this.assets.add(item);
|
|
399
|
+
} else {
|
|
400
|
+
this.add(...item.children);
|
|
401
|
+
if (item instanceof Resource) {
|
|
402
|
+
this.resources.add(item);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return this;
|
|
407
|
+
}
|
|
408
|
+
export(name, value) {
|
|
409
|
+
name = formatName(name);
|
|
410
|
+
this.exports.set(name, value);
|
|
411
|
+
return this;
|
|
412
|
+
}
|
|
413
|
+
import(name) {
|
|
414
|
+
name = formatName(name);
|
|
415
|
+
if (!this.exports.has(name)) {
|
|
416
|
+
throw new Error(`Undefined export value: ${name}`);
|
|
417
|
+
}
|
|
418
|
+
return importValue(name);
|
|
419
|
+
}
|
|
420
|
+
tag(name, value) {
|
|
421
|
+
this.tags.set(name, value);
|
|
422
|
+
return this;
|
|
423
|
+
}
|
|
424
|
+
find(resourceType) {
|
|
425
|
+
return [...this.resources].filter((resource) => resource instanceof resourceType);
|
|
426
|
+
}
|
|
427
|
+
[Symbol.iterator]() {
|
|
428
|
+
return this.resources.values();
|
|
429
|
+
}
|
|
430
|
+
// get resources() {
|
|
431
|
+
// return [ ...this.list.values() ]
|
|
432
|
+
// }
|
|
433
|
+
get size() {
|
|
434
|
+
return this.resources.size;
|
|
435
|
+
}
|
|
436
|
+
toJSON() {
|
|
437
|
+
const resources = {};
|
|
438
|
+
const outputs = {};
|
|
439
|
+
for (const resource of this) {
|
|
440
|
+
Object.assign(resources, resource.toJSON());
|
|
441
|
+
}
|
|
442
|
+
for (const [name, value] of this.exports.entries()) {
|
|
443
|
+
Object.assign(outputs, {
|
|
444
|
+
[formatLogicalId(name)]: {
|
|
445
|
+
Export: { Name: name },
|
|
446
|
+
Value: value
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
Resources: resources,
|
|
452
|
+
Outputs: outputs
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
toString(pretty = false) {
|
|
456
|
+
return JSON.stringify(
|
|
457
|
+
this.toJSON(),
|
|
458
|
+
void 0,
|
|
459
|
+
pretty ? 4 : void 0
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
// src/stack.ts
|
|
465
|
+
var toStack = ({ config, app, stackConfig, bootstrap: bootstrap2, usEastBootstrap, plugins }) => {
|
|
466
|
+
const name = stackConfig.name;
|
|
467
|
+
const stack = new Stack(name, config.region).tag("app", config.name).tag("stage", config.stage).tag("stack", name);
|
|
468
|
+
debug("Define stack:", style.info(name));
|
|
469
|
+
debug("Run plugin onStack listeners");
|
|
180
470
|
const bindings = [];
|
|
181
471
|
const bind = (cb) => {
|
|
182
472
|
bindings.push(cb);
|
|
183
473
|
};
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
474
|
+
for (const plugin of plugins) {
|
|
475
|
+
plugin.onStack?.({
|
|
476
|
+
config,
|
|
477
|
+
app,
|
|
478
|
+
stack,
|
|
479
|
+
stackConfig,
|
|
480
|
+
bootstrap: bootstrap2,
|
|
481
|
+
usEastBootstrap,
|
|
482
|
+
bind
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
if (stack.size === 0) {
|
|
486
|
+
throw new Error(`Stack ${style.info(name)} has no resources defined`);
|
|
487
|
+
}
|
|
488
|
+
const functions = stack.find(Function);
|
|
489
|
+
for (const bind2 of bindings) {
|
|
490
|
+
for (const fn of functions) {
|
|
491
|
+
bind2(fn);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
for (const fn of functions) {
|
|
495
|
+
fn.addPermissions({
|
|
496
|
+
actions: [
|
|
497
|
+
"ssm:GetParameter",
|
|
498
|
+
"ssm:GetParameters",
|
|
499
|
+
"ssm:GetParametersByPath"
|
|
500
|
+
],
|
|
501
|
+
resources: [
|
|
502
|
+
sub("arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter" + configParameterPrefix(config))
|
|
503
|
+
]
|
|
504
|
+
});
|
|
505
|
+
}
|
|
216
506
|
return {
|
|
217
507
|
stack,
|
|
218
|
-
functions,
|
|
219
|
-
bindings,
|
|
220
508
|
depends: stackConfig.depends
|
|
221
509
|
};
|
|
222
510
|
};
|
|
223
511
|
|
|
224
|
-
// src/util/
|
|
225
|
-
var
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
512
|
+
// src/util/deployment.ts
|
|
513
|
+
var createDependencyTree = (stacks) => {
|
|
514
|
+
const list3 = stacks.map(({ stack, config }) => ({
|
|
515
|
+
stack,
|
|
516
|
+
depends: config?.depends?.map((dep) => dep.name) || []
|
|
517
|
+
}));
|
|
518
|
+
const findChildren = (list4, parents) => {
|
|
519
|
+
const children = [];
|
|
520
|
+
const rests = [];
|
|
521
|
+
for (const item of list4) {
|
|
522
|
+
const isChild = item.depends.filter((dep) => !parents.includes(dep)).length === 0;
|
|
523
|
+
if (isChild) {
|
|
524
|
+
children.push(item);
|
|
525
|
+
} else {
|
|
526
|
+
rests.push(item);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
if (!rests.length) {
|
|
530
|
+
return children.map(({ stack }) => ({
|
|
531
|
+
stack,
|
|
532
|
+
children: []
|
|
533
|
+
}));
|
|
534
|
+
}
|
|
535
|
+
return children.map(({ stack }) => {
|
|
536
|
+
return {
|
|
537
|
+
stack,
|
|
538
|
+
children: findChildren(rests, [...parents, stack.name])
|
|
539
|
+
};
|
|
540
|
+
});
|
|
541
|
+
};
|
|
542
|
+
return findChildren(list3, []);
|
|
543
|
+
};
|
|
544
|
+
var createDeploymentLine = (stacks) => {
|
|
545
|
+
const line = [];
|
|
546
|
+
const walk = (stacks2, level) => {
|
|
547
|
+
stacks2.forEach((node) => {
|
|
548
|
+
if (!line[level]) {
|
|
549
|
+
line[level] = [];
|
|
550
|
+
}
|
|
551
|
+
line[level].push(node.stack);
|
|
552
|
+
walk(node.children, level + 1);
|
|
553
|
+
});
|
|
554
|
+
};
|
|
555
|
+
walk(stacks, 0);
|
|
556
|
+
return line;
|
|
557
|
+
};
|
|
231
558
|
|
|
232
|
-
// src/
|
|
233
|
-
var
|
|
559
|
+
// src/plugins/cron/index.ts
|
|
560
|
+
var import_zod7 = require("zod");
|
|
234
561
|
|
|
235
562
|
// src/plugin.ts
|
|
236
563
|
var definePlugin = (plugin) => plugin;
|
|
237
564
|
|
|
238
|
-
// src/plugins/cron/index.ts
|
|
239
|
-
var import_zod10 = require("zod");
|
|
240
|
-
|
|
241
565
|
// src/plugins/cron/schema/schedule.ts
|
|
242
|
-
var import_aws_events = require("aws-cdk-lib/aws-events");
|
|
243
566
|
var import_zod = require("zod");
|
|
244
567
|
var import_aws_cron_expression_validator = require("aws-cron-expression-validator");
|
|
245
568
|
var RateExpressionSchema = import_zod.z.custom((value) => {
|
|
@@ -248,7 +571,7 @@ var RateExpressionSchema = import_zod.z.custom((value) => {
|
|
|
248
571
|
const number = parseInt(str);
|
|
249
572
|
return number > 0;
|
|
250
573
|
}).safeParse(value).success;
|
|
251
|
-
}, "Invalid rate expression")
|
|
574
|
+
}, "Invalid rate expression");
|
|
252
575
|
var CronExpressionSchema = import_zod.z.custom((value) => {
|
|
253
576
|
return import_zod.z.string().startsWith("cron(").endsWith(")").safeParse(value).success;
|
|
254
577
|
}, "Invalid cron expression").superRefine((value, ctx) => {
|
|
@@ -268,55 +591,81 @@ var CronExpressionSchema = import_zod.z.custom((value) => {
|
|
|
268
591
|
});
|
|
269
592
|
}
|
|
270
593
|
}
|
|
271
|
-
})
|
|
594
|
+
});
|
|
272
595
|
var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
|
|
273
596
|
|
|
274
|
-
// src/plugins/
|
|
275
|
-
var
|
|
597
|
+
// src/plugins/function.ts
|
|
598
|
+
var import_zod6 = require("zod");
|
|
276
599
|
|
|
277
|
-
// src/
|
|
278
|
-
var
|
|
279
|
-
var toId = (resource, id) => {
|
|
280
|
-
return (0, import_change_case.pascalCase)(`${resource}-${id}`);
|
|
281
|
-
};
|
|
282
|
-
var toName = (stack, id) => {
|
|
283
|
-
return (0, import_change_case.paramCase)(`${stack.stackName}-${id}`);
|
|
284
|
-
};
|
|
285
|
-
var toEnvKey = (resource, id) => {
|
|
286
|
-
return `RESOURCE_${resource.toUpperCase()}_${id}`;
|
|
287
|
-
};
|
|
288
|
-
var addResourceEnvironment = (stack, resource, id, lambda) => {
|
|
289
|
-
const key = toEnvKey(resource, id);
|
|
290
|
-
const value = toName(stack, id);
|
|
291
|
-
lambda.addEnvironment(key, value, {
|
|
292
|
-
removeInEdge: true
|
|
293
|
-
});
|
|
294
|
-
};
|
|
600
|
+
// src/schema/duration.ts
|
|
601
|
+
var import_zod2 = require("zod");
|
|
295
602
|
|
|
296
|
-
// src/
|
|
297
|
-
var
|
|
603
|
+
// src/formation/property/duration.ts
|
|
604
|
+
var Duration = class {
|
|
605
|
+
constructor(value) {
|
|
606
|
+
this.value = value;
|
|
607
|
+
}
|
|
608
|
+
static milliseconds(value) {
|
|
609
|
+
return new Duration(value);
|
|
610
|
+
}
|
|
611
|
+
static seconds(value) {
|
|
612
|
+
return new Duration(value * 1e3 /* seconds */);
|
|
613
|
+
}
|
|
614
|
+
static minutes(value) {
|
|
615
|
+
return new Duration(value * 6e4 /* minutes */);
|
|
616
|
+
}
|
|
617
|
+
static hours(value) {
|
|
618
|
+
return new Duration(value * 36e5 /* hours */);
|
|
619
|
+
}
|
|
620
|
+
static days(value) {
|
|
621
|
+
return new Duration(value * 864e5 /* days */);
|
|
622
|
+
}
|
|
623
|
+
toMilliseconds() {
|
|
624
|
+
return this.value;
|
|
625
|
+
}
|
|
626
|
+
toSeconds() {
|
|
627
|
+
return Math.floor(this.value / 1e3 /* seconds */);
|
|
628
|
+
}
|
|
629
|
+
toMinutes() {
|
|
630
|
+
return Math.floor(this.value / 6e4 /* minutes */);
|
|
631
|
+
}
|
|
632
|
+
toHours() {
|
|
633
|
+
return Math.floor(this.value / 36e5 /* hours */);
|
|
634
|
+
}
|
|
635
|
+
toDays() {
|
|
636
|
+
return Math.floor(this.value / 864e5 /* days */);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
298
639
|
|
|
299
640
|
// src/schema/duration.ts
|
|
300
|
-
var import_zod2 = require("zod");
|
|
301
|
-
var import_core = require("aws-cdk-lib/core");
|
|
302
641
|
function toDuration(duration) {
|
|
303
642
|
const [count, unit] = duration.split(" ");
|
|
304
643
|
const countNum = parseInt(count);
|
|
305
644
|
const unitLower = unit.toLowerCase();
|
|
306
645
|
if (unitLower.startsWith("second")) {
|
|
307
|
-
return
|
|
646
|
+
return Duration.seconds(countNum);
|
|
308
647
|
} else if (unitLower.startsWith("minute")) {
|
|
309
|
-
return
|
|
648
|
+
return Duration.minutes(countNum);
|
|
310
649
|
} else if (unitLower.startsWith("hour")) {
|
|
311
|
-
return
|
|
650
|
+
return Duration.hours(countNum);
|
|
312
651
|
} else if (unitLower.startsWith("day")) {
|
|
313
|
-
return
|
|
652
|
+
return Duration.days(countNum);
|
|
314
653
|
}
|
|
315
|
-
return
|
|
654
|
+
return Duration.days(0);
|
|
316
655
|
}
|
|
317
656
|
var DurationSchema = import_zod2.z.custom((value) => {
|
|
318
657
|
return import_zod2.z.string().regex(/[0-9]+ (seconds?|minutes?|hours?|days?)/).safeParse(value).success;
|
|
319
658
|
}, "Invalid duration").transform(toDuration);
|
|
659
|
+
var durationMin = (min) => {
|
|
660
|
+
return (duration) => {
|
|
661
|
+
return duration.toSeconds() >= min.toSeconds();
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
var durationMax = (max) => {
|
|
665
|
+
return (duration) => {
|
|
666
|
+
return duration.toSeconds() <= max.toSeconds();
|
|
667
|
+
};
|
|
668
|
+
};
|
|
320
669
|
|
|
321
670
|
// src/schema/local-file.ts
|
|
322
671
|
var import_promises = require("fs/promises");
|
|
@@ -330,202 +679,86 @@ var LocalFileSchema = import_zod3.z.string().refine(async (path) => {
|
|
|
330
679
|
return true;
|
|
331
680
|
}, `File doesn't exist`);
|
|
332
681
|
|
|
333
|
-
// src/
|
|
334
|
-
var import_aws_lambda3 = require("aws-cdk-lib/aws-lambda");
|
|
335
|
-
|
|
336
|
-
// src/plugins/function/schema/runtime.ts
|
|
337
|
-
var import_aws_lambda = require("aws-cdk-lib/aws-lambda");
|
|
682
|
+
// src/schema/resource-id.ts
|
|
338
683
|
var import_zod4 = require("zod");
|
|
339
|
-
var
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
"nodejs16.x": import_aws_lambda.Runtime.NODEJS_16_X,
|
|
343
|
-
"nodejs18.x": import_aws_lambda.Runtime.NODEJS_18_X,
|
|
344
|
-
"python3.9": import_aws_lambda.Runtime.PYTHON_3_9,
|
|
345
|
-
"python3.10": import_aws_lambda.Runtime.PYTHON_3_10,
|
|
346
|
-
"go1.x": import_aws_lambda.Runtime.PROVIDED_AL2,
|
|
347
|
-
"go": import_aws_lambda.Runtime.PROVIDED_AL2
|
|
348
|
-
};
|
|
349
|
-
var toRuntime = (runtime) => {
|
|
350
|
-
return runtimes[runtime];
|
|
351
|
-
};
|
|
352
|
-
var RuntimeSchema = import_zod4.z.enum(Object.keys(runtimes)).transform(toRuntime);
|
|
353
|
-
|
|
354
|
-
// src/plugins/function/schema/architecture.ts
|
|
355
|
-
var import_aws_lambda2 = require("aws-cdk-lib/aws-lambda");
|
|
684
|
+
var ResourceIdSchema = import_zod4.z.string().min(3).max(24).regex(/[a-z\-]+/, "Invalid resource ID");
|
|
685
|
+
|
|
686
|
+
// src/schema/size.ts
|
|
356
687
|
var import_zod5 = require("zod");
|
|
357
|
-
var toArchitecture = (architecture) => {
|
|
358
|
-
return architecture === "x86_64" ? import_aws_lambda2.Architecture.X86_64 : import_aws_lambda2.Architecture.ARM_64;
|
|
359
|
-
};
|
|
360
|
-
var ArchitectureSchema = import_zod5.z.enum(["x86_64", "arm_64"]).transform(toArchitecture);
|
|
361
688
|
|
|
362
|
-
// src/
|
|
363
|
-
var
|
|
364
|
-
|
|
689
|
+
// src/formation/property/size.ts
|
|
690
|
+
var Size = class {
|
|
691
|
+
constructor(bytes) {
|
|
692
|
+
this.bytes = bytes;
|
|
693
|
+
}
|
|
694
|
+
static bytes(value) {
|
|
695
|
+
return new Size(value);
|
|
696
|
+
}
|
|
697
|
+
static kiloBytes(value) {
|
|
698
|
+
return new Size(value * 1024 /* kilo */);
|
|
699
|
+
}
|
|
700
|
+
static megaBytes(value) {
|
|
701
|
+
return new Size(value * 1048576 /* mega */);
|
|
702
|
+
}
|
|
703
|
+
static gigaBytes(value) {
|
|
704
|
+
return new Size(value * 1073741824 /* giga */);
|
|
705
|
+
}
|
|
706
|
+
toBytes() {
|
|
707
|
+
return this.bytes;
|
|
708
|
+
}
|
|
709
|
+
toKiloBytes() {
|
|
710
|
+
return Math.floor(this.bytes / 1024 /* kilo */);
|
|
711
|
+
}
|
|
712
|
+
toMegaBytes() {
|
|
713
|
+
return Math.floor(this.bytes / 1048576 /* mega */);
|
|
714
|
+
}
|
|
715
|
+
toGigaBytes() {
|
|
716
|
+
return Math.floor(this.bytes / 1073741824 /* giga */);
|
|
717
|
+
}
|
|
718
|
+
};
|
|
365
719
|
|
|
366
720
|
// src/schema/size.ts
|
|
367
|
-
var import_core2 = require("aws-cdk-lib/core");
|
|
368
|
-
var import_zod7 = require("zod");
|
|
369
721
|
function toSize(size) {
|
|
370
722
|
const [count, unit] = size.split(" ");
|
|
371
723
|
const countNum = parseInt(count);
|
|
372
724
|
if (unit === "KB") {
|
|
373
|
-
return
|
|
725
|
+
return Size.kiloBytes(countNum);
|
|
374
726
|
} else if (unit === "MB") {
|
|
375
|
-
return
|
|
727
|
+
return Size.megaBytes(countNum);
|
|
376
728
|
} else if (unit === "GB") {
|
|
377
|
-
return
|
|
729
|
+
return Size.gigaBytes(countNum);
|
|
378
730
|
}
|
|
379
731
|
throw new TypeError(`Invalid size ${size}`);
|
|
380
732
|
}
|
|
381
|
-
var SizeSchema =
|
|
382
|
-
return
|
|
733
|
+
var SizeSchema = import_zod5.z.custom((value) => {
|
|
734
|
+
return import_zod5.z.string().regex(/[0-9]+ (KB|MB|GB)/).safeParse(value).success;
|
|
383
735
|
}, "Invalid size").transform(toSize);
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
var import_path3 = require("path");
|
|
388
|
-
var import_promises2 = require("fs/promises");
|
|
389
|
-
var import_filesize = require("filesize");
|
|
390
|
-
var zipFiles = (files) => {
|
|
391
|
-
const zip = new import_jszip.default();
|
|
392
|
-
for (const file of files) {
|
|
393
|
-
zip.file(file.name, file.code);
|
|
394
|
-
}
|
|
395
|
-
return zip.generateAsync({
|
|
396
|
-
type: "nodebuffer",
|
|
397
|
-
compression: "DEFLATE",
|
|
398
|
-
compressionOptions: {
|
|
399
|
-
level: 9
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
};
|
|
403
|
-
var writeBuildHash = async (config, stack, id, hash) => {
|
|
404
|
-
const funcPath = (0, import_path3.join)(assetDir, "function", config.name, stack.artifactId, id);
|
|
405
|
-
const versionFile = (0, import_path3.join)(funcPath, "HASH");
|
|
406
|
-
await (0, import_promises2.writeFile)(versionFile, hash);
|
|
407
|
-
};
|
|
408
|
-
var writeBuildFiles = async (config, stack, id, files) => {
|
|
409
|
-
const bundle = await zipFiles(files);
|
|
410
|
-
const funcPath = (0, import_path3.join)(assetDir, "function", config.name, stack.artifactId, id);
|
|
411
|
-
const filesPath = (0, import_path3.join)(funcPath, "files");
|
|
412
|
-
const bundleFile = (0, import_path3.join)(funcPath, "bundle.zip");
|
|
413
|
-
debug("Bundle size of", style.info((0, import_path3.join)(config.name, stack.artifactId, id)), "is", style.attr((0, import_filesize.filesize)(bundle.byteLength)));
|
|
414
|
-
await (0, import_promises2.mkdir)(filesPath, { recursive: true });
|
|
415
|
-
await (0, import_promises2.writeFile)(bundleFile, bundle);
|
|
416
|
-
await Promise.all(files.map(async (file) => {
|
|
417
|
-
const fileName = (0, import_path3.join)(filesPath, file.name);
|
|
418
|
-
await (0, import_promises2.mkdir)((0, import_path3.basename)(fileName), { recursive: true });
|
|
419
|
-
await (0, import_promises2.writeFile)(fileName, file.code);
|
|
420
|
-
if (file.map) {
|
|
421
|
-
const mapName = (0, import_path3.join)(filesPath, `${file.name}.map`);
|
|
422
|
-
await (0, import_promises2.writeFile)(mapName, file.map);
|
|
423
|
-
}
|
|
424
|
-
}));
|
|
425
|
-
return {
|
|
426
|
-
file: bundleFile,
|
|
427
|
-
size: bundle.byteLength
|
|
736
|
+
var sizeMin = (min) => {
|
|
737
|
+
return (size) => {
|
|
738
|
+
return size.toBytes() >= min.toBytes();
|
|
428
739
|
};
|
|
429
740
|
};
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
var import_client_s3 = require("@aws-sdk/client-s3");
|
|
435
|
-
|
|
436
|
-
// src/stack/bootstrap.ts
|
|
437
|
-
var import_aws_cdk_lib2 = require("aws-cdk-lib");
|
|
438
|
-
var import_aws_s3 = require("aws-cdk-lib/aws-s3");
|
|
439
|
-
var assetBucketName = (config) => {
|
|
440
|
-
return `awsless-bootstrap-${config.account}-${config.region}`;
|
|
441
|
-
};
|
|
442
|
-
var assetBucketUrl = (config, stackName) => {
|
|
443
|
-
const bucket = assetBucketName(config);
|
|
444
|
-
return `https://s3-${config.region}.amazonaws.com/${bucket}/${stackName}/cloudformation.json`;
|
|
445
|
-
};
|
|
446
|
-
var version = "2";
|
|
447
|
-
var bootstrapStack = (config, app) => {
|
|
448
|
-
const stack = new import_aws_cdk_lib2.Stack(app, "bootstrap", {
|
|
449
|
-
stackName: `awsless-bootstrap`
|
|
450
|
-
});
|
|
451
|
-
new import_aws_s3.Bucket(stack, "assets", {
|
|
452
|
-
bucketName: assetBucketName(config),
|
|
453
|
-
versioned: true,
|
|
454
|
-
accessControl: import_aws_s3.BucketAccessControl.PRIVATE,
|
|
455
|
-
removalPolicy: import_aws_cdk_lib2.RemovalPolicy.DESTROY
|
|
456
|
-
});
|
|
457
|
-
new import_aws_cdk_lib2.CfnOutput(stack, "version", {
|
|
458
|
-
exportName: "version",
|
|
459
|
-
value: version
|
|
460
|
-
});
|
|
461
|
-
return stack;
|
|
462
|
-
};
|
|
463
|
-
var shouldDeployBootstrap = async (client, name) => {
|
|
464
|
-
debug("Check bootstrap status");
|
|
465
|
-
const info = await client.get(name);
|
|
466
|
-
return !info || info.outputs.version !== version || !["CREATE_COMPLETE", "UPDATE_COMPLETE"].includes(info.status);
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
// src/plugins/function/util/publish.ts
|
|
470
|
-
var publishFunctionAsset = async (config, stack, id) => {
|
|
471
|
-
const bucket = assetBucketName(config);
|
|
472
|
-
const key = `${config.name}/${stack.artifactId}/function/${id}.zip`;
|
|
473
|
-
const funcPath = (0, import_path5.join)(assetDir, "function", config.name, stack.artifactId, id);
|
|
474
|
-
const bundleFile = (0, import_path5.join)(funcPath, "bundle.zip");
|
|
475
|
-
const hashFile = (0, import_path5.join)(funcPath, "HASH");
|
|
476
|
-
const hash = await (0, import_promises3.readFile)(hashFile, "utf8");
|
|
477
|
-
const file = await (0, import_promises3.readFile)(bundleFile);
|
|
478
|
-
const client = new import_client_s3.S3Client({
|
|
479
|
-
credentials: config.credentials,
|
|
480
|
-
region: config.region
|
|
481
|
-
});
|
|
482
|
-
let getResult;
|
|
483
|
-
try {
|
|
484
|
-
getResult = await client.send(new import_client_s3.GetObjectCommand({
|
|
485
|
-
Bucket: bucket,
|
|
486
|
-
Key: key
|
|
487
|
-
}));
|
|
488
|
-
} catch (error) {
|
|
489
|
-
if (error instanceof Error && error.name === "NoSuchKey") {
|
|
490
|
-
} else {
|
|
491
|
-
throw error;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
if (getResult?.Metadata?.hash === hash) {
|
|
495
|
-
return getResult.VersionId;
|
|
496
|
-
}
|
|
497
|
-
const putResult = await client.send(new import_client_s3.PutObjectCommand({
|
|
498
|
-
Bucket: bucket,
|
|
499
|
-
Key: key,
|
|
500
|
-
Body: file,
|
|
501
|
-
ACL: import_client_s3.ObjectCannedACL.private,
|
|
502
|
-
StorageClass: import_client_s3.StorageClass.STANDARD,
|
|
503
|
-
Metadata: {
|
|
504
|
-
hash
|
|
505
|
-
}
|
|
506
|
-
}));
|
|
507
|
-
return putResult.VersionId;
|
|
741
|
+
var sizeMax = (max) => {
|
|
742
|
+
return (size) => {
|
|
743
|
+
return size.toBytes() <= max.toBytes();
|
|
744
|
+
};
|
|
508
745
|
};
|
|
509
746
|
|
|
510
|
-
// src/plugins/function/schema/retry-attempts.ts
|
|
511
|
-
var import_zod8 = require("zod");
|
|
512
|
-
var RetryAttempts = import_zod8.z.number().int().min(0).max(2);
|
|
513
|
-
|
|
514
747
|
// src/util/byte-size.ts
|
|
515
|
-
var
|
|
748
|
+
var import_filesize = require("filesize");
|
|
516
749
|
var formatByteSize = (size) => {
|
|
517
|
-
const [number, unit] = (0,
|
|
750
|
+
const [number, unit] = (0, import_filesize.filesize)(size).toString().split(" ");
|
|
518
751
|
return style.attr(number) + style.attr.dim(unit);
|
|
519
752
|
};
|
|
520
753
|
|
|
521
|
-
// src/
|
|
754
|
+
// src/formation/resource/lambda/util/rollup.ts
|
|
522
755
|
var import_rollup = require("rollup");
|
|
523
756
|
var import_crypto = require("crypto");
|
|
524
757
|
var import_rollup_plugin_swc3 = require("rollup-plugin-swc3");
|
|
525
758
|
var import_plugin_json = __toESM(require("@rollup/plugin-json"), 1);
|
|
526
759
|
var import_plugin_commonjs = __toESM(require("@rollup/plugin-commonjs"), 1);
|
|
527
760
|
var import_plugin_node_resolve = __toESM(require("@rollup/plugin-node-resolve"), 1);
|
|
528
|
-
var
|
|
761
|
+
var rollupBundle = async (input) => {
|
|
529
762
|
const bundle = await (0, import_rollup.rollup)({
|
|
530
763
|
input,
|
|
531
764
|
external: (importee) => {
|
|
@@ -570,34 +803,160 @@ var rollupBuild = async (input) => {
|
|
|
570
803
|
};
|
|
571
804
|
};
|
|
572
805
|
|
|
573
|
-
// src/
|
|
574
|
-
var
|
|
806
|
+
// src/formation/resource/lambda/util/zip.ts
|
|
807
|
+
var import_jszip = __toESM(require("jszip"), 1);
|
|
808
|
+
var zipFiles = (files) => {
|
|
809
|
+
const zip = new import_jszip.default();
|
|
810
|
+
for (const file of files) {
|
|
811
|
+
zip.file(file.name, file.code);
|
|
812
|
+
}
|
|
813
|
+
return zip.generateAsync({
|
|
814
|
+
type: "nodebuffer",
|
|
815
|
+
compression: "DEFLATE",
|
|
816
|
+
compressionOptions: {
|
|
817
|
+
level: 9
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
};
|
|
821
|
+
|
|
822
|
+
// src/formation/resource/lambda/code.ts
|
|
823
|
+
var import_crypto2 = require("crypto");
|
|
824
|
+
var Code = class {
|
|
825
|
+
static fromFile(id, file, bundler) {
|
|
826
|
+
return new FileCode(id, file, bundler);
|
|
827
|
+
}
|
|
828
|
+
static fromInline(id, code, handler) {
|
|
829
|
+
return new InlineCode(id, code, handler);
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
var InlineCode = class extends Asset {
|
|
833
|
+
constructor(id, code, handler = "index.default") {
|
|
834
|
+
super("function", id);
|
|
835
|
+
this.code = code;
|
|
836
|
+
this.handler = handler;
|
|
837
|
+
}
|
|
838
|
+
hash;
|
|
839
|
+
bundle;
|
|
840
|
+
s3;
|
|
841
|
+
async build({ write }) {
|
|
842
|
+
const hash = (0, import_crypto2.createHash)("sha1").update(this.code).digest("hex");
|
|
843
|
+
const bundle = await zipFiles([{
|
|
844
|
+
name: "index.js",
|
|
845
|
+
code: this.code
|
|
846
|
+
}]);
|
|
847
|
+
await Promise.all([
|
|
848
|
+
write("HASH", hash),
|
|
849
|
+
write("bundle.zip", bundle),
|
|
850
|
+
write("files/inline.js", this.code)
|
|
851
|
+
]);
|
|
852
|
+
this.bundle = bundle;
|
|
853
|
+
this.hash = hash;
|
|
854
|
+
return {
|
|
855
|
+
size: formatByteSize(bundle.byteLength)
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
async publish({ publish }) {
|
|
859
|
+
this.s3 = await publish(
|
|
860
|
+
`${this.id}.zip`,
|
|
861
|
+
this.bundle,
|
|
862
|
+
this.hash
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
toCodeJson() {
|
|
866
|
+
return {
|
|
867
|
+
Handler: this.handler,
|
|
868
|
+
Code: {
|
|
869
|
+
S3Bucket: this.s3.bucket,
|
|
870
|
+
S3Key: this.s3.key,
|
|
871
|
+
S3ObjectVersion: this.s3.version
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
var FileCode = class extends Asset {
|
|
877
|
+
constructor(id, file, bundler) {
|
|
878
|
+
super("function", id);
|
|
879
|
+
this.file = file;
|
|
880
|
+
this.bundler = bundler;
|
|
881
|
+
}
|
|
882
|
+
handler;
|
|
883
|
+
hash;
|
|
884
|
+
bundle;
|
|
885
|
+
s3;
|
|
886
|
+
async build({ write }) {
|
|
887
|
+
const bundler = this.bundler ?? rollupBundle;
|
|
888
|
+
const { hash, files, handler } = await bundler(this.file);
|
|
889
|
+
const bundle = await zipFiles(files);
|
|
890
|
+
await Promise.all([
|
|
891
|
+
write("HASH", hash),
|
|
892
|
+
write("bundle.zip", bundle),
|
|
893
|
+
...files.map((file) => write(`files/${file.name}`, file.code)),
|
|
894
|
+
...files.map((file) => file.map ? write(`files/${file.name}.map`, file.map) : void 0)
|
|
895
|
+
]);
|
|
896
|
+
this.handler = handler;
|
|
897
|
+
this.bundle = bundle;
|
|
898
|
+
this.hash = hash;
|
|
899
|
+
return {
|
|
900
|
+
size: formatByteSize(bundle.byteLength)
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
async publish({ publish }) {
|
|
904
|
+
this.s3 = await publish(
|
|
905
|
+
`${this.id}.zip`,
|
|
906
|
+
this.bundle,
|
|
907
|
+
this.hash
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
toCodeJson() {
|
|
911
|
+
return {
|
|
912
|
+
Handler: this.handler,
|
|
913
|
+
Code: {
|
|
914
|
+
S3Bucket: this.s3?.bucket ?? "",
|
|
915
|
+
S3Key: this.s3?.key ?? "",
|
|
916
|
+
S3ObjectVersion: this.s3?.version ?? ""
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
// src/plugins/function.ts
|
|
923
|
+
var MemorySizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(128)), "Minimum memory size is 128 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum memory size is 10 GB");
|
|
924
|
+
var TimeoutSchema = DurationSchema.refine(durationMin(Duration.seconds(10)), "Minimum timeout duration is 10 seconds").refine(durationMax(Duration.minutes(15)), "Maximum timeout duration is 15 minutes");
|
|
925
|
+
var EphemeralStorageSizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(512)), "Minimum ephemeral storage size is 512 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum ephemeral storage size is 10 GB");
|
|
926
|
+
var EnvironmentSchema = import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).optional();
|
|
927
|
+
var ArchitectureSchema = import_zod6.z.enum(["x86_64", "arm64"]);
|
|
928
|
+
var RetryAttemptsSchema = import_zod6.z.number().int().min(0).max(2);
|
|
929
|
+
var RuntimeSchema = import_zod6.z.enum([
|
|
930
|
+
"nodejs16.x",
|
|
931
|
+
"nodejs18.x"
|
|
932
|
+
]);
|
|
933
|
+
var FunctionSchema = import_zod6.z.union([
|
|
575
934
|
LocalFileSchema,
|
|
576
|
-
|
|
935
|
+
import_zod6.z.object({
|
|
577
936
|
file: LocalFileSchema,
|
|
578
|
-
timeout:
|
|
937
|
+
timeout: TimeoutSchema.optional(),
|
|
579
938
|
runtime: RuntimeSchema.optional(),
|
|
580
|
-
memorySize:
|
|
939
|
+
memorySize: MemorySizeSchema.optional(),
|
|
581
940
|
architecture: ArchitectureSchema.optional(),
|
|
582
|
-
ephemeralStorageSize:
|
|
583
|
-
retryAttempts:
|
|
584
|
-
environment:
|
|
941
|
+
ephemeralStorageSize: EphemeralStorageSizeSchema.optional(),
|
|
942
|
+
retryAttempts: RetryAttemptsSchema.optional(),
|
|
943
|
+
environment: EnvironmentSchema.optional()
|
|
585
944
|
})
|
|
586
945
|
]);
|
|
587
|
-
var schema =
|
|
588
|
-
defaults:
|
|
589
|
-
function:
|
|
590
|
-
timeout:
|
|
946
|
+
var schema = import_zod6.z.object({
|
|
947
|
+
defaults: import_zod6.z.object({
|
|
948
|
+
function: import_zod6.z.object({
|
|
949
|
+
timeout: TimeoutSchema.default("10 seconds"),
|
|
591
950
|
runtime: RuntimeSchema.default("nodejs18.x"),
|
|
592
|
-
memorySize:
|
|
593
|
-
architecture: ArchitectureSchema.default("
|
|
594
|
-
ephemeralStorageSize:
|
|
595
|
-
retryAttempts:
|
|
596
|
-
environment:
|
|
951
|
+
memorySize: MemorySizeSchema.default("128 MB"),
|
|
952
|
+
architecture: ArchitectureSchema.default("arm64"),
|
|
953
|
+
ephemeralStorageSize: EphemeralStorageSizeSchema.default("512 MB"),
|
|
954
|
+
retryAttempts: RetryAttemptsSchema.default(2),
|
|
955
|
+
environment: EnvironmentSchema.optional()
|
|
597
956
|
}).default({})
|
|
598
957
|
}).default({}),
|
|
599
|
-
stacks:
|
|
600
|
-
functions:
|
|
958
|
+
stacks: import_zod6.z.object({
|
|
959
|
+
functions: import_zod6.z.record(
|
|
601
960
|
ResourceIdSchema,
|
|
602
961
|
FunctionSchema
|
|
603
962
|
).optional()
|
|
@@ -606,200 +965,466 @@ var schema = import_zod9.z.object({
|
|
|
606
965
|
var functionPlugin = definePlugin({
|
|
607
966
|
name: "function",
|
|
608
967
|
schema,
|
|
609
|
-
onStack(
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
968
|
+
onStack(ctx) {
|
|
969
|
+
for (const [id, props] of Object.entries(ctx.stackConfig.functions || {})) {
|
|
970
|
+
const lambda = toLambdaFunction(ctx, id, props);
|
|
971
|
+
ctx.stack.add(lambda);
|
|
972
|
+
}
|
|
613
973
|
}
|
|
614
974
|
});
|
|
615
|
-
var
|
|
975
|
+
var toLambdaFunction = (ctx, id, fileOrProps) => {
|
|
976
|
+
const config = ctx.config;
|
|
977
|
+
const stack = ctx.stack;
|
|
616
978
|
const props = typeof fileOrProps === "string" ? { ...config.defaults?.function, file: fileOrProps } : { ...config.defaults?.function, ...fileOrProps };
|
|
617
|
-
const lambda = new
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
...props,
|
|
622
|
-
memorySize: props.memorySize.toMebibytes()
|
|
979
|
+
const lambda = new Function(id, {
|
|
980
|
+
name: `${config.name}-${stack.name}-${id}`,
|
|
981
|
+
code: Code.fromFile(id, props.file),
|
|
982
|
+
...props
|
|
623
983
|
});
|
|
624
|
-
lambda.addEnvironment("APP", config.name
|
|
625
|
-
lambda.addEnvironment("STAGE", config.stage
|
|
626
|
-
lambda.addEnvironment("STACK", stack.
|
|
627
|
-
if (
|
|
628
|
-
lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1"
|
|
629
|
-
removeInEdge: true
|
|
630
|
-
});
|
|
984
|
+
lambda.addEnvironment("APP", config.name);
|
|
985
|
+
lambda.addEnvironment("STAGE", config.stage);
|
|
986
|
+
lambda.addEnvironment("STACK", stack.name);
|
|
987
|
+
if (props.runtime.startsWith("nodejs")) {
|
|
988
|
+
lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1");
|
|
631
989
|
}
|
|
632
|
-
assets.add({
|
|
633
|
-
stackName: stack.artifactId,
|
|
634
|
-
resource: "function",
|
|
635
|
-
resourceName: id,
|
|
636
|
-
async build() {
|
|
637
|
-
const result = await rollupBuild(props.file);
|
|
638
|
-
const bundle = await writeBuildFiles(config, stack, id, result.files);
|
|
639
|
-
await writeBuildHash(config, stack, id, result.hash);
|
|
640
|
-
const func = lambda.node.defaultChild;
|
|
641
|
-
func.handler = result.handler;
|
|
642
|
-
return {
|
|
643
|
-
size: formatByteSize(bundle.size)
|
|
644
|
-
};
|
|
645
|
-
},
|
|
646
|
-
async publish() {
|
|
647
|
-
const version2 = await publishFunctionAsset(config, stack, id);
|
|
648
|
-
const func = lambda.node.defaultChild;
|
|
649
|
-
func.code = {
|
|
650
|
-
s3Bucket: assetBucketName(config),
|
|
651
|
-
s3Key: `${config.name}/${stack.artifactId}/function/${id}.zip`,
|
|
652
|
-
s3ObjectVersion: version2
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
});
|
|
656
990
|
return lambda;
|
|
657
991
|
};
|
|
658
992
|
|
|
993
|
+
// src/formation/resource/events/rule.ts
|
|
994
|
+
var Rule = class extends Resource {
|
|
995
|
+
constructor(logicalId, props) {
|
|
996
|
+
super("AWS::Events::Rule", logicalId);
|
|
997
|
+
this.props = props;
|
|
998
|
+
this.name = formatName(this.props.name || logicalId);
|
|
999
|
+
}
|
|
1000
|
+
name;
|
|
1001
|
+
get id() {
|
|
1002
|
+
return ref(this.logicalId);
|
|
1003
|
+
}
|
|
1004
|
+
get arn() {
|
|
1005
|
+
return getAtt(this.logicalId, "Arn");
|
|
1006
|
+
}
|
|
1007
|
+
properties() {
|
|
1008
|
+
return {
|
|
1009
|
+
Name: this.name,
|
|
1010
|
+
...this.attr("State", "ENABLED"),
|
|
1011
|
+
...this.attr("Description", this.props.description),
|
|
1012
|
+
...this.attr("ScheduleExpression", this.props.schedule),
|
|
1013
|
+
...this.attr("RoleArn", this.props.roleArn),
|
|
1014
|
+
...this.attr("EventBusName", this.props.eventBusName),
|
|
1015
|
+
...this.attr("EventPattern", this.props.eventPattern),
|
|
1016
|
+
Targets: this.props.targets.map((target) => ({
|
|
1017
|
+
Arn: target.arn,
|
|
1018
|
+
Id: target.id,
|
|
1019
|
+
...this.attr("Input", target.input && JSON.stringify(target.input))
|
|
1020
|
+
}))
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
|
|
1025
|
+
// src/formation/resource/lambda/permission.ts
|
|
1026
|
+
var Permission2 = class extends Resource {
|
|
1027
|
+
constructor(logicalId, props) {
|
|
1028
|
+
super("AWS::Lambda::Permission", logicalId);
|
|
1029
|
+
this.props = props;
|
|
1030
|
+
}
|
|
1031
|
+
properties() {
|
|
1032
|
+
return {
|
|
1033
|
+
FunctionName: this.props.functionArn,
|
|
1034
|
+
Action: this.props.action || "lambda:InvokeFunction",
|
|
1035
|
+
Principal: this.props.principal,
|
|
1036
|
+
SourceArn: this.props.sourceArn
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
// src/formation/resource/lambda/event-source/events.ts
|
|
1042
|
+
var EventsEventSource = class extends Group {
|
|
1043
|
+
constructor(id, lambda, props) {
|
|
1044
|
+
const rule = new Rule(id, {
|
|
1045
|
+
schedule: props.schedule,
|
|
1046
|
+
targets: [{
|
|
1047
|
+
id,
|
|
1048
|
+
arn: lambda.arn,
|
|
1049
|
+
input: props.payload
|
|
1050
|
+
}]
|
|
1051
|
+
});
|
|
1052
|
+
const permission = new Permission2(id, {
|
|
1053
|
+
action: "lambda:InvokeFunction",
|
|
1054
|
+
principal: "events.amazonaws.com",
|
|
1055
|
+
functionArn: lambda.arn,
|
|
1056
|
+
sourceArn: rule.arn
|
|
1057
|
+
});
|
|
1058
|
+
super([rule, permission]);
|
|
1059
|
+
}
|
|
1060
|
+
};
|
|
1061
|
+
|
|
659
1062
|
// src/plugins/cron/index.ts
|
|
660
|
-
var import_aws_events_targets = require("aws-cdk-lib/aws-events-targets");
|
|
661
1063
|
var cronPlugin = definePlugin({
|
|
662
1064
|
name: "cron",
|
|
663
|
-
schema:
|
|
664
|
-
stacks:
|
|
665
|
-
crons:
|
|
1065
|
+
schema: import_zod7.z.object({
|
|
1066
|
+
stacks: import_zod7.z.object({
|
|
1067
|
+
crons: import_zod7.z.record(ResourceIdSchema, import_zod7.z.object({
|
|
666
1068
|
consumer: FunctionSchema,
|
|
667
1069
|
schedule: ScheduleExpressionSchema,
|
|
668
|
-
|
|
1070
|
+
payload: import_zod7.z.unknown().optional()
|
|
669
1071
|
})).optional()
|
|
670
1072
|
}).array()
|
|
671
1073
|
}),
|
|
672
|
-
onStack(
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const
|
|
676
|
-
new
|
|
677
|
-
ruleName: toName(context.stack, id),
|
|
1074
|
+
onStack(ctx) {
|
|
1075
|
+
const { stack, stackConfig } = ctx;
|
|
1076
|
+
for (const [id, props] of Object.entries(stackConfig.crons || {})) {
|
|
1077
|
+
const lambda = toLambdaFunction(ctx, id, props.consumer);
|
|
1078
|
+
const source = new EventsEventSource(id, lambda, {
|
|
678
1079
|
schedule: props.schedule,
|
|
679
|
-
|
|
680
|
-
targets: [target]
|
|
1080
|
+
payload: props.payload
|
|
681
1081
|
});
|
|
682
|
-
|
|
683
|
-
}
|
|
1082
|
+
stack.add(lambda, source);
|
|
1083
|
+
}
|
|
684
1084
|
}
|
|
685
1085
|
});
|
|
686
1086
|
|
|
687
1087
|
// src/plugins/queue.ts
|
|
688
|
-
var
|
|
689
|
-
|
|
690
|
-
|
|
1088
|
+
var import_zod8 = require("zod");
|
|
1089
|
+
|
|
1090
|
+
// src/formation/resource/sqs/queue.ts
|
|
1091
|
+
var Queue = class extends Resource {
|
|
1092
|
+
constructor(logicalId, props = {}) {
|
|
1093
|
+
super("AWS::SQS::Queue", logicalId);
|
|
1094
|
+
this.props = props;
|
|
1095
|
+
this.name = formatName(this.props.name || logicalId);
|
|
1096
|
+
}
|
|
1097
|
+
name;
|
|
1098
|
+
get arn() {
|
|
1099
|
+
return getAtt(this.logicalId, "Arn");
|
|
1100
|
+
}
|
|
1101
|
+
get url() {
|
|
1102
|
+
return getAtt(this.logicalId, "QueueUrl");
|
|
1103
|
+
}
|
|
1104
|
+
get permissions() {
|
|
1105
|
+
return {
|
|
1106
|
+
actions: [
|
|
1107
|
+
"sqs:SendMessage",
|
|
1108
|
+
"sqs:ReceiveMessage",
|
|
1109
|
+
"sqs:GetQueueUrl",
|
|
1110
|
+
"sqs:GetQueueAttributes"
|
|
1111
|
+
],
|
|
1112
|
+
resources: [this.arn]
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
properties() {
|
|
1116
|
+
return {
|
|
1117
|
+
QueueName: this.name,
|
|
1118
|
+
DelaySeconds: this.props.deliveryDelay?.toSeconds() ?? 0,
|
|
1119
|
+
MaximumMessageSize: this.props.maxMessageSize?.toBytes() ?? Size.kiloBytes(256).toBytes(),
|
|
1120
|
+
MessageRetentionPeriod: this.props.retentionPeriod?.toSeconds() ?? Duration.days(4).toSeconds(),
|
|
1121
|
+
ReceiveMessageWaitTimeSeconds: this.props.receiveMessageWaitTime?.toSeconds() ?? 0,
|
|
1122
|
+
VisibilityTimeout: this.props.visibilityTimeout?.toSeconds() ?? 30
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
// src/formation/resource/lambda/event-source-mapping.ts
|
|
1128
|
+
var import_change_case3 = require("change-case");
|
|
1129
|
+
var EventSourceMapping = class extends Resource {
|
|
1130
|
+
constructor(logicalId, props) {
|
|
1131
|
+
super("AWS::Lambda::EventSourceMapping", logicalId);
|
|
1132
|
+
this.props = props;
|
|
1133
|
+
}
|
|
1134
|
+
properties() {
|
|
1135
|
+
return {
|
|
1136
|
+
Enabled: true,
|
|
1137
|
+
FunctionName: this.props.functionArn,
|
|
1138
|
+
EventSourceArn: this.props.sourceArn,
|
|
1139
|
+
...this.attr("BatchSize", this.props.batchSize),
|
|
1140
|
+
...this.attr("MaximumBatchingWindowInSeconds", this.props.maxBatchingWindow?.toSeconds()),
|
|
1141
|
+
...this.attr("MaximumRecordAgeInSeconds", this.props.maxRecordAge?.toSeconds()),
|
|
1142
|
+
...this.attr("MaximumRetryAttempts", this.props.retryAttempts),
|
|
1143
|
+
...this.attr("ParallelizationFactor", this.props.parallelizationFactor),
|
|
1144
|
+
...this.attr("TumblingWindowInSeconds", this.props.tumblingWindow?.toSeconds()),
|
|
1145
|
+
...this.attr("BisectBatchOnFunctionError", this.props.bisectBatchOnError),
|
|
1146
|
+
...this.attr("StartingPosition", this.props.startingPosition && (0, import_change_case3.constantCase)(this.props.startingPosition)),
|
|
1147
|
+
...this.attr("StartingPositionTimestamp", this.props.startingPositionTimestamp),
|
|
1148
|
+
...this.props.maxConcurrency ? {
|
|
1149
|
+
ScalingConfig: {
|
|
1150
|
+
MaximumConcurrency: this.props.maxConcurrency
|
|
1151
|
+
}
|
|
1152
|
+
} : {},
|
|
1153
|
+
...this.props.onFailure ? {
|
|
1154
|
+
DestinationConfig: {
|
|
1155
|
+
OnFailure: {
|
|
1156
|
+
Destination: this.props.onFailure
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
} : {}
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
|
|
1164
|
+
// src/formation/resource/lambda/event-source/sqs.ts
|
|
1165
|
+
var SqsEventSource = class extends Group {
|
|
1166
|
+
constructor(id, lambda, props) {
|
|
1167
|
+
const source = new EventSourceMapping(id, {
|
|
1168
|
+
functionArn: lambda.arn,
|
|
1169
|
+
sourceArn: props.queueArn,
|
|
1170
|
+
batchSize: props.batchSize ?? 10,
|
|
1171
|
+
maxBatchingWindow: props.maxBatchingWindow,
|
|
1172
|
+
maxConcurrency: props.maxConcurrency,
|
|
1173
|
+
onFailure: props.onFailure
|
|
1174
|
+
});
|
|
1175
|
+
lambda.addPermissions({
|
|
1176
|
+
actions: [
|
|
1177
|
+
"sqs:ReceiveMessage",
|
|
1178
|
+
"sqs:DeleteMessage",
|
|
1179
|
+
"sqs:GetQueueAttributes"
|
|
1180
|
+
],
|
|
1181
|
+
resources: [props.queueArn]
|
|
1182
|
+
});
|
|
1183
|
+
super([source]);
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
|
|
1187
|
+
// src/plugins/queue.ts
|
|
691
1188
|
var queuePlugin = definePlugin({
|
|
692
1189
|
name: "queue",
|
|
693
|
-
schema:
|
|
694
|
-
defaults:
|
|
695
|
-
queue
|
|
696
|
-
|
|
1190
|
+
schema: import_zod8.z.object({
|
|
1191
|
+
defaults: import_zod8.z.object({
|
|
1192
|
+
/** Define the defaults properties for all queue's in your app */
|
|
1193
|
+
queue: import_zod8.z.object({
|
|
1194
|
+
/** The number of seconds that Amazon SQS retains a message.
|
|
1195
|
+
* You can specify a duration value from 1 minute to 14 days.
|
|
1196
|
+
* @default '7 days' */
|
|
697
1197
|
retentionPeriod: DurationSchema.default("7 days"),
|
|
1198
|
+
/** The length of time during which a message will be unavailable after a message is delivered from the queue.
|
|
1199
|
+
* This blocks other components from receiving the same message and gives the initial component time to process and delete the message from the queue.
|
|
1200
|
+
* You can specify a duration value from 0 to 12 hours.
|
|
1201
|
+
* @default '30 seconds' */
|
|
698
1202
|
visibilityTimeout: DurationSchema.default("30 seconds"),
|
|
1203
|
+
/** The time in seconds for which the delivery of all messages in the queue is delayed.
|
|
1204
|
+
* You can specify a duration value from 0 to 15 minutes.
|
|
1205
|
+
* @default '0 seconds' */
|
|
699
1206
|
deliveryDelay: DurationSchema.default("0 seconds"),
|
|
1207
|
+
/** Specifies the duration, in seconds,
|
|
1208
|
+
* that the ReceiveMessage action call waits until a message is in the queue in order to include it in the response,
|
|
1209
|
+
* rather than returning an empty response if a message isn't yet available.
|
|
1210
|
+
* You can specify an integer from 1 to 20.
|
|
1211
|
+
* You can specify a duration value from 1 to 20 seconds.
|
|
1212
|
+
* @default '0 seconds' */
|
|
700
1213
|
receiveMessageWaitTime: DurationSchema.default("0 seconds"),
|
|
1214
|
+
/** The limit of how many bytes that a message can contain before Amazon SQS rejects it.
|
|
1215
|
+
* You can specify an size value from 1 KB to 256 KB.
|
|
1216
|
+
* @default '256 KB' */
|
|
701
1217
|
maxMessageSize: SizeSchema.default("256 KB")
|
|
702
1218
|
}).default({})
|
|
703
1219
|
}).default({}),
|
|
704
|
-
stacks:
|
|
705
|
-
queues
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1220
|
+
stacks: import_zod8.z.object({
|
|
1221
|
+
/** Define the queues in your stack
|
|
1222
|
+
* @example
|
|
1223
|
+
* {
|
|
1224
|
+
* queues: {
|
|
1225
|
+
* QUEUE_NAME: 'function.ts'
|
|
1226
|
+
* }
|
|
1227
|
+
* }
|
|
1228
|
+
* */
|
|
1229
|
+
queues: import_zod8.z.record(
|
|
1230
|
+
ResourceIdSchema,
|
|
1231
|
+
import_zod8.z.union([
|
|
1232
|
+
LocalFileSchema,
|
|
1233
|
+
import_zod8.z.object({
|
|
1234
|
+
/** The consuming lambda function properties */
|
|
1235
|
+
consumer: FunctionSchema,
|
|
1236
|
+
/** The number of seconds that Amazon SQS retains a message.
|
|
1237
|
+
* You can specify a duration value from 1 minute to 14 days.
|
|
1238
|
+
* @default '7 days' */
|
|
1239
|
+
retentionPeriod: DurationSchema.optional(),
|
|
1240
|
+
/** The length of time during which a message will be unavailable after a message is delivered from the queue.
|
|
1241
|
+
* This blocks other components from receiving the same message and gives the initial component time to process and delete the message from the queue.
|
|
1242
|
+
* You can specify a duration value from 0 to 12 hours.
|
|
1243
|
+
* @default '30 seconds' */
|
|
1244
|
+
visibilityTimeout: DurationSchema.optional(),
|
|
1245
|
+
/** The time in seconds for which the delivery of all messages in the queue is delayed.
|
|
1246
|
+
* You can specify a duration value from 0 to 15 minutes.
|
|
1247
|
+
* @default '0 seconds' */
|
|
1248
|
+
deliveryDelay: DurationSchema.optional(),
|
|
1249
|
+
/** Specifies the duration, in seconds,
|
|
1250
|
+
* that the ReceiveMessage action call waits until a message is in the queue in order to include it in the response,
|
|
1251
|
+
* rather than returning an empty response if a message isn't yet available.
|
|
1252
|
+
* You can specify an integer from 1 to 20.
|
|
1253
|
+
* You can specify a duration value from 1 to 20 seconds.
|
|
1254
|
+
* @default '0 seconds' */
|
|
1255
|
+
receiveMessageWaitTime: DurationSchema.optional(),
|
|
1256
|
+
/** The limit of how many bytes that a message can contain before Amazon SQS rejects it.
|
|
1257
|
+
* You can specify an size value from 1 KB to 256 KB.
|
|
1258
|
+
* @default '256 KB' */
|
|
1259
|
+
maxMessageSize: SizeSchema.optional()
|
|
1260
|
+
})
|
|
1261
|
+
])
|
|
1262
|
+
).optional()
|
|
717
1263
|
}).array()
|
|
718
1264
|
}),
|
|
719
1265
|
onStack(ctx) {
|
|
720
1266
|
const { stack, config, stackConfig, bind } = ctx;
|
|
721
|
-
|
|
1267
|
+
for (const [id, functionOrProps] of Object.entries(stackConfig.queues || {})) {
|
|
722
1268
|
const props = typeof functionOrProps === "string" ? { ...config.defaults.queue, consumer: functionOrProps } : { ...config.defaults.queue, ...functionOrProps };
|
|
723
|
-
const queue2 = new
|
|
724
|
-
|
|
725
|
-
...props
|
|
726
|
-
|
|
1269
|
+
const queue2 = new Queue(id, {
|
|
1270
|
+
name: `${config.name}-${stack.name}-${id}`,
|
|
1271
|
+
...props
|
|
1272
|
+
});
|
|
1273
|
+
const lambda = toLambdaFunction(ctx, id, props.consumer);
|
|
1274
|
+
const source = new SqsEventSource(id, lambda, {
|
|
1275
|
+
queueArn: queue2.arn
|
|
727
1276
|
});
|
|
728
|
-
|
|
729
|
-
lambda.addEventSource(new import_aws_lambda_event_sources.SqsEventSource(queue2));
|
|
1277
|
+
stack.add(queue2, lambda, source);
|
|
730
1278
|
bind((lambda2) => {
|
|
731
|
-
queue2.
|
|
732
|
-
addResourceEnvironment(stack, "queue", id, lambda2);
|
|
1279
|
+
lambda2.addPermissions(queue2.permissions);
|
|
733
1280
|
});
|
|
734
|
-
|
|
735
|
-
});
|
|
1281
|
+
}
|
|
736
1282
|
}
|
|
737
1283
|
});
|
|
738
1284
|
|
|
739
|
-
// src/plugins/table
|
|
740
|
-
var
|
|
741
|
-
var import_aws_dynamodb4 = require("aws-cdk-lib/aws-dynamodb");
|
|
742
|
-
|
|
743
|
-
// src/plugins/table/schema/class-type.ts
|
|
744
|
-
var import_aws_dynamodb = require("aws-cdk-lib/aws-dynamodb");
|
|
745
|
-
var import_zod12 = require("zod");
|
|
746
|
-
var types = {
|
|
747
|
-
"standard": import_aws_dynamodb.TableClass.STANDARD,
|
|
748
|
-
"standard-infrequent-access": import_aws_dynamodb.TableClass.STANDARD_INFREQUENT_ACCESS
|
|
749
|
-
};
|
|
750
|
-
var TableClassSchema = import_zod12.z.enum(Object.keys(types)).transform((value) => {
|
|
751
|
-
return types[value];
|
|
752
|
-
});
|
|
1285
|
+
// src/plugins/table.ts
|
|
1286
|
+
var import_zod9 = require("zod");
|
|
753
1287
|
|
|
754
|
-
// src/
|
|
755
|
-
var
|
|
756
|
-
var
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1288
|
+
// src/formation/resource/dynamodb/table.ts
|
|
1289
|
+
var import_change_case4 = require("change-case");
|
|
1290
|
+
var Table = class extends Resource {
|
|
1291
|
+
constructor(logicalId, props) {
|
|
1292
|
+
super("AWS::DynamoDB::Table", logicalId);
|
|
1293
|
+
this.props = props;
|
|
1294
|
+
this.name = formatName(this.props.name || logicalId);
|
|
1295
|
+
this.indexes = { ...this.props.indexes || {} };
|
|
1296
|
+
}
|
|
1297
|
+
name;
|
|
1298
|
+
indexes;
|
|
1299
|
+
addIndex(name, props) {
|
|
1300
|
+
this.indexes[name] = props;
|
|
1301
|
+
}
|
|
1302
|
+
get arn() {
|
|
1303
|
+
return ref(this.logicalId);
|
|
1304
|
+
}
|
|
1305
|
+
get permissions() {
|
|
1306
|
+
return {
|
|
1307
|
+
actions: [
|
|
1308
|
+
"dynamodb:DescribeTable",
|
|
1309
|
+
"dynamodb:PutItem",
|
|
1310
|
+
"dynamodb:GetItem",
|
|
1311
|
+
"dynamodb:DeleteItem",
|
|
1312
|
+
"dynamodb:TransactWrite",
|
|
1313
|
+
"dynamodb:BatchWriteItem",
|
|
1314
|
+
"dynamodb:BatchGetItem",
|
|
1315
|
+
"dynamodb:ConditionCheckItem",
|
|
1316
|
+
"dynamodb:Query",
|
|
1317
|
+
"dynamodb:Scan"
|
|
1318
|
+
],
|
|
1319
|
+
resources: [this.arn]
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
properties() {
|
|
1323
|
+
return {
|
|
1324
|
+
TableName: this.name,
|
|
1325
|
+
BillingMode: "PAY_PER_REQUEST",
|
|
1326
|
+
TableClass: (0, import_change_case4.constantCase)(this.props.class || "standard"),
|
|
1327
|
+
PointInTimeRecoverySpecification: {
|
|
1328
|
+
PointInTimeRecoveryEnabled: this.props.pointInTimeRecovery || false
|
|
1329
|
+
},
|
|
1330
|
+
KeySchema: [
|
|
1331
|
+
{ KeyType: "HASH", AttributeName: this.props.hash },
|
|
1332
|
+
...this.props.sort ? [{ KeyType: "RANGE", AttributeName: this.props.sort }] : []
|
|
1333
|
+
],
|
|
1334
|
+
AttributeDefinitions: Object.entries(this.props.fields).map(([name, type]) => ({
|
|
1335
|
+
AttributeName: name,
|
|
1336
|
+
AttributeType: type[0].toUpperCase()
|
|
1337
|
+
})),
|
|
1338
|
+
...this.props.timeToLiveAttribute ? {
|
|
1339
|
+
TimeToLiveSpecification: {
|
|
1340
|
+
AttributeName: this.props.timeToLiveAttribute,
|
|
1341
|
+
Enabled: true
|
|
1342
|
+
}
|
|
1343
|
+
} : {},
|
|
1344
|
+
...Object.keys(this.indexes).length ? {
|
|
1345
|
+
GlobalSecondaryIndexes: Object.entries(this.indexes).map(([name, props]) => ({
|
|
1346
|
+
IndexName: name,
|
|
1347
|
+
KeySchema: [
|
|
1348
|
+
{ KeyType: "HASH", AttributeName: props.hash },
|
|
1349
|
+
...props.sort ? [{ KeyType: "RANGE", AttributeName: props.sort }] : []
|
|
1350
|
+
],
|
|
1351
|
+
Projection: {
|
|
1352
|
+
ProjectionType: (0, import_change_case4.constantCase)(props.projection || "all")
|
|
1353
|
+
}
|
|
1354
|
+
}))
|
|
1355
|
+
} : {}
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
761
1358
|
};
|
|
762
|
-
var AttributeSchema = import_zod13.z.enum(Object.keys(types2)).transform((value) => types2[value]);
|
|
763
|
-
|
|
764
|
-
// src/plugins/table/schema/key.ts
|
|
765
|
-
var import_zod14 = require("zod");
|
|
766
|
-
var KeySchema = import_zod14.z.string().min(1).max(255);
|
|
767
|
-
|
|
768
|
-
// src/plugins/table/schema/projection-type.ts
|
|
769
|
-
var import_aws_dynamodb3 = require("aws-cdk-lib/aws-dynamodb");
|
|
770
|
-
var import_zod15 = require("zod");
|
|
771
|
-
var types3 = {
|
|
772
|
-
"all": import_aws_dynamodb3.ProjectionType.ALL,
|
|
773
|
-
"keys-only": import_aws_dynamodb3.ProjectionType.KEYS_ONLY
|
|
774
|
-
};
|
|
775
|
-
var ProjectionTypeSchema = import_zod15.z.union([
|
|
776
|
-
import_zod15.z.enum(Object.keys(types3)).transform((value) => ({
|
|
777
|
-
ProjectionType: types3[value]
|
|
778
|
-
})),
|
|
779
|
-
import_zod15.z.array(KeySchema).min(0).max(20).transform((keys) => ({
|
|
780
|
-
ProjectionType: import_aws_dynamodb3.ProjectionType.INCLUDE,
|
|
781
|
-
NonKeyAttributes: keys
|
|
782
|
-
}))
|
|
783
|
-
]);
|
|
784
1359
|
|
|
785
|
-
// src/plugins/table
|
|
1360
|
+
// src/plugins/table.ts
|
|
1361
|
+
var KeySchema = import_zod9.z.string().min(1).max(255);
|
|
786
1362
|
var tablePlugin = definePlugin({
|
|
787
1363
|
name: "table",
|
|
788
|
-
schema:
|
|
789
|
-
stacks:
|
|
790
|
-
tables
|
|
1364
|
+
schema: import_zod9.z.object({
|
|
1365
|
+
stacks: import_zod9.z.object({
|
|
1366
|
+
/** Define the tables in your stack
|
|
1367
|
+
* @example
|
|
1368
|
+
* {
|
|
1369
|
+
* tables: {
|
|
1370
|
+
* TABLE_NAME: {
|
|
1371
|
+
* hash: 'id',
|
|
1372
|
+
* fields: {
|
|
1373
|
+
* id: 'number'
|
|
1374
|
+
* }
|
|
1375
|
+
* }
|
|
1376
|
+
* }
|
|
1377
|
+
* }
|
|
1378
|
+
* */
|
|
1379
|
+
tables: import_zod9.z.record(
|
|
791
1380
|
ResourceIdSchema,
|
|
792
|
-
|
|
1381
|
+
import_zod9.z.object({
|
|
1382
|
+
/** Specifies the name of the partition / hash key that makes up the primary key for the table. */
|
|
793
1383
|
hash: KeySchema,
|
|
1384
|
+
/** Specifies the name of the range / sort key that makes up the primary key for the table. */
|
|
794
1385
|
sort: KeySchema.optional(),
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
1386
|
+
/** A list of attributes that describe the key schema for the table and indexes.
|
|
1387
|
+
* @example
|
|
1388
|
+
* {
|
|
1389
|
+
* fields: {
|
|
1390
|
+
* id: 'string'
|
|
1391
|
+
* }
|
|
1392
|
+
* }
|
|
1393
|
+
*/
|
|
1394
|
+
fields: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.enum(["string", "number", "binary"])),
|
|
1395
|
+
/** The table class of the table.
|
|
1396
|
+
* @default 'standard'
|
|
1397
|
+
*/
|
|
1398
|
+
class: import_zod9.z.enum(["standard", "standard-infrequent-access"]).default("standard"),
|
|
1399
|
+
/** Indicates whether point in time recovery is enabled on the table.
|
|
1400
|
+
* @default false
|
|
1401
|
+
*/
|
|
1402
|
+
pointInTimeRecovery: import_zod9.z.boolean().default(false),
|
|
1403
|
+
/** The name of the TTL attribute used to store the expiration time for items in the table.
|
|
1404
|
+
* - To update this property, you must first disable TTL and then enable TTL with the new attribute name.
|
|
1405
|
+
*/
|
|
1406
|
+
timeToLiveAttribute: KeySchema.optional(),
|
|
1407
|
+
/** Specifies the global secondary indexes to be created on the table.
|
|
1408
|
+
* @example
|
|
1409
|
+
* {
|
|
1410
|
+
* indexes: {
|
|
1411
|
+
* INDEX_NAME: {
|
|
1412
|
+
* hash: 'other'
|
|
1413
|
+
* }
|
|
1414
|
+
* }
|
|
1415
|
+
* }
|
|
1416
|
+
*/
|
|
1417
|
+
indexes: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.object({
|
|
1418
|
+
/** Specifies the name of the partition / hash key that makes up the primary key for the global secondary index. */
|
|
800
1419
|
hash: KeySchema,
|
|
1420
|
+
/** Specifies the name of the range / sort key that makes up the primary key for the global secondary index. */
|
|
801
1421
|
sort: KeySchema.optional(),
|
|
802
|
-
|
|
1422
|
+
/** The set of attributes that are projected into the index:
|
|
1423
|
+
* - all - All of the table attributes are projected into the index.
|
|
1424
|
+
* - keys-only - Only the index and primary keys are projected into the index.
|
|
1425
|
+
* @default 'all'
|
|
1426
|
+
*/
|
|
1427
|
+
projection: import_zod9.z.enum(["all", "keys-only"]).default("all")
|
|
803
1428
|
})).optional()
|
|
804
1429
|
}).refine((props) => {
|
|
805
1430
|
return (
|
|
@@ -816,140 +1441,321 @@ var tablePlugin = definePlugin({
|
|
|
816
1441
|
).optional()
|
|
817
1442
|
}).array()
|
|
818
1443
|
}),
|
|
819
|
-
onStack({ stack, stackConfig, bind }) {
|
|
820
|
-
Object.entries(stackConfig.tables || {})
|
|
821
|
-
const
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const table = new import_aws_dynamodb4.Table(stack, toId("table", id), {
|
|
825
|
-
tableName: toName(stack, id),
|
|
826
|
-
partitionKey: buildKey(props.hash),
|
|
827
|
-
sortKey: props.sort ? buildKey(props.sort) : void 0,
|
|
828
|
-
billingMode: import_aws_dynamodb4.BillingMode.PAY_PER_REQUEST,
|
|
829
|
-
pointInTimeRecovery: props.pointInTimeRecovery,
|
|
830
|
-
timeToLiveAttribute: props.timeToLiveAttribute,
|
|
831
|
-
tableClass: props.class
|
|
832
|
-
});
|
|
833
|
-
Object.entries(props.indexes || {}).forEach(([indexName, entry]) => {
|
|
834
|
-
table.addGlobalSecondaryIndex({
|
|
835
|
-
indexName,
|
|
836
|
-
partitionKey: buildKey(entry.hash),
|
|
837
|
-
sortKey: entry.sort ? buildKey(entry.sort) : void 0,
|
|
838
|
-
...entry.projection
|
|
839
|
-
});
|
|
1444
|
+
onStack({ config, stack, stackConfig, bind }) {
|
|
1445
|
+
for (const [id, props] of Object.entries(stackConfig.tables || {})) {
|
|
1446
|
+
const table = new Table(id, {
|
|
1447
|
+
name: `${config.name}-${stack.name}-${id}`,
|
|
1448
|
+
...props
|
|
840
1449
|
});
|
|
1450
|
+
stack.add(table);
|
|
841
1451
|
bind((lambda) => {
|
|
842
|
-
table.
|
|
843
|
-
addResourceEnvironment(stack, "table", id, lambda);
|
|
1452
|
+
lambda.addPermissions(table.permissions);
|
|
844
1453
|
});
|
|
845
|
-
}
|
|
1454
|
+
}
|
|
846
1455
|
}
|
|
847
1456
|
});
|
|
848
1457
|
|
|
849
1458
|
// src/plugins/store.ts
|
|
850
|
-
var
|
|
851
|
-
|
|
852
|
-
|
|
1459
|
+
var import_zod10 = require("zod");
|
|
1460
|
+
|
|
1461
|
+
// src/formation/resource/s3/bucket.ts
|
|
1462
|
+
var import_change_case5 = require("change-case");
|
|
1463
|
+
var Bucket = class extends Resource {
|
|
1464
|
+
constructor(logicalId, props = {}) {
|
|
1465
|
+
super("AWS::S3::Bucket", logicalId);
|
|
1466
|
+
this.props = props;
|
|
1467
|
+
this.name = formatName(this.props.name || logicalId);
|
|
1468
|
+
}
|
|
1469
|
+
name;
|
|
1470
|
+
get arn() {
|
|
1471
|
+
return ref(this.logicalId);
|
|
1472
|
+
}
|
|
1473
|
+
get domainName() {
|
|
1474
|
+
return getAtt(this.logicalId, "DomainName");
|
|
1475
|
+
}
|
|
1476
|
+
get permissions() {
|
|
1477
|
+
return {
|
|
1478
|
+
actions: [
|
|
1479
|
+
"s3:SendMessage",
|
|
1480
|
+
"s3:ReceiveMessage",
|
|
1481
|
+
"s3:GetQueueUrl",
|
|
1482
|
+
"s3:GetQueueAttributes"
|
|
1483
|
+
],
|
|
1484
|
+
resources: [this.arn]
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
properties() {
|
|
1488
|
+
return {
|
|
1489
|
+
BucketName: this.name,
|
|
1490
|
+
AccessControl: (0, import_change_case5.pascalCase)(this.props.accessControl ?? "private"),
|
|
1491
|
+
...this.props.versioned ? {
|
|
1492
|
+
VersioningConfiguration: {
|
|
1493
|
+
Status: "Enabled"
|
|
1494
|
+
}
|
|
1495
|
+
} : {}
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
|
|
1500
|
+
// src/plugins/store.ts
|
|
853
1501
|
var storePlugin = definePlugin({
|
|
854
1502
|
name: "store",
|
|
855
|
-
schema:
|
|
856
|
-
stacks:
|
|
857
|
-
stores
|
|
1503
|
+
schema: import_zod10.z.object({
|
|
1504
|
+
stacks: import_zod10.z.object({
|
|
1505
|
+
/** Define the stores in your stack
|
|
1506
|
+
* @example
|
|
1507
|
+
* {
|
|
1508
|
+
* stores: [ 'STORE_NAME' ]
|
|
1509
|
+
* }
|
|
1510
|
+
* */
|
|
1511
|
+
stores: import_zod10.z.array(ResourceIdSchema).optional()
|
|
858
1512
|
}).array()
|
|
859
1513
|
}),
|
|
860
|
-
onStack({ stack, stackConfig, bind }) {
|
|
861
|
-
(stackConfig.stores || [])
|
|
862
|
-
const bucket = new
|
|
863
|
-
|
|
864
|
-
accessControl:
|
|
865
|
-
removalPolicy: import_aws_cdk_lib3.RemovalPolicy.DESTROY
|
|
1514
|
+
onStack({ config, stack, stackConfig, bind }) {
|
|
1515
|
+
for (const id of stackConfig.stores || []) {
|
|
1516
|
+
const bucket = new Bucket(id, {
|
|
1517
|
+
name: `${config.name}-${stack.name}-${id}`,
|
|
1518
|
+
accessControl: "private"
|
|
866
1519
|
});
|
|
1520
|
+
stack.add(bucket);
|
|
867
1521
|
bind((lambda) => {
|
|
868
|
-
bucket.
|
|
1522
|
+
lambda.addPermissions(bucket.permissions);
|
|
869
1523
|
});
|
|
870
|
-
}
|
|
1524
|
+
}
|
|
871
1525
|
}
|
|
872
1526
|
});
|
|
873
1527
|
|
|
874
1528
|
// src/plugins/topic.ts
|
|
875
|
-
var
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
var
|
|
1529
|
+
var import_zod11 = require("zod");
|
|
1530
|
+
|
|
1531
|
+
// src/formation/resource/sns/topic.ts
|
|
1532
|
+
var Topic = class extends Resource {
|
|
1533
|
+
constructor(logicalId, props = {}) {
|
|
1534
|
+
super("AWS::SNS::Topic", logicalId);
|
|
1535
|
+
this.props = props;
|
|
1536
|
+
this.name = formatName(this.props.name || logicalId);
|
|
1537
|
+
}
|
|
1538
|
+
name;
|
|
1539
|
+
get arn() {
|
|
1540
|
+
return ref(this.logicalId);
|
|
1541
|
+
}
|
|
1542
|
+
get permissions() {
|
|
1543
|
+
return {
|
|
1544
|
+
actions: ["sns:Publish"],
|
|
1545
|
+
resources: [this.arn]
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
properties() {
|
|
1549
|
+
return {
|
|
1550
|
+
TopicName: this.name,
|
|
1551
|
+
DisplayName: this.name
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
};
|
|
1555
|
+
|
|
1556
|
+
// src/formation/resource/sns/subscription.ts
|
|
1557
|
+
var Subscription = class extends Resource {
|
|
1558
|
+
constructor(logicalId, props) {
|
|
1559
|
+
super("AWS::SNS::Subscription", logicalId);
|
|
1560
|
+
this.props = props;
|
|
1561
|
+
}
|
|
1562
|
+
properties() {
|
|
1563
|
+
return {
|
|
1564
|
+
TopicArn: this.props.topicArn,
|
|
1565
|
+
Protocol: this.props.protocol,
|
|
1566
|
+
Endpoint: this.props.endpoint
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
};
|
|
1570
|
+
|
|
1571
|
+
// src/formation/resource/lambda/event-source/sns.ts
|
|
1572
|
+
var SnsEventSource = class extends Group {
|
|
1573
|
+
constructor(id, lambda, props) {
|
|
1574
|
+
const topic = new Subscription(id, {
|
|
1575
|
+
topicArn: props.topicArn,
|
|
1576
|
+
protocol: "lambda",
|
|
1577
|
+
endpoint: lambda.arn
|
|
1578
|
+
});
|
|
1579
|
+
const permission = new Permission2(id, {
|
|
1580
|
+
action: "lambda:InvokeFunction",
|
|
1581
|
+
principal: "sns.amazonaws.com",
|
|
1582
|
+
functionArn: lambda.arn,
|
|
1583
|
+
sourceArn: props.topicArn
|
|
1584
|
+
});
|
|
1585
|
+
super([topic, permission]);
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1588
|
+
|
|
1589
|
+
// src/plugins/topic.ts
|
|
879
1590
|
var topicPlugin = definePlugin({
|
|
880
1591
|
name: "topic",
|
|
881
|
-
schema:
|
|
882
|
-
stacks:
|
|
883
|
-
topics
|
|
1592
|
+
schema: import_zod11.z.object({
|
|
1593
|
+
stacks: import_zod11.z.object({
|
|
1594
|
+
/** Define the topics to listen too in your stack
|
|
1595
|
+
* @example
|
|
1596
|
+
* {
|
|
1597
|
+
* topics: {
|
|
1598
|
+
* TOPIC_NAME: 'function.ts'
|
|
1599
|
+
* }
|
|
1600
|
+
* }
|
|
1601
|
+
* */
|
|
1602
|
+
topics: import_zod11.z.record(ResourceIdSchema, FunctionSchema).optional()
|
|
884
1603
|
}).array()
|
|
885
1604
|
}),
|
|
886
|
-
|
|
887
|
-
const allTopicNames = config.stacks.map((
|
|
888
|
-
return Object.keys(
|
|
1605
|
+
onApp({ config, bootstrap: bootstrap2, bind }) {
|
|
1606
|
+
const allTopicNames = config.stacks.map((stack) => {
|
|
1607
|
+
return Object.keys(stack.topics || {});
|
|
889
1608
|
}).flat();
|
|
890
1609
|
const uniqueTopicNames = [...new Set(allTopicNames)];
|
|
891
|
-
|
|
892
|
-
new
|
|
893
|
-
|
|
894
|
-
|
|
1610
|
+
for (const id of uniqueTopicNames) {
|
|
1611
|
+
const topic = new Topic(id, {
|
|
1612
|
+
name: `${config.name}-${id}`
|
|
1613
|
+
});
|
|
1614
|
+
bootstrap2.add(topic);
|
|
1615
|
+
bootstrap2.export(`topic-${id}-arn`, topic.arn);
|
|
1616
|
+
}
|
|
1617
|
+
bind((lambda) => {
|
|
1618
|
+
lambda.addPermissions({
|
|
1619
|
+
actions: ["sns:Publish"],
|
|
1620
|
+
resources: [
|
|
1621
|
+
sub("arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:${app}-*", {
|
|
1622
|
+
app: config.name
|
|
1623
|
+
})
|
|
1624
|
+
]
|
|
895
1625
|
});
|
|
896
1626
|
});
|
|
897
1627
|
},
|
|
898
1628
|
onStack(ctx) {
|
|
899
|
-
const {
|
|
900
|
-
|
|
901
|
-
const lambda =
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
toId("topic", id),
|
|
905
|
-
import_aws_cdk_lib4.Arn.format({
|
|
906
|
-
arnFormat: import_aws_cdk_lib4.ArnFormat.NO_RESOURCE_NAME,
|
|
907
|
-
service: "sns",
|
|
908
|
-
resource: `${config.name}-${id}`
|
|
909
|
-
}, stack)
|
|
910
|
-
);
|
|
911
|
-
lambda.addEventSource(new import_aws_lambda_event_sources2.SnsEventSource(topic));
|
|
912
|
-
bind((lambda2) => {
|
|
913
|
-
addResourceEnvironment(stack, "topic", id, lambda2);
|
|
914
|
-
topic.grantPublish(lambda2);
|
|
1629
|
+
const { stack, stackConfig, bootstrap: bootstrap2 } = ctx;
|
|
1630
|
+
for (const [id, props] of Object.entries(stackConfig.topics || {})) {
|
|
1631
|
+
const lambda = toLambdaFunction(ctx, id, props);
|
|
1632
|
+
const source = new SnsEventSource(id, lambda, {
|
|
1633
|
+
topicArn: bootstrap2.import(`topic-${id}-arn`)
|
|
915
1634
|
});
|
|
916
|
-
|
|
917
|
-
}
|
|
1635
|
+
stack.add(lambda, source);
|
|
1636
|
+
}
|
|
918
1637
|
}
|
|
919
1638
|
});
|
|
920
1639
|
|
|
921
|
-
// src/plugins/
|
|
922
|
-
var
|
|
923
|
-
var
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
stacks:
|
|
929
|
-
|
|
1640
|
+
// src/plugins/extend.ts
|
|
1641
|
+
var import_zod12 = require("zod");
|
|
1642
|
+
var extendPlugin = definePlugin({
|
|
1643
|
+
name: "extend",
|
|
1644
|
+
schema: import_zod12.z.object({
|
|
1645
|
+
/** Extend your app with custom resources */
|
|
1646
|
+
extend: import_zod12.z.custom().optional(),
|
|
1647
|
+
stacks: import_zod12.z.object({
|
|
1648
|
+
/** Extend your stack with custom resources */
|
|
1649
|
+
extend: import_zod12.z.custom().optional()
|
|
930
1650
|
}).array()
|
|
931
1651
|
}),
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1652
|
+
onApp(ctx) {
|
|
1653
|
+
ctx.config.extend?.(ctx);
|
|
1654
|
+
},
|
|
1655
|
+
onStack(ctx) {
|
|
1656
|
+
ctx.stackConfig.extend?.(ctx);
|
|
1657
|
+
}
|
|
1658
|
+
});
|
|
1659
|
+
|
|
1660
|
+
// src/plugins/pubsub.ts
|
|
1661
|
+
var import_zod13 = require("zod");
|
|
1662
|
+
|
|
1663
|
+
// src/formation/resource/iot/topic-rule.ts
|
|
1664
|
+
var import_change_case6 = require("change-case");
|
|
1665
|
+
var TopicRule = class extends Resource {
|
|
1666
|
+
constructor(logicalId, props) {
|
|
1667
|
+
super("AWS::IoT::TopicRule", logicalId);
|
|
1668
|
+
this.props = props;
|
|
1669
|
+
this.name = (0, import_change_case6.snakeCase)(this.props.name || logicalId);
|
|
1670
|
+
}
|
|
1671
|
+
name;
|
|
1672
|
+
get arn() {
|
|
1673
|
+
return getAtt(this.logicalId, "Arn");
|
|
1674
|
+
}
|
|
1675
|
+
properties() {
|
|
1676
|
+
return {
|
|
1677
|
+
RuleName: this.name,
|
|
1678
|
+
TopicRulePayload: {
|
|
1679
|
+
Sql: this.props.sql,
|
|
1680
|
+
AwsIotSqlVersion: this.props.sqlVersion ?? "2016-03-23",
|
|
1681
|
+
RuleDisabled: false,
|
|
1682
|
+
Actions: this.props.actions.map((action) => ({
|
|
1683
|
+
Lambda: { FunctionArn: action.lambda.functionArn }
|
|
1684
|
+
}))
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1690
|
+
// src/formation/resource/lambda/event-source/iot.ts
|
|
1691
|
+
var IotEventSource = class extends Group {
|
|
1692
|
+
constructor(id, lambda, props) {
|
|
1693
|
+
const topic = new TopicRule(id, {
|
|
1694
|
+
name: props.name,
|
|
1695
|
+
sql: props.sql,
|
|
1696
|
+
sqlVersion: props.sqlVersion,
|
|
1697
|
+
actions: [{ lambda: { functionArn: lambda.arn } }]
|
|
1698
|
+
});
|
|
1699
|
+
const permission = new Permission2(id, {
|
|
1700
|
+
action: "lambda:InvokeFunction",
|
|
1701
|
+
principal: "iot.amazonaws.com",
|
|
1702
|
+
functionArn: lambda.arn,
|
|
1703
|
+
sourceArn: topic.arn
|
|
1704
|
+
});
|
|
1705
|
+
super([topic, permission]);
|
|
1706
|
+
}
|
|
1707
|
+
};
|
|
1708
|
+
|
|
1709
|
+
// src/plugins/pubsub.ts
|
|
1710
|
+
var pubsubPlugin = definePlugin({
|
|
1711
|
+
name: "pubsub",
|
|
1712
|
+
schema: import_zod13.z.object({
|
|
1713
|
+
stacks: import_zod13.z.object({
|
|
1714
|
+
/** Define the pubsub subscriber in your stack
|
|
1715
|
+
* @example
|
|
1716
|
+
* {
|
|
1717
|
+
* pubsub: {
|
|
1718
|
+
* NAME: {
|
|
1719
|
+
* sql: 'SELECT * FROM "table"',
|
|
1720
|
+
* consumer: 'function.ts',
|
|
1721
|
+
* }
|
|
1722
|
+
* }
|
|
1723
|
+
* }
|
|
1724
|
+
*/
|
|
1725
|
+
pubsub: import_zod13.z.record(ResourceIdSchema, import_zod13.z.object({
|
|
1726
|
+
/** The SQL statement used to query the iot topic */
|
|
1727
|
+
sql: import_zod13.z.string(),
|
|
1728
|
+
/** The version of the SQL rules engine to use when evaluating the rule */
|
|
1729
|
+
sqlVersion: import_zod13.z.enum(["2015-10-08", "2016-03-23", "beta"]).default("2016-03-23"),
|
|
1730
|
+
/** The consuming lambda function properties */
|
|
1731
|
+
consumer: FunctionSchema
|
|
1732
|
+
})).optional()
|
|
1733
|
+
}).array()
|
|
1734
|
+
}),
|
|
1735
|
+
onApp({ bind }) {
|
|
1736
|
+
bind((lambda) => {
|
|
1737
|
+
lambda.addPermissions({
|
|
1738
|
+
actions: ["iot:publish"],
|
|
1739
|
+
resources: ["*"]
|
|
943
1740
|
});
|
|
944
1741
|
});
|
|
1742
|
+
},
|
|
1743
|
+
onStack(ctx) {
|
|
1744
|
+
const { config, stack, stackConfig } = ctx;
|
|
1745
|
+
for (const [id, props] of Object.entries(stackConfig.pubsub || {})) {
|
|
1746
|
+
const lambda = toLambdaFunction(ctx, id, props.consumer);
|
|
1747
|
+
const source = new IotEventSource(id, lambda, {
|
|
1748
|
+
name: `${config.name}-${stack.name}-${id}`,
|
|
1749
|
+
sql: props.sql,
|
|
1750
|
+
sqlVersion: props.sqlVersion
|
|
1751
|
+
});
|
|
1752
|
+
stack.add(lambda, source);
|
|
1753
|
+
}
|
|
945
1754
|
}
|
|
946
1755
|
});
|
|
947
1756
|
|
|
948
|
-
// src/plugins/graphql
|
|
949
|
-
var
|
|
950
|
-
var import_aws_appsync = require("aws-cdk-lib/aws-appsync");
|
|
951
|
-
var import_merge = require("@graphql-tools/merge");
|
|
952
|
-
var import_promises4 = require("fs/promises");
|
|
1757
|
+
// src/plugins/graphql.ts
|
|
1758
|
+
var import_zod14 = require("zod");
|
|
953
1759
|
|
|
954
1760
|
// src/util/array.ts
|
|
955
1761
|
var toArray = (value) => {
|
|
@@ -959,298 +1765,707 @@ var toArray = (value) => {
|
|
|
959
1765
|
return [value];
|
|
960
1766
|
};
|
|
961
1767
|
|
|
962
|
-
// src/plugins/graphql
|
|
963
|
-
var
|
|
1768
|
+
// src/plugins/graphql.ts
|
|
1769
|
+
var import_change_case10 = require("change-case");
|
|
1770
|
+
|
|
1771
|
+
// src/formation/resource/appsync/graphql-api.ts
|
|
1772
|
+
var import_change_case7 = require("change-case");
|
|
1773
|
+
var GraphQL = class extends Group {
|
|
1774
|
+
constructor(logicalId, props) {
|
|
1775
|
+
const api = new GraphQLApi(logicalId, props);
|
|
1776
|
+
const schema2 = new GraphQLSchema(logicalId, {
|
|
1777
|
+
apiId: api.id,
|
|
1778
|
+
definition: props.schema
|
|
1779
|
+
}).dependsOn(api);
|
|
1780
|
+
super([api, schema2]);
|
|
1781
|
+
this.logicalId = logicalId;
|
|
1782
|
+
this.api = api;
|
|
1783
|
+
this.schema = schema2;
|
|
1784
|
+
}
|
|
1785
|
+
api;
|
|
1786
|
+
schema;
|
|
1787
|
+
attachDomainName(domainName, certificateArn) {
|
|
1788
|
+
const id = this.logicalId + domainName;
|
|
1789
|
+
const domain = new DomainName(id, {
|
|
1790
|
+
domainName,
|
|
1791
|
+
certificateArn
|
|
1792
|
+
});
|
|
1793
|
+
const association = new DomainNameApiAssociation(id, {
|
|
1794
|
+
apiId: this.api.id,
|
|
1795
|
+
domainName
|
|
1796
|
+
}).dependsOn(this.api, domain);
|
|
1797
|
+
this.children.push(domain, association);
|
|
1798
|
+
return this;
|
|
1799
|
+
}
|
|
1800
|
+
};
|
|
1801
|
+
var GraphQLApi = class extends Resource {
|
|
1802
|
+
constructor(logicalId, props) {
|
|
1803
|
+
super("AWS::AppSync::GraphQLApi", logicalId);
|
|
1804
|
+
this.props = props;
|
|
1805
|
+
this.name = formatName(this.props.name || logicalId);
|
|
1806
|
+
}
|
|
1807
|
+
name;
|
|
1808
|
+
lambdaAuthProviders = [];
|
|
1809
|
+
get arn() {
|
|
1810
|
+
return ref(this.logicalId);
|
|
1811
|
+
}
|
|
1812
|
+
get id() {
|
|
1813
|
+
return getAtt(this.logicalId, "ApiId");
|
|
1814
|
+
}
|
|
1815
|
+
get url() {
|
|
1816
|
+
return getAtt(this.logicalId, "GraphQLUrl");
|
|
1817
|
+
}
|
|
1818
|
+
get dns() {
|
|
1819
|
+
return getAtt(this.logicalId, "GraphQLDns");
|
|
1820
|
+
}
|
|
1821
|
+
addLambdaAuthProvider(lambdaAuthorizerArn, resultTTL = Duration.seconds(0)) {
|
|
1822
|
+
this.lambdaAuthProviders.push({
|
|
1823
|
+
arn: lambdaAuthorizerArn,
|
|
1824
|
+
ttl: resultTTL
|
|
1825
|
+
});
|
|
1826
|
+
return this;
|
|
1827
|
+
}
|
|
1828
|
+
properties() {
|
|
1829
|
+
return {
|
|
1830
|
+
Name: this.name,
|
|
1831
|
+
AuthenticationType: (0, import_change_case7.constantCase)(this.props.authenticationType || "api-key"),
|
|
1832
|
+
AdditionalAuthenticationProviders: this.lambdaAuthProviders.map((provider) => ({
|
|
1833
|
+
AuthenticationType: "AWS_LAMBDA",
|
|
1834
|
+
LambdaAuthorizerConfig: {
|
|
1835
|
+
AuthorizerUri: provider.arn,
|
|
1836
|
+
AuthorizerResultTtlInSeconds: provider.ttl.toSeconds()
|
|
1837
|
+
}
|
|
1838
|
+
}))
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
var GraphQLSchema = class extends Resource {
|
|
1843
|
+
constructor(logicalId, props) {
|
|
1844
|
+
super("AWS::AppSync::GraphQLSchema", logicalId, [
|
|
1845
|
+
props.definition
|
|
1846
|
+
]);
|
|
1847
|
+
this.props = props;
|
|
1848
|
+
}
|
|
1849
|
+
properties() {
|
|
1850
|
+
return {
|
|
1851
|
+
ApiId: this.props.apiId,
|
|
1852
|
+
Definition: this.props.definition.toDefinition()
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
var DomainName = class extends Resource {
|
|
1857
|
+
constructor(logicalId, props) {
|
|
1858
|
+
super("AWS::AppSync::DomainName", logicalId);
|
|
1859
|
+
this.props = props;
|
|
1860
|
+
}
|
|
1861
|
+
properties() {
|
|
1862
|
+
return {
|
|
1863
|
+
DomainName: this.props.domainName,
|
|
1864
|
+
CertificateArn: this.props.certificateArn
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
var DomainNameApiAssociation = class extends Resource {
|
|
1869
|
+
constructor(logicalId, props) {
|
|
1870
|
+
super("AWS::AppSync::DomainNameApiAssociation", logicalId);
|
|
1871
|
+
this.props = props;
|
|
1872
|
+
}
|
|
1873
|
+
properties() {
|
|
1874
|
+
return {
|
|
1875
|
+
ApiId: this.props.apiId,
|
|
1876
|
+
DomainName: this.props.domainName
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
};
|
|
1880
|
+
|
|
1881
|
+
// src/formation/resource/route53/record-set.ts
|
|
1882
|
+
var RecordSet = class extends Resource {
|
|
1883
|
+
constructor(logicalId, props) {
|
|
1884
|
+
super("AWS::Route53::RecordSet", logicalId);
|
|
1885
|
+
this.props = props;
|
|
1886
|
+
this.name = this.props.name || this.logicalId;
|
|
1887
|
+
}
|
|
1888
|
+
name;
|
|
1889
|
+
properties() {
|
|
1890
|
+
return {
|
|
1891
|
+
HostedZoneId: this.props.hostedZoneId,
|
|
1892
|
+
Name: this.name + ".",
|
|
1893
|
+
Type: this.props.type,
|
|
1894
|
+
TTL: this.props.ttl,
|
|
1895
|
+
...this.props.records ? {
|
|
1896
|
+
ResourceRecords: this.props.records
|
|
1897
|
+
} : {},
|
|
1898
|
+
...this.props.alias ? {
|
|
1899
|
+
AliasTarget: {
|
|
1900
|
+
DNSName: this.props.alias,
|
|
1901
|
+
HostedZoneId: this.props.hostedZoneId
|
|
1902
|
+
}
|
|
1903
|
+
} : {}
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1906
|
+
};
|
|
1907
|
+
|
|
1908
|
+
// src/formation/resource/appsync/schema.ts
|
|
964
1909
|
var import_graphql = require("graphql");
|
|
965
|
-
var
|
|
1910
|
+
var import_promises2 = require("fs/promises");
|
|
1911
|
+
var import_merge = require("@graphql-tools/merge");
|
|
1912
|
+
var Schema = class extends Asset {
|
|
1913
|
+
constructor(id, files) {
|
|
1914
|
+
super("graphql", id);
|
|
1915
|
+
this.files = files;
|
|
1916
|
+
}
|
|
1917
|
+
schema;
|
|
1918
|
+
async build({ write }) {
|
|
1919
|
+
const files = [this.files].flat();
|
|
1920
|
+
const schemas = await Promise.all(files.map((file) => {
|
|
1921
|
+
return (0, import_promises2.readFile)(file, "utf8");
|
|
1922
|
+
}));
|
|
1923
|
+
const defs = (0, import_merge.mergeTypeDefs)(schemas);
|
|
1924
|
+
const schema2 = (0, import_graphql.print)(defs);
|
|
1925
|
+
await write("schema.gql", schema2);
|
|
1926
|
+
this.schema = schema2;
|
|
1927
|
+
}
|
|
1928
|
+
toDefinition() {
|
|
1929
|
+
return this.schema;
|
|
1930
|
+
}
|
|
1931
|
+
};
|
|
966
1932
|
|
|
967
|
-
// src/
|
|
968
|
-
var
|
|
969
|
-
var
|
|
970
|
-
|
|
971
|
-
|
|
1933
|
+
// src/formation/resource/appsync/code.ts
|
|
1934
|
+
var import_promises3 = require("fs/promises");
|
|
1935
|
+
var Code2 = class {
|
|
1936
|
+
static fromFile(id, file) {
|
|
1937
|
+
return new FileCode2(id, file);
|
|
1938
|
+
}
|
|
1939
|
+
static fromInline(id, code) {
|
|
1940
|
+
return new InlineCode2(id, code);
|
|
1941
|
+
}
|
|
1942
|
+
};
|
|
1943
|
+
var InlineCode2 = class extends Asset {
|
|
1944
|
+
constructor(id, code) {
|
|
1945
|
+
super("resolver", id);
|
|
1946
|
+
this.code = code;
|
|
1947
|
+
}
|
|
1948
|
+
toCodeJson() {
|
|
1949
|
+
return {
|
|
1950
|
+
Code: this.code
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
};
|
|
1954
|
+
var FileCode2 = class extends Asset {
|
|
1955
|
+
constructor(id, file) {
|
|
1956
|
+
super("resolver", id);
|
|
1957
|
+
this.file = file;
|
|
1958
|
+
}
|
|
1959
|
+
code;
|
|
1960
|
+
async build() {
|
|
1961
|
+
const code = await (0, import_promises3.readFile)(this.file);
|
|
1962
|
+
this.code = code.toString("utf8");
|
|
1963
|
+
return {
|
|
1964
|
+
size: formatByteSize(code.byteLength)
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1967
|
+
toCodeJson() {
|
|
1968
|
+
return {
|
|
1969
|
+
Code: this.code
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
|
|
1974
|
+
// src/formation/resource/appsync/data-source.ts
|
|
1975
|
+
var import_change_case8 = require("change-case");
|
|
1976
|
+
var DataSource = class extends Resource {
|
|
1977
|
+
constructor(logicalId, props) {
|
|
1978
|
+
super("AWS::AppSync::DataSource", logicalId);
|
|
1979
|
+
this.props = props;
|
|
1980
|
+
this.name = (0, import_change_case8.snakeCase)(this.props.name || logicalId);
|
|
1981
|
+
}
|
|
1982
|
+
static fromLambda(logicalId, apiId, props) {
|
|
1983
|
+
return new DataSource(logicalId, {
|
|
1984
|
+
apiId,
|
|
1985
|
+
type: "AWS_LAMBDA",
|
|
1986
|
+
serviceRoleArn: props.serviceRoleArn,
|
|
1987
|
+
config: {
|
|
1988
|
+
lambda: {
|
|
1989
|
+
functionArn: props.functionArn
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
static fromNone(logicalId, apiId) {
|
|
1995
|
+
return new DataSource(logicalId, {
|
|
1996
|
+
apiId,
|
|
1997
|
+
type: "NONE"
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
name;
|
|
2001
|
+
get arn() {
|
|
2002
|
+
return ref(this.logicalId);
|
|
2003
|
+
}
|
|
2004
|
+
properties() {
|
|
2005
|
+
return {
|
|
2006
|
+
ApiId: this.props.apiId,
|
|
2007
|
+
Name: this.name,
|
|
2008
|
+
Type: this.props.type,
|
|
2009
|
+
ServiceRoleArn: this.props.serviceRoleArn,
|
|
2010
|
+
...this.props.config?.lambda ? {
|
|
2011
|
+
LambdaConfig: {
|
|
2012
|
+
LambdaFunctionArn: this.props.config.lambda.functionArn
|
|
2013
|
+
}
|
|
2014
|
+
} : {}
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
|
|
2019
|
+
// src/formation/resource/appsync/function-configuration.ts
|
|
2020
|
+
var import_change_case9 = require("change-case");
|
|
2021
|
+
var FunctionConfiguration = class extends Resource {
|
|
2022
|
+
constructor(logicalId, props) {
|
|
2023
|
+
super("AWS::AppSync::FunctionConfiguration", logicalId, [
|
|
2024
|
+
props.code
|
|
2025
|
+
]);
|
|
2026
|
+
this.props = props;
|
|
2027
|
+
this.name = (0, import_change_case9.snakeCase)(this.props.name || logicalId);
|
|
2028
|
+
}
|
|
2029
|
+
name;
|
|
2030
|
+
get id() {
|
|
2031
|
+
return getAtt(this.logicalId, "FunctionId");
|
|
2032
|
+
}
|
|
2033
|
+
get arn() {
|
|
2034
|
+
return ref(this.logicalId);
|
|
2035
|
+
}
|
|
2036
|
+
properties() {
|
|
2037
|
+
return {
|
|
2038
|
+
ApiId: this.props.apiId,
|
|
2039
|
+
Name: this.name,
|
|
2040
|
+
DataSourceName: this.props.dataSourceName,
|
|
2041
|
+
...this.props.code.toCodeJson(),
|
|
2042
|
+
FunctionVersion: "2018-05-29",
|
|
2043
|
+
Runtime: {
|
|
2044
|
+
Name: "APPSYNC_JS",
|
|
2045
|
+
RuntimeVersion: "1.0.0"
|
|
2046
|
+
}
|
|
2047
|
+
};
|
|
2048
|
+
}
|
|
2049
|
+
};
|
|
2050
|
+
|
|
2051
|
+
// src/formation/resource/appsync/resolver.ts
|
|
2052
|
+
var Resolver = class extends Resource {
|
|
2053
|
+
constructor(logicalId, props) {
|
|
2054
|
+
super("AWS::AppSync::Resolver", logicalId);
|
|
2055
|
+
this.props = props;
|
|
2056
|
+
}
|
|
2057
|
+
properties() {
|
|
2058
|
+
return {
|
|
2059
|
+
ApiId: this.props.apiId,
|
|
2060
|
+
Kind: "PIPELINE",
|
|
2061
|
+
TypeName: this.props.typeName,
|
|
2062
|
+
FieldName: this.props.fieldName,
|
|
2063
|
+
PipelineConfig: {
|
|
2064
|
+
Functions: this.props.functions
|
|
2065
|
+
},
|
|
2066
|
+
// DataSourceName: this.props.dataSourceName,
|
|
2067
|
+
...this.props.code.toCodeJson(),
|
|
2068
|
+
Runtime: {
|
|
2069
|
+
Name: "APPSYNC_JS",
|
|
2070
|
+
RuntimeVersion: "1.0.0"
|
|
2071
|
+
}
|
|
2072
|
+
};
|
|
2073
|
+
}
|
|
2074
|
+
};
|
|
972
2075
|
|
|
973
|
-
// src/
|
|
974
|
-
var
|
|
2076
|
+
// src/formation/resource/lambda/event-source/appsync.ts
|
|
2077
|
+
var AppsyncEventSource = class extends Group {
|
|
2078
|
+
constructor(id, lambda, props) {
|
|
2079
|
+
const role = new Role(id + "AppSync", {
|
|
2080
|
+
assumedBy: "appsync.amazonaws.com"
|
|
2081
|
+
}).dependsOn(lambda);
|
|
2082
|
+
role.addInlinePolicy(new InlinePolicy(id, {
|
|
2083
|
+
statements: [{
|
|
2084
|
+
actions: ["lambda:InvokeFunction"],
|
|
2085
|
+
resources: [lambda.arn]
|
|
2086
|
+
}]
|
|
2087
|
+
}));
|
|
2088
|
+
const source = DataSource.fromLambda(id, props.apiId, {
|
|
2089
|
+
functionArn: lambda.arn,
|
|
2090
|
+
serviceRoleArn: role.arn
|
|
2091
|
+
}).dependsOn(role).dependsOn(lambda);
|
|
2092
|
+
const config = new FunctionConfiguration(id, {
|
|
2093
|
+
apiId: props.apiId,
|
|
2094
|
+
code: props.code,
|
|
2095
|
+
dataSourceName: source.name
|
|
2096
|
+
}).dependsOn(source);
|
|
2097
|
+
const resolver = new Resolver(id, {
|
|
2098
|
+
apiId: props.apiId,
|
|
2099
|
+
typeName: props.typeName,
|
|
2100
|
+
fieldName: props.fieldName,
|
|
2101
|
+
functions: [config.id],
|
|
2102
|
+
code: props.code
|
|
2103
|
+
}).dependsOn(config);
|
|
2104
|
+
super([role, source, config, resolver]);
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
|
|
2108
|
+
// src/plugins/graphql.ts
|
|
2109
|
+
var defaultResolver = `
|
|
2110
|
+
export function request(ctx) {
|
|
2111
|
+
return {
|
|
2112
|
+
operation: 'Invoke',
|
|
2113
|
+
payload: ctx,
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
export function response(ctx) {
|
|
2118
|
+
return ctx.result
|
|
2119
|
+
}
|
|
2120
|
+
`;
|
|
2121
|
+
var ResolverFieldSchema = import_zod14.z.custom((value) => {
|
|
2122
|
+
return import_zod14.z.string().regex(/([a-z0-9\_]+)(\s){1}([a-z0-9\_]+)/gi).safeParse(value).success;
|
|
2123
|
+
}, `Invalid resolver field. Valid example: "Query list"`);
|
|
975
2124
|
var graphqlPlugin = definePlugin({
|
|
976
2125
|
name: "graphql",
|
|
977
|
-
schema:
|
|
978
|
-
defaults:
|
|
979
|
-
graphql:
|
|
980
|
-
|
|
2126
|
+
schema: import_zod14.z.object({
|
|
2127
|
+
defaults: import_zod14.z.object({
|
|
2128
|
+
graphql: import_zod14.z.record(ResourceIdSchema, import_zod14.z.object({
|
|
2129
|
+
domain: import_zod14.z.string().optional(),
|
|
2130
|
+
subDomain: import_zod14.z.string().optional(),
|
|
2131
|
+
authorization: import_zod14.z.object({
|
|
981
2132
|
authorizer: FunctionSchema,
|
|
982
2133
|
ttl: DurationSchema.default("1 hour")
|
|
983
2134
|
}).optional(),
|
|
984
|
-
|
|
985
|
-
request: LocalFileSchema.optional(),
|
|
986
|
-
response: LocalFileSchema.optional()
|
|
987
|
-
}).optional()
|
|
2135
|
+
resolver: LocalFileSchema.optional()
|
|
988
2136
|
})).optional()
|
|
989
2137
|
}).default({}),
|
|
990
|
-
stacks:
|
|
991
|
-
graphql:
|
|
992
|
-
schema:
|
|
2138
|
+
stacks: import_zod14.z.object({
|
|
2139
|
+
graphql: import_zod14.z.record(ResourceIdSchema, import_zod14.z.object({
|
|
2140
|
+
schema: import_zod14.z.union([
|
|
993
2141
|
LocalFileSchema,
|
|
994
|
-
|
|
2142
|
+
import_zod14.z.array(LocalFileSchema).min(1)
|
|
995
2143
|
]).optional(),
|
|
996
|
-
resolvers:
|
|
2144
|
+
resolvers: import_zod14.z.record(ResolverFieldSchema, FunctionSchema).optional()
|
|
997
2145
|
})).optional()
|
|
998
2146
|
}).array()
|
|
999
2147
|
}),
|
|
1000
|
-
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
});
|
|
1007
|
-
list3.forEach((id) => {
|
|
1008
|
-
const file = (0, import_path6.join)(assetDir, "graphql", config.name, id, "schema.graphql");
|
|
1009
|
-
const authorization = config.defaults.graphql?.[id]?.authorization;
|
|
1010
|
-
const authProps = {};
|
|
1011
|
-
if (authorization) {
|
|
1012
|
-
const authorizer = toFunction({ config, assets, stack }, `${id}-authorizer`, authorization.authorizer);
|
|
1013
|
-
authProps.additionalAuthenticationProviders = [{
|
|
1014
|
-
authenticationType: import_aws_appsync.AuthorizationType.LAMBDA,
|
|
1015
|
-
lambdaAuthorizerConfig: {
|
|
1016
|
-
authorizerUri: authorizer.functionArn,
|
|
1017
|
-
authorizerResultTtlInSeconds: authorization.ttl.toSeconds()
|
|
1018
|
-
}
|
|
1019
|
-
}];
|
|
2148
|
+
onApp(ctx) {
|
|
2149
|
+
const { config, bootstrap: bootstrap2, usEastBootstrap } = ctx;
|
|
2150
|
+
const apis = /* @__PURE__ */ new Set();
|
|
2151
|
+
for (const stackConfig of config.stacks) {
|
|
2152
|
+
for (const id of Object.keys(stackConfig.graphql || {})) {
|
|
2153
|
+
apis.add(id);
|
|
1020
2154
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
resource: "schema",
|
|
1033
|
-
resourceName: id,
|
|
1034
|
-
async build() {
|
|
1035
|
-
const schemas = [];
|
|
1036
|
-
await Promise.all(Object.values(config.stacks).map(async (stackConfig) => {
|
|
1037
|
-
const schemaFiles = toArray(stackConfig.graphql?.[id].schema || []);
|
|
1038
|
-
await Promise.all(schemaFiles.map(async (schemaFile) => {
|
|
1039
|
-
const schema3 = await (0, import_promises4.readFile)(schemaFile, "utf8");
|
|
1040
|
-
schemas.push(schema3);
|
|
1041
|
-
}));
|
|
1042
|
-
}));
|
|
1043
|
-
const schema2 = (0, import_graphql.print)((0, import_merge.mergeTypeDefs)(schemas));
|
|
1044
|
-
await (0, import_promises4.mkdir)((0, import_path6.dirname)(file), { recursive: true });
|
|
1045
|
-
await (0, import_promises4.writeFile)(file, schema2);
|
|
1046
|
-
new import_aws_appsync.CfnGraphQLSchema(stack, toId("schema", id), {
|
|
1047
|
-
apiId: api.attrApiId,
|
|
1048
|
-
definition: schema2
|
|
1049
|
-
});
|
|
1050
|
-
}
|
|
2155
|
+
}
|
|
2156
|
+
for (const id of apis) {
|
|
2157
|
+
const schema2 = [];
|
|
2158
|
+
for (const stack of config.stacks) {
|
|
2159
|
+
const files = toArray(stack.graphql?.[id]?.schema || []);
|
|
2160
|
+
schema2.push(...files);
|
|
2161
|
+
}
|
|
2162
|
+
const graphql = new GraphQL(id, {
|
|
2163
|
+
name: `${config.name}-${id}`,
|
|
2164
|
+
authenticationType: "api-key",
|
|
2165
|
+
schema: new Schema(id, schema2)
|
|
1051
2166
|
});
|
|
1052
|
-
|
|
2167
|
+
bootstrap2.add(graphql).export(`graphql-${id}`, graphql.api.id);
|
|
2168
|
+
const props = config.defaults.graphql?.[id];
|
|
2169
|
+
if (!props) {
|
|
2170
|
+
continue;
|
|
2171
|
+
}
|
|
2172
|
+
if (props.authorization) {
|
|
2173
|
+
const lambda = toLambdaFunction(ctx, `${id}-authorizer`, props.authorization.authorizer);
|
|
2174
|
+
graphql.api.addLambdaAuthProvider(lambda.arn, props.authorization.ttl);
|
|
2175
|
+
bootstrap2.add(lambda);
|
|
2176
|
+
}
|
|
2177
|
+
if (props.domain) {
|
|
2178
|
+
const domainName = props.subDomain ? `${props.subDomain}.${props.domain}` : props.domain;
|
|
2179
|
+
const hostedZoneId = ref(`${props.domain}Route53HostedZone`);
|
|
2180
|
+
const certificateArn = usEastBootstrap.import(`certificate-${props.domain}-arn`);
|
|
2181
|
+
graphql.attachDomainName(domainName, certificateArn);
|
|
2182
|
+
const record = new RecordSet(id, {
|
|
2183
|
+
hostedZoneId,
|
|
2184
|
+
type: "A",
|
|
2185
|
+
name: domainName,
|
|
2186
|
+
alias: graphql.api.dns
|
|
2187
|
+
});
|
|
2188
|
+
bootstrap2.add(record);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
1053
2191
|
},
|
|
1054
2192
|
onStack(ctx) {
|
|
1055
|
-
const {
|
|
1056
|
-
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
const api = import_aws_appsync.GraphqlApi.fromGraphqlApiAttributes(stack, toId("graphql", id), {
|
|
1060
|
-
graphqlApiId: import_aws_cdk_lib5.Fn.importValue(toId("graphql", id))
|
|
1061
|
-
});
|
|
2193
|
+
const { stack, stackConfig, bootstrap: bootstrap2 } = ctx;
|
|
2194
|
+
for (const [id, props] of Object.entries(stackConfig.graphql || {})) {
|
|
2195
|
+
const apiId = bootstrap2.import(`graphql-${id}`);
|
|
2196
|
+
for (const [typeAndField, functionProps] of Object.entries(props.resolvers || {})) {
|
|
1062
2197
|
const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
|
|
1063
|
-
const
|
|
1064
|
-
const lambda =
|
|
1065
|
-
const source =
|
|
1066
|
-
|
|
1067
|
-
});
|
|
1068
|
-
source.createResolver(toId("resolver", functionId), {
|
|
2198
|
+
const entryId = (0, import_change_case10.paramCase)(`${id}-${typeName}-${fieldName}`);
|
|
2199
|
+
const lambda = toLambdaFunction(ctx, entryId, functionProps);
|
|
2200
|
+
const source = new AppsyncEventSource(entryId, lambda, {
|
|
2201
|
+
apiId,
|
|
1069
2202
|
typeName,
|
|
1070
2203
|
fieldName,
|
|
1071
|
-
|
|
1072
|
-
responseMappingTemplate: defaults.mappingTemplate?.response ? import_aws_appsync.MappingTemplate.fromFile(defaults.mappingTemplate.response) : import_aws_appsync.MappingTemplate.lambdaResult()
|
|
2204
|
+
code: Code2.fromInline(entryId, defaultResolver)
|
|
1073
2205
|
});
|
|
1074
|
-
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
2206
|
+
stack.add(lambda, source);
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
1077
2209
|
}
|
|
1078
2210
|
});
|
|
1079
2211
|
|
|
1080
|
-
// src/plugins/
|
|
1081
|
-
var
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
var
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
2212
|
+
// src/plugins/domain.ts
|
|
2213
|
+
var import_zod15 = require("zod");
|
|
2214
|
+
|
|
2215
|
+
// src/formation/resource/route53/hosted-zone.ts
|
|
2216
|
+
var HostedZone = class extends Resource {
|
|
2217
|
+
constructor(logicalId, props = {}) {
|
|
2218
|
+
super("AWS::Route53::HostedZone", logicalId);
|
|
2219
|
+
this.props = props;
|
|
2220
|
+
this.name = this.props.domainName || logicalId;
|
|
2221
|
+
}
|
|
2222
|
+
name;
|
|
2223
|
+
get id() {
|
|
2224
|
+
return ref(this.logicalId);
|
|
2225
|
+
}
|
|
2226
|
+
properties() {
|
|
2227
|
+
return {
|
|
2228
|
+
Name: this.name + "."
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
|
|
2233
|
+
// src/formation/resource/certificate-manager/certificate.ts
|
|
2234
|
+
var Certificate = class extends Resource {
|
|
2235
|
+
constructor(logicalId, props = {}) {
|
|
2236
|
+
super("AWS::CertificateManager::Certificate", logicalId);
|
|
2237
|
+
this.props = props;
|
|
2238
|
+
this.name = this.props.domainName || logicalId;
|
|
2239
|
+
}
|
|
2240
|
+
name;
|
|
2241
|
+
get arn() {
|
|
2242
|
+
return ref(this.logicalId);
|
|
2243
|
+
}
|
|
2244
|
+
properties() {
|
|
2245
|
+
return {
|
|
2246
|
+
DomainName: this.name,
|
|
2247
|
+
ValidationMethod: "DNS",
|
|
2248
|
+
SubjectAlternativeNames: this.props.alternativeNames || []
|
|
2249
|
+
};
|
|
2250
|
+
}
|
|
2251
|
+
};
|
|
2252
|
+
|
|
2253
|
+
// src/formation/resource/route53/record-set-group.ts
|
|
2254
|
+
var RecordSetGroup = class extends Resource {
|
|
2255
|
+
constructor(logicalId, props) {
|
|
2256
|
+
super("AWS::Route53::RecordSetGroup", logicalId);
|
|
2257
|
+
this.props = props;
|
|
2258
|
+
}
|
|
2259
|
+
properties() {
|
|
2260
|
+
return {
|
|
2261
|
+
HostedZoneId: this.props.hostedZoneId,
|
|
2262
|
+
RecordSets: this.props.records.map((props) => ({
|
|
2263
|
+
Name: props.name + ".",
|
|
2264
|
+
Type: props.type,
|
|
2265
|
+
TTL: props.ttl,
|
|
2266
|
+
...props.records ? {
|
|
2267
|
+
ResourceRecords: props.records
|
|
2268
|
+
} : {},
|
|
2269
|
+
...props.alias ? {
|
|
2270
|
+
AliasTarget: {
|
|
2271
|
+
DNSName: props.alias,
|
|
2272
|
+
HostedZoneId: this.props.hostedZoneId
|
|
2273
|
+
}
|
|
2274
|
+
} : {}
|
|
2275
|
+
}))
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
};
|
|
2279
|
+
|
|
2280
|
+
// src/plugins/domain.ts
|
|
2281
|
+
var DomainNameSchema = import_zod15.z.string().regex(/[a-z\-\_\.]/g, "Invalid domain name");
|
|
2282
|
+
var domainPlugin = definePlugin({
|
|
2283
|
+
name: "domain",
|
|
2284
|
+
schema: import_zod15.z.object({
|
|
2285
|
+
domains: import_zod15.z.record(DomainNameSchema, import_zod15.z.object({
|
|
2286
|
+
name: DomainNameSchema.optional(),
|
|
2287
|
+
type: import_zod15.z.enum(["A", "AAAA", "CAA", "CNAME", "DS", "MX", "NAPTR", "NS", "PTR", "SOA", "SPF", "SRV", "TXT"]),
|
|
2288
|
+
ttl: DurationSchema,
|
|
2289
|
+
records: import_zod15.z.string().array()
|
|
2290
|
+
}).array()).optional()
|
|
1094
2291
|
}),
|
|
1095
|
-
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
resources: ["*"]
|
|
1101
|
-
}));
|
|
1102
|
-
});
|
|
1103
|
-
return Object.entries(stackConfig.pubsub || {}).map(([id, props]) => {
|
|
1104
|
-
const lambda = toFunction(ctx, id, props.consumer);
|
|
1105
|
-
new import_aws_iot.CfnTopicRule(stack, toId("pubsub", id), {
|
|
1106
|
-
ruleName: toName(stack, id),
|
|
1107
|
-
topicRulePayload: {
|
|
1108
|
-
sql: props.sql,
|
|
1109
|
-
awsIotSqlVersion: props.sqlVersion,
|
|
1110
|
-
actions: [{
|
|
1111
|
-
lambda: {
|
|
1112
|
-
functionArn: lambda.functionArn
|
|
1113
|
-
}
|
|
1114
|
-
}]
|
|
1115
|
-
}
|
|
2292
|
+
onApp({ config, bootstrap: bootstrap2, usEastBootstrap }) {
|
|
2293
|
+
for (const [domain, records] of Object.entries(config.domains || {})) {
|
|
2294
|
+
const hostedZone = new HostedZone(domain);
|
|
2295
|
+
const certificate = new Certificate(domain, {
|
|
2296
|
+
alternativeNames: [`*.${domain}`]
|
|
1116
2297
|
});
|
|
1117
|
-
|
|
1118
|
-
|
|
2298
|
+
bootstrap2.add(certificate);
|
|
2299
|
+
usEastBootstrap.add(hostedZone).add(certificate).export(`certificate-${domain}-arn`, certificate.arn);
|
|
2300
|
+
if (records.length > 0) {
|
|
2301
|
+
const group = new RecordSetGroup(domain, {
|
|
2302
|
+
hostedZoneId: hostedZone.id,
|
|
2303
|
+
records
|
|
2304
|
+
}).dependsOn(hostedZone);
|
|
2305
|
+
usEastBootstrap.add(group);
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
1119
2308
|
}
|
|
1120
2309
|
});
|
|
1121
2310
|
|
|
1122
2311
|
// src/plugins/index.ts
|
|
1123
2312
|
var defaultPlugins = [
|
|
2313
|
+
extendPlugin,
|
|
1124
2314
|
functionPlugin,
|
|
1125
2315
|
cronPlugin,
|
|
1126
2316
|
queuePlugin,
|
|
1127
2317
|
tablePlugin,
|
|
1128
2318
|
storePlugin,
|
|
1129
2319
|
topicPlugin,
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
2320
|
+
pubsubPlugin,
|
|
2321
|
+
// searchPlugin,
|
|
2322
|
+
domainPlugin,
|
|
2323
|
+
graphqlPlugin
|
|
2324
|
+
// httpPlugin,
|
|
1133
2325
|
];
|
|
1134
2326
|
|
|
1135
|
-
// src/
|
|
1136
|
-
var
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
2327
|
+
// src/formation/app.ts
|
|
2328
|
+
var App = class {
|
|
2329
|
+
constructor(name) {
|
|
2330
|
+
this.name = name;
|
|
2331
|
+
}
|
|
2332
|
+
list = /* @__PURE__ */ new Map();
|
|
2333
|
+
add(...stacks) {
|
|
2334
|
+
stacks.forEach((stack) => this.list.set(stack.name, stack));
|
|
2335
|
+
return this;
|
|
2336
|
+
}
|
|
2337
|
+
find(resourceType) {
|
|
2338
|
+
return this.stacks.map((stack) => stack.find(resourceType)).flat();
|
|
2339
|
+
}
|
|
2340
|
+
[Symbol.iterator]() {
|
|
2341
|
+
return this.list.values();
|
|
2342
|
+
}
|
|
2343
|
+
get stacks() {
|
|
2344
|
+
return [...this.list.values()];
|
|
2345
|
+
}
|
|
2346
|
+
// get resources() {
|
|
2347
|
+
// return this.stacks.map(stack => stack.resources).flat()
|
|
2348
|
+
// }
|
|
1155
2349
|
};
|
|
1156
2350
|
|
|
1157
|
-
// src/
|
|
1158
|
-
var
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
depends: config?.depends?.map((dep) => dep.name) || []
|
|
1173
|
-
}));
|
|
1174
|
-
const findChildren = (list4, parents, level) => {
|
|
1175
|
-
const children = [];
|
|
1176
|
-
const rests = [];
|
|
1177
|
-
for (const item of list4) {
|
|
1178
|
-
const isChild = item.depends.filter((dep) => !parents.includes(dep)).length === 0;
|
|
1179
|
-
if (isChild) {
|
|
1180
|
-
children.push(item);
|
|
1181
|
-
} else {
|
|
1182
|
-
rests.push(item);
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
if (!rests.length) {
|
|
1186
|
-
return children.map(({ stack }) => ({
|
|
1187
|
-
stack,
|
|
1188
|
-
level,
|
|
1189
|
-
children: []
|
|
1190
|
-
}));
|
|
1191
|
-
}
|
|
1192
|
-
return children.map(({ stack }) => {
|
|
1193
|
-
return {
|
|
1194
|
-
stack,
|
|
1195
|
-
level,
|
|
1196
|
-
children: findChildren(rests, [...parents, stack.artifactId], level + 1)
|
|
1197
|
-
};
|
|
1198
|
-
});
|
|
1199
|
-
};
|
|
1200
|
-
return findChildren(list3, [], startingLevel);
|
|
1201
|
-
};
|
|
1202
|
-
var createDeploymentLine = (stacks) => {
|
|
1203
|
-
const flat = flattenDependencyTree(stacks);
|
|
1204
|
-
const line = [];
|
|
1205
|
-
flat.forEach((node) => {
|
|
1206
|
-
const level = node.level;
|
|
1207
|
-
if (!line[level]) {
|
|
1208
|
-
line[level] = [];
|
|
1209
|
-
}
|
|
1210
|
-
line[level].push(node.stack);
|
|
1211
|
-
});
|
|
1212
|
-
return line;
|
|
2351
|
+
// src/formation/resource/cloud-formation/custom-resource.ts
|
|
2352
|
+
var CustomResource = class extends Resource {
|
|
2353
|
+
constructor(logicalId, props) {
|
|
2354
|
+
super("AWS::CloudFormation::CustomResource", logicalId);
|
|
2355
|
+
this.props = props;
|
|
2356
|
+
}
|
|
2357
|
+
getAtt(name) {
|
|
2358
|
+
return getAtt(this.logicalId, name);
|
|
2359
|
+
}
|
|
2360
|
+
properties() {
|
|
2361
|
+
return {
|
|
2362
|
+
ServiceToken: this.props.serviceToken,
|
|
2363
|
+
...this.props.properties
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
1213
2366
|
};
|
|
1214
2367
|
|
|
1215
|
-
// src/
|
|
1216
|
-
var
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
2368
|
+
// src/custom/global-export/handler.ts
|
|
2369
|
+
var globalExportsHandlerCode = (
|
|
2370
|
+
/* JS */
|
|
2371
|
+
`
|
|
2372
|
+
|
|
2373
|
+
const { CloudFormationClient, ListExportsCommand } = require('@aws-sdk/client-cloudformation')
|
|
2374
|
+
|
|
2375
|
+
exports.handler = async (event) => {
|
|
2376
|
+
const region = event.ResourceProperties.region
|
|
2377
|
+
|
|
2378
|
+
try {
|
|
2379
|
+
const data = await listExports(region)
|
|
2380
|
+
|
|
2381
|
+
await send(event, region, 'SUCCESS', data)
|
|
2382
|
+
} catch(error) {
|
|
2383
|
+
if (error instanceof Error) {
|
|
2384
|
+
await send(event, region, 'FAILED', {}, error.message)
|
|
2385
|
+
} else {
|
|
2386
|
+
await send(event, region, 'FAILED', {}, 'Unknown error')
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
const send = async (event, id, status, data, reason = '') => {
|
|
2392
|
+
const body = JSON.stringify({
|
|
2393
|
+
Status: status,
|
|
2394
|
+
Reason: reason,
|
|
2395
|
+
PhysicalResourceId: id,
|
|
2396
|
+
StackId: event.StackId,
|
|
2397
|
+
RequestId: event.RequestId,
|
|
2398
|
+
LogicalResourceId: event.LogicalResourceId,
|
|
2399
|
+
NoEcho: false,
|
|
2400
|
+
Data: data
|
|
2401
|
+
})
|
|
2402
|
+
|
|
2403
|
+
await fetch(event.ResponseURL, {
|
|
2404
|
+
method: 'PUT',
|
|
2405
|
+
port: 443,
|
|
2406
|
+
body,
|
|
2407
|
+
headers: {
|
|
2408
|
+
'content-type': '',
|
|
2409
|
+
'content-length': Buffer.from(body).byteLength,
|
|
2410
|
+
},
|
|
2411
|
+
})
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
const listExports = async (region) => {
|
|
2415
|
+
const client = new CloudFormationClient({ region })
|
|
2416
|
+
const data = {}
|
|
2417
|
+
|
|
2418
|
+
let token
|
|
2419
|
+
|
|
2420
|
+
while(true) {
|
|
2421
|
+
const result = await client.send(new ListExportsCommand({
|
|
2422
|
+
NextToken: token
|
|
2423
|
+
}))
|
|
2424
|
+
|
|
2425
|
+
result.Exports?.forEach(item => {
|
|
2426
|
+
data[item.Name] = item.Value
|
|
2427
|
+
})
|
|
2428
|
+
|
|
2429
|
+
if(result.NextToken) {
|
|
2430
|
+
token = result.NextToken
|
|
2431
|
+
} else {
|
|
2432
|
+
return data
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
`
|
|
2437
|
+
);
|
|
2438
|
+
|
|
2439
|
+
// src/custom/global-export/extend.ts
|
|
2440
|
+
var extendWithGlobalExports = (appName, importable, exportable) => {
|
|
2441
|
+
let crossRegionExports;
|
|
2442
|
+
importable.import = (name) => {
|
|
2443
|
+
name = formatName(name);
|
|
2444
|
+
if (!importable.exports.has(name)) {
|
|
2445
|
+
throw new TypeError(`Undefined global export value: ${name}`);
|
|
2446
|
+
}
|
|
2447
|
+
if (!crossRegionExports) {
|
|
2448
|
+
const lambda = new Function("global-exports", {
|
|
2449
|
+
name: `${appName}-global-exports`,
|
|
2450
|
+
code: Code.fromInline(globalExportsHandlerCode, "index.handler")
|
|
2451
|
+
});
|
|
2452
|
+
lambda.addPermissions({
|
|
2453
|
+
actions: ["cloudformation:ListExports"],
|
|
2454
|
+
resources: ["*"]
|
|
2455
|
+
});
|
|
2456
|
+
crossRegionExports = new CustomResource("global-exports", {
|
|
2457
|
+
serviceToken: lambda.arn,
|
|
2458
|
+
properties: {
|
|
2459
|
+
region: importable.region
|
|
2460
|
+
}
|
|
2461
|
+
});
|
|
2462
|
+
exportable.add(crossRegionExports);
|
|
1222
2463
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
id: this.id++
|
|
1226
|
-
});
|
|
1227
|
-
}
|
|
1228
|
-
list() {
|
|
1229
|
-
return this.assets;
|
|
1230
|
-
}
|
|
1231
|
-
forEach(cb) {
|
|
1232
|
-
Object.values(this.assets).forEach((assets) => {
|
|
1233
|
-
cb(assets[0].stackName, assets);
|
|
1234
|
-
});
|
|
1235
|
-
}
|
|
1236
|
-
map(cb) {
|
|
1237
|
-
return Object.values(this.assets).map((assets) => {
|
|
1238
|
-
return cb(assets[0].stackName, assets);
|
|
1239
|
-
});
|
|
1240
|
-
}
|
|
2464
|
+
return crossRegionExports.getAtt(name);
|
|
2465
|
+
};
|
|
1241
2466
|
};
|
|
1242
2467
|
|
|
1243
2468
|
// src/app.ts
|
|
1244
|
-
var makeApp = (config) => {
|
|
1245
|
-
return new import_aws_cdk_lib7.App({
|
|
1246
|
-
outdir: assemblyDir,
|
|
1247
|
-
defaultStackSynthesizer: new import_aws_cdk_lib7.DefaultStackSynthesizer({
|
|
1248
|
-
fileAssetsBucketName: assetBucketName(config),
|
|
1249
|
-
fileAssetPublishingRoleArn: "",
|
|
1250
|
-
generateBootstrapVersionRule: false
|
|
1251
|
-
})
|
|
1252
|
-
});
|
|
1253
|
-
};
|
|
1254
2469
|
var getAllDepends = (filters) => {
|
|
1255
2470
|
const list3 = [];
|
|
1256
2471
|
const walk = (deps) => {
|
|
@@ -1263,111 +2478,76 @@ var getAllDepends = (filters) => {
|
|
|
1263
2478
|
return list3;
|
|
1264
2479
|
};
|
|
1265
2480
|
var toApp = async (config, filters) => {
|
|
1266
|
-
const
|
|
1267
|
-
const app = makeApp(config);
|
|
2481
|
+
const app = new App(config.name);
|
|
1268
2482
|
const stacks = [];
|
|
1269
2483
|
const plugins = [
|
|
1270
2484
|
...defaultPlugins,
|
|
1271
2485
|
...config.plugins || []
|
|
1272
2486
|
];
|
|
1273
2487
|
debug("Plugins detected:", plugins.map((plugin) => style.info(plugin.name)).join(", "));
|
|
2488
|
+
const bootstrap2 = new Stack("bootstrap", config.region);
|
|
2489
|
+
const usEastBootstrap = new Stack("us-east-bootstrap", "us-east-1");
|
|
2490
|
+
extendWithGlobalExports(config.name, usEastBootstrap, bootstrap2);
|
|
2491
|
+
app.add(bootstrap2, usEastBootstrap);
|
|
1274
2492
|
debug("Run plugin onApp listeners");
|
|
1275
|
-
|
|
1276
|
-
const
|
|
2493
|
+
const bindings = [];
|
|
2494
|
+
const bind = (cb) => {
|
|
2495
|
+
bindings.push(cb);
|
|
2496
|
+
};
|
|
2497
|
+
for (const plugin of plugins) {
|
|
2498
|
+
plugin.onApp?.({
|
|
2499
|
+
config,
|
|
2500
|
+
app,
|
|
2501
|
+
bootstrap: bootstrap2,
|
|
2502
|
+
usEastBootstrap,
|
|
2503
|
+
bind
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
1277
2506
|
debug("Stack filters:", filters.map((filter) => style.info(filter)).join(", "));
|
|
1278
2507
|
const filterdStacks = filters.length === 0 ? config.stacks : getAllDepends(
|
|
1279
2508
|
// config.stacks,
|
|
1280
2509
|
config.stacks.filter((stack) => filters.includes(stack.name))
|
|
1281
2510
|
);
|
|
1282
2511
|
for (const stackConfig of filterdStacks) {
|
|
1283
|
-
const { stack
|
|
2512
|
+
const { stack } = toStack({
|
|
1284
2513
|
config,
|
|
1285
2514
|
stackConfig,
|
|
1286
|
-
|
|
2515
|
+
bootstrap: bootstrap2,
|
|
2516
|
+
usEastBootstrap,
|
|
1287
2517
|
plugins,
|
|
1288
2518
|
app
|
|
1289
2519
|
});
|
|
2520
|
+
app.add(stack);
|
|
1290
2521
|
stacks.push({ stack, config: stackConfig });
|
|
1291
|
-
bindings.forEach((cb) => bootstrap2.functions.forEach(cb));
|
|
1292
2522
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
2523
|
+
const functions = app.find(Function);
|
|
2524
|
+
for (const bind2 of bindings) {
|
|
2525
|
+
for (const fn of functions) {
|
|
2526
|
+
bind2(fn);
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
let dependencyTree = createDependencyTree(stacks);
|
|
2530
|
+
if (bootstrap2.size > 0) {
|
|
2531
|
+
dependencyTree = [{
|
|
2532
|
+
stack: bootstrap2,
|
|
2533
|
+
children: dependencyTree
|
|
2534
|
+
}];
|
|
2535
|
+
}
|
|
2536
|
+
if (usEastBootstrap.size > 0) {
|
|
1297
2537
|
dependencyTree = [{
|
|
1298
|
-
stack:
|
|
1299
|
-
|
|
1300
|
-
children: createDependencyTree(stacks, 1)
|
|
2538
|
+
stack: usEastBootstrap,
|
|
2539
|
+
children: dependencyTree
|
|
1301
2540
|
}];
|
|
1302
2541
|
}
|
|
1303
2542
|
return {
|
|
1304
2543
|
app,
|
|
1305
|
-
assets,
|
|
1306
2544
|
plugins,
|
|
1307
|
-
stackNames: filterdStacks.map((stack) => stack.name),
|
|
1308
2545
|
dependencyTree
|
|
1309
2546
|
};
|
|
1310
2547
|
};
|
|
1311
2548
|
|
|
1312
|
-
// src/cli/ui/layout/basic.ts
|
|
1313
|
-
var br = () => {
|
|
1314
|
-
return "\n";
|
|
1315
|
-
};
|
|
1316
|
-
var hr = () => {
|
|
1317
|
-
return (term) => {
|
|
1318
|
-
term.out.write([
|
|
1319
|
-
style.placeholder("\u2500".repeat(term.out.width())),
|
|
1320
|
-
br()
|
|
1321
|
-
]);
|
|
1322
|
-
};
|
|
1323
|
-
};
|
|
1324
|
-
|
|
1325
|
-
// src/cli/ui/layout/logs.ts
|
|
1326
|
-
var import_wrap_ansi = __toESM(require("wrap-ansi"), 1);
|
|
1327
|
-
var previous = /* @__PURE__ */ new Date();
|
|
1328
|
-
var logs = () => {
|
|
1329
|
-
if (!process.env.VERBOSE) {
|
|
1330
|
-
return [];
|
|
1331
|
-
}
|
|
1332
|
-
const logs2 = flushDebug();
|
|
1333
|
-
return (term) => {
|
|
1334
|
-
term.out.write([
|
|
1335
|
-
hr(),
|
|
1336
|
-
br(),
|
|
1337
|
-
" ".repeat(3),
|
|
1338
|
-
style.label("Debug Logs:"),
|
|
1339
|
-
br(),
|
|
1340
|
-
br(),
|
|
1341
|
-
logs2.map((log) => {
|
|
1342
|
-
const diff = log.date.getTime() - previous.getTime();
|
|
1343
|
-
const time = `+${diff}`.padStart(8);
|
|
1344
|
-
previous = log.date;
|
|
1345
|
-
return (0, import_wrap_ansi.default)([
|
|
1346
|
-
style.attr(`${time}${style.attr.dim("ms")}`),
|
|
1347
|
-
" [ ",
|
|
1348
|
-
log.type,
|
|
1349
|
-
" ] ",
|
|
1350
|
-
log.message,
|
|
1351
|
-
br(),
|
|
1352
|
-
log.type === "error" ? br() : ""
|
|
1353
|
-
].join(""), term.out.width(), { hard: true, trim: false });
|
|
1354
|
-
}),
|
|
1355
|
-
br(),
|
|
1356
|
-
hr()
|
|
1357
|
-
]);
|
|
1358
|
-
};
|
|
1359
|
-
};
|
|
1360
|
-
|
|
1361
|
-
// src/cli/ui/layout/footer.ts
|
|
1362
|
-
var footer = () => {
|
|
1363
|
-
return [
|
|
1364
|
-
br(),
|
|
1365
|
-
logs()
|
|
1366
|
-
];
|
|
1367
|
-
};
|
|
1368
|
-
|
|
1369
2549
|
// src/config.ts
|
|
1370
|
-
var
|
|
2550
|
+
var import_path4 = require("path");
|
|
1371
2551
|
|
|
1372
2552
|
// src/util/account.ts
|
|
1373
2553
|
var import_client_sts = require("@aws-sdk/client-sts");
|
|
@@ -1386,17 +2566,17 @@ var getCredentials = (profile) => {
|
|
|
1386
2566
|
};
|
|
1387
2567
|
|
|
1388
2568
|
// src/schema/app.ts
|
|
1389
|
-
var
|
|
2569
|
+
var import_zod19 = require("zod");
|
|
1390
2570
|
|
|
1391
2571
|
// src/schema/stack.ts
|
|
1392
|
-
var
|
|
1393
|
-
var StackSchema =
|
|
2572
|
+
var import_zod16 = require("zod");
|
|
2573
|
+
var StackSchema = import_zod16.z.object({
|
|
1394
2574
|
name: ResourceIdSchema,
|
|
1395
|
-
depends:
|
|
2575
|
+
depends: import_zod16.z.array(import_zod16.z.lazy(() => StackSchema)).optional()
|
|
1396
2576
|
});
|
|
1397
2577
|
|
|
1398
2578
|
// src/schema/region.ts
|
|
1399
|
-
var
|
|
2579
|
+
var import_zod17 = require("zod");
|
|
1400
2580
|
var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
|
|
1401
2581
|
var AF = ["af-south-1"];
|
|
1402
2582
|
var AP = ["ap-east-1", "ap-south-2", "ap-southeast-3", "ap-southeast-4", "ap-south-1", "ap-northeast-3", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1"];
|
|
@@ -1413,35 +2593,48 @@ var regions = [
|
|
|
1413
2593
|
...ME,
|
|
1414
2594
|
...SA
|
|
1415
2595
|
];
|
|
1416
|
-
var RegionSchema =
|
|
2596
|
+
var RegionSchema = import_zod17.z.enum(regions);
|
|
1417
2597
|
|
|
1418
2598
|
// src/schema/plugin.ts
|
|
1419
|
-
var
|
|
1420
|
-
var PluginSchema =
|
|
1421
|
-
name:
|
|
1422
|
-
schema:
|
|
2599
|
+
var import_zod18 = require("zod");
|
|
2600
|
+
var PluginSchema = import_zod18.z.object({
|
|
2601
|
+
name: import_zod18.z.string(),
|
|
2602
|
+
schema: import_zod18.z.custom().optional(),
|
|
1423
2603
|
// depends: z.array(z.lazy(() => PluginSchema)).optional(),
|
|
1424
|
-
onBootstrap:
|
|
1425
|
-
onStack:
|
|
1426
|
-
onApp:
|
|
2604
|
+
onBootstrap: import_zod18.z.function().returns(import_zod18.z.any()).optional(),
|
|
2605
|
+
onStack: import_zod18.z.function().returns(import_zod18.z.any()).optional(),
|
|
2606
|
+
onApp: import_zod18.z.function().returns(import_zod18.z.void()).optional()
|
|
1427
2607
|
// bind: z.function().optional(),
|
|
1428
2608
|
});
|
|
1429
2609
|
|
|
1430
2610
|
// src/schema/app.ts
|
|
1431
|
-
var AppSchema =
|
|
2611
|
+
var AppSchema = import_zod19.z.object({
|
|
1432
2612
|
name: ResourceIdSchema,
|
|
1433
2613
|
region: RegionSchema,
|
|
1434
|
-
profile:
|
|
1435
|
-
stage:
|
|
1436
|
-
defaults:
|
|
1437
|
-
stacks:
|
|
1438
|
-
|
|
2614
|
+
profile: import_zod19.z.string(),
|
|
2615
|
+
stage: import_zod19.z.string().regex(/[a-z]+/).default("prod"),
|
|
2616
|
+
defaults: import_zod19.z.object({}).default({}),
|
|
2617
|
+
stacks: import_zod19.z.array(StackSchema).min(1).refine((stacks) => {
|
|
2618
|
+
const unique = new Set(stacks.map((stack) => stack.name));
|
|
2619
|
+
return unique.size === stacks.length;
|
|
2620
|
+
}, "Must be an array of unique stacks"),
|
|
2621
|
+
plugins: import_zod19.z.array(PluginSchema).optional()
|
|
1439
2622
|
});
|
|
1440
2623
|
|
|
1441
2624
|
// src/util/import.ts
|
|
1442
|
-
var
|
|
1443
|
-
var
|
|
1444
|
-
var
|
|
2625
|
+
var import_core = require("@swc/core");
|
|
2626
|
+
var import_path2 = require("path");
|
|
2627
|
+
var import_promises4 = require("fs/promises");
|
|
2628
|
+
|
|
2629
|
+
// src/util/path.ts
|
|
2630
|
+
var import_path = require("path");
|
|
2631
|
+
var rootDir = process.cwd();
|
|
2632
|
+
var outDir = (0, import_path.join)(rootDir, ".awsless");
|
|
2633
|
+
var templateDir = (0, import_path.join)(outDir, "template");
|
|
2634
|
+
var assetDir = (0, import_path.join)(outDir, "asset");
|
|
2635
|
+
var cacheDir = (0, import_path.join)(outDir, "cache");
|
|
2636
|
+
|
|
2637
|
+
// src/util/import.ts
|
|
1445
2638
|
var resolveFileNameExtension = async (path) => {
|
|
1446
2639
|
const options = [
|
|
1447
2640
|
"",
|
|
@@ -1451,10 +2644,10 @@ var resolveFileNameExtension = async (path) => {
|
|
|
1451
2644
|
"/index.js"
|
|
1452
2645
|
];
|
|
1453
2646
|
for (const option of options) {
|
|
1454
|
-
const file = path + option;
|
|
2647
|
+
const file = path.replace(/\.js$/, "") + option;
|
|
1455
2648
|
let stat;
|
|
1456
2649
|
try {
|
|
1457
|
-
stat = await (0,
|
|
2650
|
+
stat = await (0, import_promises4.lstat)(file);
|
|
1458
2651
|
} catch (error) {
|
|
1459
2652
|
continue;
|
|
1460
2653
|
}
|
|
@@ -1465,45 +2658,42 @@ var resolveFileNameExtension = async (path) => {
|
|
|
1465
2658
|
throw new Error(`Failed to load file: ${path}`);
|
|
1466
2659
|
};
|
|
1467
2660
|
var resolveDir = (path) => {
|
|
1468
|
-
return (0,
|
|
2661
|
+
return (0, import_path2.dirname)(path).replace(rootDir + "/", "");
|
|
1469
2662
|
};
|
|
1470
2663
|
var importFile = async (path) => {
|
|
1471
2664
|
const load = async (file) => {
|
|
1472
|
-
|
|
2665
|
+
debug("Load file", file);
|
|
2666
|
+
let { code: code2 } = await (0, import_core.transformFile)(file, {
|
|
1473
2667
|
isModule: true
|
|
1474
2668
|
});
|
|
1475
|
-
const path2 = (0,
|
|
2669
|
+
const path2 = (0, import_path2.dirname)(file);
|
|
1476
2670
|
const dir = resolveDir(file);
|
|
1477
2671
|
code2 = code2.replaceAll("__dirname", `"${dir}"`);
|
|
1478
|
-
const matches = code2.match(/import\s*{\s*[a-z0-9\_]+\s*}\s*from\s*('|")(
|
|
2672
|
+
const matches = code2.match(/(import|export)\s*{\s*[a-z0-9\_\,\s\*]+\s*}\s*from\s*('|")(\.\.?[\/a-z0-9\_\-\.]+)('|");?/ig);
|
|
1479
2673
|
if (!matches)
|
|
1480
2674
|
return code2;
|
|
1481
2675
|
await Promise.all(matches?.map(async (match) => {
|
|
1482
|
-
const parts = /('|")(
|
|
2676
|
+
const parts = /('|")(\.\.?[\/a-z0-9\_\-\.]+)('|")/ig.exec(match);
|
|
1483
2677
|
const from = parts[2];
|
|
1484
|
-
const file2 = await resolveFileNameExtension((0,
|
|
2678
|
+
const file2 = await resolveFileNameExtension((0, import_path2.join)(path2, from));
|
|
1485
2679
|
const result = await load(file2);
|
|
1486
2680
|
code2 = code2.replace(match, result);
|
|
1487
2681
|
}));
|
|
1488
2682
|
return code2;
|
|
1489
2683
|
};
|
|
1490
2684
|
const code = await load(path);
|
|
1491
|
-
const outputFile = (0,
|
|
1492
|
-
await (0,
|
|
1493
|
-
await (0,
|
|
2685
|
+
const outputFile = (0, import_path2.join)(outDir, "config.js");
|
|
2686
|
+
await (0, import_promises4.mkdir)(outDir, { recursive: true });
|
|
2687
|
+
await (0, import_promises4.writeFile)(outputFile, code);
|
|
1494
2688
|
return import(outputFile);
|
|
1495
2689
|
};
|
|
1496
2690
|
|
|
1497
2691
|
// src/config.ts
|
|
1498
2692
|
var importConfig = async (options) => {
|
|
1499
2693
|
debug("Import config file");
|
|
1500
|
-
const fileName = (0,
|
|
2694
|
+
const fileName = (0, import_path4.join)(process.cwd(), options.configFile || "awsless.config.ts");
|
|
1501
2695
|
const module2 = await importFile(fileName);
|
|
1502
|
-
const appConfig = typeof module2.default === "function" ? await module2.default(
|
|
1503
|
-
profile: options.profile,
|
|
1504
|
-
region: options.region,
|
|
1505
|
-
stage: options.stage
|
|
1506
|
-
}) : module2.default;
|
|
2696
|
+
const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
|
|
1507
2697
|
debug("Validate config file");
|
|
1508
2698
|
const plugins = [
|
|
1509
2699
|
...defaultPlugins,
|
|
@@ -1528,6 +2718,19 @@ var importConfig = async (options) => {
|
|
|
1528
2718
|
};
|
|
1529
2719
|
};
|
|
1530
2720
|
|
|
2721
|
+
// src/cli/ui/layout/basic.ts
|
|
2722
|
+
var br = () => {
|
|
2723
|
+
return "\n";
|
|
2724
|
+
};
|
|
2725
|
+
var hr = () => {
|
|
2726
|
+
return (term) => {
|
|
2727
|
+
term.out.write([
|
|
2728
|
+
style.placeholder("\u2500".repeat(term.out.width())),
|
|
2729
|
+
br()
|
|
2730
|
+
]);
|
|
2731
|
+
};
|
|
2732
|
+
};
|
|
2733
|
+
|
|
1531
2734
|
// src/cli/ui/layout/list.ts
|
|
1532
2735
|
var list = (data) => {
|
|
1533
2736
|
const padding = 3;
|
|
@@ -1535,26 +2738,26 @@ var list = (data) => {
|
|
|
1535
2738
|
const size = Object.keys(data).reduce((total, name) => {
|
|
1536
2739
|
return name.length > total ? name.length : total;
|
|
1537
2740
|
}, 0);
|
|
1538
|
-
return
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
2741
|
+
return (term) => {
|
|
2742
|
+
term.out.gap();
|
|
2743
|
+
term.out.write(Object.entries(data).map(([name, value]) => [
|
|
2744
|
+
" ".repeat(padding),
|
|
2745
|
+
style.label((name + ":").padEnd(size + gap + 1)),
|
|
2746
|
+
value,
|
|
2747
|
+
br()
|
|
2748
|
+
]));
|
|
2749
|
+
term.out.gap();
|
|
2750
|
+
};
|
|
1544
2751
|
};
|
|
1545
2752
|
|
|
1546
2753
|
// src/cli/ui/layout/header.ts
|
|
1547
2754
|
var header = (config) => {
|
|
1548
|
-
return
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
Profile: config.profile
|
|
1555
|
-
}),
|
|
1556
|
-
br()
|
|
1557
|
-
];
|
|
2755
|
+
return list({
|
|
2756
|
+
App: config.name,
|
|
2757
|
+
Stage: config.stage,
|
|
2758
|
+
Region: config.region,
|
|
2759
|
+
Profile: config.profile
|
|
2760
|
+
});
|
|
1558
2761
|
};
|
|
1559
2762
|
|
|
1560
2763
|
// src/util/timer.ts
|
|
@@ -1579,7 +2782,7 @@ var Signal = class {
|
|
|
1579
2782
|
}
|
|
1580
2783
|
set(value) {
|
|
1581
2784
|
this.value = value;
|
|
1582
|
-
this.subs.forEach((
|
|
2785
|
+
this.subs.forEach((sub2) => sub2(value));
|
|
1583
2786
|
}
|
|
1584
2787
|
update(cb) {
|
|
1585
2788
|
this.set(cb(this.value));
|
|
@@ -1621,16 +2824,16 @@ var createSpinner = () => {
|
|
|
1621
2824
|
};
|
|
1622
2825
|
|
|
1623
2826
|
// src/cli/ui/layout/dialog.ts
|
|
1624
|
-
var
|
|
2827
|
+
var import_wrap_ansi = __toESM(require("wrap-ansi"), 1);
|
|
1625
2828
|
var dialog = (type, lines) => {
|
|
1626
2829
|
const padding = 3;
|
|
1627
2830
|
const icon = style[type](symbol[type].padEnd(padding));
|
|
1628
2831
|
return (term) => {
|
|
1629
2832
|
term.out.write(lines.map((line, i) => {
|
|
1630
2833
|
if (i === 0) {
|
|
1631
|
-
return icon + (0,
|
|
2834
|
+
return icon + (0, import_wrap_ansi.default)(line, term.out.width(), { hard: true });
|
|
1632
2835
|
}
|
|
1633
|
-
return (0,
|
|
2836
|
+
return (0, import_wrap_ansi.default)(" ".repeat(padding) + line, term.out.width(), { hard: true });
|
|
1634
2837
|
}).join(br()) + br());
|
|
1635
2838
|
};
|
|
1636
2839
|
};
|
|
@@ -1772,6 +2975,7 @@ var Renderer = class {
|
|
|
1772
2975
|
fragments = [];
|
|
1773
2976
|
unsubs = [];
|
|
1774
2977
|
timeout;
|
|
2978
|
+
flushing = false;
|
|
1775
2979
|
screen = [];
|
|
1776
2980
|
width() {
|
|
1777
2981
|
return this.output.columns;
|
|
@@ -1791,14 +2995,61 @@ var Renderer = class {
|
|
|
1791
2995
|
this.update();
|
|
1792
2996
|
return fragment;
|
|
1793
2997
|
}
|
|
2998
|
+
gap() {
|
|
2999
|
+
const walk = (fragment) => {
|
|
3000
|
+
if (typeof fragment === "string") {
|
|
3001
|
+
return fragment;
|
|
3002
|
+
}
|
|
3003
|
+
if (Array.isArray(fragment)) {
|
|
3004
|
+
return fragment.map(walk).join("");
|
|
3005
|
+
}
|
|
3006
|
+
return walk(fragment.get());
|
|
3007
|
+
};
|
|
3008
|
+
const end = walk(this.fragments.slice(-2));
|
|
3009
|
+
if (end.endsWith("\n\n")) {
|
|
3010
|
+
} else if (end.endsWith("\n")) {
|
|
3011
|
+
this.fragments.push("\n");
|
|
3012
|
+
} else {
|
|
3013
|
+
this.fragments.push("\n\n");
|
|
3014
|
+
}
|
|
3015
|
+
this.update();
|
|
3016
|
+
}
|
|
1794
3017
|
update() {
|
|
1795
3018
|
clearTimeout(this.timeout);
|
|
1796
3019
|
this.timeout = setTimeout(() => {
|
|
1797
3020
|
this.flush();
|
|
1798
3021
|
}, 0);
|
|
1799
3022
|
}
|
|
1800
|
-
|
|
3023
|
+
async end() {
|
|
3024
|
+
this.gap();
|
|
3025
|
+
await this.flush();
|
|
3026
|
+
clearTimeout(this.timeout);
|
|
3027
|
+
this.unsubs.forEach((unsub) => unsub());
|
|
3028
|
+
this.unsubs = [];
|
|
3029
|
+
const y = this.screen.length - 1;
|
|
3030
|
+
await this.setCursor(0, y);
|
|
3031
|
+
}
|
|
3032
|
+
setCursor(x, y) {
|
|
3033
|
+
return new Promise((resolve) => {
|
|
3034
|
+
this.output.cursorTo?.(x, y, () => resolve(void 0));
|
|
3035
|
+
});
|
|
3036
|
+
}
|
|
3037
|
+
writeString(value) {
|
|
3038
|
+
return new Promise((resolve) => {
|
|
3039
|
+
this.output.write?.(value, () => resolve(void 0));
|
|
3040
|
+
});
|
|
3041
|
+
}
|
|
3042
|
+
clearLine() {
|
|
3043
|
+
return new Promise((resolve) => {
|
|
3044
|
+
this.output.clearLine?.(1, () => resolve(void 0));
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
async flush() {
|
|
1801
3048
|
clearTimeout(this.timeout);
|
|
3049
|
+
if (this.flushing) {
|
|
3050
|
+
this.update();
|
|
3051
|
+
return;
|
|
3052
|
+
}
|
|
1802
3053
|
const walk = (fragment) => {
|
|
1803
3054
|
if (typeof fragment === "string") {
|
|
1804
3055
|
return fragment;
|
|
@@ -1814,34 +3065,40 @@ var Renderer = class {
|
|
|
1814
3065
|
this.unsubs.forEach((unsub) => unsub());
|
|
1815
3066
|
this.unsubs = [];
|
|
1816
3067
|
const screen = walk(this.fragments).split("\n");
|
|
3068
|
+
const height = this.height();
|
|
1817
3069
|
const oldSize = this.screen.length;
|
|
1818
3070
|
const newSize = screen.length;
|
|
1819
3071
|
const size = Math.max(oldSize, newSize);
|
|
1820
|
-
const height = this.height();
|
|
1821
3072
|
const start = Math.max(oldSize - height, 0);
|
|
3073
|
+
this.flushing = true;
|
|
1822
3074
|
for (let y = start; y < size; y++) {
|
|
1823
|
-
const
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
3075
|
+
const newLine = screen[y];
|
|
3076
|
+
const oldLine = this.screen[y];
|
|
3077
|
+
if (newLine !== oldLine) {
|
|
3078
|
+
if (y >= oldSize && y !== 0) {
|
|
3079
|
+
const p = y - start - 1;
|
|
3080
|
+
const x = screen[y - 1]?.length || 0;
|
|
3081
|
+
await this.setCursor(x, p);
|
|
3082
|
+
await this.writeString("\n" + newLine);
|
|
1829
3083
|
} else {
|
|
1830
|
-
this.
|
|
1831
|
-
this.
|
|
3084
|
+
await this.setCursor(0, y - start);
|
|
3085
|
+
await this.writeString(newLine);
|
|
3086
|
+
await this.clearLine();
|
|
1832
3087
|
}
|
|
1833
|
-
this.output.clearLine?.(1);
|
|
1834
3088
|
}
|
|
1835
3089
|
}
|
|
1836
3090
|
this.screen = screen;
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
3091
|
+
this.flushing = false;
|
|
3092
|
+
}
|
|
3093
|
+
async clear() {
|
|
3094
|
+
await this.setCursor(0, 0);
|
|
3095
|
+
await this.writeString("\n".repeat(this.height()));
|
|
3096
|
+
await this.setCursor(0, 0);
|
|
3097
|
+
if (this.output.clearScreenDown) {
|
|
3098
|
+
await new Promise((resolve) => {
|
|
3099
|
+
this.output.clearScreenDown(() => resolve(void 0));
|
|
3100
|
+
});
|
|
1842
3101
|
}
|
|
1843
|
-
this.output.cursorTo?.(0, 0);
|
|
1844
|
-
this.output.clearScreenDown?.();
|
|
1845
3102
|
}
|
|
1846
3103
|
};
|
|
1847
3104
|
|
|
@@ -1857,22 +3114,62 @@ var logo = () => {
|
|
|
1857
3114
|
return [
|
|
1858
3115
|
style.warning("\u26A1\uFE0F "),
|
|
1859
3116
|
style.primary("AWS"),
|
|
1860
|
-
style.primary.dim("LESS")
|
|
1861
|
-
br()
|
|
3117
|
+
style.primary.dim("LESS")
|
|
1862
3118
|
];
|
|
1863
3119
|
};
|
|
1864
3120
|
|
|
3121
|
+
// src/cli/ui/layout/logs.ts
|
|
3122
|
+
var import_wrap_ansi2 = __toESM(require("wrap-ansi"), 1);
|
|
3123
|
+
var previous = /* @__PURE__ */ new Date();
|
|
3124
|
+
var logs = () => {
|
|
3125
|
+
if (!process.env.VERBOSE) {
|
|
3126
|
+
return [];
|
|
3127
|
+
}
|
|
3128
|
+
const logs2 = flushDebug();
|
|
3129
|
+
return (term) => {
|
|
3130
|
+
term.out.gap();
|
|
3131
|
+
term.out.write([
|
|
3132
|
+
hr(),
|
|
3133
|
+
br(),
|
|
3134
|
+
" ".repeat(3),
|
|
3135
|
+
style.label("Debug Logs:"),
|
|
3136
|
+
br(),
|
|
3137
|
+
br(),
|
|
3138
|
+
logs2.map((log) => {
|
|
3139
|
+
const diff = log.date.getTime() - previous.getTime();
|
|
3140
|
+
const time = `+${diff}`.padStart(8);
|
|
3141
|
+
previous = log.date;
|
|
3142
|
+
return (0, import_wrap_ansi2.default)([
|
|
3143
|
+
style.attr(`${time}${style.attr.dim("ms")}`),
|
|
3144
|
+
" [ ",
|
|
3145
|
+
log.type,
|
|
3146
|
+
" ] ",
|
|
3147
|
+
log.message,
|
|
3148
|
+
br(),
|
|
3149
|
+
log.type === "error" ? br() : ""
|
|
3150
|
+
].join(""), term.out.width(), { hard: true, trim: false });
|
|
3151
|
+
}),
|
|
3152
|
+
br(),
|
|
3153
|
+
hr()
|
|
3154
|
+
]);
|
|
3155
|
+
};
|
|
3156
|
+
};
|
|
3157
|
+
|
|
1865
3158
|
// src/cli/ui/layout/layout.ts
|
|
1866
3159
|
var layout = async (cb) => {
|
|
1867
3160
|
const term = createTerminal();
|
|
1868
|
-
term.out.clear();
|
|
3161
|
+
await term.out.clear();
|
|
3162
|
+
term.out.write(br());
|
|
1869
3163
|
term.out.write(logo());
|
|
3164
|
+
term.out.gap();
|
|
1870
3165
|
try {
|
|
1871
3166
|
const options = program.optsWithGlobals();
|
|
1872
3167
|
const config = await importConfig(options);
|
|
1873
3168
|
term.out.write(header(config));
|
|
3169
|
+
term.out.gap();
|
|
1874
3170
|
await cb(config, term.out.write.bind(term.out), term);
|
|
1875
3171
|
} catch (error) {
|
|
3172
|
+
term.out.gap();
|
|
1876
3173
|
if (error instanceof Error) {
|
|
1877
3174
|
term.out.write(dialog("error", [error.message]));
|
|
1878
3175
|
} else if (typeof error === "string") {
|
|
@@ -1883,7 +3180,9 @@ var layout = async (cb) => {
|
|
|
1883
3180
|
debugError(error);
|
|
1884
3181
|
} finally {
|
|
1885
3182
|
debug("Exit");
|
|
1886
|
-
term.out.
|
|
3183
|
+
term.out.gap();
|
|
3184
|
+
term.out.write(logs());
|
|
3185
|
+
await term.out.end();
|
|
1887
3186
|
term.in.unref();
|
|
1888
3187
|
setTimeout(() => {
|
|
1889
3188
|
process.exit(0);
|
|
@@ -1891,6 +3190,9 @@ var layout = async (cb) => {
|
|
|
1891
3190
|
}
|
|
1892
3191
|
};
|
|
1893
3192
|
|
|
3193
|
+
// src/cli/ui/complex/builder.ts
|
|
3194
|
+
var import_promises5 = require("fs/promises");
|
|
3195
|
+
|
|
1894
3196
|
// src/cli/ui/layout/flex-line.ts
|
|
1895
3197
|
var stripEscapeCode = (str) => {
|
|
1896
3198
|
return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
|
|
@@ -1911,34 +3213,52 @@ var flexLine = (term, left, right, reserveSpace = 0) => {
|
|
|
1911
3213
|
]);
|
|
1912
3214
|
};
|
|
1913
3215
|
|
|
1914
|
-
// src/cli/ui/complex/
|
|
1915
|
-
var
|
|
3216
|
+
// src/cli/ui/complex/builder.ts
|
|
3217
|
+
var import_path6 = require("path");
|
|
3218
|
+
var assetBuilder = (app) => {
|
|
1916
3219
|
return async (term) => {
|
|
3220
|
+
const assets = [];
|
|
3221
|
+
const stacks = [];
|
|
3222
|
+
for (const stack of app) {
|
|
3223
|
+
for (const asset of stack.assets) {
|
|
3224
|
+
if (asset.build) {
|
|
3225
|
+
assets.push(asset);
|
|
3226
|
+
stacks.push(stack);
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
if (assets.length === 0) {
|
|
3231
|
+
return;
|
|
3232
|
+
}
|
|
1917
3233
|
const done = term.out.write(loadingDialog("Building stack assets..."));
|
|
1918
|
-
const groups = new Signal([
|
|
3234
|
+
const groups = new Signal([""]);
|
|
3235
|
+
term.out.gap();
|
|
1919
3236
|
term.out.write(groups);
|
|
1920
|
-
const stackNameSize = Math.max(...
|
|
1921
|
-
const
|
|
1922
|
-
await Promise.all(
|
|
3237
|
+
const stackNameSize = Math.max(...stacks.map((stack) => stack.name.length));
|
|
3238
|
+
const assetTypeSize = Math.max(...assets.map((asset) => asset.type.length));
|
|
3239
|
+
await Promise.all(app.stacks.map(async (stack) => {
|
|
1923
3240
|
const group = new Signal([]);
|
|
1924
3241
|
groups.update((groups2) => [...groups2, group]);
|
|
1925
|
-
await Promise.all(
|
|
3242
|
+
await Promise.all([...stack.assets].map(async (asset) => {
|
|
3243
|
+
if (!asset.build) {
|
|
3244
|
+
return;
|
|
3245
|
+
}
|
|
1926
3246
|
const [icon, stop] = createSpinner();
|
|
1927
3247
|
const details = new Signal({});
|
|
1928
3248
|
const line = flexLine(term, [
|
|
1929
3249
|
icon,
|
|
1930
3250
|
" ",
|
|
1931
|
-
style.label(
|
|
1932
|
-
" ".repeat(stackNameSize -
|
|
3251
|
+
style.label(stack.name),
|
|
3252
|
+
" ".repeat(stackNameSize - stack.name.length),
|
|
1933
3253
|
" ",
|
|
1934
3254
|
style.placeholder(symbol.pointerSmall),
|
|
1935
3255
|
" ",
|
|
1936
|
-
style.warning(asset.
|
|
1937
|
-
" ".repeat(
|
|
3256
|
+
style.warning(asset.type),
|
|
3257
|
+
" ".repeat(assetTypeSize - asset.type.length),
|
|
1938
3258
|
" ",
|
|
1939
3259
|
style.placeholder(symbol.pointerSmall),
|
|
1940
3260
|
" ",
|
|
1941
|
-
style.info(asset.
|
|
3261
|
+
style.info(asset.id),
|
|
1942
3262
|
" "
|
|
1943
3263
|
], [
|
|
1944
3264
|
" ",
|
|
@@ -1951,7 +3271,14 @@ var assetBuilder = (assets) => {
|
|
|
1951
3271
|
]);
|
|
1952
3272
|
group.update((group2) => [...group2, line]);
|
|
1953
3273
|
const timer = createTimer();
|
|
1954
|
-
const data = await asset.build
|
|
3274
|
+
const data = await asset.build({
|
|
3275
|
+
async write(file, data2) {
|
|
3276
|
+
const fullpath = (0, import_path6.join)(assetDir, asset.type, app.name, stack.name, asset.id, file);
|
|
3277
|
+
const basepath = (0, import_path6.dirname)(fullpath);
|
|
3278
|
+
await (0, import_promises5.mkdir)(basepath, { recursive: true });
|
|
3279
|
+
await (0, import_promises5.writeFile)(fullpath, data2);
|
|
3280
|
+
}
|
|
3281
|
+
});
|
|
1955
3282
|
details.set({
|
|
1956
3283
|
...data,
|
|
1957
3284
|
time: timer()
|
|
@@ -1961,15 +3288,16 @@ var assetBuilder = (assets) => {
|
|
|
1961
3288
|
}));
|
|
1962
3289
|
}));
|
|
1963
3290
|
done("Done building stack assets");
|
|
3291
|
+
term.out.gap();
|
|
1964
3292
|
};
|
|
1965
3293
|
};
|
|
1966
3294
|
|
|
1967
3295
|
// src/util/cleanup.ts
|
|
1968
3296
|
var import_promises6 = require("fs/promises");
|
|
1969
3297
|
var cleanUp = async () => {
|
|
1970
|
-
debug("Clean up
|
|
3298
|
+
debug("Clean up template, cache, and asset files");
|
|
1971
3299
|
const paths = [
|
|
1972
|
-
|
|
3300
|
+
templateDir,
|
|
1973
3301
|
assetDir,
|
|
1974
3302
|
cacheDir
|
|
1975
3303
|
];
|
|
@@ -1983,108 +3311,176 @@ var cleanUp = async () => {
|
|
|
1983
3311
|
})));
|
|
1984
3312
|
};
|
|
1985
3313
|
|
|
3314
|
+
// src/cli/ui/complex/template.ts
|
|
3315
|
+
var import_promises7 = require("fs/promises");
|
|
3316
|
+
var import_path9 = require("path");
|
|
3317
|
+
var templateBuilder = (app) => {
|
|
3318
|
+
return async (term) => {
|
|
3319
|
+
const done = term.out.write(loadingDialog("Building stack templates..."));
|
|
3320
|
+
await Promise.all(app.stacks.map(async (stack) => {
|
|
3321
|
+
const template = stack.toString(true);
|
|
3322
|
+
const path = (0, import_path9.join)(templateDir, app.name);
|
|
3323
|
+
const file = (0, import_path9.join)(path, `${stack.name}.json`);
|
|
3324
|
+
await (0, import_promises7.mkdir)(path, { recursive: true });
|
|
3325
|
+
await (0, import_promises7.writeFile)(file, template);
|
|
3326
|
+
}));
|
|
3327
|
+
done("Done building stack templates");
|
|
3328
|
+
};
|
|
3329
|
+
};
|
|
3330
|
+
|
|
1986
3331
|
// src/cli/command/build.ts
|
|
1987
3332
|
var build = (program2) => {
|
|
1988
3333
|
program2.command("build").argument("[stack...]", "Optionally filter stacks to build").description("Build your app").action(async (filters) => {
|
|
1989
3334
|
await layout(async (config, write) => {
|
|
1990
|
-
const { app
|
|
3335
|
+
const { app } = await toApp(config, filters);
|
|
1991
3336
|
await cleanUp();
|
|
1992
|
-
await write(assetBuilder(
|
|
1993
|
-
app
|
|
3337
|
+
await write(assetBuilder(app));
|
|
3338
|
+
await write(templateBuilder(app));
|
|
1994
3339
|
});
|
|
1995
3340
|
});
|
|
1996
3341
|
};
|
|
1997
3342
|
|
|
1998
|
-
// src/
|
|
3343
|
+
// src/formation/bootstrap.ts
|
|
3344
|
+
var assetBucketName = (account, region) => {
|
|
3345
|
+
return `awsless-bootstrap-${account}-${region}`;
|
|
3346
|
+
};
|
|
3347
|
+
var assetBucketUrl = (account, region, stack) => {
|
|
3348
|
+
const bucket = assetBucketName(account, region);
|
|
3349
|
+
return `https://s3-${region}.amazonaws.com/${bucket}/${stack.name}/cloudformation.json`;
|
|
3350
|
+
};
|
|
3351
|
+
var version = "1";
|
|
3352
|
+
var bootstrapStack = (account, region) => {
|
|
3353
|
+
const app = new App("awsless");
|
|
3354
|
+
const stack = new Stack("bootstrap", region);
|
|
3355
|
+
stack.add(new Bucket("assets", {
|
|
3356
|
+
name: assetBucketName(account, region),
|
|
3357
|
+
accessControl: "private",
|
|
3358
|
+
versioned: true
|
|
3359
|
+
}));
|
|
3360
|
+
stack.export("version", version);
|
|
3361
|
+
app.add(stack);
|
|
3362
|
+
return { app, stack };
|
|
3363
|
+
};
|
|
3364
|
+
var shouldDeployBootstrap = async (client, stack) => {
|
|
3365
|
+
debug("Check bootstrap status");
|
|
3366
|
+
const info = await client.get(stack.name, stack.region);
|
|
3367
|
+
return !info || info.outputs.version !== version || !["CREATE_COMPLETE", "UPDATE_COMPLETE"].includes(info.status);
|
|
3368
|
+
};
|
|
3369
|
+
|
|
3370
|
+
// src/formation/client.ts
|
|
1999
3371
|
var import_client_cloudformation = require("@aws-sdk/client-cloudformation");
|
|
2000
|
-
var
|
|
3372
|
+
var import_client_s3 = require("@aws-sdk/client-s3");
|
|
3373
|
+
var import_change_case11 = require("change-case");
|
|
2001
3374
|
var StackClient = class {
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
this.
|
|
2005
|
-
this.
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
});
|
|
3375
|
+
constructor(app, account, region, credentials) {
|
|
3376
|
+
this.app = app;
|
|
3377
|
+
this.account = account;
|
|
3378
|
+
this.region = region;
|
|
3379
|
+
this.credentials = credentials;
|
|
3380
|
+
this.assetBucketName = assetBucketName(this.account, this.region);
|
|
2009
3381
|
}
|
|
2010
|
-
client;
|
|
2011
3382
|
maxWaitTime = 60 * 30;
|
|
2012
3383
|
// 30 minutes
|
|
2013
3384
|
maxDelay = 30;
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
3385
|
+
// 30 seconds
|
|
3386
|
+
assetBucketName;
|
|
3387
|
+
getClient(region) {
|
|
3388
|
+
return new import_client_cloudformation.CloudFormationClient({
|
|
3389
|
+
credentials: this.credentials,
|
|
3390
|
+
region
|
|
3391
|
+
});
|
|
3392
|
+
}
|
|
3393
|
+
shouldUploadTemplate(template) {
|
|
3394
|
+
const size = Buffer.byteLength(template, "utf8");
|
|
2017
3395
|
return size > 5e4;
|
|
2018
3396
|
}
|
|
2019
3397
|
templateProp(stack) {
|
|
2020
|
-
|
|
2021
|
-
|
|
3398
|
+
const template = stack.toString();
|
|
3399
|
+
return this.shouldUploadTemplate(template) ? {
|
|
3400
|
+
TemplateUrl: assetBucketUrl(this.account, this.region, stack)
|
|
2022
3401
|
} : {
|
|
2023
|
-
TemplateBody:
|
|
3402
|
+
TemplateBody: template
|
|
2024
3403
|
};
|
|
2025
3404
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
3405
|
+
stackName(stackName) {
|
|
3406
|
+
return (0, import_change_case11.paramCase)(`${this.app.name}-${stackName}`);
|
|
3407
|
+
}
|
|
3408
|
+
tags(stack) {
|
|
3409
|
+
const tags = [];
|
|
3410
|
+
for (const [name, value] of stack.tags.entries()) {
|
|
3411
|
+
tags.push({ Key: name, Value: value });
|
|
3412
|
+
}
|
|
3413
|
+
return tags;
|
|
3414
|
+
}
|
|
3415
|
+
async upload(stack, template) {
|
|
3416
|
+
debug("Upload the", style.info(stack.name), "stack to awsless assets bucket");
|
|
3417
|
+
const client = new import_client_s3.S3Client({
|
|
3418
|
+
credentials: this.credentials,
|
|
3419
|
+
region: stack.region
|
|
2031
3420
|
});
|
|
2032
|
-
await client.send(new
|
|
2033
|
-
Bucket:
|
|
2034
|
-
Key: `${stack.
|
|
2035
|
-
Body:
|
|
2036
|
-
ACL:
|
|
2037
|
-
StorageClass:
|
|
3421
|
+
await client.send(new import_client_s3.PutObjectCommand({
|
|
3422
|
+
Bucket: this.assetBucketName,
|
|
3423
|
+
Key: `${this.app.name}/${stack.name}/cloudformation.json`,
|
|
3424
|
+
Body: template,
|
|
3425
|
+
ACL: import_client_s3.ObjectCannedACL.private,
|
|
3426
|
+
StorageClass: import_client_s3.StorageClass.STANDARD_IA
|
|
2038
3427
|
}));
|
|
2039
3428
|
}
|
|
2040
3429
|
async create(stack, capabilities) {
|
|
2041
|
-
debug("Create the", style.info(stack.
|
|
2042
|
-
|
|
2043
|
-
|
|
3430
|
+
debug("Create the", style.info(stack.name), "stack");
|
|
3431
|
+
const client = this.getClient(stack.region);
|
|
3432
|
+
await client.send(new import_client_cloudformation.CreateStackCommand({
|
|
3433
|
+
StackName: this.stackName(stack.name),
|
|
2044
3434
|
EnableTerminationProtection: false,
|
|
2045
3435
|
OnFailure: import_client_cloudformation.OnFailure.DELETE,
|
|
2046
3436
|
Capabilities: capabilities,
|
|
3437
|
+
Tags: this.tags(stack),
|
|
2047
3438
|
...this.templateProp(stack)
|
|
2048
3439
|
}));
|
|
2049
3440
|
await (0, import_client_cloudformation.waitUntilStackCreateComplete)({
|
|
2050
|
-
client
|
|
3441
|
+
client,
|
|
2051
3442
|
maxWaitTime: this.maxWaitTime,
|
|
2052
3443
|
maxDelay: this.maxDelay
|
|
2053
3444
|
}, {
|
|
2054
|
-
StackName: stack.
|
|
3445
|
+
StackName: this.stackName(stack.name)
|
|
2055
3446
|
});
|
|
2056
3447
|
}
|
|
2057
3448
|
async update(stack, capabilities) {
|
|
2058
|
-
debug("Update the", style.info(stack.
|
|
2059
|
-
|
|
2060
|
-
|
|
3449
|
+
debug("Update the", style.info(stack.name), "stack");
|
|
3450
|
+
const client = this.getClient(stack.region);
|
|
3451
|
+
await client.send(new import_client_cloudformation.UpdateStackCommand({
|
|
3452
|
+
StackName: this.stackName(stack.name),
|
|
2061
3453
|
Capabilities: capabilities,
|
|
3454
|
+
Tags: this.tags(stack),
|
|
2062
3455
|
...this.templateProp(stack)
|
|
2063
3456
|
}));
|
|
2064
3457
|
await (0, import_client_cloudformation.waitUntilStackUpdateComplete)({
|
|
2065
|
-
client
|
|
3458
|
+
client,
|
|
2066
3459
|
maxWaitTime: this.maxWaitTime,
|
|
2067
3460
|
maxDelay: this.maxDelay
|
|
2068
3461
|
}, {
|
|
2069
|
-
StackName: stack.
|
|
3462
|
+
StackName: this.stackName(stack.name)
|
|
2070
3463
|
});
|
|
2071
3464
|
}
|
|
2072
3465
|
async validate(stack) {
|
|
2073
|
-
debug("Validate the", style.info(stack.
|
|
2074
|
-
const
|
|
3466
|
+
debug("Validate the", style.info(stack.name), "stack");
|
|
3467
|
+
const client = this.getClient(stack.region);
|
|
3468
|
+
const result = await client.send(new import_client_cloudformation.ValidateTemplateCommand({
|
|
2075
3469
|
...this.templateProp(stack)
|
|
2076
3470
|
}));
|
|
2077
3471
|
return result.Capabilities;
|
|
2078
3472
|
}
|
|
2079
|
-
async get(name) {
|
|
3473
|
+
async get(name, region) {
|
|
2080
3474
|
debug("Get stack info for:", style.info(name));
|
|
3475
|
+
const client = this.getClient(region);
|
|
2081
3476
|
let result;
|
|
2082
3477
|
try {
|
|
2083
|
-
result = await
|
|
2084
|
-
StackName: name
|
|
3478
|
+
result = await client.send(new import_client_cloudformation.DescribeStacksCommand({
|
|
3479
|
+
StackName: this.stackName(name)
|
|
2085
3480
|
}));
|
|
2086
3481
|
} catch (error) {
|
|
2087
3482
|
if (error instanceof Error && error.name === "ValidationError" && error.message.includes("does not exist")) {
|
|
3483
|
+
debug("Stack not found");
|
|
2088
3484
|
return;
|
|
2089
3485
|
}
|
|
2090
3486
|
throw error;
|
|
@@ -2094,8 +3490,8 @@ var StackClient = class {
|
|
|
2094
3490
|
debug("Stack not found");
|
|
2095
3491
|
return;
|
|
2096
3492
|
}
|
|
2097
|
-
const resultTemplate = await
|
|
2098
|
-
StackName: name,
|
|
3493
|
+
const resultTemplate = await client.send(new import_client_cloudformation.GetTemplateCommand({
|
|
3494
|
+
StackName: this.stackName(name),
|
|
2099
3495
|
TemplateStage: import_client_cloudformation.TemplateStage.Original
|
|
2100
3496
|
}));
|
|
2101
3497
|
const outputs = {};
|
|
@@ -2113,14 +3509,15 @@ var StackClient = class {
|
|
|
2113
3509
|
};
|
|
2114
3510
|
}
|
|
2115
3511
|
async deploy(stack) {
|
|
2116
|
-
const
|
|
2117
|
-
|
|
2118
|
-
|
|
3512
|
+
const template = stack.toString();
|
|
3513
|
+
const data = await this.get(stack.name, stack.region);
|
|
3514
|
+
debug("Deploy:", style.info(stack.name));
|
|
3515
|
+
if (data?.template === template) {
|
|
2119
3516
|
debug("No stack changes");
|
|
2120
3517
|
return false;
|
|
2121
3518
|
}
|
|
2122
|
-
if (this.shouldUploadTemplate(
|
|
2123
|
-
await this.upload(stack);
|
|
3519
|
+
if (this.shouldUploadTemplate(template)) {
|
|
3520
|
+
await this.upload(stack, template);
|
|
2124
3521
|
}
|
|
2125
3522
|
const capabilities = await this.validate(stack);
|
|
2126
3523
|
if (!data) {
|
|
@@ -2132,22 +3529,23 @@ var StackClient = class {
|
|
|
2132
3529
|
}
|
|
2133
3530
|
return true;
|
|
2134
3531
|
}
|
|
2135
|
-
async delete(name) {
|
|
2136
|
-
const data = await this.get(name);
|
|
3532
|
+
async delete(name, region) {
|
|
3533
|
+
const data = await this.get(name, region);
|
|
3534
|
+
const client = this.getClient(region);
|
|
2137
3535
|
debug("Delete the", style.info(name), "stack");
|
|
2138
3536
|
if (!data) {
|
|
2139
3537
|
debug("Already deleted");
|
|
2140
3538
|
return;
|
|
2141
3539
|
}
|
|
2142
|
-
await
|
|
2143
|
-
StackName: name
|
|
3540
|
+
await client.send(new import_client_cloudformation.DeleteStackCommand({
|
|
3541
|
+
StackName: this.stackName(name)
|
|
2144
3542
|
}));
|
|
2145
3543
|
await (0, import_client_cloudformation.waitUntilStackDeleteComplete)({
|
|
2146
|
-
client
|
|
3544
|
+
client,
|
|
2147
3545
|
maxWaitTime: this.maxWaitTime,
|
|
2148
3546
|
maxDelay: this.maxDelay
|
|
2149
3547
|
}, {
|
|
2150
|
-
StackName: name
|
|
3548
|
+
StackName: this.stackName(name)
|
|
2151
3549
|
});
|
|
2152
3550
|
}
|
|
2153
3551
|
};
|
|
@@ -2236,10 +3634,9 @@ var confirmPrompt = (label, options = {}) => {
|
|
|
2236
3634
|
var bootstrapDeployer = (config) => {
|
|
2237
3635
|
return async (term) => {
|
|
2238
3636
|
debug("Initializing bootstrap");
|
|
2239
|
-
const app =
|
|
2240
|
-
const client = new StackClient(config);
|
|
2241
|
-
const
|
|
2242
|
-
const shouldDeploy = await shouldDeployBootstrap(client, bootstrap2.stackName);
|
|
3637
|
+
const { app, stack } = bootstrapStack(config.account, config.region);
|
|
3638
|
+
const client = new StackClient(app, config.account, config.region, config.credentials);
|
|
3639
|
+
const shouldDeploy = await shouldDeployBootstrap(client, stack);
|
|
2243
3640
|
if (shouldDeploy) {
|
|
2244
3641
|
term.out.write(dialog("warning", [`Your app hasn't been bootstrapped yet`]));
|
|
2245
3642
|
const confirmed = await term.out.write(confirmPrompt("Would you like to bootstrap?"));
|
|
@@ -2247,8 +3644,7 @@ var bootstrapDeployer = (config) => {
|
|
|
2247
3644
|
throw new Cancelled();
|
|
2248
3645
|
}
|
|
2249
3646
|
const done = term.out.write(loadingDialog("Bootstrapping..."));
|
|
2250
|
-
|
|
2251
|
-
await client.deploy(assembly.stacks[0]);
|
|
3647
|
+
await client.deploy(stack);
|
|
2252
3648
|
done("Done deploying the bootstrap stack");
|
|
2253
3649
|
} else {
|
|
2254
3650
|
term.out.write(dialog("success", [
|
|
@@ -2274,8 +3670,8 @@ var stackTree = (nodes, statuses) => {
|
|
|
2274
3670
|
const render = (nodes2, deep = 0, parents = []) => {
|
|
2275
3671
|
const size = nodes2.length - 1;
|
|
2276
3672
|
nodes2.forEach((node, i) => {
|
|
2277
|
-
const
|
|
2278
|
-
const status2 = statuses[
|
|
3673
|
+
const name = node.stack.name;
|
|
3674
|
+
const status2 = statuses[name];
|
|
2279
3675
|
const first = i === 0 && deep === 0;
|
|
2280
3676
|
const last = i === size;
|
|
2281
3677
|
const more = i < size;
|
|
@@ -2289,7 +3685,7 @@ var stackTree = (nodes, statuses) => {
|
|
|
2289
3685
|
first && size === 0 ? " " : first ? "\u250C\u2500" : last ? "\u2514\u2500" : "\u251C\u2500"
|
|
2290
3686
|
),
|
|
2291
3687
|
" ",
|
|
2292
|
-
style.info(
|
|
3688
|
+
style.info(name),
|
|
2293
3689
|
" "
|
|
2294
3690
|
], [
|
|
2295
3691
|
" ",
|
|
@@ -2300,7 +3696,9 @@ var stackTree = (nodes, statuses) => {
|
|
|
2300
3696
|
render(node.children, deep + 1, [...parents, more]);
|
|
2301
3697
|
});
|
|
2302
3698
|
};
|
|
3699
|
+
term.out.gap();
|
|
2303
3700
|
render(nodes);
|
|
3701
|
+
term.out.gap();
|
|
2304
3702
|
};
|
|
2305
3703
|
};
|
|
2306
3704
|
|
|
@@ -2308,31 +3706,27 @@ var stackTree = (nodes, statuses) => {
|
|
|
2308
3706
|
var status = (program2) => {
|
|
2309
3707
|
program2.command("status").argument("[stacks...]", "Optionally filter stacks to lookup status").description("View the application status").action(async (filters) => {
|
|
2310
3708
|
await layout(async (config, write) => {
|
|
2311
|
-
const { app,
|
|
3709
|
+
const { app, dependencyTree } = await toApp(config, filters);
|
|
2312
3710
|
await cleanUp();
|
|
2313
|
-
await write(assetBuilder(
|
|
2314
|
-
write(
|
|
2315
|
-
const assembly = app.synth();
|
|
3711
|
+
await write(assetBuilder(app));
|
|
3712
|
+
await write(templateBuilder(app));
|
|
2316
3713
|
const doneLoading = write(loadingDialog("Loading stack information..."));
|
|
2317
|
-
const client = new StackClient(config);
|
|
3714
|
+
const client = new StackClient(app, config.account, config.region, config.credentials);
|
|
2318
3715
|
const statuses = [];
|
|
2319
3716
|
const stackStatuses = {};
|
|
2320
|
-
|
|
2321
|
-
stackStatuses[stack.
|
|
2322
|
-
}
|
|
2323
|
-
write(br());
|
|
3717
|
+
for (const stack of app) {
|
|
3718
|
+
stackStatuses[stack.name] = new Signal(style.info("Loading..."));
|
|
3719
|
+
}
|
|
2324
3720
|
write(stackTree(dependencyTree, stackStatuses));
|
|
2325
|
-
write(br());
|
|
2326
3721
|
debug("Load metadata for all deployed stacks on AWS");
|
|
2327
|
-
await Promise.all(
|
|
2328
|
-
const info = await client.get(stack.
|
|
2329
|
-
const
|
|
2330
|
-
const signal = stackStatuses[name];
|
|
3722
|
+
await Promise.all(app.stacks.map(async (stack, i) => {
|
|
3723
|
+
const info = await client.get(stack.name, stack.region);
|
|
3724
|
+
const signal = stackStatuses[stack.name];
|
|
2331
3725
|
await new Promise((resolve) => setTimeout(resolve, i * 1e3));
|
|
2332
3726
|
if (!info) {
|
|
2333
3727
|
signal.set(style.error("non-existent"));
|
|
2334
3728
|
statuses.push("non-existent");
|
|
2335
|
-
} else if (info.template !==
|
|
3729
|
+
} else if (info.template !== stack.toString()) {
|
|
2336
3730
|
signal.set(style.warning("out-of-date"));
|
|
2337
3731
|
statuses.push("out-of-date");
|
|
2338
3732
|
} else {
|
|
@@ -2351,12 +3745,77 @@ var status = (program2) => {
|
|
|
2351
3745
|
});
|
|
2352
3746
|
};
|
|
2353
3747
|
|
|
3748
|
+
// src/cli/ui/complex/publisher.ts
|
|
3749
|
+
var import_promises8 = require("fs/promises");
|
|
3750
|
+
var import_path11 = require("path");
|
|
3751
|
+
var import_client_s32 = require("@aws-sdk/client-s3");
|
|
3752
|
+
var assetPublisher = (config, app) => {
|
|
3753
|
+
const client = new import_client_s32.S3Client({
|
|
3754
|
+
credentials: config.credentials,
|
|
3755
|
+
region: config.region
|
|
3756
|
+
});
|
|
3757
|
+
return async (term) => {
|
|
3758
|
+
const done = term.out.write(loadingDialog("Publishing stack assets to AWS..."));
|
|
3759
|
+
await Promise.all(app.stacks.map(async (stack) => {
|
|
3760
|
+
await Promise.all([...stack.assets].map(async (asset) => {
|
|
3761
|
+
await asset.publish?.({
|
|
3762
|
+
async read(file) {
|
|
3763
|
+
const path = (0, import_path11.join)(assetDir, asset.type, app.name, stack.name, asset.id, file);
|
|
3764
|
+
const data = await (0, import_promises8.readFile)(path);
|
|
3765
|
+
return data;
|
|
3766
|
+
},
|
|
3767
|
+
async publish(name, data, hash) {
|
|
3768
|
+
const key = `${app.name}/${stack.name}/function/${name}`;
|
|
3769
|
+
const bucket = assetBucketName(config.account, config.region);
|
|
3770
|
+
let getResult;
|
|
3771
|
+
try {
|
|
3772
|
+
getResult = await client.send(new import_client_s32.GetObjectCommand({
|
|
3773
|
+
Bucket: bucket,
|
|
3774
|
+
Key: key
|
|
3775
|
+
}));
|
|
3776
|
+
} catch (error) {
|
|
3777
|
+
if (error instanceof Error && error.name === "NoSuchKey") {
|
|
3778
|
+
} else {
|
|
3779
|
+
throw error;
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
if (getResult?.Metadata?.hash === hash) {
|
|
3783
|
+
return {
|
|
3784
|
+
bucket,
|
|
3785
|
+
key,
|
|
3786
|
+
version: getResult.VersionId
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
const putResult = await client.send(new import_client_s32.PutObjectCommand({
|
|
3790
|
+
Bucket: bucket,
|
|
3791
|
+
Key: key,
|
|
3792
|
+
Body: data,
|
|
3793
|
+
ACL: import_client_s32.ObjectCannedACL.private,
|
|
3794
|
+
StorageClass: import_client_s32.StorageClass.STANDARD,
|
|
3795
|
+
Metadata: {
|
|
3796
|
+
hash
|
|
3797
|
+
}
|
|
3798
|
+
}));
|
|
3799
|
+
return {
|
|
3800
|
+
bucket,
|
|
3801
|
+
key,
|
|
3802
|
+
version: putResult.VersionId
|
|
3803
|
+
};
|
|
3804
|
+
}
|
|
3805
|
+
});
|
|
3806
|
+
}));
|
|
3807
|
+
}));
|
|
3808
|
+
done("Done publishing stack assets to AWS");
|
|
3809
|
+
};
|
|
3810
|
+
};
|
|
3811
|
+
|
|
2354
3812
|
// src/cli/command/deploy.ts
|
|
2355
3813
|
var deploy = (program2) => {
|
|
2356
3814
|
program2.command("deploy").argument("[stacks...]", "Optionally filter stacks to deploy").description("Deploy your app to AWS").action(async (filters) => {
|
|
2357
3815
|
await layout(async (config, write) => {
|
|
2358
3816
|
await write(bootstrapDeployer(config));
|
|
2359
|
-
const { app,
|
|
3817
|
+
const { app, dependencyTree } = await toApp(config, filters);
|
|
3818
|
+
const stackNames = app.stacks.map((stack) => stack.name);
|
|
2360
3819
|
const formattedFilter = stackNames.map((i) => style.info(i)).join(style.placeholder(", "));
|
|
2361
3820
|
debug("Stacks to deploy", formattedFilter);
|
|
2362
3821
|
const deployAll = filters.length === 0;
|
|
@@ -2366,34 +3825,23 @@ var deploy = (program2) => {
|
|
|
2366
3825
|
throw new Cancelled();
|
|
2367
3826
|
}
|
|
2368
3827
|
await cleanUp();
|
|
2369
|
-
await write(assetBuilder(
|
|
2370
|
-
write(
|
|
2371
|
-
write(
|
|
2372
|
-
const donePublishing = write(loadingDialog("Publishing stack assets to AWS..."));
|
|
2373
|
-
await Promise.all(assets.map(async (_, assets2) => {
|
|
2374
|
-
await Promise.all(assets2.map(async (asset) => {
|
|
2375
|
-
await asset.publish?.();
|
|
2376
|
-
}));
|
|
2377
|
-
}));
|
|
2378
|
-
donePublishing("Done publishing stack assets to AWS");
|
|
2379
|
-
const assembly = app.synth();
|
|
3828
|
+
await write(assetBuilder(app));
|
|
3829
|
+
await write(assetPublisher(config, app));
|
|
3830
|
+
await write(templateBuilder(app));
|
|
2380
3831
|
const statuses = {};
|
|
2381
|
-
|
|
2382
|
-
statuses[stack.
|
|
2383
|
-
}
|
|
3832
|
+
for (const stack of app) {
|
|
3833
|
+
statuses[stack.name] = new Signal(style.info("waiting"));
|
|
3834
|
+
}
|
|
2384
3835
|
const doneDeploying = write(loadingDialog("Deploying stacks to AWS..."));
|
|
2385
|
-
write(br());
|
|
2386
3836
|
write(stackTree(dependencyTree, statuses));
|
|
2387
|
-
|
|
2388
|
-
const client = new StackClient(config);
|
|
3837
|
+
const client = new StackClient(app, config.account, config.region, config.credentials);
|
|
2389
3838
|
const deploymentLine = createDeploymentLine(dependencyTree);
|
|
2390
3839
|
for (const stacks of deploymentLine) {
|
|
2391
3840
|
const results = await Promise.allSettled(stacks.map(async (stack) => {
|
|
2392
|
-
const signal = statuses[stack.
|
|
2393
|
-
const stackArtifect = assembly.stacks.find((item) => item.id === stack.artifactId);
|
|
3841
|
+
const signal = statuses[stack.name];
|
|
2394
3842
|
signal.set(style.warning("deploying"));
|
|
2395
3843
|
try {
|
|
2396
|
-
await client.deploy(
|
|
3844
|
+
await client.deploy(stack);
|
|
2397
3845
|
} catch (error) {
|
|
2398
3846
|
debugError(error);
|
|
2399
3847
|
signal.set(style.error("failed"));
|
|
@@ -2482,7 +3930,6 @@ var set = (program2) => {
|
|
|
2482
3930
|
write(list({
|
|
2483
3931
|
"Set secret parameter": style.info(name)
|
|
2484
3932
|
}));
|
|
2485
|
-
write(br());
|
|
2486
3933
|
const value = await write(textPrompt("Enter secret value"));
|
|
2487
3934
|
if (value === "") {
|
|
2488
3935
|
write(dialog("error", [`Provided secret value can't be empty`]));
|
|
@@ -2503,7 +3950,6 @@ var get = (program2) => {
|
|
|
2503
3950
|
const done = write(loadingDialog(`Getting remote secret parameter`));
|
|
2504
3951
|
const value = await params.get(name);
|
|
2505
3952
|
done(`Done getting remote secret parameter`);
|
|
2506
|
-
write(br());
|
|
2507
3953
|
write(list({
|
|
2508
3954
|
Name: name,
|
|
2509
3955
|
Value: value || style.error("(empty)")
|
|
@@ -2526,7 +3972,6 @@ var del = (program2) => {
|
|
|
2526
3972
|
const value = await params.get(name);
|
|
2527
3973
|
await params.delete(name);
|
|
2528
3974
|
done(`Done deleting remote secret parameter`);
|
|
2529
|
-
write(br());
|
|
2530
3975
|
write(list({
|
|
2531
3976
|
Name: name,
|
|
2532
3977
|
Value: value || style.error("(empty)")
|
|
@@ -2544,7 +3989,6 @@ var list2 = (program2) => {
|
|
|
2544
3989
|
const values = await params.list();
|
|
2545
3990
|
done("Done loading secret values");
|
|
2546
3991
|
if (Object.keys(values).length > 0) {
|
|
2547
|
-
write(br());
|
|
2548
3992
|
write(list(values));
|
|
2549
3993
|
} else {
|
|
2550
3994
|
write(dialog("warning", ["No secret parameters found"]));
|
|
@@ -2565,15 +4009,28 @@ var secrets = (program2) => {
|
|
|
2565
4009
|
commands.forEach((cb) => cb(command));
|
|
2566
4010
|
};
|
|
2567
4011
|
|
|
4012
|
+
// src/cli/command/test.ts
|
|
4013
|
+
var test = (program2) => {
|
|
4014
|
+
program2.command("test").action(async () => {
|
|
4015
|
+
await layout(async (config) => {
|
|
4016
|
+
const app = new App("test");
|
|
4017
|
+
const name = "test5";
|
|
4018
|
+
});
|
|
4019
|
+
});
|
|
4020
|
+
};
|
|
4021
|
+
|
|
2568
4022
|
// src/cli/program.ts
|
|
2569
4023
|
var program = new import_commander.Command();
|
|
2570
|
-
program.name("
|
|
4024
|
+
program.name(logo().join("").replace(/\s+/, ""));
|
|
2571
4025
|
program.option("--config-file <string>", "The config file location");
|
|
2572
4026
|
program.option("--stage <string>", "The stage to use, defaults to prod stage", "prod");
|
|
2573
4027
|
program.option("--profile <string>", "The AWS profile to use");
|
|
2574
4028
|
program.option("--region <string>", "The AWS region to use");
|
|
2575
4029
|
program.option("-m --mute", "Mute sound effects");
|
|
2576
4030
|
program.option("-v --verbose", "Print verbose logs");
|
|
4031
|
+
program.exitOverride(() => {
|
|
4032
|
+
process.exit(0);
|
|
4033
|
+
});
|
|
2577
4034
|
program.on("option:verbose", () => {
|
|
2578
4035
|
process.env.VERBOSE = program.opts().verbose ? "1" : void 0;
|
|
2579
4036
|
});
|
|
@@ -2582,13 +4039,12 @@ var commands2 = [
|
|
|
2582
4039
|
status,
|
|
2583
4040
|
build,
|
|
2584
4041
|
deploy,
|
|
2585
|
-
secrets
|
|
4042
|
+
secrets,
|
|
4043
|
+
test
|
|
2586
4044
|
// diff,
|
|
2587
4045
|
// remove,
|
|
2588
|
-
// test,
|
|
2589
|
-
// test2,
|
|
2590
4046
|
];
|
|
2591
|
-
commands2.forEach((
|
|
4047
|
+
commands2.forEach((fn) => fn(program));
|
|
2592
4048
|
|
|
2593
4049
|
// src/bin.ts
|
|
2594
4050
|
program.parse(process.argv);
|