@webda/aws 4.0.0-beta.2 → 4.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +64 -7
  2. package/lib/deployers/awsdeployer.d.ts +340 -0
  3. package/lib/deployers/awsdeployer.d.ts.map +1 -0
  4. package/lib/deployers/awsdeployer.js +673 -0
  5. package/lib/deployers/awsdeployer.js.map +1 -0
  6. package/lib/deployers/cloudformation.service.d.ts +438 -0
  7. package/lib/deployers/cloudformation.service.d.ts.map +1 -0
  8. package/lib/deployers/cloudformation.service.js +889 -0
  9. package/lib/deployers/cloudformation.service.js.map +1 -0
  10. package/lib/deployers/index.d.ts +4 -254
  11. package/lib/deployers/index.d.ts.map +1 -1
  12. package/lib/deployers/index.js +4 -542
  13. package/lib/deployers/index.js.map +1 -1
  14. package/lib/deployers/lambda-entrypoint.d.ts +33 -1
  15. package/lib/deployers/lambda-entrypoint.d.ts.map +1 -1
  16. package/lib/deployers/lambda-entrypoint.js +44 -10
  17. package/lib/deployers/lambda-entrypoint.js.map +1 -1
  18. package/lib/deployers/lambdapackager.service.d.ts +123 -0
  19. package/lib/deployers/lambdapackager.service.d.ts.map +1 -0
  20. package/lib/deployers/lambdapackager.service.js +149 -0
  21. package/lib/deployers/lambdapackager.service.js.map +1 -0
  22. package/lib/deployers/zip.d.ts +42 -0
  23. package/lib/deployers/zip.d.ts.map +1 -0
  24. package/lib/deployers/zip.js +129 -0
  25. package/lib/deployers/zip.js.map +1 -0
  26. package/lib/index.d.ts +1 -0
  27. package/lib/index.d.ts.map +1 -1
  28. package/lib/index.js +1 -0
  29. package/lib/index.js.map +1 -1
  30. package/lib/services/aws-parameters.d.ts +33 -0
  31. package/lib/services/aws-parameters.d.ts.map +1 -0
  32. package/lib/services/aws-parameters.js +18 -0
  33. package/lib/services/aws-parameters.js.map +1 -0
  34. package/lib/services/awscommands.service.d.ts +39 -0
  35. package/lib/services/awscommands.service.d.ts.map +1 -0
  36. package/lib/services/awscommands.service.js +127 -0
  37. package/lib/services/awscommands.service.js.map +1 -0
  38. package/lib/services/cloudwatchlogger.service.d.ts +131 -0
  39. package/lib/services/cloudwatchlogger.service.d.ts.map +1 -0
  40. package/lib/services/{cloudwatchlogger.js → cloudwatchlogger.service.js} +60 -28
  41. package/lib/services/cloudwatchlogger.service.js.map +1 -0
  42. package/lib/services/contributors.d.ts +36 -0
  43. package/lib/services/contributors.d.ts.map +1 -0
  44. package/lib/services/contributors.js +2 -0
  45. package/lib/services/contributors.js.map +1 -0
  46. package/lib/services/dynamodb.service.d.ts +298 -0
  47. package/lib/services/dynamodb.service.d.ts.map +1 -0
  48. package/lib/services/dynamodb.service.js +986 -0
  49. package/lib/services/dynamodb.service.js.map +1 -0
  50. package/lib/services/index.d.ts +11 -31
  51. package/lib/services/index.d.ts.map +1 -1
  52. package/lib/services/index.js +11 -8
  53. package/lib/services/index.js.map +1 -1
  54. package/lib/services/lambdacaller.service.d.ts +81 -0
  55. package/lib/services/lambdacaller.service.d.ts.map +1 -0
  56. package/lib/services/lambdacaller.service.js +75 -0
  57. package/lib/services/lambdacaller.service.js.map +1 -0
  58. package/lib/services/lambdaserver.service.d.ts +127 -0
  59. package/lib/services/lambdaserver.service.d.ts.map +1 -0
  60. package/lib/services/lambdaserver.service.js +294 -0
  61. package/lib/services/lambdaserver.service.js.map +1 -0
  62. package/lib/services/{route53.d.ts → route53.service.d.ts} +21 -12
  63. package/lib/services/route53.service.d.ts.map +1 -0
  64. package/lib/services/{route53.js → route53.service.js} +25 -28
  65. package/lib/services/route53.service.js.map +1 -0
  66. package/lib/services/s3binary.service.d.ts +215 -0
  67. package/lib/services/s3binary.service.d.ts.map +1 -0
  68. package/lib/services/{s3binary.js → s3binary.service.js} +93 -55
  69. package/lib/services/s3binary.service.js.map +1 -0
  70. package/lib/services/secretsmanager.service.d.ts +102 -0
  71. package/lib/services/secretsmanager.service.d.ts.map +1 -0
  72. package/lib/services/{secretsmanager.js → secretsmanager.service.js} +40 -22
  73. package/lib/services/secretsmanager.service.js.map +1 -0
  74. package/lib/services/{sqsqueue.d.ts → sqsqueue.service.d.ts} +60 -35
  75. package/lib/services/sqsqueue.service.d.ts.map +1 -0
  76. package/lib/services/{sqsqueue.js → sqsqueue.service.js} +53 -28
  77. package/lib/services/sqsqueue.service.js.map +1 -0
  78. package/package.json +56 -64
  79. package/webda.module.json +1425 -264
  80. package/lib/deployers/cloudformation.d.ts +0 -317
  81. package/lib/deployers/cloudformation.d.ts.map +0 -1
  82. package/lib/deployers/cloudformation.js +0 -837
  83. package/lib/deployers/cloudformation.js.map +0 -1
  84. package/lib/deployers/cloudformation.spec.d.ts +0 -2
  85. package/lib/deployers/cloudformation.spec.d.ts.map +0 -1
  86. package/lib/deployers/cloudformation.spec.js +0 -530
  87. package/lib/deployers/cloudformation.spec.js.map +0 -1
  88. package/lib/deployers/index.spec.d.ts +0 -9
  89. package/lib/deployers/index.spec.d.ts.map +0 -1
  90. package/lib/deployers/index.spec.js +0 -595
  91. package/lib/deployers/index.spec.js.map +0 -1
  92. package/lib/deployers/lambdapackager.d.ts +0 -28
  93. package/lib/deployers/lambdapackager.d.ts.map +0 -1
  94. package/lib/deployers/lambdapackager.js +0 -26
  95. package/lib/deployers/lambdapackager.js.map +0 -1
  96. package/lib/deployers/lambdapackager.spec.d.ts +0 -2
  97. package/lib/deployers/lambdapackager.spec.d.ts.map +0 -1
  98. package/lib/deployers/lambdapackager.spec.js +0 -44
  99. package/lib/deployers/lambdapackager.spec.js.map +0 -1
  100. package/lib/index.spec.d.ts +0 -11
  101. package/lib/index.spec.d.ts.map +0 -1
  102. package/lib/index.spec.js +0 -42
  103. package/lib/index.spec.js.map +0 -1
  104. package/lib/services/aws-mixin.d.ts +0 -25
  105. package/lib/services/aws-mixin.d.ts.map +0 -1
  106. package/lib/services/aws-mixin.js +0 -18
  107. package/lib/services/aws-mixin.js.map +0 -1
  108. package/lib/services/cloudwatchlogger.d.ts +0 -82
  109. package/lib/services/cloudwatchlogger.d.ts.map +0 -1
  110. package/lib/services/cloudwatchlogger.js.map +0 -1
  111. package/lib/services/cloudwatchlogger.spec.d.ts +0 -2
  112. package/lib/services/cloudwatchlogger.spec.d.ts.map +0 -1
  113. package/lib/services/cloudwatchlogger.spec.js +0 -104
  114. package/lib/services/cloudwatchlogger.spec.js.map +0 -1
  115. package/lib/services/dynamodb.d.ts +0 -174
  116. package/lib/services/dynamodb.d.ts.map +0 -1
  117. package/lib/services/dynamodb.js +0 -711
  118. package/lib/services/dynamodb.js.map +0 -1
  119. package/lib/services/dynamodb.spec.d.ts +0 -24
  120. package/lib/services/dynamodb.spec.d.ts.map +0 -1
  121. package/lib/services/dynamodb.spec.js +0 -344
  122. package/lib/services/dynamodb.spec.js.map +0 -1
  123. package/lib/services/lambdacaller.d.ts +0 -69
  124. package/lib/services/lambdacaller.d.ts.map +0 -1
  125. package/lib/services/lambdacaller.js +0 -63
  126. package/lib/services/lambdacaller.js.map +0 -1
  127. package/lib/services/lambdacaller.spec.d.ts +0 -2
  128. package/lib/services/lambdacaller.spec.d.ts.map +0 -1
  129. package/lib/services/lambdacaller.spec.js +0 -70
  130. package/lib/services/lambdacaller.spec.js.map +0 -1
  131. package/lib/services/lambdaserver.d.ts +0 -87
  132. package/lib/services/lambdaserver.d.ts.map +0 -1
  133. package/lib/services/lambdaserver.js +0 -263
  134. package/lib/services/lambdaserver.js.map +0 -1
  135. package/lib/services/lambdaserver.spec.d.ts +0 -2
  136. package/lib/services/lambdaserver.spec.d.ts.map +0 -1
  137. package/lib/services/lambdaserver.spec.js +0 -417
  138. package/lib/services/lambdaserver.spec.js.map +0 -1
  139. package/lib/services/route53.d.ts.map +0 -1
  140. package/lib/services/route53.js.map +0 -1
  141. package/lib/services/route53.spec.d.ts +0 -2
  142. package/lib/services/route53.spec.d.ts.map +0 -1
  143. package/lib/services/route53.spec.js +0 -102
  144. package/lib/services/route53.spec.js.map +0 -1
  145. package/lib/services/s3binary.d.ts +0 -163
  146. package/lib/services/s3binary.d.ts.map +0 -1
  147. package/lib/services/s3binary.js.map +0 -1
  148. package/lib/services/s3binary.spec.d.ts +0 -2
  149. package/lib/services/s3binary.spec.d.ts.map +0 -1
  150. package/lib/services/s3binary.spec.js +0 -284
  151. package/lib/services/s3binary.spec.js.map +0 -1
  152. package/lib/services/secretsmanager.d.ts +0 -81
  153. package/lib/services/secretsmanager.d.ts.map +0 -1
  154. package/lib/services/secretsmanager.js.map +0 -1
  155. package/lib/services/secretsmanager.spec.d.ts +0 -2
  156. package/lib/services/secretsmanager.spec.d.ts.map +0 -1
  157. package/lib/services/secretsmanager.spec.js +0 -66
  158. package/lib/services/secretsmanager.spec.js.map +0 -1
  159. package/lib/services/sqsqueue.d.ts.map +0 -1
  160. package/lib/services/sqsqueue.js.map +0 -1
  161. package/lib/services/sqsqueue.spec.d.ts +0 -2
  162. package/lib/services/sqsqueue.spec.d.ts.map +0 -1
  163. package/lib/services/sqsqueue.spec.js +0 -157
  164. package/lib/services/sqsqueue.spec.js.map +0 -1
  165. package/lib/shell.d.ts +0 -13
  166. package/lib/shell.d.ts.map +0 -1
  167. package/lib/shell.js +0 -42
  168. package/lib/shell.js.map +0 -1
  169. package/webda.shell.json +0 -11
@@ -0,0 +1,889 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { APIGateway } from "@aws-sdk/client-api-gateway";
36
+ import { CloudFormation } from "@aws-sdk/client-cloudformation";
37
+ import { Command, useApplication, useRouter, WebdaError } from "@webda/core";
38
+ import * as fs from "node:fs";
39
+ import * as path from "node:path";
40
+ import * as YAML from "yaml";
41
+ import { AWSDeployer, AWSDeployerParameters } from "./awsdeployer.js";
42
+ import { createLambdaPackage, LAMBDA_DEFAULT_HANDLER } from "./lambdapackager.service.js";
43
+ /**
44
+ * Default runtime of the Lambda function
45
+ */
46
+ export const LAMBDA_LATEST_VERSION = "nodejs22.x";
47
+ /**
48
+ * Sections of the template, in the order they are generated
49
+ *
50
+ * Lambda and Fargate add statements to the Role assume policy so they come before the Role
51
+ */
52
+ export const CLOUDFORMATION_SECTIONS = [
53
+ "Resources",
54
+ "Lambda",
55
+ "Fargate",
56
+ "Role",
57
+ "Policy",
58
+ "APIGateway",
59
+ "APIGatewayDomain"
60
+ ];
61
+ /**
62
+ * CloudFormation deployer parameters
63
+ *
64
+ * Define how to generate CloudFormation resources
65
+ */
66
+ export class CloudFormationDeployerParameters extends AWSDeployerParameters {
67
+ }
68
+ /**
69
+ * Deploy the application and its resources using AWS CloudFormation
70
+ *
71
+ * Declared as a unit of a deployment:
72
+ * ```json
73
+ * {
74
+ * "units": [{
75
+ * "name": "MyStack",
76
+ * "type": "Webda/CloudFormationDeployer",
77
+ * "AssetsBucket": "my-assets",
78
+ * "Lambda": {},
79
+ * "APIGateway": {}
80
+ * }]
81
+ * }
82
+ * ```
83
+ * then `webda -d <deployment> deploy`
84
+ *
85
+ * @WebdaModda
86
+ */
87
+ let CloudFormationDeployer = (() => {
88
+ var _a;
89
+ let _classSuper = AWSDeployer;
90
+ let _instanceExtraInitializers = [];
91
+ let _deploy_decorators;
92
+ return _a = class CloudFormationDeployer extends _classSuper {
93
+ constructor() {
94
+ super(...arguments);
95
+ /**
96
+ * The template being generated
97
+ */
98
+ this.template = (__runInitializers(this, _instanceExtraInitializers), {});
99
+ /**
100
+ * Result of the deployment
101
+ */
102
+ this.result = {};
103
+ }
104
+ /**
105
+ * @override
106
+ */
107
+ async defaultResources() {
108
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
109
+ await super.defaultResources();
110
+ const resources = this.resources;
111
+ const app = useApplication();
112
+ const packageDesc = app.getPackageDescription() ?? {};
113
+ const awsDefaults = packageDesc.webda?.aws ?? {};
114
+ if (resources.ResourcesToImport) {
115
+ resources.ChangeSetType ?? (resources.ChangeSetType = "IMPORT");
116
+ if (resources.ChangeSetType !== "IMPORT") {
117
+ throw new WebdaError.CodeError("CHANGESET_TYPE", "ChangeSetType cannot be anything else than IMPORT if you have ResourcesToImport set");
118
+ }
119
+ }
120
+ resources.ChangeSetType ?? (resources.ChangeSetType = "CREATE");
121
+ resources.AssetsBucket ?? (resources.AssetsBucket = awsDefaults.AssetsBucket);
122
+ if (!resources.AssetsBucket) {
123
+ throw new WebdaError.CodeError("ASSETS_BUCKET_REQUIRED", "AssetsBucket must be defined");
124
+ }
125
+ resources.AssetsPrefix ?? (resources.AssetsPrefix = "${deployment}/${deployer.name}/");
126
+ resources.Description ?? (resources.Description = "Deployed by @webda/aws/cloudformation");
127
+ resources.FileName ?? (resources.FileName = `cloudformation-${resources.name}`);
128
+ resources.StackName ?? (resources.StackName = resources.name);
129
+ resources.Format ?? (resources.Format = "JSON");
130
+ resources.OpenAPIFileName ?? (resources.OpenAPIFileName = "${resources.name}-openapi-${package.version}");
131
+ resources.OpenAPITitle ?? (resources.OpenAPITitle = resources.name);
132
+ resources.CustomResources ?? (resources.CustomResources = {});
133
+ // Default Lambda value
134
+ if (resources.Lambda) {
135
+ resources.LambdaPackager ?? (resources.LambdaPackager = {});
136
+ (_b = resources.LambdaPackager).zipPath ?? (_b.zipPath = "dist/lambda-${package.version}.zip");
137
+ (_c = resources.Lambda).Runtime ?? (_c.Runtime = LAMBDA_LATEST_VERSION);
138
+ (_d = resources.Lambda).MemorySize ?? (_d.MemorySize = 2048);
139
+ (_e = resources.Lambda).Timeout ?? (_e.Timeout = 30);
140
+ (_f = resources.Lambda).Handler ?? (_f.Handler = LAMBDA_DEFAULT_HANDLER);
141
+ (_g = resources.Lambda).FunctionName ?? (_g.FunctionName = resources.name);
142
+ if (!resources.Lambda.Role) {
143
+ resources.Lambda.Role = { "Fn::GetAtt": ["Role", "Arn"] };
144
+ // If no role is specified auto enable Role and Policy creation
145
+ resources.Role ?? (resources.Role = {});
146
+ resources.Policy ?? (resources.Policy = {});
147
+ }
148
+ }
149
+ // Default Role
150
+ if (resources.Role) {
151
+ (_h = resources.Role).RoleName ?? (_h.RoleName = `${resources.name}Role`);
152
+ if (!resources.Role.Policies || resources.Role.Policies.length === 0) {
153
+ resources.Policy ?? (resources.Policy = {});
154
+ }
155
+ (_j = resources.Role).AssumeRolePolicyDocument ?? (_j.AssumeRolePolicyDocument = { Statement: [] });
156
+ (_k = resources.Role.AssumeRolePolicyDocument).Statement ?? (_k.Statement = []);
157
+ (_l = resources.Role.AssumeRolePolicyDocument).Version ?? (_l.Version = "2012-10-17");
158
+ }
159
+ // Default Policy
160
+ if (resources.Policy) {
161
+ (_m = resources.Policy).PolicyName ?? (_m.PolicyName = `${resources.name}Policy`);
162
+ (_o = resources.Policy).Roles ?? (_o.Roles = []);
163
+ if (resources.Role) {
164
+ resources.Policy.Roles.push({ Ref: "Role" });
165
+ }
166
+ (_p = resources.Policy).PolicyDocument ?? (_p.PolicyDocument = { Statement: [] });
167
+ }
168
+ if (resources.APIGatewayStage) {
169
+ (_q = resources.APIGatewayStage).StageName ?? (_q.StageName = app.getCurrentDeployment() || "default");
170
+ }
171
+ // Activate Domain
172
+ if (resources.APIGatewayDomain) {
173
+ (_r = resources.APIGatewayDomain).SecurityPolicy ?? (_r.SecurityPolicy = "TLS_1_2");
174
+ // Enable BasePathMapping if does not exist
175
+ resources.APIGatewayBasePathMapping ?? (resources.APIGatewayBasePathMapping = {});
176
+ }
177
+ // Default BasePathMapping
178
+ if (resources.APIGatewayBasePathMapping) {
179
+ (_s = resources.APIGatewayBasePathMapping).BasePath ?? (_s.BasePath = "");
180
+ (_t = resources.APIGatewayBasePathMapping).DomainName ?? (_t.DomainName = resources.APIGatewayDomain?.DomainName);
181
+ if (resources.APIGatewayBasePathMapping.DomainName?.endsWith(".")) {
182
+ resources.APIGatewayBasePathMapping.DomainName = resources.APIGatewayBasePathMapping.DomainName.substring(0, resources.APIGatewayBasePathMapping.DomainName.length - 1);
183
+ }
184
+ }
185
+ resources.Statics ?? (resources.Statics = []);
186
+ resources.Statics.forEach(conf => {
187
+ if (!conf.AssetsPath) {
188
+ conf.AssetsPath = conf.Source;
189
+ if (conf.AssetsPath.startsWith("/")) {
190
+ conf.AssetsPath = conf.AssetsPath.substring(1);
191
+ }
192
+ if (!conf.AssetsPath.endsWith("/")) {
193
+ conf.AssetsPath += "/";
194
+ }
195
+ }
196
+ if (conf.CloudFront) {
197
+ const DistributionConfig = conf.CloudFront.DistributionConfig || {};
198
+ DistributionConfig.Aliases ?? (DistributionConfig.Aliases = []);
199
+ if (DistributionConfig.Aliases.indexOf(conf.DomainName) < 0) {
200
+ DistributionConfig.Aliases.push(conf.DomainName);
201
+ }
202
+ DistributionConfig.PriceClass ?? (DistributionConfig.PriceClass = "PriceClass_100");
203
+ DistributionConfig.Comment ?? (DistributionConfig.Comment = "Deployed with @webda/aws/cloudformation");
204
+ DistributionConfig.Enabled ?? (DistributionConfig.Enabled = true);
205
+ DistributionConfig.DefaultCacheBehavior ?? (DistributionConfig.DefaultCacheBehavior = {
206
+ AllowedMethods: ["GET", "HEAD"],
207
+ ViewerProtocolPolicy: "redirect-to-https",
208
+ TargetOriginId: conf.DomainName,
209
+ ForwardedValues: {
210
+ QueryString: false
211
+ }
212
+ });
213
+ DistributionConfig.Origins ?? (DistributionConfig.Origins = [
214
+ {
215
+ DomainName: `${resources.AssetsBucket}.s3.amazonaws.com`,
216
+ Id: conf.DomainName,
217
+ OriginPath: `/${conf.AssetsPath.substring(0, conf.AssetsPath.length - 1)}`,
218
+ S3OriginConfig: {}
219
+ }
220
+ ]);
221
+ conf.CloudFront.DistributionConfig = DistributionConfig;
222
+ }
223
+ });
224
+ }
225
+ /**
226
+ * Deploy the application with CloudFormation
227
+ *
228
+ * It packages the Lambda, uploads the assets, the OpenAPI definition and the template
229
+ * to the AssetsBucket, then creates or updates the stack.
230
+ *
231
+ * @returns the deployment result: the template location and content
232
+ */
233
+ async deploy() {
234
+ await this.prepare();
235
+ await this.generateTemplate();
236
+ this.log("INFO", "Deploy with CloudFormation");
237
+ // Upload new version it
238
+ await this.sendCloudFormationTemplate();
239
+ // Load the stack
240
+ await this.createCloudFormation();
241
+ return this.result;
242
+ }
243
+ /**
244
+ * Upload the assets and generate the CloudFormation template
245
+ *
246
+ * @returns the template
247
+ */
248
+ async generateTemplate() {
249
+ const { Description, AssetsBucket } = this.resources;
250
+ this.template = {
251
+ Description,
252
+ Resources: { ...this.resources.CustomResources }
253
+ };
254
+ this.result = {};
255
+ // Ensure S3 bucket exist
256
+ this.log("DEBUG", "Check assets bucket", AssetsBucket);
257
+ await this.createBucket(AssetsBucket);
258
+ // Export the OpenAPI definition
259
+ const openapi = await this.completeOpenAPI(useRouter().exportOpenAPI(false));
260
+ this.openapiS3Object = this.getStringified(openapi, this.resources.OpenAPIFileName);
261
+ await this.putFilesOnBucket(AssetsBucket, [this.openapiS3Object]);
262
+ // If APIGatewayImportOpenApi update REST API
263
+ if (this.resources.APIGatewayImportOpenApi) {
264
+ this.log("INFO", "Importing open api");
265
+ await this.importOpenApi(openapi);
266
+ }
267
+ this.log("INFO", "Uploading statics");
268
+ await this.uploadStatics();
269
+ for (const section of CLOUDFORMATION_SECTIONS) {
270
+ if (this.resources[section] !== undefined) {
271
+ this.log("TRACE", "Add CloudFormation Resource", section);
272
+ await this[section]();
273
+ }
274
+ }
275
+ // Add any static
276
+ for (const info of this.resources.Statics) {
277
+ this.log("TRACE", "Add Static Resource", info.DomainName);
278
+ await this.createStatic(info);
279
+ }
280
+ return this.template;
281
+ }
282
+ /**
283
+ * Upload any asset to bucket
284
+ */
285
+ async uploadStatics() {
286
+ for (const { Source, AssetsPath } of this.resources.Statics) {
287
+ await this.putFolderOnBucket(this.resources.AssetsBucket, useApplication().getPath(Source), AssetsPath);
288
+ }
289
+ }
290
+ /**
291
+ * Add the resources of a static website
292
+ *
293
+ * @param info - the static website
294
+ */
295
+ async createStatic(info) {
296
+ const { DomainName, CloudFront, Bucket } = info;
297
+ const resPrefix = `Static${DomainName.replace(/\./g, "")}`;
298
+ if (Bucket) {
299
+ this.template.Resources[`${resPrefix}Bucket`] = {
300
+ Type: "AWS::S3::Bucket",
301
+ Properties: {
302
+ ...Bucket,
303
+ BucketName: DomainName,
304
+ Tags: this.getDefaultTags(Bucket.Tags)
305
+ }
306
+ };
307
+ }
308
+ if (CloudFront) {
309
+ if (!CloudFront.DistributionConfig.ViewerCertificate) {
310
+ CloudFront.DistributionConfig.ViewerCertificate = {
311
+ AcmCertificateArn: (await this.getCertificate(DomainName, "us-east-1")).CertificateArn,
312
+ SslSupportMethod: "sni-only"
313
+ };
314
+ }
315
+ this.template.Resources[`${resPrefix}CloudFront`] = {
316
+ Type: "AWS::CloudFront::Distribution",
317
+ Properties: {
318
+ DistributionConfig: CloudFront.DistributionConfig,
319
+ Tags: this.getDefaultTags(CloudFront.Tags)
320
+ }
321
+ };
322
+ await this.createCloudFormationDNSEntry({ "Fn::GetAtt": [`${resPrefix}CloudFront`, "DomainName"] }, DomainName, "Z2FDTNDATAQYW2" // Constant as seen here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget-1.html#cfn-route53-aliastarget-hostedzoneid
323
+ );
324
+ }
325
+ }
326
+ /**
327
+ * Copy the CloudFormation template to the Assets bucket
328
+ */
329
+ async sendCloudFormationTemplate() {
330
+ const res = this.getStringified(this.template, this.resources.FileName);
331
+ this.result.CloudFormation = {
332
+ Bucket: this.resources.AssetsBucket,
333
+ Key: res.key
334
+ };
335
+ this.result.CloudFormationContent = res.src.toString();
336
+ await this.putFilesOnBucket(this.resources.AssetsBucket, [res]);
337
+ }
338
+ /**
339
+ * CloudFormation client
340
+ * @returns the client
341
+ */
342
+ getCloudFormation() {
343
+ return new CloudFormation(this.getClientConfig("CloudFormation"));
344
+ }
345
+ /**
346
+ * API Gateway client
347
+ * @returns the client
348
+ */
349
+ getAPIGateway() {
350
+ return new APIGateway(this.getClientConfig("APIGateway"));
351
+ }
352
+ /**
353
+ * Delete the CloudFormation stack
354
+ * @returns when the stack is deleted
355
+ */
356
+ async deleteCloudFormation() {
357
+ const cloudformation = this.getCloudFormation();
358
+ await cloudformation.deleteStack({ StackName: this.resources.StackName });
359
+ return this.waitFor(async (resolve) => {
360
+ try {
361
+ await cloudformation.describeStacks({
362
+ StackName: this.resources.StackName
363
+ });
364
+ }
365
+ catch {
366
+ resolve();
367
+ return true;
368
+ }
369
+ return false;
370
+ }, 50, "Waiting on stack to be deleted", 5000);
371
+ }
372
+ /**
373
+ * Add a Route53 alias record to the template
374
+ *
375
+ * @param ref - the alias target
376
+ * @param domain - the domain
377
+ * @param HostedZoneId - the zone of the alias target
378
+ */
379
+ async createCloudFormationDNSEntry(ref, domain, HostedZoneId) {
380
+ const zone = await this.getZoneForDomainName(domain);
381
+ if (!zone) {
382
+ this.log("WARN", "Cannot find Route53 zone for", domain, ", you will have to create manually the CNAME");
383
+ return;
384
+ }
385
+ // Possible conflict if my.name.domain.io and myn.ame.domain.io exists
386
+ this.template.Resources[`DNSEntry${domain.replace(/\./g, "")}`] = {
387
+ Type: "AWS::Route53::RecordSet",
388
+ Properties: {
389
+ AliasTarget: { DNSName: ref, HostedZoneId },
390
+ Comment: "Created by @webda/aws/cloudformation",
391
+ Type: "A",
392
+ Name: domain,
393
+ HostedZoneId: zone.Id
394
+ }
395
+ };
396
+ }
397
+ /**
398
+ * Import the OpenAPI definition into an existing REST API
399
+ *
400
+ * @param openapi - the definition
401
+ */
402
+ async importOpenApi(openapi) {
403
+ await this.getAPIGateway().putRestApi({
404
+ body: Buffer.from(JSON.stringify(openapi)),
405
+ failOnWarnings: false,
406
+ restApiId: this.resources.APIGatewayImportOpenApi,
407
+ mode: "overwrite"
408
+ });
409
+ }
410
+ /**
411
+ * Create the stack changeset
412
+ * @param cloudformation - the client
413
+ * @returns the changeset
414
+ */
415
+ async createCloudFormationChangeSet(cloudformation) {
416
+ const changeSetParams = {
417
+ ...this.resources.StackOptions,
418
+ StackName: this.resources.StackName,
419
+ ChangeSetName: "WebdaCloudFormationDeployer",
420
+ Capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
421
+ Tags: this.getDefaultTags("StackOptions"),
422
+ TemplateURL: `https://${this.result.CloudFormation.Bucket}.s3.amazonaws.com/${this.result.CloudFormation.Key}`,
423
+ ResourcesToImport: this.resources.ResourcesToImport
424
+ };
425
+ const update = this.resources.ChangeSetType === "IMPORT" ? "IMPORT" : "UPDATE";
426
+ let changeSet;
427
+ try {
428
+ changeSet = await cloudformation.createChangeSet({
429
+ ...changeSetParams,
430
+ ChangeSetType: update
431
+ });
432
+ }
433
+ catch (err) {
434
+ if (err.message.endsWith(" is in ROLLBACK_COMPLETE state and can not be updated.")) {
435
+ this.log("WARN", "Deleting buguous stack");
436
+ await this.deleteCloudFormation();
437
+ changeSet = await cloudformation.createChangeSet({
438
+ ...changeSetParams,
439
+ ChangeSetType: this.resources.ChangeSetType
440
+ });
441
+ }
442
+ else if (err.message === `Stack [${this.resources.StackName}] does not exist`) {
443
+ changeSet = await cloudformation.createChangeSet({
444
+ ...changeSetParams,
445
+ ChangeSetType: this.resources.ChangeSetType
446
+ });
447
+ }
448
+ else if (err.message.endsWith(" state and can not be updated.")) {
449
+ await this.waitFor(async (resolve) => {
450
+ const res = await cloudformation.describeStacks({
451
+ StackName: this.resources.StackName
452
+ });
453
+ if (res.Stacks.length === 0) {
454
+ // If it disapeared, recreate
455
+ changeSet = await cloudformation.createChangeSet({
456
+ ...changeSetParams,
457
+ ChangeSetType: this.resources.ChangeSetType
458
+ });
459
+ resolve();
460
+ return true;
461
+ }
462
+ if (res.Stacks[0].StackStatus.endsWith("COMPLETE")) {
463
+ changeSet = await cloudformation.createChangeSet({
464
+ ...changeSetParams,
465
+ ChangeSetType: update
466
+ });
467
+ resolve();
468
+ return true;
469
+ }
470
+ return false;
471
+ }, 50, "Waiting for COMPLETE state", 5000);
472
+ }
473
+ else if (err.name === "AlreadyExistsException" || err.code === "AlreadyExistsException") {
474
+ this.log("WARN", "ChangeSet exists and need to be clean");
475
+ await cloudformation.deleteChangeSet({
476
+ StackName: this.resources.StackName,
477
+ ChangeSetName: "WebdaCloudFormationDeployer"
478
+ });
479
+ changeSet = await cloudformation.createChangeSet({
480
+ ...changeSetParams,
481
+ ChangeSetType: update
482
+ });
483
+ }
484
+ else {
485
+ throw err;
486
+ }
487
+ }
488
+ return changeSet;
489
+ }
490
+ /**
491
+ * Upload and create the cloudformation stack or update it
492
+ */
493
+ async createCloudFormation() {
494
+ const cloudformation = this.getCloudFormation();
495
+ const changeSet = await this.createCloudFormationChangeSet(cloudformation);
496
+ // Wait for change set
497
+ this.log("TRACE", "ChangeSet", changeSet);
498
+ // It will trigger an exception if timeout
499
+ const changes = await this.waitFor(async (resolve) => {
500
+ const localChanges = await cloudformation.describeChangeSet({
501
+ ChangeSetName: "WebdaCloudFormationDeployer",
502
+ StackName: this.resources.StackName
503
+ });
504
+ if (localChanges.Status === "FAILED" || localChanges.Status === "CREATE_COMPLETE") {
505
+ resolve(localChanges);
506
+ return true;
507
+ }
508
+ return false;
509
+ }, 50, "Waiting for ChangeSet to be ready...", 5000);
510
+ if (changes.Status === "FAILED") {
511
+ if (changes.StatusReason ===
512
+ "The submitted information didn't contain changes. Submit different information to create a change set.") {
513
+ this.log("INFO", "No changes to be made");
514
+ }
515
+ else {
516
+ this.log("ERROR", "Cannot execute ChangeSet:", changes.StatusReason);
517
+ }
518
+ return;
519
+ }
520
+ changes.Changes.filter(j => j.Type === "Resource").forEach(({ ResourceChange: info }) => this.log("INFO", `${info.Action.toUpperCase().padEnd(38)} ${info.ResourceType.padEnd(30)} ${info.LogicalResourceId}`));
521
+ this.log("INFO", "Executing Change Set");
522
+ let lastEvent = (await cloudformation.describeStackEvents({
523
+ StackName: this.resources.StackName
524
+ })).StackEvents.shift();
525
+ await cloudformation.executeChangeSet({
526
+ ChangeSetName: "WebdaCloudFormationDeployer",
527
+ StackName: this.resources.StackName
528
+ });
529
+ // Wait for the completion of change and display events in the meantime
530
+ this.log("INFO", "Waiting for update completion");
531
+ let i = 0;
532
+ let Timeout = true;
533
+ do {
534
+ const events = (await cloudformation.describeStackEvents({
535
+ StackName: this.resources.StackName
536
+ })).StackEvents;
537
+ let display = !lastEvent;
538
+ let event;
539
+ while ((event = events.pop())) {
540
+ if (display) {
541
+ this.log("INFO", `${event.ResourceStatus.padEnd(38)} ${event.ResourceType.padEnd(30)} ${event.LogicalResourceId}`);
542
+ lastEvent = event;
543
+ if (lastEvent.LogicalResourceId === this.resources.StackName &&
544
+ (lastEvent.ResourceStatus === "UPDATE_COMPLETE" ||
545
+ lastEvent.ResourceStatus === "CREATE_COMPLETE" ||
546
+ lastEvent.ResourceStatus === "ROLLBACK_COMPLETE" ||
547
+ lastEvent.ResourceStatus === "UPDATE_ROLLBACK_COMPLETE")) {
548
+ Timeout = false;
549
+ break;
550
+ }
551
+ }
552
+ else if (event.EventId === lastEvent.EventId) {
553
+ display = true;
554
+ }
555
+ }
556
+ // If we are done do not pause
557
+ if (Timeout) {
558
+ await this.sleep(10);
559
+ i++;
560
+ }
561
+ } while (i < 60 && Timeout);
562
+ if (Timeout) {
563
+ this.log("WARN", "Timeout while waiting for stack to update");
564
+ return;
565
+ }
566
+ /*
567
+ CloudFormation does not update Stage when resources are modified
568
+
569
+ https://stackoverflow.com/questions/41423439/cloudformation-doesnt-deploy-to-api-gateway-stages-on-update
570
+ */
571
+ if (this.resources.APIGateway) {
572
+ let NextToken = undefined;
573
+ let stageName;
574
+ let restApiId;
575
+ // Retrieve resources
576
+ do {
577
+ const res = await cloudformation.listStackResources({
578
+ StackName: this.resources.StackName,
579
+ NextToken
580
+ });
581
+ NextToken = res.NextToken;
582
+ res.StackResourceSummaries.forEach(resource => {
583
+ if (resource.ResourceType === "AWS::ApiGateway::Stage") {
584
+ stageName = resource.PhysicalResourceId;
585
+ }
586
+ else if (resource.ResourceType === "AWS::ApiGateway::RestApi") {
587
+ restApiId = resource.PhysicalResourceId;
588
+ }
589
+ });
590
+ } while (NextToken);
591
+ if (restApiId && stageName) {
592
+ await this.getAPIGateway().createDeployment({
593
+ restApiId,
594
+ stageName
595
+ });
596
+ }
597
+ }
598
+ }
599
+ /**
600
+ * Pause for x seconds
601
+ * @param sec - seconds to wait
602
+ */
603
+ async sleep(sec) {
604
+ await new Promise(resolve => setTimeout(resolve, sec * 1000));
605
+ }
606
+ /**
607
+ * Add the CloudFormation contributions of the application services
608
+ */
609
+ async Resources() {
610
+ for (const service of this.getApplicationServices()) {
611
+ if (typeof service.getCloudFormation === "function") {
612
+ const res = service.getCloudFormation(this);
613
+ for (const j in res) {
614
+ // Logical ids are alphanumeric
615
+ this.template.Resources[`Service${service.getName()}${j}`.replace(/[^A-Za-z0-9]/g, "")] = res[j];
616
+ }
617
+ }
618
+ }
619
+ }
620
+ /**
621
+ * Add the API Gateway integration to the OpenAPI definition
622
+ *
623
+ * @param openapi - the definition
624
+ * @returns the definition
625
+ */
626
+ async completeOpenAPI(openapi) {
627
+ var _b;
628
+ openapi.info.title = this.resources.OpenAPITitle;
629
+ if (!this.resources.Lambda) {
630
+ return openapi;
631
+ }
632
+ const info = await this.getAWSIdentity();
633
+ const arn = `arn:aws:lambda:${this.getRegion()}:${info.Account}:function:${this.resources.Lambda.FunctionName}`;
634
+ for (const p in openapi.paths) {
635
+ // Not using mockCors as the {@link RequestFilter.checkRequest} can be dynamic
636
+ (_b = openapi.paths[p])["options"] ?? (_b["options"] = {});
637
+ for (const m in openapi.paths[p]) {
638
+ openapi.paths[p][m]["x-amazon-apigateway-integration"] = {
639
+ httpMethod: "POST",
640
+ uri: `arn:aws:apigateway:${this.getRegion()}:lambda:path/2015-03-31/functions/${arn}/invocations`,
641
+ type: "aws_proxy"
642
+ };
643
+ }
644
+ }
645
+ return openapi;
646
+ }
647
+ /**
648
+ * Serialize an object for the AssetsBucket
649
+ *
650
+ * @param object - to serialize
651
+ * @param filename - name of the file, its extension forces the format
652
+ * @param addPrefix - add the AssetsPrefix
653
+ * @returns the key and content
654
+ */
655
+ getStringified(object, filename, addPrefix = true) {
656
+ let key = addPrefix ? `${this.resources.AssetsPrefix}${filename}` : filename;
657
+ if (key.startsWith("/")) {
658
+ key = key.substring(1);
659
+ }
660
+ let src;
661
+ // Default to Format parameter
662
+ let format = this.resources.Format;
663
+ // Auto guess format
664
+ if (filename.endsWith(".yml") || filename.endsWith(".yaml")) {
665
+ format = "YAML";
666
+ }
667
+ else if (filename.endsWith(".json")) {
668
+ format = "JSON";
669
+ }
670
+ if (format === "YAML") {
671
+ src = Buffer.from(YAML.stringify(object));
672
+ if (!key.endsWith(".yml") && !key.endsWith(".yaml")) {
673
+ key += ".yml";
674
+ }
675
+ }
676
+ else {
677
+ src = Buffer.from(JSON.stringify(object, undefined, 2));
678
+ if (!key.endsWith(".json")) {
679
+ key += ".json";
680
+ }
681
+ }
682
+ return {
683
+ key,
684
+ src
685
+ };
686
+ }
687
+ /**
688
+ * Add the API Gateway in front of the Lambda function
689
+ */
690
+ async APIGateway() {
691
+ if (!this.resources.Lambda) {
692
+ throw new WebdaError.CodeError("LAMBDA_REQUIRED", "APIGateway requires a Lambda");
693
+ }
694
+ this.template.Resources.APIGateway = {
695
+ Type: "AWS::ApiGateway::RestApi",
696
+ Properties: {
697
+ ...this.resources.APIGateway,
698
+ Tags: this.getDefaultTags("APIGateway"),
699
+ BodyS3Location: {
700
+ Bucket: this.resources.AssetsBucket,
701
+ Key: this.openapiS3Object.key
702
+ }
703
+ },
704
+ DependsOn: "LambdaFunction"
705
+ };
706
+ this.template.Resources.LambdaApiGatewayPermission = {
707
+ Type: "AWS::Lambda::Permission",
708
+ Properties: {
709
+ Action: "lambda:InvokeFunction",
710
+ FunctionName: this.resources.Lambda.FunctionName,
711
+ Principal: "apigateway.amazonaws.com",
712
+ SourceArn: {
713
+ "Fn::Join": [
714
+ ":",
715
+ [
716
+ "arn:aws:execute-api",
717
+ { Ref: "AWS::Region" },
718
+ { Ref: "AWS::AccountId" },
719
+ { "Fn::Join": ["", [{ Ref: "APIGateway" }, "/*"]] }
720
+ ]
721
+ ]
722
+ }
723
+ },
724
+ DependsOn: "LambdaFunction"
725
+ };
726
+ this.template.Resources.APIGatewayDeployment = {
727
+ Type: "AWS::ApiGateway::Deployment",
728
+ Properties: {
729
+ ...this.resources.APIGatewayDeployment,
730
+ RestApiId: { Ref: "APIGateway" }
731
+ }
732
+ };
733
+ this.template.Resources.APIGatewayStage = {
734
+ Type: "AWS::ApiGateway::Stage",
735
+ Properties: {
736
+ ...this.resources.APIGatewayStage,
737
+ Tags: this.getDefaultTags("APIGatewayStage"),
738
+ DeploymentId: { Ref: "APIGatewayDeployment" },
739
+ RestApiId: { Ref: "APIGateway" }
740
+ }
741
+ };
742
+ }
743
+ /**
744
+ * Add the API Gateway custom domain
745
+ */
746
+ async APIGatewayDomain() {
747
+ let region;
748
+ if (this.resources.APIGatewayDomain.EndpointConfiguration) {
749
+ if (this.resources.APIGatewayDomain.EndpointConfiguration.Types.indexOf("EDGE") >= 0) {
750
+ region = "us-east-1";
751
+ }
752
+ }
753
+ else {
754
+ region = "us-east-1";
755
+ }
756
+ if (!this.resources.APIGatewayDomain.CertificateArn) {
757
+ this.resources.APIGatewayDomain.CertificateArn = (await this.getCertificate(this.resources.APIGatewayDomain.DomainName, region)).CertificateArn;
758
+ }
759
+ this.template.Resources.APIGatewayDomain = {
760
+ Type: "AWS::ApiGateway::DomainName",
761
+ Properties: {
762
+ ...this.resources.APIGatewayDomain,
763
+ Tags: this.getDefaultTags("APIGatewayDomain")
764
+ }
765
+ };
766
+ this.template.Resources.APIGatewayBasePathMapping = {
767
+ Type: "AWS::ApiGateway::BasePathMapping",
768
+ Properties: {
769
+ ...this.resources.APIGatewayBasePathMapping,
770
+ DomainName: { Ref: "APIGatewayDomain" },
771
+ RestApiId: { Ref: "APIGateway" },
772
+ Stage: { Ref: "APIGatewayStage" }
773
+ }
774
+ };
775
+ // Should do conditional with RegionalDomainName/RegionalHostedZoneId
776
+ await this.createCloudFormationDNSEntry({ "Fn::GetAtt": ["APIGatewayDomain", "DistributionDomainName"] }, this.resources.APIGatewayDomain.DomainName, { "Fn::GetAtt": ["APIGatewayDomain", "DistributionHostedZoneId"] });
777
+ }
778
+ /**
779
+ * Add the IAM policy of the application
780
+ */
781
+ async Policy() {
782
+ const PolicyDocument = await this.getPolicyDocument(this.resources.Policy.PolicyDocument.Statement);
783
+ this.template.Resources.Policy = {
784
+ Type: "AWS::IAM::Policy",
785
+ Properties: {
786
+ ...this.resources.Policy,
787
+ PolicyDocument
788
+ }
789
+ };
790
+ }
791
+ /**
792
+ * Add statements to the generated Role assume policy
793
+ *
794
+ * @param statements - to add
795
+ */
796
+ addAssumeRolePolicyStatement(...statements) {
797
+ // If we have a Role generation only
798
+ if (this.resources.Role) {
799
+ this.resources.Role.AssumeRolePolicyDocument.Statement.push(...statements);
800
+ }
801
+ }
802
+ /**
803
+ * Add the IAM role of the application
804
+ */
805
+ async Role() {
806
+ this.template.Resources.Role = {
807
+ Type: "AWS::IAM::Role",
808
+ Properties: {
809
+ ...this.resources.Role,
810
+ Tags: this.getDefaultTags("Role")
811
+ }
812
+ };
813
+ }
814
+ /**
815
+ * Package the application and add the Lambda function
816
+ */
817
+ async Lambda() {
818
+ const Code = await this.generateLambdaPackage();
819
+ this.addAssumeRolePolicyStatement({
820
+ Effect: "Allow",
821
+ Principal: { Service: "lambda.amazonaws.com" },
822
+ Action: "sts:AssumeRole"
823
+ });
824
+ this.template.Resources.LambdaFunction = {
825
+ Type: "AWS::Lambda::Function",
826
+ Properties: {
827
+ ...this.resources.Lambda,
828
+ Code,
829
+ Tags: this.getDefaultTags("Lambda")
830
+ }
831
+ };
832
+ }
833
+ /**
834
+ * Allow the ECS tasks to use the generated Role
835
+ */
836
+ async Fargate() {
837
+ this.addAssumeRolePolicyStatement({
838
+ Effect: "Allow",
839
+ Principal: { Service: "ecs-tasks.amazonaws.com" },
840
+ Action: "sts:AssumeRole"
841
+ });
842
+ }
843
+ /**
844
+ * Create the Lambda zip of the application
845
+ *
846
+ * @param options - the package options
847
+ * @returns the zip information
848
+ */
849
+ async buildLambdaPackage(options) {
850
+ return createLambdaPackage(useApplication(), options);
851
+ }
852
+ /**
853
+ * Create the Lambda package and upload it to the AssetsBucket
854
+ *
855
+ * @returns the S3 location of the package
856
+ */
857
+ async generateLambdaPackage() {
858
+ const { AssetsBucket: S3Bucket, LambdaPackager, AssetsPrefix = "", KeepPackage = false } = this.resources;
859
+ const { zipPath } = await this.buildLambdaPackage(LambdaPackager);
860
+ const result = {
861
+ S3Bucket,
862
+ S3Key: AssetsPrefix + path.basename(zipPath)
863
+ };
864
+ // Copy package to S3
865
+ await this.putFilesOnBucket(result.S3Bucket, [
866
+ {
867
+ key: result.S3Key,
868
+ src: zipPath
869
+ }
870
+ ]);
871
+ if (!KeepPackage) {
872
+ fs.unlinkSync(zipPath);
873
+ }
874
+ return result;
875
+ }
876
+ },
877
+ (() => {
878
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
879
+ _deploy_decorators = [Command("deploy", {
880
+ description: "Deploy the application with AWS CloudFormation",
881
+ requires: ["router", "rest-domain"]
882
+ })];
883
+ __esDecorate(_a, null, _deploy_decorators, { kind: "method", name: "deploy", static: false, private: false, access: { has: obj => "deploy" in obj, get: obj => obj.deploy }, metadata: _metadata }, null, _instanceExtraInitializers);
884
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
885
+ })(),
886
+ _a;
887
+ })();
888
+ export { CloudFormationDeployer };
889
+ //# sourceMappingURL=cloudformation.service.js.map