@awsless/awsless 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +293 -137
- package/dist/bin.js +281 -125
- package/dist/index.cjs +33 -2
- package/dist/index.d.ts +395 -11
- package/dist/index.js +27 -1
- package/package.json +4 -1
package/dist/bin.js
CHANGED
|
@@ -195,6 +195,8 @@ var toStack = ({ config: config2, assets, app, stackConfig, plugins }) => {
|
|
|
195
195
|
functions.forEach((lambda) => lambda.addToRolePolicy(allowConfigParameters));
|
|
196
196
|
return {
|
|
197
197
|
stack,
|
|
198
|
+
functions,
|
|
199
|
+
bindings,
|
|
198
200
|
depends: stackConfig.depends
|
|
199
201
|
};
|
|
200
202
|
};
|
|
@@ -204,7 +206,8 @@ import { join } from "path";
|
|
|
204
206
|
var rootDir = process.cwd();
|
|
205
207
|
var outDir = join(rootDir, ".awsless");
|
|
206
208
|
var assemblyDir = join(outDir, "assembly");
|
|
207
|
-
var
|
|
209
|
+
var assetDir = join(outDir, "asset");
|
|
210
|
+
var cacheDir = join(outDir, "cache");
|
|
208
211
|
|
|
209
212
|
// src/stack/app-bootstrap.ts
|
|
210
213
|
import { Stack as Stack3 } from "aws-cdk-lib";
|
|
@@ -249,7 +252,7 @@ var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
|
|
|
249
252
|
import { Rule } from "aws-cdk-lib/aws-events";
|
|
250
253
|
|
|
251
254
|
// src/util/resource.ts
|
|
252
|
-
import {
|
|
255
|
+
import { paramCase, pascalCase } from "change-case";
|
|
253
256
|
var toId = (resource, id) => {
|
|
254
257
|
return pascalCase(`${resource}-${id}`);
|
|
255
258
|
};
|
|
@@ -257,7 +260,7 @@ var toName = (stack, id) => {
|
|
|
257
260
|
return paramCase(`${stack.stackName}-${id}`);
|
|
258
261
|
};
|
|
259
262
|
var toEnvKey = (resource, id) => {
|
|
260
|
-
return
|
|
263
|
+
return `RESOURCE_${resource.toUpperCase()}_${id}`;
|
|
261
264
|
};
|
|
262
265
|
var addResourceEnvironment = (stack, resource, id, lambda) => {
|
|
263
266
|
const key = toEnvKey(resource, id);
|
|
@@ -356,43 +359,45 @@ var SizeSchema = z7.custom((value) => {
|
|
|
356
359
|
return z7.string().regex(/[0-9]+ (KB|MB|GB)/).safeParse(value).success;
|
|
357
360
|
}, "Invalid size").transform(toSize);
|
|
358
361
|
|
|
359
|
-
// src/plugins/function/util/
|
|
360
|
-
import {
|
|
361
|
-
import { createHash } from "crypto";
|
|
362
|
+
// src/plugins/function/util/esbuild.ts
|
|
363
|
+
import { build } from "esbuild";
|
|
364
|
+
import { createHash, randomUUID } from "crypto";
|
|
365
|
+
import { join as join2 } from "path";
|
|
366
|
+
import { readFile, rm } from "fs/promises";
|
|
362
367
|
var defaultBuild = async (file) => {
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
368
|
+
const random = randomUUID();
|
|
369
|
+
const codeFile = join2(cacheDir, `${random}.mjs`);
|
|
370
|
+
const mapFile = join2(cacheDir, `${random}.mjs.map`);
|
|
371
|
+
await build({
|
|
372
|
+
entryPoints: [file],
|
|
373
|
+
minify: true,
|
|
374
|
+
bundle: true,
|
|
375
|
+
external: [
|
|
370
376
|
"@aws-sdk/*",
|
|
371
377
|
"@aws-sdk",
|
|
372
378
|
"aws-sdk"
|
|
373
379
|
],
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
},
|
|
382
|
-
output: {
|
|
383
|
-
name: "output",
|
|
384
|
-
path: ""
|
|
385
|
-
}
|
|
380
|
+
sourcemap: "external",
|
|
381
|
+
target: "esnext",
|
|
382
|
+
treeShaking: true,
|
|
383
|
+
// jsxSideEffects:
|
|
384
|
+
format: "esm",
|
|
385
|
+
platform: "node",
|
|
386
|
+
outfile: codeFile
|
|
386
387
|
});
|
|
387
|
-
const
|
|
388
|
+
const code = await readFile(codeFile, "utf8");
|
|
389
|
+
const map = await readFile(mapFile, "utf8");
|
|
390
|
+
await rm(codeFile);
|
|
391
|
+
await rm(mapFile);
|
|
392
|
+
const hash = createHash("sha1").update(code).digest("hex");
|
|
388
393
|
return {
|
|
389
394
|
handler: "index.default",
|
|
390
395
|
hash,
|
|
391
396
|
files: [
|
|
392
397
|
{
|
|
393
|
-
name: "index.
|
|
394
|
-
code
|
|
395
|
-
map
|
|
398
|
+
name: "index.mjs",
|
|
399
|
+
code,
|
|
400
|
+
map
|
|
396
401
|
}
|
|
397
402
|
]
|
|
398
403
|
};
|
|
@@ -400,7 +405,7 @@ var defaultBuild = async (file) => {
|
|
|
400
405
|
|
|
401
406
|
// src/plugins/function/util/build.ts
|
|
402
407
|
import JSZip from "jszip";
|
|
403
|
-
import { basename, join as
|
|
408
|
+
import { basename, join as join3 } from "path";
|
|
404
409
|
import { mkdir, writeFile } from "fs/promises";
|
|
405
410
|
import { filesize } from "filesize";
|
|
406
411
|
var zipFiles = (files) => {
|
|
@@ -417,36 +422,36 @@ var zipFiles = (files) => {
|
|
|
417
422
|
});
|
|
418
423
|
};
|
|
419
424
|
var writeBuildHash = async (config2, stack, id, hash) => {
|
|
420
|
-
const funcPath =
|
|
421
|
-
const versionFile =
|
|
425
|
+
const funcPath = join3(assetDir, "function", config2.name, stack.artifactId, id);
|
|
426
|
+
const versionFile = join3(funcPath, "HASH");
|
|
422
427
|
await writeFile(versionFile, hash);
|
|
423
428
|
};
|
|
424
429
|
var writeBuildFiles = async (config2, stack, id, files) => {
|
|
425
|
-
const
|
|
426
|
-
const funcPath =
|
|
427
|
-
const filesPath =
|
|
428
|
-
const bundleFile =
|
|
429
|
-
debug("Bundle size of", style.info(
|
|
430
|
+
const bundle = await zipFiles(files);
|
|
431
|
+
const funcPath = join3(assetDir, "function", config2.name, stack.artifactId, id);
|
|
432
|
+
const filesPath = join3(funcPath, "files");
|
|
433
|
+
const bundleFile = join3(funcPath, "bundle.zip");
|
|
434
|
+
debug("Bundle size of", style.info(join3(config2.name, stack.artifactId, id)), "is", style.attr(filesize(bundle.byteLength)));
|
|
430
435
|
await mkdir(filesPath, { recursive: true });
|
|
431
|
-
await writeFile(bundleFile,
|
|
436
|
+
await writeFile(bundleFile, bundle);
|
|
432
437
|
await Promise.all(files.map(async (file) => {
|
|
433
|
-
const fileName =
|
|
438
|
+
const fileName = join3(filesPath, file.name);
|
|
434
439
|
await mkdir(basename(fileName), { recursive: true });
|
|
435
440
|
await writeFile(fileName, file.code);
|
|
436
441
|
if (file.map) {
|
|
437
|
-
const mapName =
|
|
442
|
+
const mapName = join3(filesPath, `${file.name}.map`);
|
|
438
443
|
await writeFile(mapName, file.map);
|
|
439
444
|
}
|
|
440
445
|
}));
|
|
441
446
|
return {
|
|
442
447
|
file: bundleFile,
|
|
443
|
-
size:
|
|
448
|
+
size: bundle.byteLength
|
|
444
449
|
};
|
|
445
450
|
};
|
|
446
451
|
|
|
447
452
|
// src/plugins/function/util/publish.ts
|
|
448
|
-
import { join as
|
|
449
|
-
import { readFile } from "fs/promises";
|
|
453
|
+
import { join as join4 } from "path";
|
|
454
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
450
455
|
import { GetObjectCommand, ObjectCannedACL, PutObjectCommand, S3Client, StorageClass } from "@aws-sdk/client-s3";
|
|
451
456
|
|
|
452
457
|
// src/stack/bootstrap.ts
|
|
@@ -486,11 +491,11 @@ var shouldDeployBootstrap = async (client, name) => {
|
|
|
486
491
|
var publishFunctionAsset = async (config2, stack, id) => {
|
|
487
492
|
const bucket = assetBucketName(config2);
|
|
488
493
|
const key = `${config2.name}/${stack.artifactId}/function/${id}.zip`;
|
|
489
|
-
const funcPath =
|
|
490
|
-
const bundleFile =
|
|
491
|
-
const hashFile =
|
|
492
|
-
const hash = await
|
|
493
|
-
const file = await
|
|
494
|
+
const funcPath = join4(assetDir, "function", config2.name, stack.artifactId, id);
|
|
495
|
+
const bundleFile = join4(funcPath, "bundle.zip");
|
|
496
|
+
const hashFile = join4(funcPath, "HASH");
|
|
497
|
+
const hash = await readFile2(hashFile, "utf8");
|
|
498
|
+
const file = await readFile2(bundleFile);
|
|
494
499
|
const client = new S3Client({
|
|
495
500
|
credentials: config2.credentials,
|
|
496
501
|
region: config2.region
|
|
@@ -576,7 +581,7 @@ var functionPlugin = definePlugin({
|
|
|
576
581
|
});
|
|
577
582
|
}
|
|
578
583
|
});
|
|
579
|
-
var toFunction = ({ config: config2, stack,
|
|
584
|
+
var toFunction = ({ config: config2, stack, assets }, id, fileOrProps) => {
|
|
580
585
|
const props = typeof fileOrProps === "string" ? { ...config2.defaults?.function, file: fileOrProps } : { ...config2.defaults?.function, ...fileOrProps };
|
|
581
586
|
const lambda = new Function(stack, toId("function", id), {
|
|
582
587
|
functionName: toName(stack, id),
|
|
@@ -587,24 +592,24 @@ var toFunction = ({ config: config2, stack, stackConfig, assets }, id, fileOrPro
|
|
|
587
592
|
});
|
|
588
593
|
lambda.addEnvironment("APP", config2.name, { removeInEdge: true });
|
|
589
594
|
lambda.addEnvironment("STAGE", config2.stage, { removeInEdge: true });
|
|
590
|
-
lambda.addEnvironment("STACK",
|
|
595
|
+
lambda.addEnvironment("STACK", stack.artifactId, { removeInEdge: true });
|
|
591
596
|
if (lambda.runtime.toString().startsWith("nodejs")) {
|
|
592
597
|
lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1", {
|
|
593
598
|
removeInEdge: true
|
|
594
599
|
});
|
|
595
600
|
}
|
|
596
601
|
assets.add({
|
|
597
|
-
|
|
602
|
+
stackName: stack.artifactId,
|
|
598
603
|
resource: "function",
|
|
599
604
|
resourceName: id,
|
|
600
605
|
async build() {
|
|
601
606
|
const result = await defaultBuild(props.file);
|
|
602
|
-
const
|
|
607
|
+
const bundle = await writeBuildFiles(config2, stack, id, result.files);
|
|
603
608
|
await writeBuildHash(config2, stack, id, result.hash);
|
|
604
609
|
const func = lambda.node.defaultChild;
|
|
605
610
|
func.handler = result.handler;
|
|
606
611
|
return {
|
|
607
|
-
size: formatByteSize(
|
|
612
|
+
size: formatByteSize(bundle.size)
|
|
608
613
|
};
|
|
609
614
|
},
|
|
610
615
|
async publish() {
|
|
@@ -840,7 +845,6 @@ import { z as z18 } from "zod";
|
|
|
840
845
|
import { Topic } from "aws-cdk-lib/aws-sns";
|
|
841
846
|
import { SnsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
842
847
|
import { Arn as Arn2, ArnFormat } from "aws-cdk-lib";
|
|
843
|
-
import { PolicyStatement as PolicyStatement2 } from "aws-cdk-lib/aws-iam";
|
|
844
848
|
var topicPlugin = definePlugin({
|
|
845
849
|
name: "topic",
|
|
846
850
|
schema: z18.object({
|
|
@@ -862,12 +866,6 @@ var topicPlugin = definePlugin({
|
|
|
862
866
|
},
|
|
863
867
|
onStack(ctx) {
|
|
864
868
|
const { config: config2, stack, stackConfig, bind } = ctx;
|
|
865
|
-
bind((lambda) => {
|
|
866
|
-
lambda.addToRolePolicy(new PolicyStatement2({
|
|
867
|
-
actions: ["sns:publish"],
|
|
868
|
-
resources: ["*"]
|
|
869
|
-
}));
|
|
870
|
-
});
|
|
871
869
|
return Object.entries(stackConfig.topics || {}).map(([id, props]) => {
|
|
872
870
|
const lambda = toFunction(ctx, id, props);
|
|
873
871
|
const topic = Topic.fromTopicArn(
|
|
@@ -880,6 +878,10 @@ var topicPlugin = definePlugin({
|
|
|
880
878
|
}, stack)
|
|
881
879
|
);
|
|
882
880
|
lambda.addEventSource(new SnsEventSource(topic));
|
|
881
|
+
bind((lambda2) => {
|
|
882
|
+
addResourceEnvironment(stack, "topic", id, lambda2);
|
|
883
|
+
topic.grantPublish(lambda2);
|
|
884
|
+
});
|
|
883
885
|
return lambda;
|
|
884
886
|
});
|
|
885
887
|
}
|
|
@@ -888,7 +890,7 @@ var topicPlugin = definePlugin({
|
|
|
888
890
|
// src/plugins/search.ts
|
|
889
891
|
import { z as z19 } from "zod";
|
|
890
892
|
import { CfnCollection } from "aws-cdk-lib/aws-opensearchserverless";
|
|
891
|
-
import { PolicyStatement as
|
|
893
|
+
import { PolicyStatement as PolicyStatement2 } from "aws-cdk-lib/aws-iam";
|
|
892
894
|
var searchPlugin = definePlugin({
|
|
893
895
|
name: "search",
|
|
894
896
|
schema: z19.object({
|
|
@@ -903,7 +905,7 @@ var searchPlugin = definePlugin({
|
|
|
903
905
|
type: "SEARCH"
|
|
904
906
|
});
|
|
905
907
|
bind((lambda) => {
|
|
906
|
-
lambda.addToRolePolicy(new
|
|
908
|
+
lambda.addToRolePolicy(new PolicyStatement2({
|
|
907
909
|
actions: ["aoss:APIAccessAll"],
|
|
908
910
|
resources: [collection.attrArn]
|
|
909
911
|
}));
|
|
@@ -912,6 +914,138 @@ var searchPlugin = definePlugin({
|
|
|
912
914
|
}
|
|
913
915
|
});
|
|
914
916
|
|
|
917
|
+
// src/plugins/graphql/index.ts
|
|
918
|
+
import { z as z21 } from "zod";
|
|
919
|
+
import { AuthorizationType, CfnGraphQLApi, CfnGraphQLSchema, GraphqlApi, MappingTemplate } from "aws-cdk-lib/aws-appsync";
|
|
920
|
+
import { mergeTypeDefs } from "@graphql-tools/merge";
|
|
921
|
+
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
922
|
+
|
|
923
|
+
// src/util/array.ts
|
|
924
|
+
var toArray = (value) => {
|
|
925
|
+
if (Array.isArray(value)) {
|
|
926
|
+
return value;
|
|
927
|
+
}
|
|
928
|
+
return [value];
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
// src/plugins/graphql/index.ts
|
|
932
|
+
import { dirname, join as join5 } from "path";
|
|
933
|
+
import { print } from "graphql";
|
|
934
|
+
import { paramCase as paramCase2 } from "change-case";
|
|
935
|
+
|
|
936
|
+
// src/plugins/graphql/schema/resolver-field.ts
|
|
937
|
+
import { z as z20 } from "zod";
|
|
938
|
+
var ResolverFieldSchema = z20.custom((value) => {
|
|
939
|
+
return z20.string().regex(/([a-z0-9\_]+)(\s){1}([a-z0-9\_]+)/gi).safeParse(value).success;
|
|
940
|
+
}, `Invalid resolver field. Valid example: "Query list"`);
|
|
941
|
+
|
|
942
|
+
// src/plugins/graphql/index.ts
|
|
943
|
+
import { CfnOutput as CfnOutput2, Fn } from "aws-cdk-lib";
|
|
944
|
+
var graphqlPlugin = definePlugin({
|
|
945
|
+
name: "graphql",
|
|
946
|
+
schema: z21.object({
|
|
947
|
+
defaults: z21.object({
|
|
948
|
+
graphql: z21.record(ResourceIdSchema, z21.object({
|
|
949
|
+
authorization: z21.object({
|
|
950
|
+
authorizer: FunctionSchema,
|
|
951
|
+
ttl: DurationSchema.default("1 hour")
|
|
952
|
+
}).optional(),
|
|
953
|
+
mappingTemplate: z21.object({
|
|
954
|
+
request: LocalFileSchema.optional(),
|
|
955
|
+
response: LocalFileSchema.optional()
|
|
956
|
+
}).optional()
|
|
957
|
+
})).optional()
|
|
958
|
+
}).default({}),
|
|
959
|
+
stacks: z21.object({
|
|
960
|
+
graphql: z21.record(ResourceIdSchema, z21.object({
|
|
961
|
+
schema: z21.union([
|
|
962
|
+
LocalFileSchema,
|
|
963
|
+
z21.array(LocalFileSchema).min(1)
|
|
964
|
+
]).optional(),
|
|
965
|
+
resolvers: z21.record(ResolverFieldSchema, FunctionSchema).optional()
|
|
966
|
+
})).optional()
|
|
967
|
+
}).array()
|
|
968
|
+
}),
|
|
969
|
+
onBootstrap({ config: config2, stack, assets }) {
|
|
970
|
+
const list3 = /* @__PURE__ */ new Set();
|
|
971
|
+
Object.values(config2.stacks).forEach((stackConfig) => {
|
|
972
|
+
Object.keys(stackConfig.graphql || {}).forEach((id) => {
|
|
973
|
+
list3.add(id);
|
|
974
|
+
});
|
|
975
|
+
});
|
|
976
|
+
list3.forEach((id) => {
|
|
977
|
+
const file = join5(assetDir, "graphql", config2.name, id, "schema.graphql");
|
|
978
|
+
const authorization = config2.defaults.graphql?.[id]?.authorization;
|
|
979
|
+
const authProps = {};
|
|
980
|
+
if (authorization) {
|
|
981
|
+
const authorizer = toFunction({ config: config2, assets, stack }, `${id}-authorizer`, authorization.authorizer);
|
|
982
|
+
authProps.additionalAuthenticationProviders = [{
|
|
983
|
+
authenticationType: AuthorizationType.LAMBDA,
|
|
984
|
+
lambdaAuthorizerConfig: {
|
|
985
|
+
authorizerUri: authorizer.functionArn,
|
|
986
|
+
authorizerResultTtlInSeconds: authorization.ttl.toSeconds()
|
|
987
|
+
}
|
|
988
|
+
}];
|
|
989
|
+
}
|
|
990
|
+
const api = new CfnGraphQLApi(stack, toId("graphql", id), {
|
|
991
|
+
...authProps,
|
|
992
|
+
name: toName(stack, id),
|
|
993
|
+
authenticationType: AuthorizationType.API_KEY
|
|
994
|
+
});
|
|
995
|
+
new CfnOutput2(stack, toId("output", id), {
|
|
996
|
+
exportName: toId("graphql", id),
|
|
997
|
+
value: api.attrApiId
|
|
998
|
+
});
|
|
999
|
+
assets.add({
|
|
1000
|
+
stackName: stack.artifactId,
|
|
1001
|
+
resource: "schema",
|
|
1002
|
+
resourceName: id,
|
|
1003
|
+
async build() {
|
|
1004
|
+
const schemas = [];
|
|
1005
|
+
await Promise.all(Object.values(config2.stacks).map(async (stackConfig) => {
|
|
1006
|
+
const schemaFiles = toArray(stackConfig.graphql?.[id].schema || []);
|
|
1007
|
+
await Promise.all(schemaFiles.map(async (schemaFile) => {
|
|
1008
|
+
const schema3 = await readFile3(schemaFile, "utf8");
|
|
1009
|
+
schemas.push(schema3);
|
|
1010
|
+
}));
|
|
1011
|
+
}));
|
|
1012
|
+
const schema2 = print(mergeTypeDefs(schemas));
|
|
1013
|
+
await mkdir2(dirname(file), { recursive: true });
|
|
1014
|
+
await writeFile2(file, schema2);
|
|
1015
|
+
new CfnGraphQLSchema(stack, toId("schema", id), {
|
|
1016
|
+
apiId: api.attrApiId,
|
|
1017
|
+
definition: schema2
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
});
|
|
1021
|
+
});
|
|
1022
|
+
},
|
|
1023
|
+
onStack(ctx) {
|
|
1024
|
+
const { config: config2, stack, stackConfig } = ctx;
|
|
1025
|
+
return Object.entries(stackConfig.graphql || {}).map(([id, props]) => {
|
|
1026
|
+
const defaults = config2.defaults.graphql?.[id] || {};
|
|
1027
|
+
return Object.entries(props.resolvers || {}).map(([typeAndField, functionProps]) => {
|
|
1028
|
+
const api = GraphqlApi.fromGraphqlApiAttributes(stack, toId("graphql", id), {
|
|
1029
|
+
graphqlApiId: Fn.importValue(toId("graphql", id))
|
|
1030
|
+
});
|
|
1031
|
+
const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
|
|
1032
|
+
const functionId = paramCase2(`${id}-${typeName}-${fieldName}`);
|
|
1033
|
+
const lambda = toFunction(ctx, functionId, functionProps);
|
|
1034
|
+
const source = api.addLambdaDataSource(toId("data-source", functionId), lambda, {
|
|
1035
|
+
name: toId("data-source", functionId)
|
|
1036
|
+
});
|
|
1037
|
+
source.createResolver(toId("resolver", functionId), {
|
|
1038
|
+
typeName,
|
|
1039
|
+
fieldName,
|
|
1040
|
+
requestMappingTemplate: defaults.mappingTemplate?.request ? MappingTemplate.fromFile(defaults.mappingTemplate.request) : MappingTemplate.lambdaRequest(),
|
|
1041
|
+
responseMappingTemplate: defaults.mappingTemplate?.response ? MappingTemplate.fromFile(defaults.mappingTemplate.response) : MappingTemplate.lambdaResult()
|
|
1042
|
+
});
|
|
1043
|
+
return lambda;
|
|
1044
|
+
});
|
|
1045
|
+
}).flat();
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
1048
|
+
|
|
915
1049
|
// src/plugins/index.ts
|
|
916
1050
|
var defaultPlugins = [
|
|
917
1051
|
functionPlugin,
|
|
@@ -920,7 +1054,8 @@ var defaultPlugins = [
|
|
|
920
1054
|
tablePlugin,
|
|
921
1055
|
storePlugin,
|
|
922
1056
|
topicPlugin,
|
|
923
|
-
searchPlugin
|
|
1057
|
+
searchPlugin,
|
|
1058
|
+
graphqlPlugin
|
|
924
1059
|
];
|
|
925
1060
|
|
|
926
1061
|
// src/stack/app-bootstrap.ts
|
|
@@ -933,8 +1068,16 @@ var appBootstrapStack = ({ config: config2, app, assets }) => {
|
|
|
933
1068
|
...config2.plugins || []
|
|
934
1069
|
];
|
|
935
1070
|
debug("Run plugin onBootstrap listeners");
|
|
936
|
-
plugins.
|
|
937
|
-
|
|
1071
|
+
const functions = plugins.map((plugin) => plugin.onBootstrap?.({
|
|
1072
|
+
config: config2,
|
|
1073
|
+
app,
|
|
1074
|
+
stack,
|
|
1075
|
+
assets
|
|
1076
|
+
})).filter(Boolean).flat().filter(Boolean);
|
|
1077
|
+
return {
|
|
1078
|
+
stack,
|
|
1079
|
+
functions
|
|
1080
|
+
};
|
|
938
1081
|
};
|
|
939
1082
|
|
|
940
1083
|
// src/util/deployment.ts
|
|
@@ -1000,10 +1143,10 @@ var Assets = class {
|
|
|
1000
1143
|
assets = {};
|
|
1001
1144
|
id = 0;
|
|
1002
1145
|
add(opts) {
|
|
1003
|
-
if (!this.assets[opts.
|
|
1004
|
-
this.assets[opts.
|
|
1146
|
+
if (!this.assets[opts.stackName]) {
|
|
1147
|
+
this.assets[opts.stackName] = [];
|
|
1005
1148
|
}
|
|
1006
|
-
this.assets[opts.
|
|
1149
|
+
this.assets[opts.stackName].push({
|
|
1007
1150
|
...opts,
|
|
1008
1151
|
id: this.id++
|
|
1009
1152
|
});
|
|
@@ -1013,12 +1156,12 @@ var Assets = class {
|
|
|
1013
1156
|
}
|
|
1014
1157
|
forEach(cb) {
|
|
1015
1158
|
Object.values(this.assets).forEach((assets) => {
|
|
1016
|
-
cb(assets[0].
|
|
1159
|
+
cb(assets[0].stackName, assets);
|
|
1017
1160
|
});
|
|
1018
1161
|
}
|
|
1019
1162
|
map(cb) {
|
|
1020
1163
|
return Object.values(this.assets).map((assets) => {
|
|
1021
|
-
return cb(assets[0].
|
|
1164
|
+
return cb(assets[0].stackName, assets);
|
|
1022
1165
|
});
|
|
1023
1166
|
}
|
|
1024
1167
|
};
|
|
@@ -1056,13 +1199,14 @@ var toApp = async (config2, filters) => {
|
|
|
1056
1199
|
debug("Plugins detected:", plugins.map((plugin) => style.info(plugin.name)).join(", "));
|
|
1057
1200
|
debug("Run plugin onApp listeners");
|
|
1058
1201
|
plugins.forEach((plugin) => plugin.onApp?.({ config: config2, app, assets }));
|
|
1202
|
+
const bootstrap2 = appBootstrapStack({ config: config2, app, assets });
|
|
1059
1203
|
debug("Stack filters:", filters.map((filter) => style.info(filter)).join(", "));
|
|
1060
1204
|
const filterdStacks = filters.length === 0 ? config2.stacks : getAllDepends(
|
|
1061
1205
|
// config.stacks,
|
|
1062
1206
|
config2.stacks.filter((stack) => filters.includes(stack.name))
|
|
1063
1207
|
);
|
|
1064
1208
|
for (const stackConfig of filterdStacks) {
|
|
1065
|
-
const { stack } = toStack({
|
|
1209
|
+
const { stack, bindings } = toStack({
|
|
1066
1210
|
config: config2,
|
|
1067
1211
|
stackConfig,
|
|
1068
1212
|
assets,
|
|
@@ -1070,14 +1214,14 @@ var toApp = async (config2, filters) => {
|
|
|
1070
1214
|
app
|
|
1071
1215
|
});
|
|
1072
1216
|
stacks.push({ stack, config: stackConfig });
|
|
1217
|
+
bindings.forEach((cb) => bootstrap2.functions.forEach(cb));
|
|
1073
1218
|
}
|
|
1074
1219
|
let dependencyTree;
|
|
1075
|
-
|
|
1076
|
-
if (bootstrap2.node.children.length === 0) {
|
|
1220
|
+
if (bootstrap2.stack.node.children.length === 0) {
|
|
1077
1221
|
dependencyTree = createDependencyTree(stacks, 0);
|
|
1078
1222
|
} else {
|
|
1079
1223
|
dependencyTree = [{
|
|
1080
|
-
stack: bootstrap2,
|
|
1224
|
+
stack: bootstrap2.stack,
|
|
1081
1225
|
level: 0,
|
|
1082
1226
|
children: createDependencyTree(stacks, 1)
|
|
1083
1227
|
}];
|
|
@@ -1149,7 +1293,7 @@ var footer = () => {
|
|
|
1149
1293
|
};
|
|
1150
1294
|
|
|
1151
1295
|
// src/config.ts
|
|
1152
|
-
import { join as
|
|
1296
|
+
import { join as join7 } from "path";
|
|
1153
1297
|
|
|
1154
1298
|
// src/util/account.ts
|
|
1155
1299
|
import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
|
|
@@ -1168,17 +1312,17 @@ var getCredentials = (profile) => {
|
|
|
1168
1312
|
};
|
|
1169
1313
|
|
|
1170
1314
|
// src/schema/app.ts
|
|
1171
|
-
import { z as
|
|
1315
|
+
import { z as z25 } from "zod";
|
|
1172
1316
|
|
|
1173
1317
|
// src/schema/stack.ts
|
|
1174
|
-
import { z as
|
|
1175
|
-
var StackSchema =
|
|
1318
|
+
import { z as z22 } from "zod";
|
|
1319
|
+
var StackSchema = z22.object({
|
|
1176
1320
|
name: ResourceIdSchema,
|
|
1177
|
-
depends:
|
|
1321
|
+
depends: z22.array(z22.lazy(() => StackSchema)).optional()
|
|
1178
1322
|
});
|
|
1179
1323
|
|
|
1180
1324
|
// src/schema/region.ts
|
|
1181
|
-
import { z as
|
|
1325
|
+
import { z as z23 } from "zod";
|
|
1182
1326
|
var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
|
|
1183
1327
|
var AF = ["af-south-1"];
|
|
1184
1328
|
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"];
|
|
@@ -1195,35 +1339,35 @@ var regions = [
|
|
|
1195
1339
|
...ME,
|
|
1196
1340
|
...SA
|
|
1197
1341
|
];
|
|
1198
|
-
var RegionSchema =
|
|
1342
|
+
var RegionSchema = z23.enum(regions);
|
|
1199
1343
|
|
|
1200
1344
|
// src/schema/plugin.ts
|
|
1201
|
-
import { z as
|
|
1202
|
-
var PluginSchema =
|
|
1203
|
-
name:
|
|
1204
|
-
schema:
|
|
1205
|
-
depends:
|
|
1206
|
-
onBootstrap:
|
|
1207
|
-
onStack:
|
|
1208
|
-
onApp:
|
|
1345
|
+
import { z as z24 } from "zod";
|
|
1346
|
+
var PluginSchema = z24.object({
|
|
1347
|
+
name: z24.string(),
|
|
1348
|
+
schema: z24.custom().optional(),
|
|
1349
|
+
// depends: z.array(z.lazy(() => PluginSchema)).optional(),
|
|
1350
|
+
onBootstrap: z24.function().returns(z24.any()).optional(),
|
|
1351
|
+
onStack: z24.function().returns(z24.any()).optional(),
|
|
1352
|
+
onApp: z24.function().returns(z24.void()).optional()
|
|
1209
1353
|
// bind: z.function().optional(),
|
|
1210
1354
|
});
|
|
1211
1355
|
|
|
1212
1356
|
// src/schema/app.ts
|
|
1213
|
-
var AppSchema =
|
|
1357
|
+
var AppSchema = z25.object({
|
|
1214
1358
|
name: ResourceIdSchema,
|
|
1215
1359
|
region: RegionSchema,
|
|
1216
|
-
profile:
|
|
1217
|
-
stage:
|
|
1218
|
-
defaults:
|
|
1219
|
-
stacks:
|
|
1220
|
-
plugins:
|
|
1360
|
+
profile: z25.string(),
|
|
1361
|
+
stage: z25.string().regex(/[a-z]+/).default("prod"),
|
|
1362
|
+
defaults: z25.object({}).default({}),
|
|
1363
|
+
stacks: z25.array(StackSchema).min(1),
|
|
1364
|
+
plugins: z25.array(PluginSchema).optional()
|
|
1221
1365
|
});
|
|
1222
1366
|
|
|
1223
1367
|
// src/util/import.ts
|
|
1224
1368
|
import { transformFile } from "@swc/core";
|
|
1225
|
-
import { dirname, join as
|
|
1226
|
-
import { lstat, mkdir as
|
|
1369
|
+
import { dirname as dirname2, join as join6 } from "path";
|
|
1370
|
+
import { lstat, mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
1227
1371
|
var resolveFileNameExtension = async (path) => {
|
|
1228
1372
|
const options = [
|
|
1229
1373
|
"",
|
|
@@ -1247,14 +1391,14 @@ var resolveFileNameExtension = async (path) => {
|
|
|
1247
1391
|
throw new Error(`Failed to load file: ${path}`);
|
|
1248
1392
|
};
|
|
1249
1393
|
var resolveDir = (path) => {
|
|
1250
|
-
return
|
|
1394
|
+
return dirname2(path).replace(rootDir + "/", "");
|
|
1251
1395
|
};
|
|
1252
1396
|
var importFile = async (path) => {
|
|
1253
1397
|
const load = async (file) => {
|
|
1254
1398
|
let { code: code2 } = await transformFile(file, {
|
|
1255
1399
|
isModule: true
|
|
1256
1400
|
});
|
|
1257
|
-
const path2 =
|
|
1401
|
+
const path2 = dirname2(file);
|
|
1258
1402
|
const dir = resolveDir(file);
|
|
1259
1403
|
code2 = code2.replaceAll("__dirname", `"${dir}"`);
|
|
1260
1404
|
const matches = code2.match(/import\s*{\s*[a-z0-9\_]+\s*}\s*from\s*('|")(\.[\/a-z0-9\_\-]+)('|");?/ig);
|
|
@@ -1263,23 +1407,23 @@ var importFile = async (path) => {
|
|
|
1263
1407
|
await Promise.all(matches?.map(async (match) => {
|
|
1264
1408
|
const parts = /('|")(\.[\/a-z0-9\_\-]+)('|")/ig.exec(match);
|
|
1265
1409
|
const from = parts[2];
|
|
1266
|
-
const file2 = await resolveFileNameExtension(
|
|
1410
|
+
const file2 = await resolveFileNameExtension(join6(path2, from));
|
|
1267
1411
|
const result = await load(file2);
|
|
1268
1412
|
code2 = code2.replace(match, result);
|
|
1269
1413
|
}));
|
|
1270
1414
|
return code2;
|
|
1271
1415
|
};
|
|
1272
1416
|
const code = await load(path);
|
|
1273
|
-
const outputFile =
|
|
1274
|
-
await
|
|
1275
|
-
await
|
|
1417
|
+
const outputFile = join6(outDir, "config.js");
|
|
1418
|
+
await mkdir3(outDir, { recursive: true });
|
|
1419
|
+
await writeFile3(outputFile, code);
|
|
1276
1420
|
return import(outputFile);
|
|
1277
1421
|
};
|
|
1278
1422
|
|
|
1279
1423
|
// src/config.ts
|
|
1280
1424
|
var importConfig = async (options) => {
|
|
1281
1425
|
debug("Import config file");
|
|
1282
|
-
const fileName =
|
|
1426
|
+
const fileName = join7(process.cwd(), options.configFile || "awsless.config.ts");
|
|
1283
1427
|
const module = await importFile(fileName);
|
|
1284
1428
|
const appConfig = typeof module.default === "function" ? await module.default({
|
|
1285
1429
|
profile: options.profile,
|
|
@@ -1493,6 +1637,13 @@ var Interface = class {
|
|
|
1493
1637
|
if (this.input.isTTY) {
|
|
1494
1638
|
this.input.setRawMode(true);
|
|
1495
1639
|
}
|
|
1640
|
+
this.input.on("keypress", (_, key) => {
|
|
1641
|
+
const action = parseAction(key);
|
|
1642
|
+
if (action === "abort") {
|
|
1643
|
+
this.unref();
|
|
1644
|
+
process.exit(1);
|
|
1645
|
+
}
|
|
1646
|
+
});
|
|
1496
1647
|
}
|
|
1497
1648
|
// private subscriber: Actions | undefined
|
|
1498
1649
|
readline;
|
|
@@ -1642,12 +1793,6 @@ var layout = async (cb) => {
|
|
|
1642
1793
|
const term = createTerminal();
|
|
1643
1794
|
term.out.clear();
|
|
1644
1795
|
term.out.write(logo());
|
|
1645
|
-
term.in.captureInput({
|
|
1646
|
-
abort: () => {
|
|
1647
|
-
term.in.showCursor();
|
|
1648
|
-
process.exit(1);
|
|
1649
|
-
}
|
|
1650
|
-
});
|
|
1651
1796
|
try {
|
|
1652
1797
|
const options = program.optsWithGlobals();
|
|
1653
1798
|
const config2 = await importConfig(options);
|
|
@@ -1668,7 +1813,7 @@ var layout = async (cb) => {
|
|
|
1668
1813
|
term.in.unref();
|
|
1669
1814
|
setTimeout(() => {
|
|
1670
1815
|
process.exit(0);
|
|
1671
|
-
},
|
|
1816
|
+
}, 100);
|
|
1672
1817
|
}
|
|
1673
1818
|
};
|
|
1674
1819
|
|
|
@@ -1699,7 +1844,8 @@ var assetBuilder = (assets) => {
|
|
|
1699
1844
|
const groups = new Signal([br()]);
|
|
1700
1845
|
term.out.write(groups);
|
|
1701
1846
|
const stackNameSize = Math.max(...Object.keys(assets.list()).map((stack) => stack.length));
|
|
1702
|
-
|
|
1847
|
+
const resourceSize = Math.max(...Object.values(assets.list()).map((assets2) => assets2.map((asset) => asset.resource.length)).flat());
|
|
1848
|
+
await Promise.all(assets.map(async (stackName, assets2) => {
|
|
1703
1849
|
const group = new Signal([]);
|
|
1704
1850
|
groups.update((groups2) => [...groups2, group]);
|
|
1705
1851
|
await Promise.all(assets2.map(async (asset) => {
|
|
@@ -1708,12 +1854,13 @@ var assetBuilder = (assets) => {
|
|
|
1708
1854
|
const line = flexLine(term, [
|
|
1709
1855
|
icon,
|
|
1710
1856
|
" ",
|
|
1711
|
-
style.label(
|
|
1712
|
-
" ".repeat(stackNameSize -
|
|
1857
|
+
style.label(stackName),
|
|
1858
|
+
" ".repeat(stackNameSize - stackName.length),
|
|
1713
1859
|
" ",
|
|
1714
1860
|
style.placeholder(symbol.pointerSmall),
|
|
1715
1861
|
" ",
|
|
1716
1862
|
style.warning(asset.resource),
|
|
1863
|
+
" ".repeat(resourceSize - asset.resource.length),
|
|
1717
1864
|
" ",
|
|
1718
1865
|
style.placeholder(symbol.pointerSmall),
|
|
1719
1866
|
" ",
|
|
@@ -1744,25 +1891,26 @@ var assetBuilder = (assets) => {
|
|
|
1744
1891
|
};
|
|
1745
1892
|
|
|
1746
1893
|
// src/util/cleanup.ts
|
|
1747
|
-
import { mkdir as
|
|
1894
|
+
import { mkdir as mkdir4, rm as rm2 } from "fs/promises";
|
|
1748
1895
|
var cleanUp = async () => {
|
|
1749
1896
|
debug("Clean up assembly & asset files");
|
|
1750
1897
|
const paths = [
|
|
1751
1898
|
assemblyDir,
|
|
1752
|
-
|
|
1899
|
+
assetDir,
|
|
1900
|
+
cacheDir
|
|
1753
1901
|
];
|
|
1754
|
-
await Promise.all(paths.map((path) =>
|
|
1902
|
+
await Promise.all(paths.map((path) => rm2(path, {
|
|
1755
1903
|
recursive: true,
|
|
1756
1904
|
force: true,
|
|
1757
1905
|
maxRetries: 2
|
|
1758
1906
|
})));
|
|
1759
|
-
await Promise.all(paths.map((path) =>
|
|
1907
|
+
await Promise.all(paths.map((path) => mkdir4(path, {
|
|
1760
1908
|
recursive: true
|
|
1761
1909
|
})));
|
|
1762
1910
|
};
|
|
1763
1911
|
|
|
1764
1912
|
// src/cli/command/build.ts
|
|
1765
|
-
var
|
|
1913
|
+
var build2 = (program2) => {
|
|
1766
1914
|
program2.command("build").argument("[stack...]", "Optionally filter stacks to build").description("Build your app").action(async (filters) => {
|
|
1767
1915
|
await layout(async (config2, write) => {
|
|
1768
1916
|
const { app, assets } = await toApp(config2, filters);
|
|
@@ -1880,7 +2028,7 @@ var StackClient = class {
|
|
|
1880
2028
|
stack.Outputs?.forEach((output) => {
|
|
1881
2029
|
outputs[output.OutputKey] = output.OutputValue;
|
|
1882
2030
|
});
|
|
1883
|
-
debug("Status for:
|
|
2031
|
+
debug("Status for:", style.info(name), "is", style.attr(stack.StackStatus));
|
|
1884
2032
|
return {
|
|
1885
2033
|
status: stack.StackStatus,
|
|
1886
2034
|
reason: stack.StackStatusReason,
|
|
@@ -2146,6 +2294,7 @@ var deploy = (program2) => {
|
|
|
2146
2294
|
await cleanUp();
|
|
2147
2295
|
await write(assetBuilder(assets));
|
|
2148
2296
|
write(br());
|
|
2297
|
+
write(br());
|
|
2149
2298
|
const donePublishing = write(loadingDialog("Publishing stack assets to AWS..."));
|
|
2150
2299
|
await Promise.all(assets.map(async (_, assets2) => {
|
|
2151
2300
|
await Promise.all(assets2.map(async (asset) => {
|
|
@@ -2161,21 +2310,28 @@ var deploy = (program2) => {
|
|
|
2161
2310
|
const doneDeploying = write(loadingDialog("Deploying stacks to AWS..."));
|
|
2162
2311
|
write(br());
|
|
2163
2312
|
write(stackTree(dependencyTree, statuses));
|
|
2313
|
+
write(br());
|
|
2164
2314
|
const client = new StackClient(config2);
|
|
2165
2315
|
const deploymentLine = createDeploymentLine(dependencyTree);
|
|
2166
2316
|
for (const stacks of deploymentLine) {
|
|
2167
|
-
await Promise.allSettled(stacks.map(async (stack) => {
|
|
2317
|
+
const results = await Promise.allSettled(stacks.map(async (stack) => {
|
|
2318
|
+
const signal = statuses[stack.artifactId];
|
|
2168
2319
|
const stackArtifect = assembly.stacks.find((item) => item.id === stack.artifactId);
|
|
2169
|
-
|
|
2320
|
+
signal.set(style.warning("deploying"));
|
|
2170
2321
|
try {
|
|
2171
2322
|
await client.deploy(stackArtifect);
|
|
2172
2323
|
} catch (error) {
|
|
2173
2324
|
debugError(error);
|
|
2174
|
-
|
|
2325
|
+
signal.set(style.error("failed"));
|
|
2175
2326
|
throw error;
|
|
2176
2327
|
}
|
|
2177
|
-
|
|
2328
|
+
signal.set(style.success("deployed"));
|
|
2178
2329
|
}));
|
|
2330
|
+
for (const result of results) {
|
|
2331
|
+
if (result.status === "rejected") {
|
|
2332
|
+
throw result.reason;
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2179
2335
|
}
|
|
2180
2336
|
doneDeploying("Done deploying stacks to AWS");
|
|
2181
2337
|
});
|
|
@@ -2350,7 +2506,7 @@ program.on("option:verbose", () => {
|
|
|
2350
2506
|
var commands2 = [
|
|
2351
2507
|
bootstrap,
|
|
2352
2508
|
status,
|
|
2353
|
-
|
|
2509
|
+
build2,
|
|
2354
2510
|
deploy,
|
|
2355
2511
|
config
|
|
2356
2512
|
// diff,
|