@pwrdrvr/microapps-publish 0.0.21 → 0.0.25

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 (34) hide show
  1. package/dist/commands/nextjs-docker-auto.d.ts +6 -0
  2. package/dist/commands/nextjs-docker-auto.d.ts.map +1 -1
  3. package/dist/commands/nextjs-docker-auto.js +87 -26
  4. package/dist/commands/nextjs-docker-auto.js.map +1 -1
  5. package/dist/commands/nextjs-version-restore.d.ts.map +1 -1
  6. package/dist/commands/nextjs-version-restore.js +4 -10
  7. package/dist/commands/nextjs-version-restore.js.map +1 -1
  8. package/dist/commands/nextjs-version.d.ts.map +1 -1
  9. package/dist/commands/nextjs-version.js +4 -10
  10. package/dist/commands/nextjs-version.js.map +1 -1
  11. package/dist/commands/preflight.d.ts +1 -0
  12. package/dist/commands/preflight.d.ts.map +1 -1
  13. package/dist/commands/preflight.js +21 -14
  14. package/dist/commands/preflight.js.map +1 -1
  15. package/dist/commands/publish-static.d.ts +20 -0
  16. package/dist/commands/publish-static.d.ts.map +1 -0
  17. package/dist/commands/publish-static.js +281 -0
  18. package/dist/commands/publish-static.js.map +1 -0
  19. package/dist/commands/publish.d.ts +4 -0
  20. package/dist/commands/publish.d.ts.map +1 -1
  21. package/dist/commands/publish.js +61 -17
  22. package/dist/commands/publish.js.map +1 -1
  23. package/dist/lib/DeployClient.d.ts +10 -2
  24. package/dist/lib/DeployClient.d.ts.map +1 -1
  25. package/dist/lib/DeployClient.js +9 -4
  26. package/dist/lib/DeployClient.js.map +1 -1
  27. package/package.json +1 -2
  28. package/src/commands/nextjs-docker-auto.ts +91 -26
  29. package/src/commands/nextjs-version-restore.ts +5 -9
  30. package/src/commands/nextjs-version.ts +5 -9
  31. package/src/commands/preflight.ts +23 -16
  32. package/src/commands/publish-static.ts +322 -0
  33. package/src/commands/publish.ts +64 -16
  34. package/src/lib/DeployClient.ts +15 -7
@@ -0,0 +1,322 @@
1
+ import 'reflect-metadata';
2
+ import * as s3 from '@aws-sdk/client-s3';
3
+ import * as sts from '@aws-sdk/client-sts';
4
+ import { Command, flags as flagsParser } from '@oclif/command';
5
+ import * as path from 'path';
6
+ import { pathExists, createReadStream } from 'fs-extra';
7
+ import { Listr, ListrTask } from 'listr2';
8
+ import { Config } from '../config/Config';
9
+ import DeployClient, { IDeployVersionPreflightResult } from '../lib/DeployClient';
10
+ import S3Uploader from '../lib/S3Uploader';
11
+ import S3TransferUtility from '../lib/S3TransferUtility';
12
+ import { Upload } from '@aws-sdk/lib-storage';
13
+ import { contentType } from 'mime-types';
14
+ import { createVersions, IVersions } from '../lib/Versions';
15
+
16
+ interface IContext {
17
+ preflightResult: IDeployVersionPreflightResult;
18
+ files: string[];
19
+ }
20
+
21
+ export class PublishCommand extends Command {
22
+ static description = 'Publish arbitrary framework static app - deploy static assets to S3 only.';
23
+
24
+ static examples = [
25
+ `$ microapps-publish publish-static -d microapps-deployer-dev -n 0.0.21 -l microapps-app-release-dev -a release
26
+ ✔ Get S3 Temp Credentials [1s]
27
+ ✔ Confirm Static Assets Folder Exists [0.0s]
28
+ ✔ Copy Static Files to Local Upload Dir [0.0s]
29
+ ✔ Enumerate Files to Upload to S3 [0.0s]
30
+ ✔ Upload Static Files to S3 [1s]
31
+ ✔ Creating MicroApp Application: release [0.0s]
32
+ ✔ Creating MicroApp Version: 0.0.21 [1s]
33
+ `,
34
+ ];
35
+
36
+ static flags = {
37
+ version: flagsParser.version({
38
+ char: 'v',
39
+ }),
40
+ help: flagsParser.help(),
41
+ deployerLambdaName: flagsParser.string({
42
+ char: 'd',
43
+ multiple: false,
44
+ required: true,
45
+ description: 'Name of the deployer lambda function',
46
+ }),
47
+ newVersion: flagsParser.string({
48
+ char: 'n',
49
+ multiple: false,
50
+ required: true,
51
+ description: 'New semantic version to apply',
52
+ }),
53
+ appName: flagsParser.string({
54
+ char: 'a',
55
+ multiple: false,
56
+ required: false,
57
+ description: 'MicroApps app name',
58
+ }),
59
+ staticAssetsPath: flagsParser.string({
60
+ char: 's',
61
+ multiple: false,
62
+ required: false,
63
+ description:
64
+ 'Path to files to be uploaded to S3 static bucket at app/version/ path. Do include app/version/ in path if files are already "rooted" under that path locally.',
65
+ }),
66
+ defaultFile: flagsParser.string({
67
+ char: 'i',
68
+ multiple: false,
69
+ required: false,
70
+ description:
71
+ 'Default file to return when the app is loaded via the router without a version (e.g. when app/ is requested).',
72
+ }),
73
+ overwrite: flagsParser.boolean({
74
+ char: 'o',
75
+ required: false,
76
+ default: false,
77
+ description:
78
+ 'Allow overwrite - Warn but do not fail if version exists. Discouraged outside of test envs if cacheable static files have changed.',
79
+ }),
80
+ noCache: flagsParser.boolean({
81
+ required: false,
82
+ default: false,
83
+ description: 'Force revalidation of CloudFront and browser caching of static assets',
84
+ }),
85
+ };
86
+
87
+ private VersionAndAlias: IVersions;
88
+
89
+ async run(): Promise<void> {
90
+ const config = Config.instance;
91
+
92
+ // const RUNNING_TEXT = ' RUNS ';
93
+ // const RUNNING = chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
94
+ const RUNNING = ''; //chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
95
+
96
+ const { flags: parsedFlags } = this.parse(PublishCommand);
97
+ const appName = parsedFlags.appName ?? config.app.name;
98
+ const deployerLambdaName = parsedFlags.deployerLambdaName ?? config.deployer.lambdaName;
99
+ const semVer = parsedFlags.newVersion ?? config.app.semVer;
100
+ const staticAssetsPath = parsedFlags.staticAssetsPath ?? config.app.staticAssetsPath;
101
+ const defaultFile = parsedFlags.defaultFile ?? config.app.defaultFile;
102
+ const overwrite = parsedFlags.overwrite;
103
+ const noCache = parsedFlags.noCache;
104
+
105
+ // Override the config value
106
+ config.deployer.lambdaName = deployerLambdaName;
107
+ delete config.app.lambdaName;
108
+ config.app.name = appName;
109
+ config.app.semVer = semVer;
110
+ config.app.staticAssetsPath = staticAssetsPath;
111
+ config.app.defaultFile = defaultFile;
112
+
113
+ // Get the account ID and region from STS
114
+ // TODO: Move this to the right place
115
+ if (config.app.awsAccountID === 0 || config.app.awsRegion === '') {
116
+ const stsClient = new sts.STSClient({
117
+ maxAttempts: 8,
118
+ });
119
+ const stsResponse = await stsClient.send(new sts.GetCallerIdentityCommand({}));
120
+ if (config.app.awsAccountID === 0) {
121
+ config.app.awsAccountID = parseInt(stsResponse.Account, 10);
122
+ }
123
+ if (config.app.awsRegion === '') {
124
+ config.app.awsRegion = stsClient.config.region as string;
125
+ }
126
+ }
127
+
128
+ this.VersionAndAlias = createVersions(semVer);
129
+
130
+ if (config.app.staticAssetsPath === undefined) {
131
+ this.error('staticAssetsPath must be specified');
132
+ }
133
+ if (config.app.defaultFile === undefined || config.app.defaultFile === '') {
134
+ this.error('defaultFile must be specified');
135
+ }
136
+
137
+ //
138
+ // Setup Tasks
139
+ //
140
+
141
+ const tasks = new Listr<IContext>(
142
+ [
143
+ {
144
+ // TODO: Disable this task if no static assets path
145
+ title: 'Get S3 Temp Credentials',
146
+ task: async (ctx, task) => {
147
+ const origTitle = task.title;
148
+ task.title = RUNNING + origTitle;
149
+
150
+ // Confirm the Version Does Not Exist in Published State
151
+ task.output = `Checking if deployed app/version already exists for ${config.app.name}/${semVer}`;
152
+ ctx.preflightResult = await DeployClient.DeployVersionPreflight({
153
+ config,
154
+ overwrite,
155
+ output: (message: string) => (task.output = message),
156
+ });
157
+ if (ctx.preflightResult.exists) {
158
+ if (!overwrite) {
159
+ throw new Error(
160
+ `App/Version already exists: ${config.app.name}/${config.app.semVer}`,
161
+ );
162
+ } else {
163
+ task.title = `Warning: App/Version already exists: ${config.app.name}/${config.app.semVer}`;
164
+ }
165
+ } else {
166
+ task.title = `App/Version does not exist: ${config.app.name}/${config.app.semVer}`;
167
+ }
168
+ },
169
+ },
170
+ {
171
+ // TODO: Disable this task if no static assets path
172
+ title: 'Confirm Static Assets Folder Exists',
173
+ task: async (ctx, task) => {
174
+ const origTitle = task.title;
175
+ task.title = RUNNING + origTitle;
176
+
177
+ // Check that Static Assets Folder exists
178
+ if (!(await pathExists(config.app.staticAssetsPath))) {
179
+ this.error(`Static asset path does not exist: ${config.app.staticAssetsPath}`);
180
+ }
181
+
182
+ task.title = origTitle;
183
+ },
184
+ },
185
+ {
186
+ // TODO: Disable this task if no static assets path
187
+ title: 'Copy Static Files to Local Upload Dir',
188
+ task: async (ctx, task) => {
189
+ const origTitle = task.title;
190
+ task.title = RUNNING + origTitle;
191
+
192
+ // Copy files to local dir to be uploaded
193
+ await S3Uploader.CopyToUploadDir(config, ctx.preflightResult.response.s3UploadUrl);
194
+
195
+ task.title = origTitle;
196
+ },
197
+ },
198
+ {
199
+ // TODO: Disable this task if no static assets path
200
+ title: 'Enumerate Files to Upload to S3',
201
+ task: async (ctx, task) => {
202
+ const origTitle = task.title;
203
+ task.title = RUNNING + origTitle;
204
+
205
+ ctx.files = (await S3TransferUtility.GetFiles(S3Uploader.TempDir)) as string[];
206
+
207
+ task.title = origTitle;
208
+ },
209
+ },
210
+ {
211
+ // TODO: Disable this task if no static assets path
212
+ title: 'Upload Static Files to S3',
213
+ task: (ctx, task) => {
214
+ const origTitle = task.title;
215
+ task.title = RUNNING + origTitle;
216
+
217
+ const { bucketName, destinationPrefix } = S3Uploader.ParseUploadPath(
218
+ ctx.preflightResult.response.s3UploadUrl,
219
+ );
220
+
221
+ // Use temp credentials for S3
222
+ const s3Client = new s3.S3Client({
223
+ maxAttempts: 16,
224
+ credentials: {
225
+ accessKeyId: ctx.preflightResult.response.awsCredentials.accessKeyId,
226
+ secretAccessKey: ctx.preflightResult.response.awsCredentials.secretAccessKey,
227
+ sessionToken: ctx.preflightResult.response.awsCredentials.sessionToken,
228
+ },
229
+ });
230
+
231
+ // Setup caching on static assets
232
+ // NoCache - Only used for test deploys, requires browser and CloudFront to refetch every time
233
+ // Overwrite - Reduces default cache time period from 24 hours to 15 minutes
234
+ // Default - 24 hours
235
+ const CacheControl = noCache
236
+ ? 'max-age=0, must-revalidate, public'
237
+ : overwrite
238
+ ? `max-age=${15 * 60}, public`
239
+ : `max-age=${24 * 60 * 60}, public`;
240
+
241
+ const pathWithoutAppAndVer = path.join(S3Uploader.TempDir, destinationPrefix);
242
+
243
+ const tasks: ListrTask<IContext>[] = ctx.files.map((filePath) => ({
244
+ task: async (ctx: IContext, subtask) => {
245
+ const relFilePath = path.relative(pathWithoutAppAndVer, filePath);
246
+
247
+ const origTitle = relFilePath;
248
+ subtask.title = RUNNING + origTitle;
249
+
250
+ const upload = new Upload({
251
+ client: s3Client,
252
+ leavePartsOnError: false,
253
+ params: {
254
+ Bucket: bucketName,
255
+ Key: path.relative(S3Uploader.TempDir, filePath),
256
+ Body: createReadStream(filePath),
257
+ ContentType: contentType(path.basename(filePath)) || 'application/octet-stream',
258
+ CacheControl,
259
+ },
260
+ });
261
+ await upload.done();
262
+
263
+ subtask.title = origTitle;
264
+ },
265
+ }));
266
+
267
+ task.title = origTitle;
268
+
269
+ return task.newListr(tasks, {
270
+ concurrent: 8,
271
+ rendererOptions: {
272
+ clearOutput: false,
273
+ showErrorMessage: true,
274
+ showTimer: true,
275
+ },
276
+ });
277
+ },
278
+ },
279
+ {
280
+ title: `Creating MicroApp Application: ${config.app.name}`,
281
+ task: async (ctx, task) => {
282
+ const origTitle = task.title;
283
+ task.title = RUNNING + origTitle;
284
+
285
+ // Call Deployer to Create App if Not Exists
286
+ await DeployClient.CreateApp({ config });
287
+
288
+ task.title = origTitle;
289
+ },
290
+ },
291
+ {
292
+ title: `Creating MicroApp Version: ${config.app.semVer}`,
293
+ task: async (ctx, task) => {
294
+ const origTitle = task.title;
295
+ task.title = RUNNING + origTitle;
296
+
297
+ // Call Deployer to Deploy AppName/Version
298
+ await DeployClient.DeployVersion({
299
+ config,
300
+ appType: 'static',
301
+ overwrite,
302
+ output: (message: string) => (task.output = message),
303
+ });
304
+
305
+ task.title = origTitle;
306
+ },
307
+ },
308
+ ],
309
+ {
310
+ rendererOptions: {
311
+ showTimer: true,
312
+ },
313
+ },
314
+ );
315
+
316
+ try {
317
+ await tasks.run();
318
+ } finally {
319
+ await S3Uploader.removeTempDirIfExists();
320
+ }
321
+ }
322
+ }
@@ -4,7 +4,6 @@ import * as lambda from '@aws-sdk/client-lambda';
4
4
  import * as s3 from '@aws-sdk/client-s3';
5
5
  import * as sts from '@aws-sdk/client-sts';
6
6
  import { Command, flags as flagsParser } from '@oclif/command';
7
- import * as chalk from 'chalk';
8
7
  import * as path from 'path';
9
8
  import { pathExists, createReadStream } from 'fs-extra';
10
9
  import { Listr, ListrTask } from 'listr2';
@@ -74,6 +73,32 @@ export class PublishCommand extends Command {
74
73
  required: false,
75
74
  description: 'MicroApps app name',
76
75
  }),
76
+ staticAssetsPath: flagsParser.string({
77
+ char: 's',
78
+ multiple: false,
79
+ required: false,
80
+ description:
81
+ 'Path to files to be uploaded to S3 static bucket at app/version/ path. Do include app/version/ in path if files are already "rooted" under that path locally.',
82
+ }),
83
+ defaultFile: flagsParser.string({
84
+ char: 'i',
85
+ multiple: false,
86
+ required: false,
87
+ description:
88
+ 'Default file to return when the app is loaded via the router without a version (e.g. when app/ is requested).',
89
+ }),
90
+ overwrite: flagsParser.boolean({
91
+ char: 'o',
92
+ required: false,
93
+ default: false,
94
+ description:
95
+ 'Allow overwrite - Warn but do not fail if version exists. Discouraged outside of test envs if cacheable static files have changed.',
96
+ }),
97
+ noCache: flagsParser.boolean({
98
+ required: false,
99
+ default: false,
100
+ description: 'Force revalidation of CloudFront and browser caching of static assets',
101
+ }),
77
102
  };
78
103
 
79
104
  private VersionAndAlias: IVersions;
@@ -81,20 +106,27 @@ export class PublishCommand extends Command {
81
106
  async run(): Promise<void> {
82
107
  const config = Config.instance;
83
108
 
84
- const RUNNING_TEXT = ' RUNS ';
85
- const RUNNING = chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
109
+ // const RUNNING_TEXT = ' RUNS ';
110
+ // const RUNNING = chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
111
+ const RUNNING = ''; //chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
86
112
 
87
113
  const { flags: parsedFlags } = this.parse(PublishCommand);
88
114
  const appLambdaName = parsedFlags.appLambdaName ?? config.app.lambdaName;
89
115
  const appName = parsedFlags.appName ?? config.app.name;
90
116
  const deployerLambdaName = parsedFlags.deployerLambdaName ?? config.deployer.lambdaName;
91
117
  const semVer = parsedFlags.newVersion ?? config.app.semVer;
118
+ const staticAssetsPath = parsedFlags.staticAssetsPath ?? config.app.staticAssetsPath;
119
+ const defaultFile = parsedFlags.defaultFile ?? config.app.defaultFile;
120
+ const overwrite = parsedFlags.overwrite;
121
+ const noCache = parsedFlags.noCache;
92
122
 
93
123
  // Override the config value
94
124
  config.deployer.lambdaName = deployerLambdaName;
95
125
  config.app.lambdaName = appLambdaName;
96
126
  config.app.name = appName;
97
127
  config.app.semVer = semVer;
128
+ config.app.staticAssetsPath = staticAssetsPath;
129
+ config.app.defaultFile = defaultFile;
98
130
 
99
131
  // Get the account ID and region from STS
100
132
  // TODO: Move this to the right place
@@ -113,11 +145,8 @@ export class PublishCommand extends Command {
113
145
 
114
146
  this.VersionAndAlias = createVersions(semVer);
115
147
 
116
- if (config === undefined) {
117
- this.error('Failed to load the config file');
118
- }
119
148
  if (config.app.staticAssetsPath === undefined) {
120
- this.error('StaticAssetsPath must be specified in the config file');
149
+ this.error('staticAssetsPath must be specified');
121
150
  }
122
151
 
123
152
  //
@@ -137,13 +166,20 @@ export class PublishCommand extends Command {
137
166
  task.output = `Checking if deployed app/version already exists for ${config.app.name}/${semVer}`;
138
167
  ctx.preflightResult = await DeployClient.DeployVersionPreflight({
139
168
  config,
169
+ overwrite,
140
170
  output: (message: string) => (task.output = message),
141
171
  });
142
172
  if (ctx.preflightResult.exists) {
143
- task.output = `Warning: App/Version already exists: ${config.app.name}/${config.app.semVer}`;
173
+ if (!overwrite) {
174
+ throw new Error(
175
+ `App/Version already exists: ${config.app.name}/${config.app.semVer}`,
176
+ );
177
+ } else {
178
+ task.title = `Warning: App/Version already exists: ${config.app.name}/${config.app.semVer}`;
179
+ }
180
+ } else {
181
+ task.title = `App/Version does not exist: ${config.app.name}/${config.app.semVer}`;
144
182
  }
145
-
146
- task.title = origTitle;
147
183
  },
148
184
  },
149
185
  {
@@ -220,6 +256,16 @@ export class PublishCommand extends Command {
220
256
  },
221
257
  });
222
258
 
259
+ // Setup caching on static assets
260
+ // NoCache - Only used for test deploys, requires browser and CloudFront to refetch every time
261
+ // Overwrite - Reduces default cache time period from 24 hours to 15 minutes
262
+ // Default - 24 hours
263
+ const CacheControl = noCache
264
+ ? 'max-age=0, must-revalidate, public'
265
+ : overwrite
266
+ ? `max-age=${15 * 60}, public`
267
+ : `max-age=${24 * 60 * 60}, public`;
268
+
223
269
  const pathWithoutAppAndVer = path.join(S3Uploader.TempDir, destinationPrefix);
224
270
 
225
271
  const tasks: ListrTask<IContext>[] = ctx.files.map((filePath) => ({
@@ -237,7 +283,7 @@ export class PublishCommand extends Command {
237
283
  Key: path.relative(S3Uploader.TempDir, filePath),
238
284
  Body: createReadStream(filePath),
239
285
  ContentType: contentType(path.basename(filePath)) || 'application/octet-stream',
240
- CacheControl: 'max-age=86400; public',
286
+ CacheControl,
241
287
  },
242
288
  });
243
289
  await upload.done();
@@ -265,7 +311,7 @@ export class PublishCommand extends Command {
265
311
  task.title = RUNNING + origTitle;
266
312
 
267
313
  // Call Deployer to Create App if Not Exists
268
- await DeployClient.CreateApp(config);
314
+ await DeployClient.CreateApp({ config });
269
315
 
270
316
  task.title = origTitle;
271
317
  },
@@ -277,7 +323,12 @@ export class PublishCommand extends Command {
277
323
  task.title = RUNNING + origTitle;
278
324
 
279
325
  // Call Deployer to Deploy AppName/Version
280
- await DeployClient.DeployVersion(config, (message: string) => (task.output = message));
326
+ await DeployClient.DeployVersion({
327
+ config,
328
+ appType: 'lambda',
329
+ overwrite,
330
+ output: (message: string) => (task.output = message),
331
+ });
281
332
 
282
333
  task.title = origTitle;
283
334
  },
@@ -292,9 +343,6 @@ export class PublishCommand extends Command {
292
343
 
293
344
  try {
294
345
  await tasks.run();
295
- // this.log(`Published: ${config.app.name}/${config.app.semVer}`);
296
- } catch (error) {
297
- this.log(`Caught exception: ${error.message}`);
298
346
  } finally {
299
347
  await S3Uploader.removeTempDirIfExists();
300
348
  }
@@ -19,7 +19,8 @@ export default class DeployClient {
19
19
  });
20
20
  static readonly _decoder = new TextDecoder('utf-8');
21
21
 
22
- public static async CreateApp(config: IConfig): Promise<void> {
22
+ public static async CreateApp(opts: { config: IConfig }): Promise<void> {
23
+ const { config } = opts;
23
24
  const request = {
24
25
  type: 'createApp',
25
26
  appName: config.app.name,
@@ -54,14 +55,16 @@ export default class DeployClient {
54
55
  public static async DeployVersionPreflight(opts: {
55
56
  config: IConfig;
56
57
  needS3Creds?: boolean;
58
+ overwrite: boolean;
57
59
  output: (message: string) => void;
58
60
  }): Promise<IDeployVersionPreflightResult> {
59
- const { config, needS3Creds = true, output } = opts;
61
+ const { config, needS3Creds = true, overwrite, output } = opts;
60
62
 
61
63
  const request = {
62
64
  type: 'deployVersionPreflight',
63
65
  appName: config.app.name,
64
66
  semVer: config.app.semVer,
67
+ overwrite,
65
68
  needS3Creds,
66
69
  } as IDeployVersionPreflightRequest;
67
70
  const response = await this._client.send(
@@ -95,16 +98,21 @@ export default class DeployClient {
95
98
  * @param config
96
99
  * @param task
97
100
  */
98
- public static async DeployVersion(
99
- config: IConfig,
100
- output: (message: string) => void,
101
- ): Promise<void> {
101
+ public static async DeployVersion(opts: {
102
+ config: IConfig;
103
+ appType: 'lambda' | 'static';
104
+ overwrite: boolean;
105
+ output: (message: string) => void;
106
+ }): Promise<void> {
107
+ const { config, appType, overwrite, output } = opts;
102
108
  const request = {
103
109
  type: 'deployVersion',
110
+ appType,
104
111
  appName: config.app.name,
105
112
  semVer: config.app.semVer,
106
113
  defaultFile: config.app.defaultFile,
107
- lambdaARN: config.app.lambdaARN,
114
+ lambdaARN: appType === 'lambda' ? config.app.lambdaARN : undefined,
115
+ overwrite,
108
116
  } as IDeployVersionRequest;
109
117
  const response = await this._client.send(
110
118
  new lambda.InvokeCommand({