@raisenow/tamaro-cli 1.0.8 → 1.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/cli.js CHANGED
@@ -23,7 +23,7 @@ var import_commander = require("commander");
23
23
 
24
24
  // package.json
25
25
  var name = "@raisenow/tamaro-cli";
26
- var version = "1.0.8";
26
+ var version = "1.0.9";
27
27
  var author = {
28
28
  name: "RaiseNow",
29
29
  email: "development@raisenow.com"
@@ -35,8 +35,7 @@ var scripts = {
35
35
  dev: "npm run build -- --watch --ignore-watch .idea",
36
36
  build: "tsup src/cli.ts src/webpack.config.ts --format cjs",
37
37
  docs: "npx -y http-server . --cors -o /readme.html",
38
- lint: "eslint .",
39
- "lint:fix": "eslint . --fix"
38
+ lint: "eslint . --fix && prettier --write ."
40
39
  };
41
40
  var bin = "dist/cli.js";
42
41
  var engines = {
@@ -44,83 +43,81 @@ var engines = {
44
43
  npm: ">=8"
45
44
  };
46
45
  var dependencies = {
47
- "@babel/cli": "^7.16.8",
48
- "@babel/core": "^7.16.12",
49
- "@babel/plugin-proposal-decorators": "^7.16.7",
46
+ "@babel/cli": "^7.17.0",
47
+ "@babel/core": "^7.17.0",
48
+ "@babel/plugin-proposal-decorators": "^7.17.0",
50
49
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
51
- "@babel/plugin-transform-runtime": "^7.16.10",
50
+ "@babel/plugin-transform-runtime": "^7.17.0",
52
51
  "@babel/preset-env": "^7.16.11",
53
52
  "@babel/preset-react": "^7.16.7",
54
53
  "@babel/preset-typescript": "^7.16.7",
55
- "@babel/runtime-corejs3": "^7.16.8",
54
+ "@babel/runtime-corejs3": "^7.17.0",
56
55
  "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
57
- "@statoscope/webpack-plugin": "^5.20.0",
58
- "@svgr/webpack": "^6.2.0",
56
+ "@statoscope/webpack-plugin": "^5.20.1",
57
+ "@svgr/webpack": "^6.2.1",
59
58
  "@types/columnify": "^1.5.1",
60
59
  "@types/lodash": "^4.14.178",
61
60
  "@types/mini-css-extract-plugin": "^2.5.1",
62
- "@types/node": "^17.0.12",
61
+ "@types/node": "^17.0.16",
63
62
  "@types/node-notifier": "^8.0.2",
64
63
  "@types/resolve-bin": "^0.4.1",
65
64
  "@types/webpack-config-utils": "^2.3.1",
66
- "@typescript-eslint/eslint-plugin": "^5.10.1",
67
- "@typescript-eslint/parser": "^5.10.1",
65
+ "@typescript-eslint/eslint-plugin": "^5.11.0",
66
+ "@typescript-eslint/parser": "^5.11.0",
68
67
  autoprefixer: "^10.4.2",
69
68
  "babel-loader": "^8.2.3",
70
69
  "babel-plugin-lodash": "^3.3.4",
71
70
  boxen: "^5.1.2",
72
71
  chalk: "^4.1.2",
73
72
  "clean-webpack-plugin": "^4.0.0",
74
- columnify: "^1.5.4",
75
- commander: "^8.3.0",
76
- "copy-webpack-plugin": "^10.2.1",
77
- "core-js": "^3.20.3",
78
- "css-loader": "^6.5.1",
73
+ columnify: "^1.6.0",
74
+ commander: "^9.0.0",
75
+ "copy-webpack-plugin": "^10.2.4",
76
+ "core-js": "^3.21.0",
77
+ "css-loader": "^6.6.0",
79
78
  "css-minimizer-webpack-plugin": "^3.4.1",
80
79
  "current-script-polyfill": "^1.0.0",
81
- dotenv: "^14.3.2",
82
- "dotenv-expand": "^6.0.1",
80
+ dotenv: "^16.0.0",
81
+ "dotenv-expand": "^8.0.1",
83
82
  "element-closest": "^3.0.2",
84
83
  "escape-string-regexp": "^4.0.0",
85
- eslint: "^8.7.0",
86
- "eslint-config-prettier": "^8.3.0",
84
+ eslint: "^8.8.0",
87
85
  "eslint-plugin-node": "^11.1.0",
88
- "eslint-plugin-prettier": "^4.0.0",
89
86
  "eslint-plugin-promise": "^6.0.0",
90
87
  "eslint-webpack-plugin": "^3.1.0",
91
88
  execa: "^5.1.1",
92
89
  "file-loader": "^6.2.0",
93
- "fork-ts-checker-webpack-plugin": "^6.5.0",
90
+ "fork-ts-checker-webpack-plugin": "^7.1.1",
94
91
  glob: "^7.2.0",
95
92
  "html-loader": "^3.1.0",
96
93
  "html-webpack-plugin": "^5.5.0",
97
94
  "json-loader": "^0.5.7",
98
95
  lodash: "^4.17.21",
99
96
  "mini-css-extract-plugin": "^2.5.3",
100
- "node-notifier": "^10.0.0",
97
+ "node-notifier": "^10.0.1",
98
+ open: "^8.4.0",
101
99
  portfinder: "^1.0.28",
102
- postcss: "^8.4.5",
103
- "postcss-custom-properties": "^12.1.3",
100
+ postcss: "^8.4.6",
101
+ "postcss-custom-properties": "^12.1.4",
104
102
  "postcss-loader": "^6.2.1",
105
103
  prettier: "^2.5.1",
106
104
  "react-refresh": "^0.11.0",
107
105
  "resolve-bin": "^1.0.0",
108
106
  "resolve-url-loader": "^5.0.0",
109
- sass: "^1.49.0",
107
+ sass: "^1.49.7",
110
108
  "sass-loader": "^12.4.0",
111
109
  "source-map-loader": "^3.0.1",
112
110
  "strip-indent": "^3.0.0",
113
111
  "style-loader": "^3.3.1",
114
- tailwindcss: "^0.7.4",
115
112
  "tsconfig-paths-webpack-plugin": "^3.5.2",
116
- tsup: "^5.11.11",
113
+ tsup: "^5.11.13",
117
114
  typescript: "^4.5.5",
118
115
  unfetch: "^4.2.0",
119
116
  "url-loader": "^4.1.1",
120
- webpack: "^5.67.0",
117
+ webpack: "^5.68.0",
121
118
  "webpack-cli": "^4.9.2",
122
119
  "webpack-config-utils": "^2.3.1",
123
- "webpack-dev-server": "^4.7.3",
120
+ "webpack-dev-server": "^4.7.4",
124
121
  "yaml-loader": "^0.6.0"
125
122
  };
126
123
  var package_default = {
@@ -134,25 +131,21 @@ var package_default = {
134
131
  dependencies
135
132
  };
136
133
 
137
- // src/commands/dev/index.ts
138
- var import_execa = require("execa");
139
-
140
134
  // src/lib/helpers.ts
141
135
  var import_path = require("path");
142
136
  var import_fs = require("fs");
143
137
  var import_chalk = __toESM(require("chalk"));
144
- var import_node_notifier = require("node-notifier");
138
+ var import_node_notifier = __toESM(require("node-notifier"));
145
139
  var import_webpack_config_utils = require("webpack-config-utils");
146
140
  var import_columnify = __toESM(require("columnify"));
147
141
  var import_boxen = __toESM(require("boxen"));
148
142
  var import_dotenv_expand = require("dotenv-expand");
149
143
  var import_dotenv = require("dotenv");
144
+ var import_open = __toESM(require("open"));
150
145
  var import_strip_indent = __toESM(require("strip-indent"));
151
- var TAMARO_CORE_PACKAGE_NAMES = ["@raisenow/tamaro-core", "demo-tamaro-core"];
152
- var TAMARO_CONFIGURATIONS_PACKAGE_NAMES = [
153
- "@raisenow/tamaro-configurations",
154
- "demo-tamaro-configurations"
155
- ];
146
+ var import_execa = require("execa");
147
+ var TAMARO_CORE_PACKAGE_NAMES = ["@raisenow/tamaro-core"];
148
+ var TAMARO_CONFIGURATIONS_PACKAGE_NAMES = ["@raisenow/tamaro-configurations"];
156
149
  var getIfCoreFns = () => {
157
150
  const corePkgPath = resolveApp("package.json");
158
151
  const configsPkgPath = resolveApp("../../package.json");
@@ -168,12 +161,12 @@ var getIfCoreFns = () => {
168
161
  return (0, import_webpack_config_utils.getIfUtils)({ core: false }, ["core"]);
169
162
  }
170
163
  }
171
- console.error(import_chalk.default.red((0, import_strip_indent.default)(` You must run "npx @raisenow/tamaro-cli" commands from:
164
+ logError((0, import_strip_indent.default)(` You must run "npx @raisenow/tamaro-cli" commands from:
172
165
  1. Root of "${import_chalk.default.bold(TAMARO_CORE_PACKAGE_NAMES[0])}" package folder.
173
166
  2. Root of particular customer configuration folder of "${import_chalk.default.bold(TAMARO_CONFIGURATIONS_PACKAGE_NAMES[0])}" package.
174
167
  You are currently in "${import_chalk.default.bold((0, import_fs.realpathSync)(process.cwd()))}".
175
- `)));
176
- process.exit(0);
168
+ `));
169
+ process.exit(1);
177
170
  };
178
171
  var moduleFileExtensions = ["ts", "tsx", "js", "jsx"];
179
172
  var extensions = moduleFileExtensions.map((v) => `.${v}`);
@@ -208,77 +201,418 @@ var getPaths = (ifCore) => {
208
201
  appTailwindConfig: void 0
209
202
  });
210
203
  };
211
- var logCommand = (...args) => {
212
- console.log(import_chalk.default.dim(...args));
204
+ var logTitle = (title) => {
205
+ console.log(`
206
+ ${import_chalk.default.bold(title)}`);
207
+ };
208
+ var logError = (message) => {
209
+ if (message) {
210
+ console.log(import_chalk.default.red(message));
211
+ }
212
+ };
213
+ var fail = (message) => {
214
+ logError(message);
215
+ process.exit(1);
216
+ };
217
+ var logCommand = (command) => {
218
+ console.log(import_chalk.default.dim((0, import_strip_indent.default)(command)));
219
+ };
220
+ var prepareCommand = (command) => {
221
+ return command.replace(/\n/gm, " ").replace(/[ \t]{2,}/gm, " ").trim();
222
+ };
223
+ var runCommandSync = (command, options) => {
224
+ return (0, import_execa.commandSync)(prepareCommand(command), options);
225
+ };
226
+ var logDataTable = (vars, title) => {
227
+ logTable((0, import_columnify.default)(vars, { showHeaders: false }), title);
228
+ };
229
+ var logTable = (text, title) => {
230
+ let out = "";
231
+ const boxTitle = title ? import_chalk.default.bold(`${title}`) : void 0;
232
+ if (boxTitle) {
233
+ out += `${boxTitle}
234
+ `;
235
+ }
236
+ out += text;
237
+ console.log((0, import_boxen.default)(out, {
238
+ margin: 0,
239
+ padding: {
240
+ top: 0,
241
+ right: 1,
242
+ bottom: 0,
243
+ left: 1
244
+ },
245
+ borderColor: "green"
246
+ }));
213
247
  };
214
248
  var notify = (args) => {
215
- const { title, message } = args;
216
- (0, import_node_notifier.notify)({
249
+ const { title, message, target } = args;
250
+ import_node_notifier.default.notify({
217
251
  title,
218
252
  message,
219
- contentImage: resolveOwn("src/assets/rnw-logo.png"),
220
- sound: "Funk"
253
+ contentImage: "https://assets.raisenow.io/favicon.png",
254
+ sound: "Funk",
255
+ timeout: 30
221
256
  });
257
+ if (target) {
258
+ import_node_notifier.default.on("click", () => {
259
+ (0, import_open.default)(target);
260
+ });
261
+ }
222
262
  };
223
263
 
224
- // src/commands/dev/index.ts
264
+ // src/commands/dev.ts
225
265
  var import_resolve_bin = __toESM(require("resolve-bin"));
226
- var prepareDevFlags = (options) => {
227
- const { localCore } = options;
228
- let flags = [];
229
- flags = localCore ? [...flags, "--env localCore"] : flags;
230
- return flags.join(" ");
231
- };
232
266
  var dev = async (options) => {
233
- const flags = prepareDevFlags(options);
267
+ assertOptionsValid(options);
268
+ const flags = prepareFlags(options);
269
+ const { ifCore } = getIfCoreFns();
270
+ const title = ifCore("Running dev web-server for Tamaro Core \u2026", "Running dev web-server for customer configuration \u2026");
234
271
  const wpBin = import_resolve_bin.default.sync("webpack");
235
272
  const wpConfig = resolveOwn("dist/webpack.config.js");
236
- const cmd = `${wpBin} serve --config ${wpConfig} ${flags}`;
273
+ const cmd = `
274
+ ${wpBin} serve
275
+ --config ${wpConfig}
276
+ ${flags}
277
+ `;
278
+ logTitle(title);
237
279
  logCommand(cmd);
238
- (0, import_execa.commandSync)(cmd, { stdio: "inherit" });
280
+ runCommandSync(cmd, { stdio: "inherit" });
239
281
  };
240
-
241
- // src/commands/build/index.ts
242
- var import_execa2 = require("execa");
243
- var import_resolve_bin2 = __toESM(require("resolve-bin"));
244
- var prepareBuildFlags = (options) => {
245
- const { localCore, analyze } = options;
282
+ var assertOptionsValid = (options) => {
283
+ const { localCore } = options;
284
+ const { ifCore } = getIfCoreFns();
285
+ if (ifCore() && localCore) {
286
+ fail('Flag "--local-core" is redundant if running in Tamaro Core context.');
287
+ }
288
+ };
289
+ var prepareFlags = (options) => {
290
+ const { localCore } = options;
246
291
  let flags = [];
247
292
  flags = localCore ? [...flags, "--env localCore"] : flags;
248
- flags = analyze ? [...flags, "--env analyze"] : flags;
249
293
  return flags.join(" ");
250
294
  };
295
+
296
+ // src/commands/build.ts
297
+ var import_resolve_bin2 = __toESM(require("resolve-bin"));
298
+
299
+ // src/lib/aws.ts
300
+ var import_execa2 = require("execa");
301
+ var import_strip_indent2 = __toESM(require("strip-indent"));
302
+ var DEFAULT_AWS_PROFILE = "payments-prod-cs-deployer";
303
+ var runAwsCommandSync = (command, options) => {
304
+ authenticate();
305
+ return (0, import_execa2.commandSync)(prepareCommand(command), options);
306
+ };
307
+ var authenticate = () => {
308
+ if (isSetEnv()) {
309
+ return;
310
+ }
311
+ try {
312
+ checkIdentity();
313
+ } catch (error) {
314
+ login();
315
+ }
316
+ };
317
+ var isSetEnv = () => {
318
+ return !!(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY);
319
+ };
320
+ var assertProfileValid = (profile) => {
321
+ if (isSetEnv()) {
322
+ return;
323
+ }
324
+ const profiles = getAvailableProfiles();
325
+ if (!profiles.includes(profile)) {
326
+ console.log(`Using AWS profile: \u201C${profile}\u201D`);
327
+ let message;
328
+ if (profiles.length === 0) {
329
+ message = (0, import_strip_indent2.default)(`
330
+ No AWS profiles found.
331
+ `);
332
+ } else {
333
+ message = (0, import_strip_indent2.default)(`
334
+ AWS profile \u201C${profile}\u201D has not been found.
335
+ Available profiles are: ${profiles.map((v) => `\u201C${v}\u201D`).join(", ")}.
336
+ `);
337
+ }
338
+ message += (0, import_strip_indent2.default)(`
339
+ Run \u201Caws configure sso\u201D to set up SSO-enabled profile.
340
+ Check the wiki for more information:
341
+ https://raisenow.atlassian.net/wiki/x/lIrWvg
342
+ `);
343
+ fail(message);
344
+ }
345
+ process.env.AWS_PROFILE = profile;
346
+ };
347
+ var getAvailableProfiles = () => {
348
+ const { stdout } = (0, import_execa2.commandSync)("aws configure list-profiles");
349
+ return stdout.split("\n");
350
+ };
351
+ var checkIdentity = () => {
352
+ (0, import_execa2.commandSync)("aws sts get-caller-identity");
353
+ };
354
+ var login = () => {
355
+ try {
356
+ (0, import_execa2.commandSync)("aws sso login", { stdio: "inherit" });
357
+ console.log("");
358
+ } catch (error) {
359
+ fail("Login failed");
360
+ }
361
+ };
362
+
363
+ // src/commands/deploy.ts
364
+ var import_fs2 = require("fs");
365
+ var import_strip_indent3 = __toESM(require("strip-indent"));
366
+ var AWS_S3_BUCKET = "tamaro.raisenow.com";
367
+ var CORE_CONFIG_NAME = "tamaro-core";
368
+ var AWS_CLOUDFRONT_DISTRIBUTION_ID = "EHJ1OM458YQ0I";
369
+ var DEFAULT_TAG = "latest";
370
+ var deploy = async (options) => {
371
+ const { ifCore } = getIfCoreFns();
372
+ const paths = getPaths(ifCore);
373
+ assertOptionsValid2(options);
374
+ assertDistPathExists(paths.appDist);
375
+ const { tag } = options;
376
+ const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
377
+ const deployUrl = `s3://${AWS_S3_BUCKET}/${configName}/${tag}`;
378
+ const entryFilename = ifCore("index.js", "widget.js");
379
+ const cmdSyncAll = `
380
+ aws s3 sync ${paths.appDist} ${deployUrl}
381
+ --acl public-read
382
+ --size-only
383
+ --exclude ${paths.appDist}/${entryFilename}
384
+ --cache-control max-age=31536000
385
+ `;
386
+ logTitle("Deploying to AWS S3 \u2026");
387
+ logCommand(cmdSyncAll);
388
+ try {
389
+ runAwsCommandSync(cmdSyncAll, { stdout: "inherit" });
390
+ } catch (error) {
391
+ fail(error.stderr);
392
+ }
393
+ const cmdCpEntry = `
394
+ aws s3 cp ${paths.appDist}/${entryFilename} ${deployUrl}/${entryFilename}
395
+ --acl public-read
396
+ --cache-control max-age=64800
397
+ `;
398
+ logCommand(cmdCpEntry);
399
+ try {
400
+ runAwsCommandSync(cmdCpEntry, { stdout: "inherit" });
401
+ } catch (error) {
402
+ fail(error.stderr);
403
+ }
404
+ const cmdInvalidateCache = `
405
+ aws cloudfront create-invalidation
406
+ --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
407
+ --paths /${configName}/${tag}/*
408
+ `;
409
+ logTitle("Invalidating edge cache \u2026");
410
+ logCommand(cmdInvalidateCache);
411
+ try {
412
+ runAwsCommandSync(cmdInvalidateCache);
413
+ } catch (error) {
414
+ fail(error.stderr);
415
+ }
416
+ const demoPage = `https://${AWS_S3_BUCKET}/${configName}/${tag}/index.html`;
417
+ const entryPoint = `https://${AWS_S3_BUCKET}/${configName}/${tag}/${entryFilename}`;
418
+ logDataTable({
419
+ "Demo page:": demoPage,
420
+ "Entry point:": entryPoint
421
+ }, `Bundle for \u201C${configName}\u201D is deployed with tag \u201C${tag}\u201D`);
422
+ notify({
423
+ title: "deploy",
424
+ message: (0, import_strip_indent3.default)(`
425
+ Bundle for \u201C${configName}\u201D is deployed with tag \u201C${tag}\u201D.
426
+ Demo page: ${demoPage}
427
+ `),
428
+ target: demoPage
429
+ });
430
+ };
431
+ var assertOptionsValid2 = (options) => {
432
+ const { tag, profile } = options;
433
+ assertTagValid(tag);
434
+ assertProfileValid(profile);
435
+ };
436
+ var assertDistPathExists = (distPath) => {
437
+ if (!(0, import_fs2.existsSync)(distPath)) {
438
+ fail(`
439
+ Dist folder does not exists.
440
+ Make sure you have built the bundle before trying to deploy it.
441
+ `);
442
+ }
443
+ };
444
+ var assertTagValid = (tag) => {
445
+ const regex = /^[a-zA-Z0-9-_]+$/;
446
+ if (!regex.test(tag)) {
447
+ fail(`Flag "--tag" has forbidden format. Allowed format: ${regex}.`);
448
+ }
449
+ };
450
+
451
+ // src/commands/build.ts
251
452
  var build = async (options) => {
252
- const flags = prepareBuildFlags(options);
453
+ assertOptionsValid3(options);
454
+ const flags = prepareFlags2(options);
455
+ const { ifCore } = getIfCoreFns();
456
+ const paths = getPaths(ifCore);
457
+ const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
458
+ const title = ifCore("Building optimised (minified) bundle of Tamaro Core \u2026", `Building optimised (minified) bundle of \u201C${configName}\u201D customer configuration \u2026`);
253
459
  const wpBin = import_resolve_bin2.default.sync("webpack");
254
460
  const wpConfig = resolveOwn("dist/webpack.config.js");
255
- const cmd = `${wpBin} --config ${wpConfig} --env min ${flags}`;
461
+ const cmd = `
462
+ ${wpBin}
463
+ --config ${wpConfig}
464
+ --env min
465
+ ${flags}
466
+ `;
467
+ logTitle(title);
256
468
  logCommand(cmd);
257
- (0, import_execa2.commandSync)(cmd, { stdio: "inherit" });
469
+ runCommandSync(cmd, { stdio: "inherit" });
470
+ logDataTable({ "Path:": paths.appDist }, `Bundle for \u201C${configName}\u201D customer configuration is done.`);
258
471
  notify({
259
- title: '"build" command',
260
- message: "Process is done"
472
+ title: "build",
473
+ message: `Bundle for \u201C${configName}\u201D customer configuration is done.`
261
474
  });
262
475
  };
476
+ var assertOptionsValid3 = (options) => {
477
+ const { localCore, deploy: deploy2, profile } = options;
478
+ const { ifCore } = getIfCoreFns();
479
+ if (ifCore() && localCore) {
480
+ fail('Flag "--local-core" is redundant if running in Tamaro Core context.');
481
+ }
482
+ if (localCore && deploy2) {
483
+ fail('Flags "--local-core" and "--deploy" must not be used together.');
484
+ }
485
+ assertProfileValid(profile);
486
+ };
487
+ var prepareFlags2 = (options) => {
488
+ const { localCore, analyze } = options;
489
+ let flags = [];
490
+ flags = localCore ? [...flags, "--env localCore"] : flags;
491
+ flags = analyze ? [...flags, "--env analyze"] : flags;
492
+ return flags.join(" ");
493
+ };
263
494
 
264
- // src/commands/deploy/index.ts
265
- var import_execa3 = require("execa");
266
- var deploy = async (options) => {
495
+ // src/commands/serve.ts
496
+ var import_portfinder = require("portfinder");
497
+ var DEFAULT_PORT = 1234;
498
+ var serve = async () => {
267
499
  const { ifCore } = getIfCoreFns();
268
500
  const paths = getPaths(ifCore);
269
- const cmd = `echo Deploying to AWS is not implemented yet`;
501
+ const port = await (0, import_portfinder.getPortPromise)({ port: DEFAULT_PORT });
502
+ const cmd = `
503
+ npx -y http-server ${paths.appDist}
504
+ --cors
505
+ --port ${port}
506
+ `;
507
+ logTitle(`Running web-server for pre-built bundle \u2026`);
270
508
  logCommand(cmd);
271
- (0, import_execa3.commandSync)(cmd, { stdio: "inherit" });
509
+ runCommandSync(cmd, { stdio: "inherit" });
272
510
  };
273
511
 
274
- // src/commands/serve/index.ts
275
- var import_execa4 = require("execa");
276
- var serve = async () => {
512
+ // src/commands/list-deployed.ts
513
+ var listDeployed = async (options) => {
514
+ assertOptionsValid4(options);
515
+ const { config } = options;
516
+ const { ifCore } = getIfCoreFns();
517
+ const configName = config != null ? config : ifCore(CORE_CONFIG_NAME, getWidgetUuid());
518
+ const title = !config && ifCore() ? `Listing deployments of Tamaro Core \u2026` : `Listing deployments of \u201C${configName}\u201D customer configuration \u2026`;
519
+ const deployUrl = `s3://${AWS_S3_BUCKET}/${configName}/`;
520
+ const cmd = `aws s3 ls ${deployUrl}`;
521
+ let out = "";
522
+ logTitle(title);
523
+ logCommand(cmd);
524
+ try {
525
+ const result = runAwsCommandSync(cmd);
526
+ out = result.stdout;
527
+ } catch (error) {
528
+ out = error.stdout;
529
+ if (error.stderr) {
530
+ fail(error.stderr);
531
+ }
532
+ }
533
+ const lines = out.split("\n");
534
+ const tags = parseTags(lines);
535
+ let text = "";
536
+ if (tags.length === 0) {
537
+ text = "No deployments found.";
538
+ } else {
539
+ text = tags.map((tag, idx) => {
540
+ return `${idx + 1}. https://${AWS_S3_BUCKET}/${configName}/${tag}/index.html`;
541
+ }).join("\n");
542
+ }
543
+ logTable(text);
544
+ };
545
+ var assertOptionsValid4 = (options) => {
546
+ const { config, profile } = options;
547
+ assertConfigValid(config);
548
+ assertProfileValid(profile);
549
+ };
550
+ var assertConfigValid = (config) => {
551
+ if (!config) {
552
+ return;
553
+ }
554
+ const regex = /^[a-zA-Z0-9-_]+$/;
555
+ if (!regex.test(config)) {
556
+ fail(`Flag "--config" has forbidden format. Allowed format: ${regex}.`);
557
+ }
558
+ };
559
+ var parseTags = (lines) => {
560
+ const regex = /^\s*PRE\s*/;
561
+ return lines.filter((line) => regex.test(line)).map((line) => line.replace(regex, "").replace(/\/$/, ""));
562
+ };
563
+
564
+ // src/commands/deploy-email-config.ts
565
+ var import_fs3 = require("fs");
566
+ var DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET = "rnw-email-service";
567
+ var deployEmailConfig = async (options) => {
277
568
  const { ifCore } = getIfCoreFns();
278
569
  const paths = getPaths(ifCore);
279
- const cmd = `npx -y http-server ${paths.appDist} --cors --port 1234`;
570
+ const emailConfigPath = `${paths.app}/email-config`;
571
+ assertOptionsValid5(options);
572
+ assertEmailConfigPathExists(emailConfigPath);
573
+ assertIsNotCore();
574
+ const { bucket } = options;
575
+ const configName = getWidgetUuid();
576
+ const deployUrl = `s3://${bucket}/${configName}`;
577
+ const cmd = `
578
+ aws s3 sync ${emailConfigPath} ${deployUrl}
579
+ --delete
580
+ --exact-timestamps
581
+ `;
582
+ logTitle(`Deploying email configuration for \u201C${configName}\u201D customer configuration to AWS S3 \u2026`);
280
583
  logCommand(cmd);
281
- (0, import_execa4.commandSync)(cmd, { stdio: "inherit" });
584
+ try {
585
+ runAwsCommandSync(cmd, { stdout: "inherit" });
586
+ } catch (error) {
587
+ fail(error.stderr);
588
+ }
589
+ logDataTable({ "Deploy URL:": deployUrl }, `Email configuration for \u201C${configName}\u201D customer configuration is deployed.`);
590
+ notify({
591
+ title: `deploy-email-config`,
592
+ message: `Email configuration for \u201C${configName}\u201D customer configuration is deployed.`
593
+ });
594
+ };
595
+ var assertOptionsValid5 = (options) => {
596
+ const { bucket, profile } = options;
597
+ assertBucketValid(bucket);
598
+ assertProfileValid(profile);
599
+ };
600
+ var assertEmailConfigPathExists = (distPath) => {
601
+ if (!(0, import_fs3.existsSync)(distPath)) {
602
+ fail("Email config folder does not exists. Nothing to deploy.");
603
+ }
604
+ };
605
+ var assertBucketValid = (tag) => {
606
+ const regex = /^[a-zA-Z0-9-_]+$/;
607
+ if (!regex.test(tag)) {
608
+ fail(`Flag "--bucket" has forbidden format. Allowed format: ${regex}.`);
609
+ }
610
+ };
611
+ var assertIsNotCore = () => {
612
+ const { ifCore } = getIfCoreFns();
613
+ if (ifCore()) {
614
+ fail("You cannot deploy widget email configuration for Tamaro Core.");
615
+ }
282
616
  };
283
617
 
284
618
  // src/cli.ts
@@ -286,13 +620,13 @@ process.on("unhandledRejection", (error) => {
286
620
  throw error;
287
621
  });
288
622
  process.on("SIGINT", () => {
289
- process.exit(0);
623
+ process.exit(1);
290
624
  });
291
625
  var cli = (0, import_commander.createCommand)().name(package_default.name).version(package_default.version, "-v, --version");
292
- cli.command("dev").description("Run dev web-server for Tamaro Core or customer configuration").option("--local-core", "Load Tamaro Core from localhost instead of CDN").action(async (options) => {
626
+ cli.command("dev").description("Run the local development server for Tamaro Core or a particular customer configuration").option("--local-core", "Load Tamaro Core from localhost instead of the CDN", false).action(async (options) => {
293
627
  await dev(options);
294
628
  });
295
- cli.command("build").description("Build optimised (minified) bundle of Tamaro Core or customer configuration for production").option("--local-core", "Load Tamaro Core from localhost instead of CDN").option("--analyze", 'Generate bundle statistics to "reports" folder').option("--deploy", "Deploy Tamaro Core or customer configuration bundle to AWS").option("--serve", "Run web-server for the bundle").option("--tag <tag>", "Tag which will be used for deployment of the bundle").action(async (options) => {
629
+ cli.command("build").description("Build an optimised (minified) bundle of Tamaro Core or a customer configuration").option("--local-core", "Load Tamaro Core from localhost instead of the CDN", false).option("--analyze", 'Generate bundle statistics to "reports" folder', false).option("--deploy", "Deploy Tamaro Core or a customer configuration bundle to AWS S3", false).option("--serve", "Run the generated bundle with a local web server", false).option("--tag <tag>", "Tag which should be used for the deployment of the bundle", DEFAULT_TAG).option("--profile <profile>", "AWS profile which should be used for the deployment of the bundle", DEFAULT_AWS_PROFILE).action(async (options) => {
296
630
  await build(options);
297
631
  if (options.deploy) {
298
632
  await deploy(options);
@@ -301,12 +635,25 @@ cli.command("build").description("Build optimised (minified) bundle of Tamaro Co
301
635
  await serve();
302
636
  }
303
637
  });
304
- cli.command("deploy").description("Deploy prebuilt Tamaro Core or customer configuration bundle to AWS").option("--tag <tag>", "Tag which will be used for deployment of the bundle").action(async (options) => {
638
+ cli.command("deploy").description("Deploy a pre-built Tamaro Core or customer configuration bundle to AWS S3").option("--tag <tag>", "Tag which should be used for the deployment of the bundle", DEFAULT_TAG).option("--profile <profile>", "AWS profile which should be used for the deployment of the bundle", DEFAULT_AWS_PROFILE).action(async (options) => {
305
639
  await deploy(options);
306
640
  });
307
- cli.command("serve").description("Run web-server for prebuilt bundle").action(async () => {
641
+ cli.command("serve").description("Run a local web server for pre-built bundle").action(async () => {
308
642
  await serve();
309
643
  });
644
+ cli.command("list-deployed").description("List deployments of Tamaro Core or a particular customer configuration").option("--config <config>", "Configuration name (default: current customer configuration)").option("--profile <profile>", "AWS profile which should be used for fetching deployments", DEFAULT_AWS_PROFILE).action(async (options) => {
645
+ await listDeployed(options);
646
+ });
647
+ cli.command("deploy-email-config").description("Deploy a widget\u2019s email configuration to AWS S3").option("--bucket <bucket>", "AWS S3 bucket where it should be deployed", DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET).option("--profile <profile>", "AWS profile which should be used for the deployment of email configuration", DEFAULT_AWS_PROFILE).action(async (options) => {
648
+ await deployEmailConfig(options);
649
+ });
310
650
  (async () => {
311
- await cli.parseAsync(process.argv);
651
+ try {
652
+ await cli.parseAsync(process.argv);
653
+ } catch (error) {
654
+ if (error.signal === "SIGINT" && error.signalDescription) {
655
+ logError(`
656
+ ${error.signalDescription}`);
657
+ }
658
+ }
312
659
  })();