@pwrdrvr/microapps-publish 0.4.0-alpha.9 → 1.0.2

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 (81) hide show
  1. package/README.md +25 -25
  2. package/package.json +5 -52
  3. package/bin/run +0 -5
  4. package/dist/commands/delete.d.ts +0 -18
  5. package/dist/commands/delete.d.ts.map +0 -1
  6. package/dist/commands/delete.js +0 -125
  7. package/dist/commands/delete.js.map +0 -1
  8. package/dist/commands/nextjs-version-restore.d.ts +0 -14
  9. package/dist/commands/nextjs-version-restore.d.ts.map +0 -1
  10. package/dist/commands/nextjs-version-restore.js +0 -53
  11. package/dist/commands/nextjs-version-restore.js.map +0 -1
  12. package/dist/commands/nextjs-version.d.ts +0 -18
  13. package/dist/commands/nextjs-version.d.ts.map +0 -1
  14. package/dist/commands/nextjs-version.js +0 -103
  15. package/dist/commands/nextjs-version.js.map +0 -1
  16. package/dist/commands/preflight.d.ts +0 -19
  17. package/dist/commands/preflight.d.ts.map +0 -1
  18. package/dist/commands/preflight.js +0 -135
  19. package/dist/commands/preflight.js.map +0 -1
  20. package/dist/commands/publish-static.d.ts +0 -25
  21. package/dist/commands/publish-static.d.ts.map +0 -1
  22. package/dist/commands/publish-static.js +0 -361
  23. package/dist/commands/publish-static.js.map +0 -1
  24. package/dist/commands/publish.d.ts +0 -39
  25. package/dist/commands/publish.d.ts.map +0 -1
  26. package/dist/commands/publish.js +0 -565
  27. package/dist/commands/publish.js.map +0 -1
  28. package/dist/config/Application.d.ts +0 -26
  29. package/dist/config/Application.d.ts.map +0 -1
  30. package/dist/config/Application.js +0 -99
  31. package/dist/config/Application.js.map +0 -1
  32. package/dist/config/Config.d.ts +0 -18
  33. package/dist/config/Config.d.ts.map +0 -1
  34. package/dist/config/Config.js +0 -71
  35. package/dist/config/Config.js.map +0 -1
  36. package/dist/config/Deployer.d.ts +0 -10
  37. package/dist/config/Deployer.d.ts.map +0 -1
  38. package/dist/config/Deployer.js +0 -17
  39. package/dist/config/Deployer.js.map +0 -1
  40. package/dist/index.d.ts +0 -2
  41. package/dist/index.d.ts.map +0 -1
  42. package/dist/index.js +0 -6
  43. package/dist/index.js.map +0 -1
  44. package/dist/lib/DeployClient.d.ts +0 -102
  45. package/dist/lib/DeployClient.d.ts.map +0 -1
  46. package/dist/lib/DeployClient.js +0 -233
  47. package/dist/lib/DeployClient.js.map +0 -1
  48. package/dist/lib/FilesExist.d.ts +0 -5
  49. package/dist/lib/FilesExist.d.ts.map +0 -1
  50. package/dist/lib/FilesExist.js +0 -26
  51. package/dist/lib/FilesExist.js.map +0 -1
  52. package/dist/lib/S3TransferUtility.d.ts +0 -19
  53. package/dist/lib/S3TransferUtility.d.ts.map +0 -1
  54. package/dist/lib/S3TransferUtility.js +0 -94
  55. package/dist/lib/S3TransferUtility.js.map +0 -1
  56. package/dist/lib/S3Uploader.d.ts +0 -27
  57. package/dist/lib/S3Uploader.d.ts.map +0 -1
  58. package/dist/lib/S3Uploader.js +0 -77
  59. package/dist/lib/S3Uploader.js.map +0 -1
  60. package/dist/lib/Versions.d.ts +0 -33
  61. package/dist/lib/Versions.d.ts.map +0 -1
  62. package/dist/lib/Versions.js +0 -76
  63. package/dist/lib/Versions.js.map +0 -1
  64. package/src/commands/delete.ts +0 -135
  65. package/src/commands/nextjs-version-restore.ts +0 -70
  66. package/src/commands/nextjs-version.ts +0 -123
  67. package/src/commands/preflight.ts +0 -148
  68. package/src/commands/publish-static.ts +0 -416
  69. package/src/commands/publish.ts +0 -662
  70. package/src/commands-deprecated/nextjs-docker-auto.skip +0 -590
  71. package/src/config/Application.ts +0 -98
  72. package/src/config/Config.ts +0 -81
  73. package/src/config/Deployer.ts +0 -17
  74. package/src/index.ts +0 -1
  75. package/src/lib/DeployClient.ts +0 -334
  76. package/src/lib/FilesExist.ts +0 -25
  77. package/src/lib/S3TransferUtility.spec.ts +0 -15
  78. package/src/lib/S3TransferUtility.ts +0 -113
  79. package/src/lib/S3Uploader.ts +0 -94
  80. package/src/lib/Versions.ts +0 -101
  81. package/src/lib/__snapshots__/S3TransferUtility.spec.ts.snap +0 -12
@@ -1,81 +0,0 @@
1
- import { url, ipaddress } from 'convict-format-with-validator';
2
- import * as yaml from 'js-yaml';
3
- import * as convict from 'ts-convict';
4
- import { TSConvict } from 'ts-convict';
5
- import { FilesExist } from '../lib/FilesExist';
6
- import { ApplicationConfig, IApplicationConfig } from './Application';
7
- import { DeployerConfig, IDeployerConfig } from './Deployer';
8
-
9
- /**
10
- * Represents a Config
11
- */
12
- export interface IConfig {
13
- deployer: IDeployerConfig;
14
- app: IApplicationConfig;
15
- }
16
-
17
- @convict.Config({
18
- // optional default file to load, no errors if it doesn't exist
19
- file: 'config.yml', // relative to NODE_PATH or cwd()
20
-
21
- // optional parameter. Defaults to 'strict', can also be 'warn'
22
- validationMethod: 'strict',
23
-
24
- // optionally add parsers like yaml or toml
25
- parser: {
26
- extension: ['yml', 'yaml'],
27
- parse: yaml.load,
28
- },
29
-
30
- //optional extra formats to use in validation
31
- formats: {
32
- url,
33
- ipaddress,
34
- },
35
- })
36
- export class Config implements IConfig {
37
- public static configFiles(): string[] {
38
- const possibleFiles = [
39
- './microapps.yaml',
40
- './microapps.yml',
41
- `./microapps-${Config.envLevel}.yaml`,
42
- `./microapps-${Config.envLevel}.yml`,
43
- ];
44
- return FilesExist.getExistingFilesSync(possibleFiles);
45
- }
46
-
47
- private static _instance: IConfig;
48
- public static get instance(): IConfig {
49
- if (Config._instance === undefined) {
50
- const configLoader = new TSConvict<Config>(Config);
51
- Config._instance = configLoader.load(Config.configFiles());
52
- }
53
- return Config._instance;
54
- }
55
-
56
- public static get envLevel(): 'dev' | 'qa' | 'prod' | 'local' {
57
- const nodeEnv = process.env.NODE_ENV || 'dev';
58
- if (nodeEnv.startsWith('prod')) {
59
- return 'prod';
60
- } else if (nodeEnv === 'qa') {
61
- return 'qa';
62
- } else if (nodeEnv === 'local') {
63
- return 'local';
64
- }
65
- return 'dev';
66
- }
67
-
68
- // ts-convict will use the Typescript type if no format given
69
- // @convict.Property({
70
- // doc: 'The name of the thing',
71
- // default: 'Convict',
72
- // env: 'MY_CONFIG_NAME',
73
- // })
74
- // public name!: string;
75
-
76
- @convict.Property(ApplicationConfig)
77
- public app!: IApplicationConfig;
78
-
79
- @convict.Property(DeployerConfig)
80
- public deployer!: IDeployerConfig;
81
- }
@@ -1,17 +0,0 @@
1
- import { Property } from 'ts-convict';
2
-
3
- /**
4
- * Represents a Deployer Config
5
- */
6
- export interface IDeployerConfig {
7
- lambdaName: string;
8
- }
9
-
10
- export class DeployerConfig implements IDeployerConfig {
11
- @Property({
12
- doc: 'Name of Deployer Lambda function',
13
- default: 'microapps-deployer',
14
- env: 'DEPLOYER_LAMBDA_NAME',
15
- })
16
- public lambdaName!: string;
17
- }
package/src/index.ts DELETED
@@ -1 +0,0 @@
1
- export { run } from '@oclif/command';
@@ -1,334 +0,0 @@
1
- import * as lambda from '@aws-sdk/client-lambda';
2
- import type {
3
- ICreateApplicationRequest,
4
- IDeployerResponse,
5
- IDeployVersionPreflightRequest,
6
- IDeployVersionPreflightResponse,
7
- IDeployVersionRequest,
8
- IDeleteVersionRequest,
9
- ILambdaAliasRequest,
10
- ILambdaAliasResponse,
11
- } from '@pwrdrvr/microapps-deployer-lib';
12
- import { IConfig } from '../config/Config';
13
-
14
- /**
15
- * Represents a Deploy Version Preflight Result
16
- */
17
- export interface IDeployVersionPreflightResult {
18
- exists: boolean;
19
- response: IDeployVersionPreflightResponse;
20
- }
21
-
22
- export type DeployVersionArgs = Parameters<typeof DeployClient.DeployVersionLite>[0];
23
-
24
- export default class DeployClient {
25
- static readonly _client = new lambda.LambdaClient({
26
- maxAttempts: 8,
27
- });
28
- static readonly _decoder = new TextDecoder('utf-8');
29
-
30
- /**
31
- * Create an application
32
- * @param opts
33
- */
34
- public static async CreateApp(opts: { config: IConfig }): Promise<void> {
35
- const { config } = opts;
36
- const request: ICreateApplicationRequest = {
37
- type: 'createApp',
38
- appName: config.app.name,
39
- displayName: config.app.name,
40
- };
41
- const response = await this._client.send(
42
- new lambda.InvokeCommand({
43
- FunctionName: config.deployer.lambdaName,
44
- Payload: Buffer.from(JSON.stringify(request)),
45
- }),
46
- );
47
-
48
- if (response.$metadata.httpStatusCode === 200 && response.Payload !== undefined) {
49
- const dResponse = JSON.parse(
50
- Buffer.from(response.Payload).toString('utf-8'),
51
- ) as IDeployerResponse;
52
- if (!(dResponse.statusCode === 201 || dResponse.statusCode === 200)) {
53
- throw new Error(`App create failed: ${JSON.stringify(dResponse)}`);
54
- }
55
- } else {
56
- throw new Error(`App Create - Lambda Invoke Failed: ${JSON.stringify(response)}`);
57
- }
58
- }
59
-
60
- /**
61
- * Delete version
62
- * @param config
63
- * @param output
64
- * @returns
65
- */
66
- public static async DeleteVersion(opts: {
67
- config: IConfig;
68
- output: (message: string) => void;
69
- }): Promise<IDeployerResponse> {
70
- const { config, output } = opts;
71
-
72
- const request: IDeleteVersionRequest = {
73
- type: 'deleteVersion',
74
- appName: config.app.name,
75
- semVer: config.app.semVer,
76
- };
77
- const response = await this._client.send(
78
- new lambda.InvokeCommand({
79
- FunctionName: config.deployer.lambdaName,
80
- Payload: Buffer.from(JSON.stringify(request)),
81
- }),
82
- );
83
-
84
- if (response.$metadata.httpStatusCode === 200 && response.Payload !== undefined) {
85
- const dResponse = JSON.parse(
86
- Buffer.from(response.Payload).toString('utf-8'),
87
- ) as IDeployerResponse;
88
- if (dResponse.statusCode === 404) {
89
- output(`App/Version does not exist: ${config.app.name}/${config.app.semVer}`);
90
- return dResponse;
91
- } else {
92
- output(`App/Version deleted: ${config.app.name}/${config.app.semVer}`);
93
- return dResponse;
94
- }
95
- } else {
96
- throw new Error(`Lambda call to DeleteVersion failed: ${JSON.stringify(response)}`);
97
- }
98
- }
99
-
100
- /**
101
- * Check if version exists.
102
- * Optionally get S3 creds for static asset upload.
103
- * @param config
104
- * @param output
105
- * @returns
106
- */
107
- public static async DeployVersionPreflight(opts: {
108
- config: IConfig;
109
- needS3Creds?: boolean;
110
- overwrite: boolean;
111
- output: (message: string) => void;
112
- }): Promise<IDeployVersionPreflightResult> {
113
- const { config, needS3Creds = true, overwrite, output } = opts;
114
-
115
- const request: IDeployVersionPreflightRequest = {
116
- type: 'deployVersionPreflight',
117
- appName: config.app.name,
118
- semVer: config.app.semVer,
119
- overwrite,
120
- needS3Creds,
121
- };
122
- const response = await this._client.send(
123
- new lambda.InvokeCommand({
124
- FunctionName: config.deployer.lambdaName,
125
- Payload: Buffer.from(JSON.stringify(request)),
126
- }),
127
- );
128
-
129
- if (response.$metadata.httpStatusCode === 200 && response.Payload !== undefined) {
130
- const dResponse = JSON.parse(
131
- Buffer.from(response.Payload).toString('utf-8'),
132
- ) as IDeployVersionPreflightResponse;
133
- if (dResponse.statusCode === 404) {
134
- output(`App/Version does not exist: ${config.app.name}/${config.app.semVer}`);
135
- return { exists: false, response: dResponse };
136
- } else if (dResponse.statusCode > 299) {
137
- // @ts-expect-error remove awsCredentials from response
138
- delete dResponse.awsCredentials;
139
- output(`DeployVersionPreflight failed: ${JSON.stringify(dResponse)}`);
140
- throw new Error('DeployVersionPreflight failed');
141
- } else {
142
- output(`App/Version exists: ${config.app.name}/${config.app.semVer}`);
143
- return { exists: true, response: dResponse };
144
- }
145
- } else {
146
- // @ts-expect-error remove awsCredentials from response
147
- delete dResponse.awsCredentials;
148
- throw new Error(`Lambda call to DeployVersionPreflight failed: ${JSON.stringify(response)}`);
149
- }
150
- }
151
-
152
- /**
153
- * Create or update Lambda alias for specified Lambda version
154
- * @param config
155
- * @param output
156
- * @returns
157
- */
158
- public static async LambdaAlias(opts: {
159
- appName: string;
160
- semVer: string;
161
- lambdaVersionArn: string;
162
- overwrite: boolean;
163
- deployerLambdaName: string;
164
- output: (message: string) => void;
165
- }): Promise<{ response: ILambdaAliasResponse }> {
166
- const { appName, deployerLambdaName, lambdaVersionArn, overwrite, output, semVer } = opts;
167
-
168
- const request: ILambdaAliasRequest = {
169
- type: 'lambdaAlias',
170
- appName,
171
- semVer,
172
- lambdaARN: lambdaVersionArn,
173
- overwrite,
174
- };
175
- output(`Creating alias for version ARN: ${lambdaVersionArn}`);
176
- const response = await this._client.send(
177
- new lambda.InvokeCommand({
178
- FunctionName: deployerLambdaName,
179
- Payload: Buffer.from(JSON.stringify(request)),
180
- }),
181
- );
182
-
183
- if (response.$metadata.httpStatusCode === 200 && response.Payload !== undefined) {
184
- const dResponse = JSON.parse(
185
- Buffer.from(response.Payload).toString('utf-8'),
186
- ) as ILambdaAliasResponse;
187
- if (dResponse.statusCode > 299) {
188
- output(`LambdaAlias failed: ${JSON.stringify(dResponse)}`);
189
- throw new Error('LambdaAlias failed');
190
- } else if (!dResponse.functionUrl) {
191
- output(`LambdaAlias failed to return functionUrl: ${JSON.stringify(dResponse)}`);
192
- throw new Error('LambdaAlias failed to return functionUrl');
193
- } else if (dResponse.statusCode === 201) {
194
- output(`Alias created: ${dResponse.lambdaAliasARN}`);
195
- return { response: dResponse };
196
- } else {
197
- output(`Alias ${dResponse.actionTaken}: ${dResponse.lambdaAliasARN}`);
198
- return { response: dResponse };
199
- }
200
- } else {
201
- throw new Error(`Lambda call to LambdaAlias failed: ${JSON.stringify(response)}`);
202
- }
203
- }
204
-
205
- /**
206
- * Copy S3 static assets from staging to live bucket.
207
- * Create API Gateway Integration for app (if needed).
208
- * Give API Gateway permission to call the Lambda.
209
- * Create API Gateway routes for this specific version.
210
- * @param config
211
- * @param task
212
- */
213
- public static async DeployVersion(opts: {
214
- appName: string;
215
- semVer: string;
216
- defaultFile?: string;
217
- lambdaAliasArn?: string;
218
- deployerLambdaName: string;
219
- appType: 'lambda' | 'static' | 'lambda-url' | 'url';
220
- startupType?: 'iframe' | 'direct';
221
- url?: string;
222
- overwrite: boolean;
223
- output: (message: string) => void;
224
- }): Promise<void> {
225
- const {
226
- appName,
227
- semVer,
228
- defaultFile,
229
- lambdaAliasArn,
230
- deployerLambdaName,
231
- appType,
232
- startupType = 'iframe',
233
- url,
234
- overwrite,
235
- output,
236
- } = opts;
237
- const request: IDeployVersionRequest = {
238
- type: 'deployVersion',
239
- appType,
240
- startupType,
241
- appName,
242
- semVer,
243
- defaultFile: defaultFile,
244
- url,
245
- overwrite,
246
- ...(['lambda', 'lambda-url'].includes(appType) ? { lambdaARN: lambdaAliasArn } : {}),
247
- };
248
- const response = await this._client.send(
249
- new lambda.InvokeCommand({
250
- FunctionName: deployerLambdaName,
251
- Payload: Buffer.from(JSON.stringify(request)),
252
- }),
253
- );
254
-
255
- if (response.$metadata.httpStatusCode === 200 && response.Payload !== undefined) {
256
- const dResponse = JSON.parse(
257
- Buffer.from(response.Payload).toString('utf-8'),
258
- ) as IDeployerResponse;
259
- if (dResponse.statusCode === 201) {
260
- output(`Deploy succeeded: ${appName}/${semVer}`);
261
- } else {
262
- output(`Deploy failed with: ${dResponse.statusCode}`);
263
- throw new Error(`Lambda call to DeployVersion failed with: ${dResponse.statusCode}`);
264
- }
265
- } else {
266
- throw new Error(`Lambda call to DeployVersion failed: ${JSON.stringify(response)}`);
267
- }
268
- }
269
-
270
- /**
271
- * Copy S3 static assets from staging to live bucket.
272
- * Create DB records.
273
- * Proxied to parent account if needed.
274
- *
275
- * @param config
276
- * @param task
277
- */
278
- public static async DeployVersionLite(opts: {
279
- appName: string;
280
- semVer: string;
281
- defaultFile?: string;
282
- lambdaAliasArn?: string;
283
- deployerLambdaName: string;
284
- appType: 'lambda' | 'static' | 'lambda-url' | 'url';
285
- startupType?: 'iframe' | 'direct';
286
- url?: string;
287
- overwrite: boolean;
288
- output: (message: string) => void;
289
- }): Promise<void> {
290
- const {
291
- appName,
292
- semVer,
293
- defaultFile,
294
- lambdaAliasArn,
295
- deployerLambdaName,
296
- appType,
297
- startupType = 'iframe',
298
- url,
299
- overwrite,
300
- output,
301
- } = opts;
302
- const request: IDeployVersionRequest = {
303
- type: 'deployVersionLite',
304
- appType,
305
- startupType,
306
- appName,
307
- semVer,
308
- defaultFile: defaultFile,
309
- url,
310
- overwrite,
311
- ...(['lambda', 'lambda-url'].includes(appType) ? { lambdaARN: lambdaAliasArn } : {}),
312
- };
313
- const response = await this._client.send(
314
- new lambda.InvokeCommand({
315
- FunctionName: deployerLambdaName,
316
- Payload: Buffer.from(JSON.stringify(request)),
317
- }),
318
- );
319
-
320
- if (response.$metadata.httpStatusCode === 200 && response.Payload !== undefined) {
321
- const dResponse = JSON.parse(
322
- Buffer.from(response.Payload).toString('utf-8'),
323
- ) as IDeployerResponse;
324
- if (dResponse.statusCode === 201) {
325
- output(`Deploy succeeded: ${appName}/${semVer}`);
326
- } else {
327
- output(`Deploy failed with: ${dResponse.statusCode}`);
328
- throw new Error(`Lambda call to DeployVersionLite failed with: ${dResponse.statusCode}`);
329
- }
330
- } else {
331
- throw new Error(`Lambda call to DeployVersionLite failed: ${JSON.stringify(response)}`);
332
- }
333
- }
334
- }
@@ -1,25 +0,0 @@
1
- import { pathExists, pathExistsSync } from 'fs-extra';
2
-
3
- export class FilesExist {
4
- public static async getExistingFiles(filesToCheck: string[]): Promise<string[]> {
5
- const existingFiles: string[] = [];
6
- for (const file of filesToCheck) {
7
- if (await pathExists(file)) {
8
- existingFiles.push(file);
9
- }
10
- }
11
-
12
- return existingFiles;
13
- }
14
-
15
- public static getExistingFilesSync(filesToCheck: string[]): string[] {
16
- const existingFiles: string[] = [];
17
- for (const file of filesToCheck) {
18
- if (pathExistsSync(file)) {
19
- existingFiles.push(file);
20
- }
21
- }
22
-
23
- return existingFiles;
24
- }
25
- }
@@ -1,15 +0,0 @@
1
- import { S3TransferUtility } from './S3TransferUtility';
2
- import path from 'path';
3
-
4
- describe('S3TransferUtility', () => {
5
- it('collects the files', () => {
6
- const testFilesRoot = path.join(__dirname, '../../tests/files');
7
- const files = S3TransferUtility.GetFiles(path.join(__dirname, '../../tests/files'));
8
-
9
- expect(files).toBeDefined();
10
- expect(files).toHaveLength(6);
11
-
12
- const relativeFiles = files.map((file) => path.relative(testFilesRoot, file));
13
- expect(relativeFiles).toMatchSnapshot();
14
- });
15
- });
@@ -1,113 +0,0 @@
1
- //
2
- // From: https://stackoverflow.com/a/65862128/878903
3
- //
4
-
5
- import { createReadStream, readdirSync } from 'fs';
6
- import * as path from 'path';
7
- import * as s3 from '@aws-sdk/client-s3';
8
- import { Upload } from '@aws-sdk/lib-storage';
9
- import type { IDeployVersionPreflightResponse } from '@pwrdrvr/microapps-deployer-lib';
10
- import { contentType } from 'mime-types';
11
- import pMap from 'p-map';
12
-
13
- export class S3TransferUtility {
14
- /**
15
- * @deprecated 2021-11-27
16
- *
17
- * @param s3Path
18
- * @param destPrefixPath
19
- * @param bucketName
20
- * @param preflightResponse
21
- */
22
- public static async UploadDir(
23
- s3Path: string,
24
- destPrefixPath: string,
25
- bucketName: string,
26
- preflightResponse: IDeployVersionPreflightResponse,
27
- ): Promise<void> {
28
- // Use temp credentials for S3
29
- const s3Client = new s3.S3Client({
30
- maxAttempts: 16,
31
- credentials: {
32
- accessKeyId: preflightResponse.awsCredentials.accessKeyId,
33
- secretAccessKey: preflightResponse.awsCredentials.secretAccessKey,
34
- sessionToken: preflightResponse.awsCredentials.sessionToken,
35
- },
36
- });
37
-
38
- // console.log('Uploading files to S3');
39
- const files = S3TransferUtility.GetFiles(s3Path);
40
- // const pathWithoutAppAndVer = path.join(s3Path, destPrefixPath);
41
- // for (const filePath of files) {
42
- // const relFilePath = path.relative(pathWithoutAppAndVer, filePath);
43
- // console.log(` ${relFilePath}`);
44
- // }
45
-
46
- // Use p-map to limit upload parallelism
47
- await pMap(
48
- files,
49
- async (filePath) => {
50
- // Use 4 multi-part parallel uploads for items > 5 MB
51
- const upload = new Upload({
52
- client: s3Client,
53
- leavePartsOnError: false,
54
- params: {
55
- Bucket: bucketName,
56
- Key: path.relative(s3Path, filePath),
57
- Body: createReadStream(filePath),
58
- ContentType: contentType(path.basename(filePath)) || 'application/octet-stream',
59
- CacheControl: 'max-age=86400; public',
60
- },
61
- });
62
- await upload.done();
63
- },
64
- {
65
- concurrency: 10,
66
- },
67
- // await s3.send(
68
- // new S3.PutObjectCommand({
69
- // Key: path.relative(s3Path, filePath),
70
- // Bucket: bucketName,
71
- // Body: createReadStream(filePath),
72
- // ContentType: contentType(path.basename(filePath)) || 'application/octet-stream',
73
- // CacheControl: 'max-age=86400; public',
74
- // }),
75
- );
76
- }
77
- // Recursive getFiles from
78
- // https://stackoverflow.com/a/45130990/831465
79
-
80
- /**
81
- * Resursively enumerate the files to be uploaded
82
- * @param dir
83
- * @returns
84
- */
85
- public static GetFiles(dir: string): string[] {
86
- const dirents = readdirSync(dir, { withFileTypes: true });
87
- const files: string[] = [];
88
- const toScan = dirents.map((dirent) => ({
89
- path: path.resolve(dir, dirent.name),
90
- isDirectory: dirent.isDirectory(),
91
- }));
92
-
93
- // Iteratively collect all the files in the directories
94
- // Do not use function call recursion
95
- while (toScan.length > 0) {
96
- const dirOrFile = toScan.pop();
97
-
98
- if (dirOrFile.isDirectory) {
99
- const direntsChild = readdirSync(dirOrFile.path, { withFileTypes: true });
100
- const toScanChild = direntsChild.map((dirent) => ({
101
- path: path.resolve(dirOrFile.path, dirent.name),
102
- isDirectory: dirent.isDirectory(),
103
- }));
104
- Array.prototype.push.apply(toScan, toScanChild);
105
- } else {
106
- files.push(dirOrFile.path);
107
- }
108
- }
109
-
110
- // Reverse the array so that the files are in the same order as the original
111
- return files.reverse();
112
- }
113
- }
@@ -1,94 +0,0 @@
1
- import * as path from 'path';
2
- import type { IDeployVersionPreflightResponse } from '@pwrdrvr/microapps-deployer-lib';
3
- import * as fs from 'fs-extra';
4
- import { IConfig } from '../config/Config';
5
- import { S3TransferUtility } from './S3TransferUtility';
6
-
7
- export class S3Uploader {
8
- /**
9
- * Copy files to local upload directory
10
- * @param config
11
- * @param s3UploadPath
12
- * @param preflightResponse
13
- */
14
- public static async CopyToUploadDir(config: IConfig, s3UploadPath: string): Promise<void> {
15
- const { destinationPrefix } = S3Uploader.ParseUploadPath(s3UploadPath);
16
-
17
- // Make a local root dir for the upload
18
- const tempUploadPath = path.join(S3Uploader._tempDir, destinationPrefix);
19
- await S3Uploader.removeTempDirIfExists();
20
- await fs.mkdir(tempUploadPath, { recursive: true });
21
-
22
- // Copy the files in the source dir to the root dir
23
- // Note: It would be faster to move the files, then move them back
24
- await fs.copy(config.app.staticAssetsPath, tempUploadPath);
25
- }
26
-
27
- public static ParseUploadPath(s3UploadPath: string): {
28
- bucketName: string;
29
- destinationPrefix: string;
30
- } {
31
- // Parse the S3 Source URI
32
- const uri = new URL(s3UploadPath);
33
- const bucketName = uri.host;
34
- const destinationPrefix = uri.pathname.length >= 1 ? uri.pathname.slice(1) : '';
35
-
36
- return { bucketName, destinationPrefix };
37
- }
38
-
39
- /**
40
- * Upload files to S3
41
- * @deprecated 2021-11-27
42
- * @param config
43
- * @param s3UploadPath
44
- * @param preflightResponse
45
- */
46
- public static async Upload(
47
- config: IConfig,
48
- s3UploadPath: string,
49
- preflightResponse: IDeployVersionPreflightResponse,
50
- ): Promise<void> {
51
- try {
52
- const { destinationPrefix, bucketName } = S3Uploader.ParseUploadPath(s3UploadPath);
53
-
54
- // Make a local root dir for the upload
55
- const tempUploadPath = path.join(S3Uploader._tempDir, destinationPrefix);
56
- await S3Uploader.removeTempDirIfExists();
57
- await fs.mkdir(tempUploadPath, { recursive: true });
58
-
59
- // Copy the files in the source dir to the root dir
60
- // Note: It would be faster to move the files, then move them back
61
- // FIXME: Use p-map for controlled parallelism
62
- await fs.copy(config.app.staticAssetsPath, tempUploadPath);
63
-
64
- // Do the upload
65
- await S3TransferUtility.UploadDir(
66
- this._tempDir,
67
- destinationPrefix,
68
- bucketName,
69
- preflightResponse,
70
- );
71
- } finally {
72
- // Delete the directory, now that it's uploaded or if we failed
73
- await S3Uploader.removeTempDirIfExists();
74
- }
75
- }
76
-
77
- public static async removeTempDirIfExists(): Promise<void> {
78
- try {
79
- const stats = await fs.stat(S3Uploader._tempDir);
80
- if (stats.isDirectory()) {
81
- await fs.rm(S3Uploader._tempDir, { recursive: true });
82
- }
83
- } catch {
84
- // Don't care
85
- // fs.stat will throw if file/dir does not exist
86
- // Since we want the directory deleted this is ok
87
- }
88
- }
89
-
90
- private static readonly _tempDir = './deploytool-temp';
91
- public static get TempDir(): string {
92
- return S3Uploader._tempDir;
93
- }
94
- }