@awsless/awsless 0.0.15 → 0.0.17
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/README.MD +212 -0
- package/dist/bin.cjs +1485 -297
- package/dist/bin.js +1469 -281
- package/dist/index.d.ts +493 -13
- package/package.json +1 -1
package/dist/bin.cjs
CHANGED
|
@@ -77,7 +77,7 @@ var flushDebug = () => {
|
|
|
77
77
|
// src/util/param.ts
|
|
78
78
|
var import_client_ssm = require("@aws-sdk/client-ssm");
|
|
79
79
|
var configParameterPrefix = (config) => {
|
|
80
|
-
return
|
|
80
|
+
return `/.awsless/${config.name}`;
|
|
81
81
|
};
|
|
82
82
|
var Params = class {
|
|
83
83
|
constructor(config) {
|
|
@@ -158,8 +158,18 @@ var Params = class {
|
|
|
158
158
|
}
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
-
// src/formation/
|
|
161
|
+
// src/formation/asset.ts
|
|
162
162
|
var import_change_case = require("change-case");
|
|
163
|
+
var Asset = class {
|
|
164
|
+
constructor(type, id) {
|
|
165
|
+
this.type = type;
|
|
166
|
+
this.id = (0, import_change_case.paramCase)(id);
|
|
167
|
+
}
|
|
168
|
+
id;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/formation/util.ts
|
|
172
|
+
var import_change_case2 = require("change-case");
|
|
163
173
|
var ref = (logicalId) => {
|
|
164
174
|
return { Ref: logicalId };
|
|
165
175
|
};
|
|
@@ -176,10 +186,10 @@ var importValue = (name) => {
|
|
|
176
186
|
return { "Fn::ImportValue": name };
|
|
177
187
|
};
|
|
178
188
|
var formatLogicalId = (id) => {
|
|
179
|
-
return (0,
|
|
189
|
+
return (0, import_change_case2.pascalCase)(id).replaceAll("_", "");
|
|
180
190
|
};
|
|
181
191
|
var formatName = (name) => {
|
|
182
|
-
return (0,
|
|
192
|
+
return (0, import_change_case2.paramCase)(name);
|
|
183
193
|
};
|
|
184
194
|
|
|
185
195
|
// src/formation/resource.ts
|
|
@@ -315,11 +325,11 @@ var Function = class extends Resource {
|
|
|
315
325
|
});
|
|
316
326
|
role.addInlinePolicy(policy);
|
|
317
327
|
role.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName("AWSLambdaBasicExecutionRole"));
|
|
318
|
-
super("AWS::Lambda::Function", logicalId, [
|
|
319
|
-
role,
|
|
320
|
-
props.code
|
|
321
|
-
]);
|
|
328
|
+
super("AWS::Lambda::Function", logicalId, [role]);
|
|
322
329
|
this.props = props;
|
|
330
|
+
if (props.code instanceof Asset) {
|
|
331
|
+
this.children.push(props.code);
|
|
332
|
+
}
|
|
323
333
|
this.dependsOn(role);
|
|
324
334
|
this.role = role;
|
|
325
335
|
this.policy = policy;
|
|
@@ -372,16 +382,6 @@ var Function = class extends Resource {
|
|
|
372
382
|
}
|
|
373
383
|
};
|
|
374
384
|
|
|
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
385
|
// src/formation/stack.ts
|
|
386
386
|
var Stack = class {
|
|
387
387
|
constructor(name, region) {
|
|
@@ -406,10 +406,16 @@ var Stack = class {
|
|
|
406
406
|
return this;
|
|
407
407
|
}
|
|
408
408
|
export(name, value) {
|
|
409
|
-
|
|
410
|
-
this.exports.set(name, value);
|
|
409
|
+
this.exports.set(formatName(name), value);
|
|
411
410
|
return this;
|
|
412
411
|
}
|
|
412
|
+
get(name) {
|
|
413
|
+
name = formatName(name);
|
|
414
|
+
if (!this.exports.has(name)) {
|
|
415
|
+
throw new Error(`Undefined export value: ${name}`);
|
|
416
|
+
}
|
|
417
|
+
return this.exports.get(name);
|
|
418
|
+
}
|
|
413
419
|
import(name) {
|
|
414
420
|
name = formatName(name);
|
|
415
421
|
if (!this.exports.has(name)) {
|
|
@@ -820,55 +826,24 @@ var zipFiles = (files) => {
|
|
|
820
826
|
};
|
|
821
827
|
|
|
822
828
|
// src/formation/resource/lambda/code.ts
|
|
823
|
-
var import_crypto2 = require("crypto");
|
|
824
829
|
var Code = class {
|
|
825
830
|
static fromFile(id, file, bundler) {
|
|
826
831
|
return new FileCode(id, file, bundler);
|
|
827
832
|
}
|
|
828
|
-
static fromInline(
|
|
829
|
-
return new InlineCode(
|
|
833
|
+
static fromInline(code, handler) {
|
|
834
|
+
return new InlineCode(code, handler);
|
|
830
835
|
}
|
|
831
836
|
};
|
|
832
|
-
var InlineCode = class
|
|
833
|
-
constructor(
|
|
834
|
-
super("function", id);
|
|
837
|
+
var InlineCode = class {
|
|
838
|
+
constructor(code, handler = "index.default") {
|
|
835
839
|
this.code = code;
|
|
836
840
|
this.handler = handler;
|
|
837
841
|
}
|
|
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
842
|
toCodeJson() {
|
|
866
843
|
return {
|
|
867
844
|
Handler: this.handler,
|
|
868
845
|
Code: {
|
|
869
|
-
|
|
870
|
-
S3Key: this.s3.key,
|
|
871
|
-
S3ObjectVersion: this.s3.version
|
|
846
|
+
ZipFile: this.code
|
|
872
847
|
}
|
|
873
848
|
};
|
|
874
849
|
}
|
|
@@ -919,6 +894,55 @@ var FileCode = class extends Asset {
|
|
|
919
894
|
}
|
|
920
895
|
};
|
|
921
896
|
|
|
897
|
+
// src/formation/resource/lambda/event-invoke-config.ts
|
|
898
|
+
var EventInvokeConfig = class extends Resource {
|
|
899
|
+
constructor(logicalId, props) {
|
|
900
|
+
super("AWS::Lambda::EventInvokeConfig", logicalId);
|
|
901
|
+
this.props = props;
|
|
902
|
+
}
|
|
903
|
+
setOnFailure(arn) {
|
|
904
|
+
this.props.onFailure = arn;
|
|
905
|
+
return this;
|
|
906
|
+
}
|
|
907
|
+
setOnSuccess(arn) {
|
|
908
|
+
this.props.onSuccess = arn;
|
|
909
|
+
return this;
|
|
910
|
+
}
|
|
911
|
+
properties() {
|
|
912
|
+
return {
|
|
913
|
+
FunctionName: this.props.functionName,
|
|
914
|
+
Qualifier: this.props.qualifier || "$LATEST",
|
|
915
|
+
...this.attr("MaximumEventAgeInSeconds", this.props.maxEventAge?.toSeconds()),
|
|
916
|
+
...this.attr("MaximumRetryAttempts", this.props.retryAttempts),
|
|
917
|
+
...this.props.onFailure || this.props.onSuccess ? {
|
|
918
|
+
DestinationConfig: {
|
|
919
|
+
...this.props.onFailure ? {
|
|
920
|
+
OnFailure: {
|
|
921
|
+
Destination: this.props.onFailure
|
|
922
|
+
}
|
|
923
|
+
} : {},
|
|
924
|
+
...this.props.onSuccess ? {
|
|
925
|
+
OnSuccess: {
|
|
926
|
+
Destination: this.props.onSuccess
|
|
927
|
+
}
|
|
928
|
+
} : {}
|
|
929
|
+
}
|
|
930
|
+
} : {}
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
// src/plugins/on-failure/util.ts
|
|
936
|
+
var getGlobalOnFailure = ({ config, bootstrap: bootstrap2 }) => {
|
|
937
|
+
return hasOnFailure(config) ? bootstrap2.import("on-failure-queue-arn") : void 0;
|
|
938
|
+
};
|
|
939
|
+
var hasOnFailure = (config) => {
|
|
940
|
+
const onFailure = config.stacks.find((stack) => {
|
|
941
|
+
return typeof stack.onFailure !== "undefined";
|
|
942
|
+
});
|
|
943
|
+
return !!onFailure;
|
|
944
|
+
};
|
|
945
|
+
|
|
922
946
|
// src/plugins/function.ts
|
|
923
947
|
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
948
|
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");
|
|
@@ -933,29 +957,104 @@ var RuntimeSchema = import_zod6.z.enum([
|
|
|
933
957
|
var FunctionSchema = import_zod6.z.union([
|
|
934
958
|
LocalFileSchema,
|
|
935
959
|
import_zod6.z.object({
|
|
960
|
+
/** The file path ofthe function code. */
|
|
936
961
|
file: LocalFileSchema,
|
|
962
|
+
/** The amount of time that Lambda allows a function to run before stopping it.
|
|
963
|
+
* You can specify a size value from 1 second to 15 minutes.
|
|
964
|
+
* @default '10 seconds'
|
|
965
|
+
*/
|
|
937
966
|
timeout: TimeoutSchema.optional(),
|
|
967
|
+
/** The identifier of the function's runtime.
|
|
968
|
+
* @default 'nodejs18.x'
|
|
969
|
+
*/
|
|
938
970
|
runtime: RuntimeSchema.optional(),
|
|
971
|
+
/** The amount of memory available to the function at runtime.
|
|
972
|
+
* Increasing the function memory also increases its CPU allocation.
|
|
973
|
+
* The value can be any multiple of 1 MB.
|
|
974
|
+
* You can specify a size value from 128 MB to 10 GB.
|
|
975
|
+
* @default '128 MB'
|
|
976
|
+
*/
|
|
939
977
|
memorySize: MemorySizeSchema.optional(),
|
|
978
|
+
/** The instruction set architecture that the function supports.
|
|
979
|
+
* @default 'arm64'
|
|
980
|
+
*/
|
|
940
981
|
architecture: ArchitectureSchema.optional(),
|
|
982
|
+
/** The size of the function's /tmp directory.
|
|
983
|
+
* You can specify a size value from 512 MB to 10 GB.
|
|
984
|
+
* @default 512 MB
|
|
985
|
+
*/
|
|
941
986
|
ephemeralStorageSize: EphemeralStorageSizeSchema.optional(),
|
|
987
|
+
/** The maximum number of times to retry when the function returns an error.
|
|
988
|
+
* You can specify a number from 0 to 2.
|
|
989
|
+
* @default 2
|
|
990
|
+
*/
|
|
942
991
|
retryAttempts: RetryAttemptsSchema.optional(),
|
|
992
|
+
/** Environment variable key-value pairs.
|
|
993
|
+
* @example
|
|
994
|
+
* {
|
|
995
|
+
* environment: {
|
|
996
|
+
* name: 'value'
|
|
997
|
+
* }
|
|
998
|
+
* }
|
|
999
|
+
*/
|
|
943
1000
|
environment: EnvironmentSchema.optional()
|
|
1001
|
+
// onFailure: ResourceIdSchema.optional(),
|
|
944
1002
|
})
|
|
945
1003
|
]);
|
|
946
1004
|
var schema = import_zod6.z.object({
|
|
947
1005
|
defaults: import_zod6.z.object({
|
|
948
1006
|
function: import_zod6.z.object({
|
|
1007
|
+
/** The amount of time that Lambda allows a function to run before stopping it.
|
|
1008
|
+
* You can specify a size value from 1 second to 15 minutes.
|
|
1009
|
+
* @default '10 seconds'
|
|
1010
|
+
*/
|
|
949
1011
|
timeout: TimeoutSchema.default("10 seconds"),
|
|
1012
|
+
/** The identifier of the function's runtime.
|
|
1013
|
+
* @default 'nodejs18.x'
|
|
1014
|
+
*/
|
|
950
1015
|
runtime: RuntimeSchema.default("nodejs18.x"),
|
|
1016
|
+
/** The amount of memory available to the function at runtime.
|
|
1017
|
+
* Increasing the function memory also increases its CPU allocation.
|
|
1018
|
+
* The value can be any multiple of 1 MB.
|
|
1019
|
+
* You can specify a size value from 128 MB to 10 GB.
|
|
1020
|
+
* @default '128 MB'
|
|
1021
|
+
*/
|
|
951
1022
|
memorySize: MemorySizeSchema.default("128 MB"),
|
|
1023
|
+
/** The instruction set architecture that the function supports.
|
|
1024
|
+
* @default 'arm64'
|
|
1025
|
+
*/
|
|
952
1026
|
architecture: ArchitectureSchema.default("arm64"),
|
|
1027
|
+
/** The size of the function's /tmp directory.
|
|
1028
|
+
* You can specify a size value from 512 MB to 10 GB.
|
|
1029
|
+
* @default 512 MB
|
|
1030
|
+
*/
|
|
953
1031
|
ephemeralStorageSize: EphemeralStorageSizeSchema.default("512 MB"),
|
|
1032
|
+
/** The maximum number of times to retry when the function returns an error.
|
|
1033
|
+
* You can specify a number from 0 to 2.
|
|
1034
|
+
* @default 2
|
|
1035
|
+
*/
|
|
954
1036
|
retryAttempts: RetryAttemptsSchema.default(2),
|
|
1037
|
+
/** Environment variable key-value pairs.
|
|
1038
|
+
* @example
|
|
1039
|
+
* {
|
|
1040
|
+
* environment: {
|
|
1041
|
+
* name: 'value'
|
|
1042
|
+
* }
|
|
1043
|
+
* }
|
|
1044
|
+
*/
|
|
955
1045
|
environment: EnvironmentSchema.optional()
|
|
1046
|
+
// onFailure: ResourceIdSchema.optional(),
|
|
956
1047
|
}).default({})
|
|
957
1048
|
}).default({}),
|
|
958
1049
|
stacks: import_zod6.z.object({
|
|
1050
|
+
/** Define the functions in your stack.
|
|
1051
|
+
* @example
|
|
1052
|
+
* {
|
|
1053
|
+
* functions: {
|
|
1054
|
+
* FUNCTION_NAME: 'function.ts'
|
|
1055
|
+
* }
|
|
1056
|
+
* }
|
|
1057
|
+
*/
|
|
959
1058
|
functions: import_zod6.z.record(
|
|
960
1059
|
ResourceIdSchema,
|
|
961
1060
|
FunctionSchema
|
|
@@ -966,9 +1065,16 @@ var functionPlugin = definePlugin({
|
|
|
966
1065
|
name: "function",
|
|
967
1066
|
schema,
|
|
968
1067
|
onStack(ctx) {
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1068
|
+
const { config, stack } = ctx;
|
|
1069
|
+
for (const [id, fileOrProps] of Object.entries(ctx.stackConfig.functions || {})) {
|
|
1070
|
+
const props = typeof fileOrProps === "string" ? { ...config.defaults?.function, file: fileOrProps } : { ...config.defaults?.function, ...fileOrProps };
|
|
1071
|
+
const lambda = toLambdaFunction(ctx, id, fileOrProps);
|
|
1072
|
+
const invoke = new EventInvokeConfig(id, {
|
|
1073
|
+
functionName: lambda.name,
|
|
1074
|
+
retryAttempts: props.retryAttempts,
|
|
1075
|
+
onFailure: getGlobalOnFailure(ctx)
|
|
1076
|
+
}).dependsOn(lambda);
|
|
1077
|
+
stack.add(invoke, lambda);
|
|
972
1078
|
}
|
|
973
1079
|
}
|
|
974
1080
|
});
|
|
@@ -981,9 +1087,7 @@ var toLambdaFunction = (ctx, id, fileOrProps) => {
|
|
|
981
1087
|
code: Code.fromFile(id, props.file),
|
|
982
1088
|
...props
|
|
983
1089
|
});
|
|
984
|
-
lambda.addEnvironment("APP", config.name);
|
|
985
|
-
lambda.addEnvironment("STAGE", config.stage);
|
|
986
|
-
lambda.addEnvironment("STACK", stack.name);
|
|
1090
|
+
lambda.addEnvironment("APP", config.name).addEnvironment("STAGE", config.stage).addEnvironment("STACK", stack.name);
|
|
987
1091
|
if (props.runtime.startsWith("nodejs")) {
|
|
988
1092
|
lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1");
|
|
989
1093
|
}
|
|
@@ -1064,9 +1168,26 @@ var cronPlugin = definePlugin({
|
|
|
1064
1168
|
name: "cron",
|
|
1065
1169
|
schema: import_zod7.z.object({
|
|
1066
1170
|
stacks: import_zod7.z.object({
|
|
1171
|
+
/** Define the crons in your stack
|
|
1172
|
+
* @example
|
|
1173
|
+
* {
|
|
1174
|
+
* crons: {
|
|
1175
|
+
* CRON_NAME: {
|
|
1176
|
+
* consumer: 'function.ts',
|
|
1177
|
+
* schedule: 'rate(5 minutes)',
|
|
1178
|
+
* }
|
|
1179
|
+
* }
|
|
1180
|
+
* }
|
|
1181
|
+
* */
|
|
1067
1182
|
crons: import_zod7.z.record(ResourceIdSchema, import_zod7.z.object({
|
|
1183
|
+
/** The consuming lambda function properties */
|
|
1068
1184
|
consumer: FunctionSchema,
|
|
1185
|
+
/** The scheduling expression.
|
|
1186
|
+
* @example 'cron(0 20 * * ? *)'
|
|
1187
|
+
* @example 'rate(5 minutes)'
|
|
1188
|
+
*/
|
|
1069
1189
|
schedule: ScheduleExpressionSchema,
|
|
1190
|
+
// Valid JSON passed to the consumer.
|
|
1070
1191
|
payload: import_zod7.z.unknown().optional()
|
|
1071
1192
|
})).optional()
|
|
1072
1193
|
}).array()
|
|
@@ -1095,6 +1216,10 @@ var Queue = class extends Resource {
|
|
|
1095
1216
|
this.name = formatName(this.props.name || logicalId);
|
|
1096
1217
|
}
|
|
1097
1218
|
name;
|
|
1219
|
+
setDeadLetter(arn) {
|
|
1220
|
+
this.props.deadLetterArn = arn;
|
|
1221
|
+
return this;
|
|
1222
|
+
}
|
|
1098
1223
|
get arn() {
|
|
1099
1224
|
return getAtt(this.logicalId, "Arn");
|
|
1100
1225
|
}
|
|
@@ -1119,7 +1244,12 @@ var Queue = class extends Resource {
|
|
|
1119
1244
|
MaximumMessageSize: this.props.maxMessageSize?.toBytes() ?? Size.kiloBytes(256).toBytes(),
|
|
1120
1245
|
MessageRetentionPeriod: this.props.retentionPeriod?.toSeconds() ?? Duration.days(4).toSeconds(),
|
|
1121
1246
|
ReceiveMessageWaitTimeSeconds: this.props.receiveMessageWaitTime?.toSeconds() ?? 0,
|
|
1122
|
-
VisibilityTimeout: this.props.visibilityTimeout?.toSeconds() ?? 30
|
|
1247
|
+
VisibilityTimeout: this.props.visibilityTimeout?.toSeconds() ?? 30,
|
|
1248
|
+
...this.props.deadLetterArn ? {
|
|
1249
|
+
RedrivePolicy: {
|
|
1250
|
+
deadLetterTargetArn: this.props.deadLetterArn
|
|
1251
|
+
}
|
|
1252
|
+
} : {}
|
|
1123
1253
|
};
|
|
1124
1254
|
}
|
|
1125
1255
|
};
|
|
@@ -1131,6 +1261,10 @@ var EventSourceMapping = class extends Resource {
|
|
|
1131
1261
|
super("AWS::Lambda::EventSourceMapping", logicalId);
|
|
1132
1262
|
this.props = props;
|
|
1133
1263
|
}
|
|
1264
|
+
setOnFailure(arn) {
|
|
1265
|
+
this.props.onFailure = arn;
|
|
1266
|
+
return this;
|
|
1267
|
+
}
|
|
1134
1268
|
properties() {
|
|
1135
1269
|
return {
|
|
1136
1270
|
Enabled: true,
|
|
@@ -1189,7 +1323,7 @@ var queuePlugin = definePlugin({
|
|
|
1189
1323
|
name: "queue",
|
|
1190
1324
|
schema: import_zod8.z.object({
|
|
1191
1325
|
defaults: import_zod8.z.object({
|
|
1192
|
-
/** Define the defaults properties for all queue's in your app */
|
|
1326
|
+
/** Define the defaults properties for all queue's in your app. */
|
|
1193
1327
|
queue: import_zod8.z.object({
|
|
1194
1328
|
/** The number of seconds that Amazon SQS retains a message.
|
|
1195
1329
|
* You can specify a duration value from 1 minute to 14 days.
|
|
@@ -1218,20 +1352,20 @@ var queuePlugin = definePlugin({
|
|
|
1218
1352
|
}).default({})
|
|
1219
1353
|
}).default({}),
|
|
1220
1354
|
stacks: import_zod8.z.object({
|
|
1221
|
-
/** Define the queues in your stack
|
|
1355
|
+
/** Define the queues in your stack.
|
|
1222
1356
|
* @example
|
|
1223
1357
|
* {
|
|
1224
1358
|
* queues: {
|
|
1225
1359
|
* QUEUE_NAME: 'function.ts'
|
|
1226
1360
|
* }
|
|
1227
1361
|
* }
|
|
1228
|
-
|
|
1362
|
+
*/
|
|
1229
1363
|
queues: import_zod8.z.record(
|
|
1230
1364
|
ResourceIdSchema,
|
|
1231
1365
|
import_zod8.z.union([
|
|
1232
1366
|
LocalFileSchema,
|
|
1233
1367
|
import_zod8.z.object({
|
|
1234
|
-
/** The consuming lambda function properties */
|
|
1368
|
+
/** The consuming lambda function properties. */
|
|
1235
1369
|
consumer: FunctionSchema,
|
|
1236
1370
|
/** The number of seconds that Amazon SQS retains a message.
|
|
1237
1371
|
* You can specify a duration value from 1 minute to 14 days.
|
|
@@ -1249,7 +1383,6 @@ var queuePlugin = definePlugin({
|
|
|
1249
1383
|
/** Specifies the duration, in seconds,
|
|
1250
1384
|
* that the ReceiveMessage action call waits until a message is in the queue in order to include it in the response,
|
|
1251
1385
|
* rather than returning an empty response if a message isn't yet available.
|
|
1252
|
-
* You can specify an integer from 1 to 20.
|
|
1253
1386
|
* You can specify a duration value from 1 to 20 seconds.
|
|
1254
1387
|
* @default '0 seconds' */
|
|
1255
1388
|
receiveMessageWaitTime: DurationSchema.optional(),
|
|
@@ -1270,9 +1403,10 @@ var queuePlugin = definePlugin({
|
|
|
1270
1403
|
name: `${config.name}-${stack.name}-${id}`,
|
|
1271
1404
|
...props
|
|
1272
1405
|
});
|
|
1273
|
-
const lambda = toLambdaFunction(ctx, id
|
|
1406
|
+
const lambda = toLambdaFunction(ctx, `queue-${id}`, props.consumer);
|
|
1274
1407
|
const source = new SqsEventSource(id, lambda, {
|
|
1275
|
-
queueArn: queue2.arn
|
|
1408
|
+
queueArn: queue2.arn,
|
|
1409
|
+
onFailure: getGlobalOnFailure(ctx)
|
|
1276
1410
|
});
|
|
1277
1411
|
stack.add(queue2, lambda, source);
|
|
1278
1412
|
bind((lambda2) => {
|
|
@@ -1296,12 +1430,21 @@ var Table = class extends Resource {
|
|
|
1296
1430
|
}
|
|
1297
1431
|
name;
|
|
1298
1432
|
indexes;
|
|
1433
|
+
enableStream(viewType) {
|
|
1434
|
+
this.props.stream = viewType;
|
|
1435
|
+
}
|
|
1299
1436
|
addIndex(name, props) {
|
|
1300
1437
|
this.indexes[name] = props;
|
|
1301
1438
|
}
|
|
1302
|
-
get
|
|
1439
|
+
get id() {
|
|
1303
1440
|
return ref(this.logicalId);
|
|
1304
1441
|
}
|
|
1442
|
+
get arn() {
|
|
1443
|
+
return getAtt(this.logicalId, "Arn");
|
|
1444
|
+
}
|
|
1445
|
+
get streamArn() {
|
|
1446
|
+
return getAtt(this.logicalId, "StreamArn");
|
|
1447
|
+
}
|
|
1305
1448
|
get permissions() {
|
|
1306
1449
|
return {
|
|
1307
1450
|
actions: [
|
|
@@ -1335,6 +1478,11 @@ var Table = class extends Resource {
|
|
|
1335
1478
|
AttributeName: name,
|
|
1336
1479
|
AttributeType: type[0].toUpperCase()
|
|
1337
1480
|
})),
|
|
1481
|
+
...this.props.stream ? {
|
|
1482
|
+
StreamSpecification: {
|
|
1483
|
+
StreamViewType: (0, import_change_case4.constantCase)(this.props.stream)
|
|
1484
|
+
}
|
|
1485
|
+
} : {},
|
|
1338
1486
|
...this.props.timeToLiveAttribute ? {
|
|
1339
1487
|
TimeToLiveSpecification: {
|
|
1340
1488
|
AttributeName: this.props.timeToLiveAttribute,
|
|
@@ -1357,13 +1505,43 @@ var Table = class extends Resource {
|
|
|
1357
1505
|
}
|
|
1358
1506
|
};
|
|
1359
1507
|
|
|
1508
|
+
// src/formation/resource/lambda/event-source/dynamodb.ts
|
|
1509
|
+
var DynamoDBEventSource = class extends Group {
|
|
1510
|
+
constructor(id, lambda, props) {
|
|
1511
|
+
const source = new EventSourceMapping(id, {
|
|
1512
|
+
functionArn: lambda.arn,
|
|
1513
|
+
sourceArn: props.tableArn,
|
|
1514
|
+
batchSize: props.batchSize ?? 100,
|
|
1515
|
+
bisectBatchOnError: props.bisectBatchOnError ?? true,
|
|
1516
|
+
maxBatchingWindow: props.maxBatchingWindow,
|
|
1517
|
+
maxRecordAge: props.maxRecordAge,
|
|
1518
|
+
retryAttempts: props.retryAttempts ?? -1,
|
|
1519
|
+
parallelizationFactor: props.parallelizationFactor ?? 1,
|
|
1520
|
+
startingPosition: props.startingPosition,
|
|
1521
|
+
startingPositionTimestamp: props.startingPositionTimestamp,
|
|
1522
|
+
tumblingWindow: props.tumblingWindow,
|
|
1523
|
+
onFailure: props.onFailure
|
|
1524
|
+
});
|
|
1525
|
+
lambda.addPermissions({
|
|
1526
|
+
actions: [
|
|
1527
|
+
"dynamodb:ListStreams",
|
|
1528
|
+
"dynamodb:DescribeStream",
|
|
1529
|
+
"dynamodb:GetRecords",
|
|
1530
|
+
"dynamodb:GetShardIterator"
|
|
1531
|
+
],
|
|
1532
|
+
resources: [props.tableArn]
|
|
1533
|
+
});
|
|
1534
|
+
super([source]);
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1537
|
+
|
|
1360
1538
|
// src/plugins/table.ts
|
|
1361
1539
|
var KeySchema = import_zod9.z.string().min(1).max(255);
|
|
1362
1540
|
var tablePlugin = definePlugin({
|
|
1363
1541
|
name: "table",
|
|
1364
1542
|
schema: import_zod9.z.object({
|
|
1365
1543
|
stacks: import_zod9.z.object({
|
|
1366
|
-
/** Define the tables in your stack
|
|
1544
|
+
/** Define the tables in your stack.
|
|
1367
1545
|
* @example
|
|
1368
1546
|
* {
|
|
1369
1547
|
* tables: {
|
|
@@ -1390,20 +1568,34 @@ var tablePlugin = definePlugin({
|
|
|
1390
1568
|
* id: 'string'
|
|
1391
1569
|
* }
|
|
1392
1570
|
* }
|
|
1393
|
-
|
|
1571
|
+
*/
|
|
1394
1572
|
fields: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.enum(["string", "number", "binary"])),
|
|
1395
1573
|
/** The table class of the table.
|
|
1396
1574
|
* @default 'standard'
|
|
1397
|
-
|
|
1575
|
+
*/
|
|
1398
1576
|
class: import_zod9.z.enum(["standard", "standard-infrequent-access"]).default("standard"),
|
|
1399
1577
|
/** Indicates whether point in time recovery is enabled on the table.
|
|
1400
1578
|
* @default false
|
|
1401
|
-
|
|
1579
|
+
*/
|
|
1402
1580
|
pointInTimeRecovery: import_zod9.z.boolean().default(false),
|
|
1403
1581
|
/** The name of the TTL attribute used to store the expiration time for items in the table.
|
|
1404
1582
|
* - To update this property, you must first disable TTL and then enable TTL with the new attribute name.
|
|
1405
|
-
|
|
1583
|
+
*/
|
|
1406
1584
|
timeToLiveAttribute: KeySchema.optional(),
|
|
1585
|
+
/** The settings for the DynamoDB table stream, which capture changes to items stored in the table. */
|
|
1586
|
+
stream: import_zod9.z.object({
|
|
1587
|
+
/** When an item in the table is modified,
|
|
1588
|
+
* stream.type determines what information is written to the stream for this table.
|
|
1589
|
+
* Valid values are:
|
|
1590
|
+
* - keys-only - Only the key attributes of the modified item are written to the stream.
|
|
1591
|
+
* - new-image - The entire item, as it appears after it was modified, is written to the stream.
|
|
1592
|
+
* - old-image - The entire item, as it appeared before it was modified, is written to the stream.
|
|
1593
|
+
* - new-and-old-images - Both the new and the old item images of the item are written to the stream.
|
|
1594
|
+
*/
|
|
1595
|
+
type: import_zod9.z.enum(["keys-only", "new-image", "old-image", "new-and-old-images"]),
|
|
1596
|
+
/** The consuming lambda function for the stream */
|
|
1597
|
+
consumer: FunctionSchema
|
|
1598
|
+
}).optional(),
|
|
1407
1599
|
/** Specifies the global secondary indexes to be created on the table.
|
|
1408
1600
|
* @example
|
|
1409
1601
|
* {
|
|
@@ -1413,7 +1605,7 @@ var tablePlugin = definePlugin({
|
|
|
1413
1605
|
* }
|
|
1414
1606
|
* }
|
|
1415
1607
|
* }
|
|
1416
|
-
|
|
1608
|
+
*/
|
|
1417
1609
|
indexes: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.object({
|
|
1418
1610
|
/** Specifies the name of the partition / hash key that makes up the primary key for the global secondary index. */
|
|
1419
1611
|
hash: KeySchema,
|
|
@@ -1441,13 +1633,24 @@ var tablePlugin = definePlugin({
|
|
|
1441
1633
|
).optional()
|
|
1442
1634
|
}).array()
|
|
1443
1635
|
}),
|
|
1444
|
-
onStack(
|
|
1636
|
+
onStack(ctx) {
|
|
1637
|
+
const { config, stack, stackConfig, bind } = ctx;
|
|
1445
1638
|
for (const [id, props] of Object.entries(stackConfig.tables || {})) {
|
|
1446
1639
|
const table = new Table(id, {
|
|
1640
|
+
...props,
|
|
1447
1641
|
name: `${config.name}-${stack.name}-${id}`,
|
|
1448
|
-
|
|
1642
|
+
stream: props.stream?.type
|
|
1449
1643
|
});
|
|
1450
1644
|
stack.add(table);
|
|
1645
|
+
if (props.stream) {
|
|
1646
|
+
const lambda = toLambdaFunction(ctx, `stream-${id}`, props.stream.consumer);
|
|
1647
|
+
const source = new DynamoDBEventSource(id, lambda, {
|
|
1648
|
+
tableArn: table.arn,
|
|
1649
|
+
onFailure: getGlobalOnFailure(ctx),
|
|
1650
|
+
...props.stream
|
|
1651
|
+
});
|
|
1652
|
+
stack.add(lambda, source);
|
|
1653
|
+
}
|
|
1451
1654
|
bind((lambda) => {
|
|
1452
1655
|
lambda.addPermissions(table.permissions);
|
|
1453
1656
|
});
|
|
@@ -1502,12 +1705,12 @@ var storePlugin = definePlugin({
|
|
|
1502
1705
|
name: "store",
|
|
1503
1706
|
schema: import_zod10.z.object({
|
|
1504
1707
|
stacks: import_zod10.z.object({
|
|
1505
|
-
/** Define the stores in your stack
|
|
1708
|
+
/** Define the stores in your stack.
|
|
1506
1709
|
* @example
|
|
1507
1710
|
* {
|
|
1508
1711
|
* stores: [ 'STORE_NAME' ]
|
|
1509
1712
|
* }
|
|
1510
|
-
|
|
1713
|
+
*/
|
|
1511
1714
|
stores: import_zod10.z.array(ResourceIdSchema).optional()
|
|
1512
1715
|
}).array()
|
|
1513
1716
|
}),
|
|
@@ -1591,14 +1794,14 @@ var topicPlugin = definePlugin({
|
|
|
1591
1794
|
name: "topic",
|
|
1592
1795
|
schema: import_zod11.z.object({
|
|
1593
1796
|
stacks: import_zod11.z.object({
|
|
1594
|
-
/** Define the topics to listen too in your stack
|
|
1797
|
+
/** Define the topics to listen too in your stack.
|
|
1595
1798
|
* @example
|
|
1596
1799
|
* {
|
|
1597
1800
|
* topics: {
|
|
1598
1801
|
* TOPIC_NAME: 'function.ts'
|
|
1599
1802
|
* }
|
|
1600
1803
|
* }
|
|
1601
|
-
|
|
1804
|
+
*/
|
|
1602
1805
|
topics: import_zod11.z.record(ResourceIdSchema, FunctionSchema).optional()
|
|
1603
1806
|
}).array()
|
|
1604
1807
|
}),
|
|
@@ -1628,7 +1831,7 @@ var topicPlugin = definePlugin({
|
|
|
1628
1831
|
onStack(ctx) {
|
|
1629
1832
|
const { stack, stackConfig, bootstrap: bootstrap2 } = ctx;
|
|
1630
1833
|
for (const [id, props] of Object.entries(stackConfig.topics || {})) {
|
|
1631
|
-
const lambda = toLambdaFunction(ctx, id
|
|
1834
|
+
const lambda = toLambdaFunction(ctx, `topic-${id}`, props);
|
|
1632
1835
|
const source = new SnsEventSource(id, lambda, {
|
|
1633
1836
|
topicArn: bootstrap2.import(`topic-${id}-arn`)
|
|
1634
1837
|
});
|
|
@@ -1642,10 +1845,10 @@ var import_zod12 = require("zod");
|
|
|
1642
1845
|
var extendPlugin = definePlugin({
|
|
1643
1846
|
name: "extend",
|
|
1644
1847
|
schema: import_zod12.z.object({
|
|
1645
|
-
/** Extend your app with custom resources */
|
|
1848
|
+
/** Extend your app with custom resources. */
|
|
1646
1849
|
extend: import_zod12.z.custom().optional(),
|
|
1647
1850
|
stacks: import_zod12.z.object({
|
|
1648
|
-
/** Extend your stack with custom resources */
|
|
1851
|
+
/** Extend your stack with custom resources. */
|
|
1649
1852
|
extend: import_zod12.z.custom().optional()
|
|
1650
1853
|
}).array()
|
|
1651
1854
|
}),
|
|
@@ -1711,7 +1914,7 @@ var pubsubPlugin = definePlugin({
|
|
|
1711
1914
|
name: "pubsub",
|
|
1712
1915
|
schema: import_zod13.z.object({
|
|
1713
1916
|
stacks: import_zod13.z.object({
|
|
1714
|
-
/** Define the pubsub subscriber in your stack
|
|
1917
|
+
/** Define the pubsub subscriber in your stack.
|
|
1715
1918
|
* @example
|
|
1716
1919
|
* {
|
|
1717
1920
|
* pubsub: {
|
|
@@ -1723,11 +1926,11 @@ var pubsubPlugin = definePlugin({
|
|
|
1723
1926
|
* }
|
|
1724
1927
|
*/
|
|
1725
1928
|
pubsub: import_zod13.z.record(ResourceIdSchema, import_zod13.z.object({
|
|
1726
|
-
/** The SQL statement used to query the iot topic */
|
|
1929
|
+
/** The SQL statement used to query the iot topic. */
|
|
1727
1930
|
sql: import_zod13.z.string(),
|
|
1728
|
-
/** The version of the SQL rules engine to use when evaluating the rule */
|
|
1931
|
+
/** The version of the SQL rules engine to use when evaluating the rule. */
|
|
1729
1932
|
sqlVersion: import_zod13.z.enum(["2015-10-08", "2016-03-23", "beta"]).default("2016-03-23"),
|
|
1730
|
-
/** The consuming lambda function properties */
|
|
1933
|
+
/** The consuming lambda function properties. */
|
|
1731
1934
|
consumer: FunctionSchema
|
|
1732
1935
|
})).optional()
|
|
1733
1936
|
}).array()
|
|
@@ -1743,7 +1946,7 @@ var pubsubPlugin = definePlugin({
|
|
|
1743
1946
|
onStack(ctx) {
|
|
1744
1947
|
const { config, stack, stackConfig } = ctx;
|
|
1745
1948
|
for (const [id, props] of Object.entries(stackConfig.pubsub || {})) {
|
|
1746
|
-
const lambda = toLambdaFunction(ctx, id
|
|
1949
|
+
const lambda = toLambdaFunction(ctx, `pubsub-${id}`, props.consumer);
|
|
1747
1950
|
const source = new IotEventSource(id, lambda, {
|
|
1748
1951
|
name: `${config.name}-${stack.name}-${id}`,
|
|
1749
1952
|
sql: props.sql,
|
|
@@ -1770,34 +1973,6 @@ var import_change_case10 = require("change-case");
|
|
|
1770
1973
|
|
|
1771
1974
|
// src/formation/resource/appsync/graphql-api.ts
|
|
1772
1975
|
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
1976
|
var GraphQLApi = class extends Resource {
|
|
1802
1977
|
constructor(logicalId, props) {
|
|
1803
1978
|
super("AWS::AppSync::GraphQLApi", logicalId);
|
|
@@ -1839,44 +2014,6 @@ var GraphQLApi = class extends Resource {
|
|
|
1839
2014
|
};
|
|
1840
2015
|
}
|
|
1841
2016
|
};
|
|
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
2017
|
|
|
1881
2018
|
// src/formation/resource/route53/record-set.ts
|
|
1882
2019
|
var RecordSet = class extends Resource {
|
|
@@ -1897,19 +2034,33 @@ var RecordSet = class extends Resource {
|
|
|
1897
2034
|
} : {},
|
|
1898
2035
|
...this.props.alias ? {
|
|
1899
2036
|
AliasTarget: {
|
|
1900
|
-
DNSName: this.props.alias,
|
|
1901
|
-
HostedZoneId: this.props.hostedZoneId
|
|
2037
|
+
DNSName: this.props.alias.dnsName,
|
|
2038
|
+
HostedZoneId: this.props.alias.hostedZoneId
|
|
1902
2039
|
}
|
|
1903
2040
|
} : {}
|
|
1904
2041
|
};
|
|
1905
2042
|
}
|
|
1906
2043
|
};
|
|
1907
2044
|
|
|
1908
|
-
// src/formation/resource/appsync/schema.ts
|
|
2045
|
+
// src/formation/resource/appsync/graphql-schema.ts
|
|
1909
2046
|
var import_graphql = require("graphql");
|
|
1910
2047
|
var import_promises2 = require("fs/promises");
|
|
1911
2048
|
var import_merge = require("@graphql-tools/merge");
|
|
1912
|
-
var
|
|
2049
|
+
var GraphQLSchema = class extends Resource {
|
|
2050
|
+
constructor(logicalId, props) {
|
|
2051
|
+
super("AWS::AppSync::GraphQLSchema", logicalId, [
|
|
2052
|
+
props.definition
|
|
2053
|
+
]);
|
|
2054
|
+
this.props = props;
|
|
2055
|
+
}
|
|
2056
|
+
properties() {
|
|
2057
|
+
return {
|
|
2058
|
+
ApiId: this.props.apiId,
|
|
2059
|
+
Definition: this.props.definition.toString()
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
var Definition = class extends Asset {
|
|
1913
2064
|
constructor(id, files) {
|
|
1914
2065
|
super("graphql", id);
|
|
1915
2066
|
this.files = files;
|
|
@@ -1922,10 +2073,14 @@ var Schema = class extends Asset {
|
|
|
1922
2073
|
}));
|
|
1923
2074
|
const defs = (0, import_merge.mergeTypeDefs)(schemas);
|
|
1924
2075
|
const schema2 = (0, import_graphql.print)(defs);
|
|
2076
|
+
const size = Buffer.from(schema2, "utf8").byteLength;
|
|
1925
2077
|
await write("schema.gql", schema2);
|
|
1926
2078
|
this.schema = schema2;
|
|
2079
|
+
return {
|
|
2080
|
+
size: formatByteSize(size)
|
|
2081
|
+
};
|
|
1927
2082
|
}
|
|
1928
|
-
|
|
2083
|
+
toString() {
|
|
1929
2084
|
return this.schema;
|
|
1930
2085
|
}
|
|
1931
2086
|
};
|
|
@@ -2105,6 +2260,41 @@ var AppsyncEventSource = class extends Group {
|
|
|
2105
2260
|
}
|
|
2106
2261
|
};
|
|
2107
2262
|
|
|
2263
|
+
// src/formation/resource/appsync/domain-name.ts
|
|
2264
|
+
var DomainName = class extends Resource {
|
|
2265
|
+
constructor(logicalId, props) {
|
|
2266
|
+
super("AWS::AppSync::DomainName", logicalId);
|
|
2267
|
+
this.props = props;
|
|
2268
|
+
}
|
|
2269
|
+
get appSyncDomainName() {
|
|
2270
|
+
return getAtt(this.logicalId, "AppSyncDomainName");
|
|
2271
|
+
}
|
|
2272
|
+
get domainName() {
|
|
2273
|
+
return getAtt(this.logicalId, "DomainName");
|
|
2274
|
+
}
|
|
2275
|
+
get hostedZoneId() {
|
|
2276
|
+
return getAtt(this.logicalId, "HostedZoneId");
|
|
2277
|
+
}
|
|
2278
|
+
properties() {
|
|
2279
|
+
return {
|
|
2280
|
+
DomainName: this.props.domainName,
|
|
2281
|
+
CertificateArn: this.props.certificateArn
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
};
|
|
2285
|
+
var DomainNameApiAssociation = class extends Resource {
|
|
2286
|
+
constructor(logicalId, props) {
|
|
2287
|
+
super("AWS::AppSync::DomainNameApiAssociation", logicalId);
|
|
2288
|
+
this.props = props;
|
|
2289
|
+
}
|
|
2290
|
+
properties() {
|
|
2291
|
+
return {
|
|
2292
|
+
ApiId: this.props.apiId,
|
|
2293
|
+
DomainName: this.props.domainName
|
|
2294
|
+
};
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
|
|
2108
2298
|
// src/plugins/graphql.ts
|
|
2109
2299
|
var defaultResolver = `
|
|
2110
2300
|
export function request(ctx) {
|
|
@@ -2154,38 +2344,51 @@ var graphqlPlugin = definePlugin({
|
|
|
2154
2344
|
}
|
|
2155
2345
|
}
|
|
2156
2346
|
for (const id of apis) {
|
|
2157
|
-
const
|
|
2347
|
+
const schemaFiles = [];
|
|
2158
2348
|
for (const stack of config.stacks) {
|
|
2159
2349
|
const files = toArray(stack.graphql?.[id]?.schema || []);
|
|
2160
|
-
|
|
2350
|
+
schemaFiles.push(...files);
|
|
2161
2351
|
}
|
|
2162
|
-
const
|
|
2352
|
+
const api = new GraphQLApi(id, {
|
|
2163
2353
|
name: `${config.name}-${id}`,
|
|
2164
|
-
authenticationType: "api-key"
|
|
2165
|
-
schema: new Schema(id, schema2)
|
|
2354
|
+
authenticationType: "api-key"
|
|
2166
2355
|
});
|
|
2167
|
-
|
|
2356
|
+
const schema2 = new GraphQLSchema(id, {
|
|
2357
|
+
apiId: api.id,
|
|
2358
|
+
definition: new Definition(id, schemaFiles)
|
|
2359
|
+
}).dependsOn(api);
|
|
2360
|
+
bootstrap2.add(api).add(schema2).export(`graphql-${id}`, api.id);
|
|
2168
2361
|
const props = config.defaults.graphql?.[id];
|
|
2169
2362
|
if (!props) {
|
|
2170
2363
|
continue;
|
|
2171
2364
|
}
|
|
2172
2365
|
if (props.authorization) {
|
|
2173
2366
|
const lambda = toLambdaFunction(ctx, `${id}-authorizer`, props.authorization.authorizer);
|
|
2174
|
-
|
|
2367
|
+
api.addLambdaAuthProvider(lambda.arn, props.authorization.ttl);
|
|
2175
2368
|
bootstrap2.add(lambda);
|
|
2176
2369
|
}
|
|
2177
2370
|
if (props.domain) {
|
|
2178
2371
|
const domainName = props.subDomain ? `${props.subDomain}.${props.domain}` : props.domain;
|
|
2179
|
-
const hostedZoneId =
|
|
2372
|
+
const hostedZoneId = usEastBootstrap.import(`hosted-zone-${props.domain}-id`);
|
|
2180
2373
|
const certificateArn = usEastBootstrap.import(`certificate-${props.domain}-arn`);
|
|
2181
|
-
|
|
2182
|
-
|
|
2374
|
+
const domain = new DomainName(id, {
|
|
2375
|
+
domainName,
|
|
2376
|
+
certificateArn
|
|
2377
|
+
});
|
|
2378
|
+
const association = new DomainNameApiAssociation(id, {
|
|
2379
|
+
apiId: api.id,
|
|
2380
|
+
domainName: domain.domainName
|
|
2381
|
+
}).dependsOn(api, domain);
|
|
2382
|
+
const record = new RecordSet(`${id}-graphql`, {
|
|
2183
2383
|
hostedZoneId,
|
|
2184
2384
|
type: "A",
|
|
2185
2385
|
name: domainName,
|
|
2186
|
-
alias:
|
|
2187
|
-
|
|
2188
|
-
|
|
2386
|
+
alias: {
|
|
2387
|
+
dnsName: domain.appSyncDomainName,
|
|
2388
|
+
hostedZoneId: domain.hostedZoneId
|
|
2389
|
+
}
|
|
2390
|
+
}).dependsOn(domain, association);
|
|
2391
|
+
bootstrap2.add(domain, association, record);
|
|
2189
2392
|
}
|
|
2190
2393
|
}
|
|
2191
2394
|
},
|
|
@@ -2196,7 +2399,7 @@ var graphqlPlugin = definePlugin({
|
|
|
2196
2399
|
for (const [typeAndField, functionProps] of Object.entries(props.resolvers || {})) {
|
|
2197
2400
|
const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
|
|
2198
2401
|
const entryId = (0, import_change_case10.paramCase)(`${id}-${typeName}-${fieldName}`);
|
|
2199
|
-
const lambda = toLambdaFunction(ctx, entryId
|
|
2402
|
+
const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
|
|
2200
2403
|
const source = new AppsyncEventSource(entryId, lambda, {
|
|
2201
2404
|
apiId,
|
|
2202
2405
|
typeName,
|
|
@@ -2232,7 +2435,7 @@ var HostedZone = class extends Resource {
|
|
|
2232
2435
|
|
|
2233
2436
|
// src/formation/resource/certificate-manager/certificate.ts
|
|
2234
2437
|
var Certificate = class extends Resource {
|
|
2235
|
-
constructor(logicalId, props
|
|
2438
|
+
constructor(logicalId, props) {
|
|
2236
2439
|
super("AWS::CertificateManager::Certificate", logicalId);
|
|
2237
2440
|
this.props = props;
|
|
2238
2441
|
this.name = this.props.domainName || logicalId;
|
|
@@ -2244,8 +2447,12 @@ var Certificate = class extends Resource {
|
|
|
2244
2447
|
properties() {
|
|
2245
2448
|
return {
|
|
2246
2449
|
DomainName: this.name,
|
|
2450
|
+
SubjectAlternativeNames: this.props.alternativeNames || [],
|
|
2247
2451
|
ValidationMethod: "DNS",
|
|
2248
|
-
|
|
2452
|
+
DomainValidationOptions: [{
|
|
2453
|
+
DomainName: this.name,
|
|
2454
|
+
HostedZoneId: this.props.hostedZoneId
|
|
2455
|
+
}]
|
|
2249
2456
|
};
|
|
2250
2457
|
}
|
|
2251
2458
|
};
|
|
@@ -2277,40 +2484,965 @@ var RecordSetGroup = class extends Resource {
|
|
|
2277
2484
|
}
|
|
2278
2485
|
};
|
|
2279
2486
|
|
|
2280
|
-
// src/
|
|
2281
|
-
var
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2487
|
+
// src/custom/delete-hosted-zone/handler.ts
|
|
2488
|
+
var deleteHostedZoneRecordsHandlerCode = (
|
|
2489
|
+
/* JS */
|
|
2490
|
+
`
|
|
2491
|
+
|
|
2492
|
+
const { Route53Client, ListResourceRecordSetsCommand, ChangeResourceRecordSetsCommand } = require('@aws-sdk/client-route-53')
|
|
2493
|
+
|
|
2494
|
+
const client = new Route53Client({})
|
|
2495
|
+
|
|
2496
|
+
exports.handler = async (event) => {
|
|
2497
|
+
const type = event.RequestType
|
|
2498
|
+
const hostedZoneId = event.ResourceProperties.hostedZoneId
|
|
2499
|
+
|
|
2500
|
+
try {
|
|
2501
|
+
if(type === 'Delete') {
|
|
2502
|
+
const records = await listHostedZoneRecords(hostedZoneId)
|
|
2503
|
+
console.log(records)
|
|
2504
|
+
|
|
2505
|
+
await deleteHostedZoneRecords(hostedZoneId, records)
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
await send(event, hostedZoneId, 'SUCCESS')
|
|
2509
|
+
}
|
|
2510
|
+
catch(error) {
|
|
2511
|
+
if (error instanceof Error) {
|
|
2512
|
+
await send(event, hostedZoneId, 'FAILED', {}, error.message)
|
|
2513
|
+
} else {
|
|
2514
|
+
await send(event, hostedZoneId, 'FAILED', {}, 'Unknown error')
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
const send = async (event, id, status, data = {}, reason = '') => {
|
|
2520
|
+
const body = JSON.stringify({
|
|
2521
|
+
Status: status,
|
|
2522
|
+
Reason: reason,
|
|
2523
|
+
PhysicalResourceId: id,
|
|
2524
|
+
StackId: event.StackId,
|
|
2525
|
+
RequestId: event.RequestId,
|
|
2526
|
+
LogicalResourceId: event.LogicalResourceId,
|
|
2527
|
+
NoEcho: false,
|
|
2528
|
+
Data: data
|
|
2529
|
+
})
|
|
2530
|
+
|
|
2531
|
+
await fetch(event.ResponseURL, {
|
|
2532
|
+
method: 'PUT',
|
|
2533
|
+
port: 443,
|
|
2534
|
+
body,
|
|
2535
|
+
headers: {
|
|
2536
|
+
'content-type': '',
|
|
2537
|
+
'content-length': Buffer.from(body).byteLength,
|
|
2538
|
+
},
|
|
2539
|
+
})
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
const deleteHostedZoneRecords = async (hostedZoneId, records) => {
|
|
2543
|
+
records = records.filter(record => ![ 'SOA', 'NS' ].includes(record.Type))
|
|
2544
|
+
if(records.length === 0) {
|
|
2545
|
+
return
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
const chunkSize = 100;
|
|
2549
|
+
for (let i = 0; i < records.length; i += chunkSize) {
|
|
2550
|
+
const chunk = records.slice(i, i + chunkSize);
|
|
2551
|
+
|
|
2552
|
+
await client.send(new ChangeResourceRecordSetsCommand({
|
|
2553
|
+
HostedZoneId: hostedZoneId,
|
|
2554
|
+
ChangeBatch: {
|
|
2555
|
+
Changes: chunk.map(record => ({
|
|
2556
|
+
Action: 'DELETE',
|
|
2557
|
+
ResourceRecordSet: record
|
|
2558
|
+
}))
|
|
2559
|
+
}
|
|
2560
|
+
}))
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
|
|
2564
|
+
const listHostedZoneRecords = async (hostedZoneId) => {
|
|
2565
|
+
|
|
2566
|
+
const records = []
|
|
2567
|
+
let token
|
|
2568
|
+
|
|
2569
|
+
while(true) {
|
|
2570
|
+
const result = await client.send(new ListResourceRecordSetsCommand({
|
|
2571
|
+
HostedZoneId: hostedZoneId,
|
|
2572
|
+
NextRecordName: token
|
|
2573
|
+
}))
|
|
2574
|
+
|
|
2575
|
+
if(result.ResourceRecordSets && result.ResourceRecordSets.length) {
|
|
2576
|
+
records.push(...result.ResourceRecordSets)
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
if(result.NextRecordName) {
|
|
2580
|
+
token = result.NextRecordName
|
|
2581
|
+
} else {
|
|
2582
|
+
return records
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
`
|
|
2587
|
+
);
|
|
2588
|
+
|
|
2589
|
+
// src/formation/resource/cloud-formation/custom-resource.ts
|
|
2590
|
+
var CustomResource = class extends Resource {
|
|
2591
|
+
constructor(logicalId, props) {
|
|
2592
|
+
super("AWS::CloudFormation::CustomResource", logicalId);
|
|
2593
|
+
this.props = props;
|
|
2594
|
+
}
|
|
2595
|
+
getAtt(name) {
|
|
2596
|
+
return getAtt(this.logicalId, name);
|
|
2597
|
+
}
|
|
2598
|
+
properties() {
|
|
2599
|
+
return {
|
|
2600
|
+
ServiceToken: this.props.serviceToken,
|
|
2601
|
+
...this.props.properties
|
|
2602
|
+
};
|
|
2603
|
+
}
|
|
2604
|
+
};
|
|
2605
|
+
|
|
2606
|
+
// src/plugins/domain.ts
|
|
2607
|
+
var DomainNameSchema = import_zod15.z.string().regex(/[a-z\-\_\.]/g, "Invalid domain name");
|
|
2608
|
+
var domainPlugin = definePlugin({
|
|
2609
|
+
name: "domain",
|
|
2610
|
+
schema: import_zod15.z.object({
|
|
2611
|
+
/** Define the domains for your application.
|
|
2612
|
+
* @example
|
|
2613
|
+
* {
|
|
2614
|
+
* domains: {
|
|
2615
|
+
* 'example.com': [{
|
|
2616
|
+
* name: 'www',
|
|
2617
|
+
* type: 'TXT',
|
|
2618
|
+
* ttl: '60 seconds',
|
|
2619
|
+
* records: [ 'value' ]
|
|
2620
|
+
* }]
|
|
2621
|
+
* }
|
|
2622
|
+
* }
|
|
2623
|
+
*/
|
|
2624
|
+
domains: import_zod15.z.record(DomainNameSchema, import_zod15.z.object({
|
|
2625
|
+
/** Enter a fully qualified domain name, for example, www.example.com.
|
|
2626
|
+
* You can optionally include a trailing dot.
|
|
2627
|
+
* If you omit the trailing dot, Amazon Route 53 assumes that the domain name that you specify is fully qualified.
|
|
2628
|
+
* This means that Route 53 treats www.example.com (without a trailing dot) and www.example.com. (with a trailing dot) as identical.
|
|
2629
|
+
*/
|
|
2630
|
+
name: DomainNameSchema.optional(),
|
|
2631
|
+
/** The DNS record type. */
|
|
2632
|
+
type: import_zod15.z.enum(["A", "AAAA", "CAA", "CNAME", "DS", "MX", "NAPTR", "NS", "PTR", "SOA", "SPF", "SRV", "TXT"]),
|
|
2633
|
+
/** The resource record cache time to live (TTL) */
|
|
2634
|
+
ttl: DurationSchema,
|
|
2635
|
+
/** One or more values that correspond with the value that you specified for the Type property. */
|
|
2636
|
+
records: import_zod15.z.string().array()
|
|
2637
|
+
}).array()).optional()
|
|
2638
|
+
}),
|
|
2639
|
+
onApp({ config, bootstrap: bootstrap2, usEastBootstrap }) {
|
|
2640
|
+
const domains = Object.entries(config.domains || {});
|
|
2641
|
+
if (domains.length === 0) {
|
|
2642
|
+
return;
|
|
2643
|
+
}
|
|
2644
|
+
const lambda = new Function("delete-hosted-zone", {
|
|
2645
|
+
name: `${config.name}-delete-hosted-zone`,
|
|
2646
|
+
code: Code.fromInline(deleteHostedZoneRecordsHandlerCode, "index.handler")
|
|
2647
|
+
});
|
|
2648
|
+
lambda.addPermissions({
|
|
2649
|
+
actions: [
|
|
2650
|
+
"route53:ListResourceRecordSets",
|
|
2651
|
+
"route53:ChangeResourceRecordSets"
|
|
2652
|
+
],
|
|
2653
|
+
resources: ["*"]
|
|
2654
|
+
});
|
|
2655
|
+
usEastBootstrap.add(lambda);
|
|
2656
|
+
for (const [domain, records] of domains) {
|
|
2657
|
+
const hostedZone = new HostedZone(domain);
|
|
2658
|
+
const usEastCertificate = new Certificate(domain, {
|
|
2659
|
+
hostedZoneId: hostedZone.id,
|
|
2660
|
+
alternativeNames: [`*.${domain}`]
|
|
2661
|
+
});
|
|
2662
|
+
const custom = new CustomResource(domain, {
|
|
2663
|
+
serviceToken: lambda.arn,
|
|
2664
|
+
properties: {
|
|
2665
|
+
hostedZoneId: hostedZone.id
|
|
2666
|
+
}
|
|
2667
|
+
}).dependsOn(hostedZone);
|
|
2668
|
+
usEastBootstrap.add(custom).add(hostedZone).add(usEastCertificate).export(`certificate-${domain}-arn`, usEastCertificate.arn).export(`hosted-zone-${domain}-id`, hostedZone.id);
|
|
2669
|
+
const certificate = new Certificate(domain, {
|
|
2670
|
+
hostedZoneId: usEastBootstrap.import(`hosted-zone-${domain}-id`),
|
|
2671
|
+
alternativeNames: [`*.${domain}`]
|
|
2672
|
+
});
|
|
2673
|
+
bootstrap2.add(certificate).export(`certificate-${domain}-arn`, certificate.arn);
|
|
2674
|
+
if (records.length > 0) {
|
|
2675
|
+
const group = new RecordSetGroup(domain, {
|
|
2676
|
+
hostedZoneId: hostedZone.id,
|
|
2677
|
+
records
|
|
2678
|
+
}).dependsOn(hostedZone);
|
|
2679
|
+
usEastBootstrap.add(group);
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
});
|
|
2684
|
+
|
|
2685
|
+
// src/plugins/on-failure/index.ts
|
|
2686
|
+
var import_zod16 = require("zod");
|
|
2687
|
+
var onFailurePlugin = definePlugin({
|
|
2688
|
+
name: "on-failure",
|
|
2689
|
+
schema: import_zod16.z.object({
|
|
2690
|
+
stacks: import_zod16.z.object({
|
|
2691
|
+
/** Defining a onFailure handler will add a global onFailure handler for the following resources:
|
|
2692
|
+
* - Async lambda functions
|
|
2693
|
+
* - SQS queues
|
|
2694
|
+
* - DynamoDB streams
|
|
2695
|
+
* @example
|
|
2696
|
+
* {
|
|
2697
|
+
* onFailure: 'on-failure.ts'
|
|
2698
|
+
* }
|
|
2699
|
+
*/
|
|
2700
|
+
onFailure: FunctionSchema.optional()
|
|
2701
|
+
}).array()
|
|
2702
|
+
}),
|
|
2703
|
+
onApp({ config, bootstrap: bootstrap2 }) {
|
|
2704
|
+
if (!hasOnFailure(config)) {
|
|
2705
|
+
return;
|
|
2706
|
+
}
|
|
2707
|
+
const queue2 = new Queue("on-failure", {
|
|
2708
|
+
name: `${config.name}-failure`
|
|
2709
|
+
});
|
|
2710
|
+
bootstrap2.add(queue2).export("on-failure-queue-arn", queue2.arn);
|
|
2711
|
+
},
|
|
2712
|
+
onStack(ctx) {
|
|
2713
|
+
const { stack, stackConfig, bootstrap: bootstrap2 } = ctx;
|
|
2714
|
+
const onFailure = stackConfig.onFailure;
|
|
2715
|
+
if (!onFailure) {
|
|
2716
|
+
return;
|
|
2717
|
+
}
|
|
2718
|
+
const queueArn = bootstrap2.import("on-failure-queue-arn");
|
|
2719
|
+
const lambda = toLambdaFunction(ctx, "on-failure", onFailure);
|
|
2720
|
+
const source = new SqsEventSource("on-failure", lambda, {
|
|
2721
|
+
queueArn
|
|
2722
|
+
});
|
|
2723
|
+
lambda.addPermissions({
|
|
2724
|
+
actions: [
|
|
2725
|
+
"sqs:SendMessage",
|
|
2726
|
+
"sqs:ReceiveMessage",
|
|
2727
|
+
"sqs:GetQueueUrl",
|
|
2728
|
+
"sqs:GetQueueAttributes"
|
|
2729
|
+
],
|
|
2730
|
+
resources: [queueArn]
|
|
2731
|
+
});
|
|
2732
|
+
stack.add(lambda, source);
|
|
2733
|
+
}
|
|
2734
|
+
});
|
|
2735
|
+
|
|
2736
|
+
// src/formation/resource/ec2/vpc.ts
|
|
2737
|
+
var Vpc = class extends Resource {
|
|
2738
|
+
constructor(logicalId, props) {
|
|
2739
|
+
super("AWS::EC2::VPC", logicalId);
|
|
2740
|
+
this.props = props;
|
|
2741
|
+
}
|
|
2742
|
+
get id() {
|
|
2743
|
+
return ref(this.logicalId);
|
|
2744
|
+
}
|
|
2745
|
+
properties() {
|
|
2746
|
+
return {
|
|
2747
|
+
CidrBlock: this.props.cidrBlock.ip
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
};
|
|
2751
|
+
var RouteTable = class extends Resource {
|
|
2752
|
+
constructor(logicalId, props) {
|
|
2753
|
+
super("AWS::EC2::RouteTable", logicalId);
|
|
2754
|
+
this.props = props;
|
|
2755
|
+
this.name = formatName(props.name || logicalId);
|
|
2756
|
+
}
|
|
2757
|
+
name;
|
|
2758
|
+
get id() {
|
|
2759
|
+
return ref(this.logicalId);
|
|
2760
|
+
}
|
|
2761
|
+
properties() {
|
|
2762
|
+
return {
|
|
2763
|
+
VpcId: this.props.vpcId,
|
|
2764
|
+
Tags: [{
|
|
2765
|
+
Key: "name",
|
|
2766
|
+
Value: this.name
|
|
2767
|
+
}]
|
|
2768
|
+
};
|
|
2769
|
+
}
|
|
2770
|
+
};
|
|
2771
|
+
var InternetGateway = class extends Resource {
|
|
2772
|
+
constructor(logicalId) {
|
|
2773
|
+
super("AWS::EC2::InternetGateway", logicalId);
|
|
2774
|
+
}
|
|
2775
|
+
get id() {
|
|
2776
|
+
return ref(this.logicalId);
|
|
2777
|
+
}
|
|
2778
|
+
properties() {
|
|
2779
|
+
return {};
|
|
2780
|
+
}
|
|
2781
|
+
};
|
|
2782
|
+
var VPCGatewayAttachment = class extends Resource {
|
|
2783
|
+
constructor(logicalId, props) {
|
|
2784
|
+
super("AWS::EC2::VPCGatewayAttachment", logicalId);
|
|
2785
|
+
this.props = props;
|
|
2786
|
+
}
|
|
2787
|
+
get id() {
|
|
2788
|
+
return ref(this.logicalId);
|
|
2789
|
+
}
|
|
2790
|
+
properties() {
|
|
2791
|
+
return {
|
|
2792
|
+
VpcId: this.props.vpcId,
|
|
2793
|
+
InternetGatewayId: this.props.internetGatewayId
|
|
2794
|
+
};
|
|
2795
|
+
}
|
|
2796
|
+
};
|
|
2797
|
+
var Route = class extends Resource {
|
|
2798
|
+
constructor(logicalId, props) {
|
|
2799
|
+
super("AWS::EC2::Route", logicalId);
|
|
2800
|
+
this.props = props;
|
|
2801
|
+
}
|
|
2802
|
+
get id() {
|
|
2803
|
+
return ref(this.logicalId);
|
|
2804
|
+
}
|
|
2805
|
+
properties() {
|
|
2806
|
+
return {
|
|
2807
|
+
GatewayId: this.props.gatewayId,
|
|
2808
|
+
RouteTableId: this.props.routeTableId,
|
|
2809
|
+
DestinationCidrBlock: this.props.destination.ip
|
|
2810
|
+
};
|
|
2811
|
+
}
|
|
2812
|
+
};
|
|
2813
|
+
var Subnet = class extends Resource {
|
|
2814
|
+
constructor(logicalId, props) {
|
|
2815
|
+
super("AWS::EC2::Subnet", logicalId);
|
|
2816
|
+
this.props = props;
|
|
2817
|
+
}
|
|
2818
|
+
get id() {
|
|
2819
|
+
return ref(this.logicalId);
|
|
2820
|
+
}
|
|
2821
|
+
properties() {
|
|
2822
|
+
return {
|
|
2823
|
+
VpcId: this.props.vpcId,
|
|
2824
|
+
CidrBlock: this.props.cidrBlock.ip,
|
|
2825
|
+
AvailabilityZone: this.props.availabilityZone
|
|
2826
|
+
};
|
|
2827
|
+
}
|
|
2828
|
+
};
|
|
2829
|
+
var SubnetRouteTableAssociation = class extends Resource {
|
|
2830
|
+
constructor(logicalId, props) {
|
|
2831
|
+
super("AWS::EC2::SubnetRouteTableAssociation", logicalId);
|
|
2832
|
+
this.props = props;
|
|
2833
|
+
}
|
|
2834
|
+
get id() {
|
|
2835
|
+
return ref(this.logicalId);
|
|
2836
|
+
}
|
|
2837
|
+
properties() {
|
|
2838
|
+
return {
|
|
2839
|
+
SubnetId: this.props.subnetId,
|
|
2840
|
+
RouteTableId: this.props.routeTableId
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2843
|
+
};
|
|
2844
|
+
|
|
2845
|
+
// src/formation/resource/ec2/peer.ts
|
|
2846
|
+
var Peer = class {
|
|
2847
|
+
constructor(ip, type) {
|
|
2848
|
+
this.ip = ip;
|
|
2849
|
+
this.type = type;
|
|
2850
|
+
}
|
|
2851
|
+
static ipv4(cidrIp) {
|
|
2852
|
+
const cidrMatch = cidrIp.match(/^(\d{1,3}\.){3}\d{1,3}(\/\d+)?$/);
|
|
2853
|
+
if (!cidrMatch) {
|
|
2854
|
+
throw new Error(`Invalid IPv4 CIDR: "${cidrIp}"`);
|
|
2855
|
+
}
|
|
2856
|
+
if (!cidrMatch[2]) {
|
|
2857
|
+
throw new Error(`CIDR mask is missing in IPv4: "${cidrIp}". Did you mean "${cidrIp}/32"?`);
|
|
2858
|
+
}
|
|
2859
|
+
return new Peer(cidrIp, "v4");
|
|
2860
|
+
}
|
|
2861
|
+
static anyIpv4() {
|
|
2862
|
+
return new Peer("0.0.0.0/0", "v4");
|
|
2863
|
+
}
|
|
2864
|
+
static ipv6(cidrIpv6) {
|
|
2865
|
+
const cidrMatch = cidrIpv6.match(/^([\da-f]{0,4}:){2,7}([\da-f]{0,4})?(\/\d+)?$/);
|
|
2866
|
+
if (!cidrMatch) {
|
|
2867
|
+
throw new Error(`Invalid IPv6 CIDR: "${cidrIpv6}"`);
|
|
2868
|
+
}
|
|
2869
|
+
if (!cidrMatch[3]) {
|
|
2870
|
+
throw new Error(`CIDR mask is missing in IPv6: "${cidrIpv6}". Did you mean "${cidrIpv6}/128"?`);
|
|
2871
|
+
}
|
|
2872
|
+
return new Peer(cidrIpv6, "v6");
|
|
2873
|
+
}
|
|
2874
|
+
static anyIpv6() {
|
|
2875
|
+
return new Peer("::/0", "v6");
|
|
2876
|
+
}
|
|
2877
|
+
toRuleJson() {
|
|
2878
|
+
switch (this.type) {
|
|
2879
|
+
case "v4":
|
|
2880
|
+
return { CidrIp: this.ip };
|
|
2881
|
+
case "v6":
|
|
2882
|
+
return { CidrIpv6: this.ip };
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
toString() {
|
|
2886
|
+
return this.ip;
|
|
2887
|
+
}
|
|
2888
|
+
};
|
|
2889
|
+
|
|
2890
|
+
// src/plugins/vpc.ts
|
|
2891
|
+
var vpcPlugin = definePlugin({
|
|
2892
|
+
name: "vpc",
|
|
2893
|
+
// schema: z.object({
|
|
2894
|
+
// defaults: z.object({
|
|
2895
|
+
// vpc: z.boolean().default(false),
|
|
2896
|
+
// }).default({}),
|
|
2897
|
+
// }),
|
|
2898
|
+
onApp({ config, bootstrap: bootstrap2 }) {
|
|
2899
|
+
const vpc = new Vpc("main", {
|
|
2900
|
+
cidrBlock: Peer.ipv4("10.0.0.0/16")
|
|
2901
|
+
});
|
|
2902
|
+
const privateRouteTable = new RouteTable("private", {
|
|
2903
|
+
vpcId: vpc.id,
|
|
2904
|
+
name: "private"
|
|
2905
|
+
}).dependsOn(vpc);
|
|
2906
|
+
const publicRouteTable = new RouteTable("public", {
|
|
2907
|
+
vpcId: vpc.id,
|
|
2908
|
+
name: "public"
|
|
2909
|
+
}).dependsOn(vpc);
|
|
2910
|
+
const gateway = new InternetGateway("");
|
|
2911
|
+
const attachment = new VPCGatewayAttachment("", {
|
|
2912
|
+
vpcId: vpc.id,
|
|
2913
|
+
internetGatewayId: gateway.id
|
|
2914
|
+
}).dependsOn(vpc, gateway);
|
|
2915
|
+
const route = new Route("", {
|
|
2916
|
+
gatewayId: gateway.id,
|
|
2917
|
+
routeTableId: publicRouteTable.id,
|
|
2918
|
+
destination: Peer.anyIpv4()
|
|
2919
|
+
}).dependsOn(gateway, publicRouteTable);
|
|
2920
|
+
bootstrap2.export(`vpc-id`, vpc.id);
|
|
2921
|
+
bootstrap2.add(
|
|
2922
|
+
vpc,
|
|
2923
|
+
privateRouteTable,
|
|
2924
|
+
publicRouteTable,
|
|
2925
|
+
gateway,
|
|
2926
|
+
attachment,
|
|
2927
|
+
route
|
|
2928
|
+
);
|
|
2929
|
+
const zones = ["a", "b"];
|
|
2930
|
+
const tables = [privateRouteTable, publicRouteTable];
|
|
2931
|
+
let block = 0;
|
|
2932
|
+
for (const table of tables) {
|
|
2933
|
+
for (const i in zones) {
|
|
2934
|
+
const id = `${table.name}-${i}`;
|
|
2935
|
+
const subnet = new Subnet(id, {
|
|
2936
|
+
vpcId: vpc.id,
|
|
2937
|
+
cidrBlock: Peer.ipv4(`10.0.${block++}.0/24`),
|
|
2938
|
+
availabilityZone: config.region + zones[i]
|
|
2939
|
+
}).dependsOn(vpc);
|
|
2940
|
+
const association = new SubnetRouteTableAssociation(id, {
|
|
2941
|
+
routeTableId: table.id,
|
|
2942
|
+
subnetId: subnet.id
|
|
2943
|
+
}).dependsOn(subnet, table);
|
|
2944
|
+
bootstrap2.export(`${table.name}-subnet-${Number(i) + 1}`, subnet.id);
|
|
2945
|
+
bootstrap2.add(
|
|
2946
|
+
subnet,
|
|
2947
|
+
association
|
|
2948
|
+
);
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
});
|
|
2953
|
+
|
|
2954
|
+
// src/plugins/http.ts
|
|
2955
|
+
var import_zod17 = require("zod");
|
|
2956
|
+
|
|
2957
|
+
// src/formation/resource/ec2/security-group.ts
|
|
2958
|
+
var SecurityGroup = class extends Resource {
|
|
2959
|
+
constructor(logicalId, props) {
|
|
2960
|
+
super("AWS::EC2::SecurityGroup", logicalId);
|
|
2961
|
+
this.props = props;
|
|
2962
|
+
}
|
|
2963
|
+
ingress = [];
|
|
2964
|
+
egress = [];
|
|
2965
|
+
get id() {
|
|
2966
|
+
return ref(this.logicalId);
|
|
2967
|
+
}
|
|
2968
|
+
addIngressRule(peer, port, description) {
|
|
2969
|
+
this.ingress.push({
|
|
2970
|
+
peer,
|
|
2971
|
+
port,
|
|
2972
|
+
description
|
|
2973
|
+
});
|
|
2974
|
+
return this;
|
|
2975
|
+
}
|
|
2976
|
+
addEgressRule(peer, port, description) {
|
|
2977
|
+
this.egress.push({
|
|
2978
|
+
peer,
|
|
2979
|
+
port,
|
|
2980
|
+
description
|
|
2981
|
+
});
|
|
2982
|
+
return this;
|
|
2983
|
+
}
|
|
2984
|
+
properties() {
|
|
2985
|
+
return {
|
|
2986
|
+
VpcId: this.props.vpcId,
|
|
2987
|
+
GroupName: this.logicalId,
|
|
2988
|
+
GroupDescription: this.props.description,
|
|
2989
|
+
SecurityGroupIngress: this.ingress.map((rule) => ({
|
|
2990
|
+
Description: rule.description || "",
|
|
2991
|
+
...rule.port.toRuleJson(),
|
|
2992
|
+
...rule.peer.toRuleJson()
|
|
2993
|
+
})),
|
|
2994
|
+
SecurityGroupEgress: this.egress.map((rule) => ({
|
|
2995
|
+
Description: rule.description || "",
|
|
2996
|
+
...rule.port.toRuleJson(),
|
|
2997
|
+
...rule.peer.toRuleJson()
|
|
2998
|
+
}))
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
};
|
|
3002
|
+
|
|
3003
|
+
// src/formation/resource/ec2/port.ts
|
|
3004
|
+
var Port = class {
|
|
3005
|
+
static tcp(port) {
|
|
3006
|
+
return new Port({
|
|
3007
|
+
protocol: "tcp" /* TCP */,
|
|
3008
|
+
from: port,
|
|
3009
|
+
to: port
|
|
3010
|
+
});
|
|
3011
|
+
}
|
|
3012
|
+
static tcpRange(startPort, endPort) {
|
|
3013
|
+
return new Port({
|
|
3014
|
+
protocol: "tcp" /* TCP */,
|
|
3015
|
+
from: startPort,
|
|
3016
|
+
to: endPort
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3019
|
+
static allTcp() {
|
|
3020
|
+
return new Port({
|
|
3021
|
+
protocol: "tcp" /* TCP */,
|
|
3022
|
+
from: 0,
|
|
3023
|
+
to: 65535
|
|
3024
|
+
});
|
|
3025
|
+
}
|
|
3026
|
+
static allTraffic() {
|
|
3027
|
+
return new Port({
|
|
3028
|
+
protocol: "-1" /* ALL */
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
protocol;
|
|
3032
|
+
from;
|
|
3033
|
+
to;
|
|
3034
|
+
constructor(props) {
|
|
3035
|
+
this.protocol = props.protocol;
|
|
3036
|
+
this.from = props.from;
|
|
3037
|
+
this.to = props.to;
|
|
3038
|
+
}
|
|
3039
|
+
toRuleJson() {
|
|
3040
|
+
return {
|
|
3041
|
+
IpProtocol: this.protocol,
|
|
3042
|
+
FromPort: this.from,
|
|
3043
|
+
ToPort: this.to
|
|
3044
|
+
};
|
|
3045
|
+
}
|
|
3046
|
+
};
|
|
3047
|
+
|
|
3048
|
+
// src/formation/resource/elb/load-balancer.ts
|
|
3049
|
+
var LoadBalancer = class extends Resource {
|
|
3050
|
+
constructor(logicalId, props) {
|
|
3051
|
+
super("AWS::ElasticLoadBalancingV2::LoadBalancer", logicalId);
|
|
3052
|
+
this.props = props;
|
|
3053
|
+
this.name = this.props.name || logicalId;
|
|
3054
|
+
}
|
|
3055
|
+
name;
|
|
3056
|
+
get arn() {
|
|
3057
|
+
return ref(this.logicalId);
|
|
3058
|
+
}
|
|
3059
|
+
get dnsName() {
|
|
3060
|
+
return getAtt(this.logicalId, "DNSName");
|
|
3061
|
+
}
|
|
3062
|
+
get hostedZoneId() {
|
|
3063
|
+
return getAtt(this.logicalId, "CanonicalHostedZoneID");
|
|
3064
|
+
}
|
|
3065
|
+
properties() {
|
|
3066
|
+
return {
|
|
3067
|
+
Name: this.name,
|
|
3068
|
+
Type: this.props.type,
|
|
3069
|
+
Scheme: this.props.schema || "internet-facing",
|
|
3070
|
+
SecurityGroups: this.props.securityGroups,
|
|
3071
|
+
Subnets: this.props.subnets
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
};
|
|
3075
|
+
|
|
3076
|
+
// src/formation/resource/elb/listener.ts
|
|
3077
|
+
var import_change_case11 = require("change-case");
|
|
3078
|
+
var Listener = class extends Resource {
|
|
3079
|
+
constructor(logicalId, props) {
|
|
3080
|
+
super("AWS::ElasticLoadBalancingV2::Listener", logicalId);
|
|
3081
|
+
this.props = props;
|
|
3082
|
+
}
|
|
3083
|
+
get id() {
|
|
3084
|
+
return ref(this.logicalId);
|
|
3085
|
+
}
|
|
3086
|
+
get arn() {
|
|
3087
|
+
return getAtt(this.logicalId, "ListenerArn");
|
|
3088
|
+
}
|
|
3089
|
+
properties() {
|
|
3090
|
+
return {
|
|
3091
|
+
LoadBalancerArn: this.props.loadBalancerArn,
|
|
3092
|
+
Port: this.props.port,
|
|
3093
|
+
Protocol: (0, import_change_case11.constantCase)(this.props.protocol),
|
|
3094
|
+
Certificates: this.props.certificates.map((arn) => ({
|
|
3095
|
+
CertificateArn: arn
|
|
3096
|
+
})),
|
|
3097
|
+
...this.attr("DefaultActions", this.props.defaultActions?.map((action) => action.toJSON()))
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
};
|
|
3101
|
+
var ListenerAction = class {
|
|
3102
|
+
constructor(props) {
|
|
3103
|
+
this.props = props;
|
|
3104
|
+
}
|
|
3105
|
+
static fixedResponse(statusCode, props = {}) {
|
|
3106
|
+
return new ListenerAction({
|
|
3107
|
+
type: "fixed-response",
|
|
3108
|
+
fixedResponse: {
|
|
3109
|
+
statusCode,
|
|
3110
|
+
...props
|
|
3111
|
+
}
|
|
3112
|
+
});
|
|
3113
|
+
}
|
|
3114
|
+
static forward(targets) {
|
|
3115
|
+
return new ListenerAction({
|
|
3116
|
+
type: "forward",
|
|
3117
|
+
forward: {
|
|
3118
|
+
targetGroups: targets
|
|
3119
|
+
}
|
|
3120
|
+
});
|
|
3121
|
+
}
|
|
3122
|
+
toJSON() {
|
|
3123
|
+
return {
|
|
3124
|
+
// AuthenticateCognitoConfig: AuthenticateCognitoConfig,
|
|
3125
|
+
// AuthenticateOidcConfig: AuthenticateOidcConfig,
|
|
3126
|
+
// RedirectConfig: RedirectConfig,
|
|
3127
|
+
Type: this.props.type,
|
|
3128
|
+
// Order: Integer,
|
|
3129
|
+
...this.props.type === "fixed-response" ? {
|
|
3130
|
+
FixedResponseConfig: {
|
|
3131
|
+
StatusCode: this.props.fixedResponse.statusCode,
|
|
3132
|
+
...this.props.fixedResponse.contentType ? {
|
|
3133
|
+
ContentType: this.props.fixedResponse.contentType
|
|
3134
|
+
} : {},
|
|
3135
|
+
...this.props.fixedResponse.messageBody ? {
|
|
3136
|
+
MessageBody: this.props.fixedResponse.messageBody
|
|
3137
|
+
} : {}
|
|
3138
|
+
}
|
|
3139
|
+
} : {},
|
|
3140
|
+
...this.props.type === "forward" ? {
|
|
3141
|
+
ForwardConfig: {
|
|
3142
|
+
TargetGroups: this.props.forward.targetGroups.map((target) => ({
|
|
3143
|
+
TargetGroupArn: target
|
|
3144
|
+
}))
|
|
3145
|
+
}
|
|
3146
|
+
} : {}
|
|
3147
|
+
};
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
|
|
3151
|
+
// src/formation/resource/elb/listener-rule.ts
|
|
3152
|
+
var ListenerRule = class extends Resource {
|
|
3153
|
+
constructor(logicalId, props) {
|
|
3154
|
+
super("AWS::ElasticLoadBalancingV2::ListenerRule", logicalId);
|
|
3155
|
+
this.props = props;
|
|
3156
|
+
}
|
|
3157
|
+
get id() {
|
|
3158
|
+
return ref(this.logicalId);
|
|
3159
|
+
}
|
|
3160
|
+
get arn() {
|
|
3161
|
+
return getAtt(this.logicalId, "ListenerArn");
|
|
3162
|
+
}
|
|
3163
|
+
properties() {
|
|
3164
|
+
return {
|
|
3165
|
+
ListenerArn: this.props.listenerArn,
|
|
3166
|
+
Priority: this.props.priority,
|
|
3167
|
+
Conditions: this.props.conditions.map((condition) => condition.toJSON()),
|
|
3168
|
+
Actions: this.props.actions.map((action) => action.toJSON())
|
|
3169
|
+
};
|
|
3170
|
+
}
|
|
3171
|
+
};
|
|
3172
|
+
var ListenerCondition = class {
|
|
3173
|
+
constructor(props) {
|
|
3174
|
+
this.props = props;
|
|
3175
|
+
}
|
|
3176
|
+
static httpRequestMethods(methods) {
|
|
3177
|
+
return new ListenerCondition({
|
|
3178
|
+
field: "http-request-method",
|
|
3179
|
+
methods
|
|
3180
|
+
});
|
|
3181
|
+
}
|
|
3182
|
+
static pathPatterns(paths) {
|
|
3183
|
+
return new ListenerCondition({
|
|
3184
|
+
field: "path-pattern",
|
|
3185
|
+
paths
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3188
|
+
toJSON() {
|
|
3189
|
+
return {
|
|
3190
|
+
Field: this.props.field,
|
|
3191
|
+
...this.props.field === "http-request-method" ? {
|
|
3192
|
+
HttpRequestMethodConfig: {
|
|
3193
|
+
Values: this.props.methods
|
|
3194
|
+
}
|
|
3195
|
+
} : {},
|
|
3196
|
+
...this.props.field === "path-pattern" ? {
|
|
3197
|
+
PathPatternConfig: {
|
|
3198
|
+
Values: this.props.paths
|
|
3199
|
+
}
|
|
3200
|
+
} : {}
|
|
3201
|
+
};
|
|
3202
|
+
}
|
|
3203
|
+
};
|
|
3204
|
+
|
|
3205
|
+
// src/formation/resource/elb/target-group.ts
|
|
3206
|
+
var TargetGroup = class extends Resource {
|
|
3207
|
+
constructor(logicalId, props) {
|
|
3208
|
+
super("AWS::ElasticLoadBalancingV2::TargetGroup", logicalId);
|
|
3209
|
+
this.props = props;
|
|
3210
|
+
this.name = formatName(this.props.name || logicalId);
|
|
3211
|
+
}
|
|
3212
|
+
name;
|
|
3213
|
+
get arn() {
|
|
3214
|
+
return ref(this.logicalId);
|
|
3215
|
+
}
|
|
3216
|
+
get fullName() {
|
|
3217
|
+
return getAtt(this.logicalId, "TargetGroupFullName");
|
|
3218
|
+
}
|
|
3219
|
+
properties() {
|
|
3220
|
+
return {
|
|
3221
|
+
Name: this.name,
|
|
3222
|
+
TargetType: this.props.type,
|
|
3223
|
+
Targets: this.props.targets.map((target) => ({
|
|
3224
|
+
Id: target
|
|
3225
|
+
}))
|
|
3226
|
+
};
|
|
3227
|
+
}
|
|
3228
|
+
};
|
|
3229
|
+
|
|
3230
|
+
// src/formation/resource/lambda/event-source/elb.ts
|
|
3231
|
+
var ElbEventSource = class extends Group {
|
|
3232
|
+
constructor(id, lambda, props) {
|
|
3233
|
+
const name = formatName(id);
|
|
3234
|
+
const permission = new Permission2(id, {
|
|
3235
|
+
action: "lambda:InvokeFunction",
|
|
3236
|
+
principal: "elasticloadbalancing.amazonaws.com",
|
|
3237
|
+
functionArn: lambda.arn,
|
|
3238
|
+
sourceArn: sub("arn:${AWS::Partition}:elasticloadbalancing:${AWS::Region}:${AWS::AccountId}:targetgroup/${name}/*", {
|
|
3239
|
+
name
|
|
3240
|
+
})
|
|
3241
|
+
}).dependsOn(lambda);
|
|
3242
|
+
const target = new TargetGroup(id, {
|
|
3243
|
+
name,
|
|
3244
|
+
type: "lambda",
|
|
3245
|
+
targets: [lambda.arn]
|
|
3246
|
+
}).dependsOn(lambda, permission);
|
|
3247
|
+
const rule = new ListenerRule(id, {
|
|
3248
|
+
listenerArn: props.listenerArn,
|
|
3249
|
+
priority: props.priority,
|
|
3250
|
+
conditions: props.conditions,
|
|
3251
|
+
actions: [
|
|
3252
|
+
ListenerAction.forward([target.arn])
|
|
3253
|
+
]
|
|
3254
|
+
}).dependsOn(target);
|
|
3255
|
+
super([target, rule, permission]);
|
|
3256
|
+
}
|
|
3257
|
+
};
|
|
3258
|
+
|
|
3259
|
+
// src/plugins/http.ts
|
|
3260
|
+
var RouteSchema = import_zod17.z.custom((route) => {
|
|
3261
|
+
return import_zod17.z.string().regex(/^(POST|GET|PUT|DELETE|HEAD|OPTIONS)(\s\/[a-z0-9\+\_\-\/]*)$/ig).safeParse(route).success;
|
|
3262
|
+
}, "Invalid route");
|
|
3263
|
+
var parseRoute = (route) => {
|
|
3264
|
+
const [method, ...paths] = route.split(" ");
|
|
3265
|
+
const path = paths.join(" ");
|
|
3266
|
+
return { method, path };
|
|
3267
|
+
};
|
|
3268
|
+
var strToInt = (str) => {
|
|
3269
|
+
return parseInt(Buffer.from(str, "utf8").toString("hex"), 16);
|
|
3270
|
+
};
|
|
3271
|
+
var generatePriority = (stackName, route) => {
|
|
3272
|
+
const start = strToInt(stackName) % 500 + 1;
|
|
3273
|
+
const end = strToInt(route) % 100;
|
|
3274
|
+
const priority = start + "" + end;
|
|
3275
|
+
return parseInt(priority, 10);
|
|
3276
|
+
};
|
|
3277
|
+
var httpPlugin = definePlugin({
|
|
3278
|
+
name: "http",
|
|
3279
|
+
schema: import_zod17.z.object({
|
|
3280
|
+
defaults: import_zod17.z.object({
|
|
3281
|
+
/** Define your global http api's.
|
|
3282
|
+
* @example
|
|
3283
|
+
* {
|
|
3284
|
+
* http: {
|
|
3285
|
+
* HTTP_API_NAME: {
|
|
3286
|
+
* domain: 'example.com',
|
|
3287
|
+
* subDomain: 'api',
|
|
3288
|
+
* }
|
|
3289
|
+
* }
|
|
3290
|
+
* }
|
|
3291
|
+
*/
|
|
3292
|
+
http: import_zod17.z.record(
|
|
3293
|
+
ResourceIdSchema,
|
|
3294
|
+
import_zod17.z.object({
|
|
3295
|
+
/** The domain to link your api with. */
|
|
3296
|
+
domain: import_zod17.z.string(),
|
|
3297
|
+
subDomain: import_zod17.z.string().optional()
|
|
3298
|
+
})
|
|
3299
|
+
).optional()
|
|
3300
|
+
}).default({}),
|
|
3301
|
+
stacks: import_zod17.z.object({
|
|
3302
|
+
/** Define routes in your stack for your global http api.
|
|
3303
|
+
* @example
|
|
3304
|
+
* {
|
|
3305
|
+
* http: {
|
|
3306
|
+
* HTTP_API_NAME: {
|
|
3307
|
+
* 'GET /': 'index.ts',
|
|
3308
|
+
* 'POST /posts': 'create-post.ts',
|
|
3309
|
+
* }
|
|
3310
|
+
* }
|
|
3311
|
+
* }
|
|
3312
|
+
*/
|
|
3313
|
+
http: import_zod17.z.record(
|
|
3314
|
+
ResourceIdSchema,
|
|
3315
|
+
import_zod17.z.record(RouteSchema, FunctionSchema)
|
|
3316
|
+
).optional()
|
|
3317
|
+
}).array()
|
|
3318
|
+
}),
|
|
3319
|
+
onApp({ config, bootstrap: bootstrap2, usEastBootstrap }) {
|
|
3320
|
+
if (Object.keys(config.defaults?.http || {}).length === 0) {
|
|
3321
|
+
return;
|
|
3322
|
+
}
|
|
3323
|
+
const vpcId = bootstrap2.get("vpc-id");
|
|
3324
|
+
const securityGroup = new SecurityGroup("http", {
|
|
3325
|
+
description: "http security group",
|
|
3326
|
+
vpcId
|
|
3327
|
+
});
|
|
3328
|
+
securityGroup.addIngressRule(Peer.anyIpv4(), Port.tcp(443));
|
|
3329
|
+
securityGroup.addIngressRule(Peer.anyIpv6(), Port.tcp(443));
|
|
3330
|
+
bootstrap2.add(securityGroup);
|
|
3331
|
+
for (const [id, props] of Object.entries(config.defaults?.http || {})) {
|
|
3332
|
+
const loadBalancer = new LoadBalancer(id, {
|
|
3333
|
+
name: `${config.name}-${id}`,
|
|
3334
|
+
type: "application",
|
|
3335
|
+
securityGroups: [securityGroup.id],
|
|
3336
|
+
subnets: [
|
|
3337
|
+
bootstrap2.get("public-subnet-1"),
|
|
3338
|
+
bootstrap2.get("public-subnet-2")
|
|
3339
|
+
]
|
|
3340
|
+
}).dependsOn(securityGroup);
|
|
3341
|
+
const listener = new Listener(id, {
|
|
3342
|
+
loadBalancerArn: loadBalancer.arn,
|
|
3343
|
+
port: 443,
|
|
3344
|
+
protocol: "https",
|
|
3345
|
+
certificates: [
|
|
3346
|
+
bootstrap2.get(`certificate-${props.domain}-arn`)
|
|
3347
|
+
],
|
|
3348
|
+
defaultActions: [
|
|
3349
|
+
ListenerAction.fixedResponse(404, {
|
|
3350
|
+
contentType: "application/json",
|
|
3351
|
+
messageBody: JSON.stringify({
|
|
3352
|
+
message: "Route not found"
|
|
3353
|
+
})
|
|
3354
|
+
})
|
|
3355
|
+
]
|
|
3356
|
+
}).dependsOn(loadBalancer);
|
|
3357
|
+
const record = new RecordSet(`${id}-http`, {
|
|
3358
|
+
hostedZoneId: usEastBootstrap.import(`hosted-zone-${props.domain}-id`),
|
|
3359
|
+
name: props.subDomain ? `${props.subDomain}.${props.domain}` : props.domain,
|
|
3360
|
+
type: "A",
|
|
3361
|
+
alias: {
|
|
3362
|
+
hostedZoneId: loadBalancer.hostedZoneId,
|
|
3363
|
+
dnsName: loadBalancer.dnsName
|
|
3364
|
+
}
|
|
3365
|
+
}).dependsOn(loadBalancer);
|
|
3366
|
+
bootstrap2.add(loadBalancer, listener, record).export(`http-${id}-listener-arn`, listener.arn);
|
|
3367
|
+
}
|
|
3368
|
+
},
|
|
3369
|
+
onStack(ctx) {
|
|
3370
|
+
const { stack, stackConfig, bootstrap: bootstrap2 } = ctx;
|
|
3371
|
+
for (const [id, routes] of Object.entries(stackConfig.http || {})) {
|
|
3372
|
+
for (const [route, props] of Object.entries(routes)) {
|
|
3373
|
+
const { method, path } = parseRoute(route);
|
|
3374
|
+
const lambda = toLambdaFunction(ctx, `http-${id}`, props);
|
|
3375
|
+
const source = new ElbEventSource(`http-${id}-${route}`, lambda, {
|
|
3376
|
+
listenerArn: bootstrap2.import(`http-${id}-listener-arn`),
|
|
3377
|
+
priority: generatePriority(stackConfig.name, route),
|
|
3378
|
+
conditions: [
|
|
3379
|
+
ListenerCondition.httpRequestMethods([method]),
|
|
3380
|
+
ListenerCondition.pathPatterns([path])
|
|
3381
|
+
]
|
|
3382
|
+
});
|
|
3383
|
+
stack.add(lambda, source);
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
});
|
|
3388
|
+
|
|
3389
|
+
// src/plugins/search.ts
|
|
3390
|
+
var import_zod18 = require("zod");
|
|
3391
|
+
|
|
3392
|
+
// src/formation/resource/open-search-serverless/collection.ts
|
|
3393
|
+
var Collection = class extends Resource {
|
|
3394
|
+
constructor(logicalId, props) {
|
|
3395
|
+
super("AWS::OpenSearchServerless::Collection", logicalId);
|
|
3396
|
+
this.props = props;
|
|
3397
|
+
this.name = this.props.name || logicalId;
|
|
3398
|
+
}
|
|
3399
|
+
name;
|
|
3400
|
+
get id() {
|
|
3401
|
+
return ref(this.logicalId);
|
|
3402
|
+
}
|
|
3403
|
+
get arn() {
|
|
3404
|
+
return getAtt(this.logicalId, "Arn");
|
|
3405
|
+
}
|
|
3406
|
+
get endpoint() {
|
|
3407
|
+
return getAtt(this.logicalId, "CollectionEndpoint");
|
|
3408
|
+
}
|
|
3409
|
+
properties() {
|
|
3410
|
+
return {
|
|
3411
|
+
Name: this.name,
|
|
3412
|
+
Type: this.props.type.toUpperCase(),
|
|
3413
|
+
...this.attr("Description", this.props.description)
|
|
3414
|
+
};
|
|
3415
|
+
}
|
|
3416
|
+
};
|
|
3417
|
+
|
|
3418
|
+
// src/plugins/search.ts
|
|
3419
|
+
var searchPlugin = definePlugin({
|
|
3420
|
+
name: "search",
|
|
3421
|
+
schema: import_zod18.z.object({
|
|
3422
|
+
stacks: import_zod18.z.object({
|
|
3423
|
+
searchs: import_zod18.z.array(ResourceIdSchema).optional()
|
|
3424
|
+
}).array()
|
|
3425
|
+
}),
|
|
3426
|
+
onStack({ config, stack, stackConfig, bind }) {
|
|
3427
|
+
for (const id of stackConfig.searchs || []) {
|
|
3428
|
+
const collection = new Collection(id, {
|
|
3429
|
+
name: `${config.name}-${stack.name}-${id}`,
|
|
3430
|
+
type: "search"
|
|
3431
|
+
});
|
|
3432
|
+
bind((lambda) => {
|
|
3433
|
+
lambda.addPermissions({
|
|
3434
|
+
actions: ["aoss:APIAccessAll"],
|
|
3435
|
+
resources: [collection.arn]
|
|
3436
|
+
});
|
|
3437
|
+
});
|
|
3438
|
+
}
|
|
2308
3439
|
}
|
|
2309
3440
|
});
|
|
2310
3441
|
|
|
2311
3442
|
// src/plugins/index.ts
|
|
2312
3443
|
var defaultPlugins = [
|
|
2313
3444
|
extendPlugin,
|
|
3445
|
+
vpcPlugin,
|
|
2314
3446
|
functionPlugin,
|
|
2315
3447
|
cronPlugin,
|
|
2316
3448
|
queuePlugin,
|
|
@@ -2318,10 +3450,11 @@ var defaultPlugins = [
|
|
|
2318
3450
|
storePlugin,
|
|
2319
3451
|
topicPlugin,
|
|
2320
3452
|
pubsubPlugin,
|
|
2321
|
-
|
|
3453
|
+
searchPlugin,
|
|
2322
3454
|
domainPlugin,
|
|
2323
|
-
graphqlPlugin
|
|
2324
|
-
|
|
3455
|
+
graphqlPlugin,
|
|
3456
|
+
httpPlugin,
|
|
3457
|
+
onFailurePlugin
|
|
2325
3458
|
];
|
|
2326
3459
|
|
|
2327
3460
|
// src/formation/app.ts
|
|
@@ -2348,23 +3481,6 @@ var App = class {
|
|
|
2348
3481
|
// }
|
|
2349
3482
|
};
|
|
2350
3483
|
|
|
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
|
-
}
|
|
2366
|
-
};
|
|
2367
|
-
|
|
2368
3484
|
// src/custom/global-export/handler.ts
|
|
2369
3485
|
var globalExportsHandlerCode = (
|
|
2370
3486
|
/* JS */
|
|
@@ -2459,7 +3575,7 @@ var extendWithGlobalExports = (appName, importable, exportable) => {
|
|
|
2459
3575
|
region: importable.region
|
|
2460
3576
|
}
|
|
2461
3577
|
});
|
|
2462
|
-
exportable.add(crossRegionExports);
|
|
3578
|
+
exportable.add(lambda, crossRegionExports);
|
|
2463
3579
|
}
|
|
2464
3580
|
return crossRegionExports.getAtt(name);
|
|
2465
3581
|
};
|
|
@@ -2520,6 +3636,20 @@ var toApp = async (config, filters) => {
|
|
|
2520
3636
|
app.add(stack);
|
|
2521
3637
|
stacks.push({ stack, config: stackConfig });
|
|
2522
3638
|
}
|
|
3639
|
+
for (const plugin of plugins) {
|
|
3640
|
+
for (const stack of app.stacks) {
|
|
3641
|
+
for (const resource of stack) {
|
|
3642
|
+
plugin.onResource?.({
|
|
3643
|
+
config,
|
|
3644
|
+
app,
|
|
3645
|
+
stack,
|
|
3646
|
+
bootstrap: bootstrap2,
|
|
3647
|
+
usEastBootstrap,
|
|
3648
|
+
resource
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
2523
3653
|
const functions = app.find(Function);
|
|
2524
3654
|
for (const bind2 of bindings) {
|
|
2525
3655
|
for (const fn of functions) {
|
|
@@ -2566,17 +3696,17 @@ var getCredentials = (profile) => {
|
|
|
2566
3696
|
};
|
|
2567
3697
|
|
|
2568
3698
|
// src/schema/app.ts
|
|
2569
|
-
var
|
|
3699
|
+
var import_zod22 = require("zod");
|
|
2570
3700
|
|
|
2571
3701
|
// src/schema/stack.ts
|
|
2572
|
-
var
|
|
2573
|
-
var StackSchema =
|
|
3702
|
+
var import_zod19 = require("zod");
|
|
3703
|
+
var StackSchema = import_zod19.z.object({
|
|
2574
3704
|
name: ResourceIdSchema,
|
|
2575
|
-
depends:
|
|
3705
|
+
depends: import_zod19.z.array(import_zod19.z.lazy(() => StackSchema)).optional()
|
|
2576
3706
|
});
|
|
2577
3707
|
|
|
2578
3708
|
// src/schema/region.ts
|
|
2579
|
-
var
|
|
3709
|
+
var import_zod20 = require("zod");
|
|
2580
3710
|
var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
|
|
2581
3711
|
var AF = ["af-south-1"];
|
|
2582
3712
|
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"];
|
|
@@ -2593,46 +3723,91 @@ var regions = [
|
|
|
2593
3723
|
...ME,
|
|
2594
3724
|
...SA
|
|
2595
3725
|
];
|
|
2596
|
-
var RegionSchema =
|
|
3726
|
+
var RegionSchema = import_zod20.z.enum(regions);
|
|
2597
3727
|
|
|
2598
3728
|
// src/schema/plugin.ts
|
|
2599
|
-
var
|
|
2600
|
-
var PluginSchema =
|
|
2601
|
-
name:
|
|
2602
|
-
schema:
|
|
3729
|
+
var import_zod21 = require("zod");
|
|
3730
|
+
var PluginSchema = import_zod21.z.object({
|
|
3731
|
+
name: import_zod21.z.string(),
|
|
3732
|
+
schema: import_zod21.z.custom().optional(),
|
|
2603
3733
|
// depends: z.array(z.lazy(() => PluginSchema)).optional(),
|
|
2604
|
-
|
|
2605
|
-
onStack:
|
|
2606
|
-
|
|
3734
|
+
onApp: import_zod21.z.function().returns(import_zod21.z.void()).optional(),
|
|
3735
|
+
onStack: import_zod21.z.function().returns(import_zod21.z.any()).optional(),
|
|
3736
|
+
onResource: import_zod21.z.function().returns(import_zod21.z.any()).optional()
|
|
2607
3737
|
// bind: z.function().optional(),
|
|
2608
3738
|
});
|
|
2609
3739
|
|
|
2610
3740
|
// src/schema/app.ts
|
|
2611
|
-
var AppSchema =
|
|
3741
|
+
var AppSchema = import_zod22.z.object({
|
|
3742
|
+
/** App name */
|
|
2612
3743
|
name: ResourceIdSchema,
|
|
3744
|
+
/** The AWS region to deploy to. */
|
|
2613
3745
|
region: RegionSchema,
|
|
2614
|
-
profile
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
3746
|
+
/** The AWS profile to deploy to. */
|
|
3747
|
+
profile: import_zod22.z.string(),
|
|
3748
|
+
/** The deployment stage.
|
|
3749
|
+
* @default 'prod'
|
|
3750
|
+
*/
|
|
3751
|
+
stage: import_zod22.z.string().regex(/[a-z]+/).default("prod"),
|
|
3752
|
+
/** Default properties. */
|
|
3753
|
+
defaults: import_zod22.z.object({}).default({}),
|
|
3754
|
+
/** The application stacks. */
|
|
3755
|
+
stacks: import_zod22.z.array(StackSchema).min(1).refine((stacks) => {
|
|
2618
3756
|
const unique = new Set(stacks.map((stack) => stack.name));
|
|
2619
3757
|
return unique.size === stacks.length;
|
|
2620
3758
|
}, "Must be an array of unique stacks"),
|
|
2621
|
-
plugins
|
|
3759
|
+
/** Custom plugins. */
|
|
3760
|
+
plugins: import_zod22.z.array(PluginSchema).optional()
|
|
2622
3761
|
});
|
|
2623
3762
|
|
|
2624
3763
|
// src/util/import.ts
|
|
2625
3764
|
var import_core = require("@swc/core");
|
|
2626
3765
|
var import_path2 = require("path");
|
|
2627
|
-
var
|
|
3766
|
+
var import_promises5 = require("fs/promises");
|
|
2628
3767
|
|
|
2629
3768
|
// src/util/path.ts
|
|
3769
|
+
var import_promises4 = require("fs/promises");
|
|
2630
3770
|
var import_path = require("path");
|
|
2631
|
-
var
|
|
2632
|
-
var
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
3771
|
+
var root = process.cwd();
|
|
3772
|
+
var directories = {
|
|
3773
|
+
root,
|
|
3774
|
+
get output() {
|
|
3775
|
+
return (0, import_path.join)(this.root, ".awsless");
|
|
3776
|
+
},
|
|
3777
|
+
get cache() {
|
|
3778
|
+
return (0, import_path.join)(this.output, "cache");
|
|
3779
|
+
},
|
|
3780
|
+
get asset() {
|
|
3781
|
+
return (0, import_path.join)(this.output, "asset");
|
|
3782
|
+
},
|
|
3783
|
+
get template() {
|
|
3784
|
+
return (0, import_path.join)(this.output, "template");
|
|
3785
|
+
}
|
|
3786
|
+
};
|
|
3787
|
+
var setRoot = (path = root) => {
|
|
3788
|
+
directories.root = path;
|
|
3789
|
+
};
|
|
3790
|
+
var findRootDir = async (path, configFile, level = 5) => {
|
|
3791
|
+
if (!level) {
|
|
3792
|
+
throw new TypeError("No awsless project found");
|
|
3793
|
+
}
|
|
3794
|
+
const file = (0, import_path.join)(path, configFile);
|
|
3795
|
+
const exists = await fileExist(file);
|
|
3796
|
+
if (exists) {
|
|
3797
|
+
return path;
|
|
3798
|
+
}
|
|
3799
|
+
return findRootDir((0, import_path.normalize)((0, import_path.join)(path, "..")), configFile, level - 1);
|
|
3800
|
+
};
|
|
3801
|
+
var fileExist = async (file) => {
|
|
3802
|
+
try {
|
|
3803
|
+
const stat = await (0, import_promises4.lstat)(file);
|
|
3804
|
+
if (stat.isFile()) {
|
|
3805
|
+
return true;
|
|
3806
|
+
}
|
|
3807
|
+
} catch (error) {
|
|
3808
|
+
}
|
|
3809
|
+
return false;
|
|
3810
|
+
};
|
|
2636
3811
|
|
|
2637
3812
|
// src/util/import.ts
|
|
2638
3813
|
var resolveFileNameExtension = async (path) => {
|
|
@@ -2647,7 +3822,7 @@ var resolveFileNameExtension = async (path) => {
|
|
|
2647
3822
|
const file = path.replace(/\.js$/, "") + option;
|
|
2648
3823
|
let stat;
|
|
2649
3824
|
try {
|
|
2650
|
-
stat = await (0,
|
|
3825
|
+
stat = await (0, import_promises5.lstat)(file);
|
|
2651
3826
|
} catch (error) {
|
|
2652
3827
|
continue;
|
|
2653
3828
|
}
|
|
@@ -2658,11 +3833,11 @@ var resolveFileNameExtension = async (path) => {
|
|
|
2658
3833
|
throw new Error(`Failed to load file: ${path}`);
|
|
2659
3834
|
};
|
|
2660
3835
|
var resolveDir = (path) => {
|
|
2661
|
-
return (0, import_path2.dirname)(path).replace(
|
|
3836
|
+
return (0, import_path2.dirname)(path).replace(directories.root + "/", "");
|
|
2662
3837
|
};
|
|
2663
3838
|
var importFile = async (path) => {
|
|
2664
3839
|
const load = async (file) => {
|
|
2665
|
-
debug("Load file", file);
|
|
3840
|
+
debug("Load file:", style.info(file));
|
|
2666
3841
|
let { code: code2 } = await (0, import_core.transformFile)(file, {
|
|
2667
3842
|
isModule: true
|
|
2668
3843
|
});
|
|
@@ -2682,16 +3857,22 @@ var importFile = async (path) => {
|
|
|
2682
3857
|
return code2;
|
|
2683
3858
|
};
|
|
2684
3859
|
const code = await load(path);
|
|
2685
|
-
const outputFile = (0, import_path2.join)(
|
|
2686
|
-
await (0,
|
|
2687
|
-
await (0,
|
|
3860
|
+
const outputFile = (0, import_path2.join)(directories.cache, "config.js");
|
|
3861
|
+
await (0, import_promises5.mkdir)(directories.cache, { recursive: true });
|
|
3862
|
+
await (0, import_promises5.writeFile)(outputFile, code);
|
|
3863
|
+
debug("Save config file:", style.info(outputFile));
|
|
2688
3864
|
return import(outputFile);
|
|
2689
3865
|
};
|
|
2690
3866
|
|
|
2691
3867
|
// src/config.ts
|
|
2692
3868
|
var importConfig = async (options) => {
|
|
3869
|
+
debug("Find the root directory");
|
|
3870
|
+
const configFile = options.configFile || "awsless.config.ts";
|
|
3871
|
+
const root2 = await findRootDir(process.cwd(), configFile);
|
|
3872
|
+
setRoot(root2);
|
|
3873
|
+
debug("CWD:", style.info(root2));
|
|
2693
3874
|
debug("Import config file");
|
|
2694
|
-
const fileName = (0, import_path4.join)(
|
|
3875
|
+
const fileName = (0, import_path4.join)(root2, configFile);
|
|
2695
3876
|
const module2 = await importFile(fileName);
|
|
2696
3877
|
const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
|
|
2697
3878
|
debug("Validate config file");
|
|
@@ -3191,7 +4372,7 @@ var layout = async (cb) => {
|
|
|
3191
4372
|
};
|
|
3192
4373
|
|
|
3193
4374
|
// src/cli/ui/complex/builder.ts
|
|
3194
|
-
var
|
|
4375
|
+
var import_promises6 = require("fs/promises");
|
|
3195
4376
|
|
|
3196
4377
|
// src/cli/ui/layout/flex-line.ts
|
|
3197
4378
|
var stripEscapeCode = (str) => {
|
|
@@ -3214,7 +4395,7 @@ var flexLine = (term, left, right, reserveSpace = 0) => {
|
|
|
3214
4395
|
};
|
|
3215
4396
|
|
|
3216
4397
|
// src/cli/ui/complex/builder.ts
|
|
3217
|
-
var
|
|
4398
|
+
var import_path7 = require("path");
|
|
3218
4399
|
var assetBuilder = (app) => {
|
|
3219
4400
|
return async (term) => {
|
|
3220
4401
|
const assets = [];
|
|
@@ -3265,7 +4446,7 @@ var assetBuilder = (app) => {
|
|
|
3265
4446
|
derive([details], (details2) => {
|
|
3266
4447
|
return Object.entries(details2).map(([key, value]) => {
|
|
3267
4448
|
return `${style.label(key)} ${value}`;
|
|
3268
|
-
}).join("
|
|
4449
|
+
}).join(style.placeholder(" \u2500 "));
|
|
3269
4450
|
}),
|
|
3270
4451
|
br()
|
|
3271
4452
|
]);
|
|
@@ -3273,10 +4454,10 @@ var assetBuilder = (app) => {
|
|
|
3273
4454
|
const timer = createTimer();
|
|
3274
4455
|
const data = await asset.build({
|
|
3275
4456
|
async write(file, data2) {
|
|
3276
|
-
const fullpath = (0,
|
|
3277
|
-
const basepath = (0,
|
|
3278
|
-
await (0,
|
|
3279
|
-
await (0,
|
|
4457
|
+
const fullpath = (0, import_path7.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
|
|
4458
|
+
const basepath = (0, import_path7.dirname)(fullpath);
|
|
4459
|
+
await (0, import_promises6.mkdir)(basepath, { recursive: true });
|
|
4460
|
+
await (0, import_promises6.writeFile)(fullpath, data2);
|
|
3280
4461
|
}
|
|
3281
4462
|
});
|
|
3282
4463
|
details.set({
|
|
@@ -3293,36 +4474,36 @@ var assetBuilder = (app) => {
|
|
|
3293
4474
|
};
|
|
3294
4475
|
|
|
3295
4476
|
// src/util/cleanup.ts
|
|
3296
|
-
var
|
|
4477
|
+
var import_promises7 = require("fs/promises");
|
|
3297
4478
|
var cleanUp = async () => {
|
|
3298
4479
|
debug("Clean up template, cache, and asset files");
|
|
3299
4480
|
const paths = [
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
4481
|
+
directories.asset,
|
|
4482
|
+
directories.cache,
|
|
4483
|
+
directories.template
|
|
3303
4484
|
];
|
|
3304
|
-
await Promise.all(paths.map((path) => (0,
|
|
4485
|
+
await Promise.all(paths.map((path) => (0, import_promises7.rm)(path, {
|
|
3305
4486
|
recursive: true,
|
|
3306
4487
|
force: true,
|
|
3307
4488
|
maxRetries: 2
|
|
3308
4489
|
})));
|
|
3309
|
-
await Promise.all(paths.map((path) => (0,
|
|
4490
|
+
await Promise.all(paths.map((path) => (0, import_promises7.mkdir)(path, {
|
|
3310
4491
|
recursive: true
|
|
3311
4492
|
})));
|
|
3312
4493
|
};
|
|
3313
4494
|
|
|
3314
4495
|
// src/cli/ui/complex/template.ts
|
|
3315
|
-
var
|
|
3316
|
-
var
|
|
4496
|
+
var import_promises8 = require("fs/promises");
|
|
4497
|
+
var import_path10 = require("path");
|
|
3317
4498
|
var templateBuilder = (app) => {
|
|
3318
4499
|
return async (term) => {
|
|
3319
4500
|
const done = term.out.write(loadingDialog("Building stack templates..."));
|
|
3320
4501
|
await Promise.all(app.stacks.map(async (stack) => {
|
|
3321
4502
|
const template = stack.toString(true);
|
|
3322
|
-
const path = (0,
|
|
3323
|
-
const file = (0,
|
|
3324
|
-
await (0,
|
|
3325
|
-
await (0,
|
|
4503
|
+
const path = (0, import_path10.join)(directories.template, app.name);
|
|
4504
|
+
const file = (0, import_path10.join)(path, `${stack.name}.json`);
|
|
4505
|
+
await (0, import_promises8.mkdir)(path, { recursive: true });
|
|
4506
|
+
await (0, import_promises8.writeFile)(file, template);
|
|
3326
4507
|
}));
|
|
3327
4508
|
done("Done building stack templates");
|
|
3328
4509
|
};
|
|
@@ -3370,7 +4551,7 @@ var shouldDeployBootstrap = async (client, stack) => {
|
|
|
3370
4551
|
// src/formation/client.ts
|
|
3371
4552
|
var import_client_cloudformation = require("@aws-sdk/client-cloudformation");
|
|
3372
4553
|
var import_client_s3 = require("@aws-sdk/client-s3");
|
|
3373
|
-
var
|
|
4554
|
+
var import_change_case12 = require("change-case");
|
|
3374
4555
|
var StackClient = class {
|
|
3375
4556
|
constructor(app, account, region, credentials) {
|
|
3376
4557
|
this.app = app;
|
|
@@ -3403,7 +4584,7 @@ var StackClient = class {
|
|
|
3403
4584
|
};
|
|
3404
4585
|
}
|
|
3405
4586
|
stackName(stackName) {
|
|
3406
|
-
return (0,
|
|
4587
|
+
return (0, import_change_case12.paramCase)(`${this.app.name}-${stackName}`);
|
|
3407
4588
|
}
|
|
3408
4589
|
tags(stack) {
|
|
3409
4590
|
const tags = [];
|
|
@@ -3448,19 +4629,26 @@ var StackClient = class {
|
|
|
3448
4629
|
async update(stack, capabilities) {
|
|
3449
4630
|
debug("Update the", style.info(stack.name), "stack");
|
|
3450
4631
|
const client = this.getClient(stack.region);
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
4632
|
+
try {
|
|
4633
|
+
await client.send(new import_client_cloudformation.UpdateStackCommand({
|
|
4634
|
+
StackName: this.stackName(stack.name),
|
|
4635
|
+
Capabilities: capabilities,
|
|
4636
|
+
Tags: this.tags(stack),
|
|
4637
|
+
...this.templateProp(stack)
|
|
4638
|
+
}));
|
|
4639
|
+
await (0, import_client_cloudformation.waitUntilStackUpdateComplete)({
|
|
4640
|
+
client,
|
|
4641
|
+
maxWaitTime: this.maxWaitTime,
|
|
4642
|
+
maxDelay: this.maxDelay
|
|
4643
|
+
}, {
|
|
4644
|
+
StackName: this.stackName(stack.name)
|
|
4645
|
+
});
|
|
4646
|
+
} catch (error) {
|
|
4647
|
+
if (error instanceof Error && error.name === "ValidationError" && error.message.toLowerCase().includes("no updates")) {
|
|
4648
|
+
return;
|
|
4649
|
+
}
|
|
4650
|
+
throw error;
|
|
4651
|
+
}
|
|
3464
4652
|
}
|
|
3465
4653
|
async validate(stack) {
|
|
3466
4654
|
debug("Validate the", style.info(stack.name), "stack");
|
|
@@ -3746,8 +4934,8 @@ var status = (program2) => {
|
|
|
3746
4934
|
};
|
|
3747
4935
|
|
|
3748
4936
|
// src/cli/ui/complex/publisher.ts
|
|
3749
|
-
var
|
|
3750
|
-
var
|
|
4937
|
+
var import_promises9 = require("fs/promises");
|
|
4938
|
+
var import_path12 = require("path");
|
|
3751
4939
|
var import_client_s32 = require("@aws-sdk/client-s3");
|
|
3752
4940
|
var assetPublisher = (config, app) => {
|
|
3753
4941
|
const client = new import_client_s32.S3Client({
|
|
@@ -3760,8 +4948,8 @@ var assetPublisher = (config, app) => {
|
|
|
3760
4948
|
await Promise.all([...stack.assets].map(async (asset) => {
|
|
3761
4949
|
await asset.publish?.({
|
|
3762
4950
|
async read(file) {
|
|
3763
|
-
const path = (0,
|
|
3764
|
-
const data = await (0,
|
|
4951
|
+
const path = (0, import_path12.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
|
|
4952
|
+
const data = await (0, import_promises9.readFile)(path);
|
|
3765
4953
|
return data;
|
|
3766
4954
|
},
|
|
3767
4955
|
async publish(name, data, hash) {
|