@raisenow/tamaro-cli 1.0.5 → 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
@@ -6,24 +6,24 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
9
- var __reExport = (target, module2, desc) => {
9
+ var __reExport = (target, module2, copyDefault, desc) => {
10
10
  if (module2 && typeof module2 === "object" || typeof module2 === "function") {
11
11
  for (let key of __getOwnPropNames(module2))
12
- if (!__hasOwnProp.call(target, key) && key !== "default")
12
+ if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default"))
13
13
  __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
14
14
  }
15
15
  return target;
16
16
  };
17
- var __toModule = (module2) => {
18
- return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
17
+ var __toESM = (module2, isNodeMode) => {
18
+ return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", !isNodeMode && module2 && module2.__esModule ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
19
19
  };
20
20
 
21
21
  // src/cli.ts
22
- var import_commander = __toModule(require("commander"));
22
+ var import_commander = require("commander");
23
23
 
24
24
  // package.json
25
25
  var name = "@raisenow/tamaro-cli";
26
- var version = "1.0.5";
26
+ var version = "1.0.9";
27
27
  var author = {
28
28
  name: "RaiseNow",
29
29
  email: "development@raisenow.com"
@@ -34,94 +34,90 @@ var scripts = {
34
34
  start: "npm run dev",
35
35
  dev: "npm run build -- --watch --ignore-watch .idea",
36
36
  build: "tsup src/cli.ts src/webpack.config.ts --format cjs",
37
- lint: "eslint .",
38
- "lint:fix": "eslint . --fix"
37
+ docs: "npx -y http-server . --cors -o /readme.html",
38
+ lint: "eslint . --fix && prettier --write ."
39
39
  };
40
40
  var bin = "dist/cli.js";
41
41
  var engines = {
42
- node: ">=14",
42
+ node: ">=16",
43
43
  npm: ">=8"
44
44
  };
45
45
  var dependencies = {
46
- "@babel/cli": "^7.15.7",
47
- "@babel/core": "^7.15.8",
48
- "@babel/plugin-proposal-decorators": "^7.15.8",
46
+ "@babel/cli": "^7.17.0",
47
+ "@babel/core": "^7.17.0",
48
+ "@babel/plugin-proposal-decorators": "^7.17.0",
49
49
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
50
- "@babel/plugin-transform-runtime": "^7.15.8",
51
- "@babel/preset-env": "^7.15.8",
52
- "@babel/preset-react": "^7.14.5",
53
- "@babel/preset-typescript": "^7.15.0",
54
- "@babel/runtime-corejs3": "^7.15.4",
55
- "@pmmmwh/react-refresh-webpack-plugin": "^0.5.1",
56
- "@statoscope/webpack-plugin": "^5.16.0",
57
- "@svgr/webpack": "^5.5.0",
50
+ "@babel/plugin-transform-runtime": "^7.17.0",
51
+ "@babel/preset-env": "^7.16.11",
52
+ "@babel/preset-react": "^7.16.7",
53
+ "@babel/preset-typescript": "^7.16.7",
54
+ "@babel/runtime-corejs3": "^7.17.0",
55
+ "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
56
+ "@statoscope/webpack-plugin": "^5.20.1",
57
+ "@svgr/webpack": "^6.2.1",
58
58
  "@types/columnify": "^1.5.1",
59
- "@types/copy-webpack-plugin": "^8.0.1",
60
- "@types/css-minimizer-webpack-plugin": "^3.0.2",
61
- "@types/lodash": "^4.14.176",
62
- "@types/mini-css-extract-plugin": "^2.4.0",
63
- "@types/node": "^16.11.6",
64
- "@types/node-notifier": "^8.0.1",
59
+ "@types/lodash": "^4.14.178",
60
+ "@types/mini-css-extract-plugin": "^2.5.1",
61
+ "@types/node": "^17.0.16",
62
+ "@types/node-notifier": "^8.0.2",
65
63
  "@types/resolve-bin": "^0.4.1",
66
64
  "@types/webpack-config-utils": "^2.3.1",
67
- "@types/webpack-dev-server": "^4.3.1",
68
- "@typescript-eslint/eslint-plugin": "^5.2.0",
69
- "@typescript-eslint/parser": "^5.2.0",
70
- autoprefixer: "^10.3.7",
65
+ "@typescript-eslint/eslint-plugin": "^5.11.0",
66
+ "@typescript-eslint/parser": "^5.11.0",
67
+ autoprefixer: "^10.4.2",
71
68
  "babel-loader": "^8.2.3",
72
69
  "babel-plugin-lodash": "^3.3.4",
73
70
  boxen: "^5.1.2",
74
71
  chalk: "^4.1.2",
75
72
  "clean-webpack-plugin": "^4.0.0",
76
- columnify: "^1.5.4",
77
- commander: "^8.3.0",
78
- "copy-webpack-plugin": "^9.0.1",
79
- "core-js": "^3.19.0",
80
- "css-loader": "^6.4.0",
81
- "css-minimizer-webpack-plugin": "^3.1.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",
78
+ "css-minimizer-webpack-plugin": "^3.4.1",
82
79
  "current-script-polyfill": "^1.0.0",
83
- dotenv: "^10.0.0",
84
- "dotenv-expand": "^5.1.0",
80
+ dotenv: "^16.0.0",
81
+ "dotenv-expand": "^8.0.1",
85
82
  "element-closest": "^3.0.2",
86
83
  "escape-string-regexp": "^4.0.0",
87
- eslint: "^8.1.0",
88
- "eslint-config-prettier": "^8.3.0",
84
+ eslint: "^8.8.0",
89
85
  "eslint-plugin-node": "^11.1.0",
90
- "eslint-plugin-prettier": "^4.0.0",
91
- "eslint-plugin-promise": "^5.1.1",
92
- "eslint-webpack-plugin": "^3.0.1",
86
+ "eslint-plugin-promise": "^6.0.0",
87
+ "eslint-webpack-plugin": "^3.1.0",
93
88
  execa: "^5.1.1",
94
89
  "file-loader": "^6.2.0",
95
- "fork-ts-checker-webpack-plugin": "^6.4.0",
90
+ "fork-ts-checker-webpack-plugin": "^7.1.1",
96
91
  glob: "^7.2.0",
97
- "html-loader": "^3.0.0",
92
+ "html-loader": "^3.1.0",
98
93
  "html-webpack-plugin": "^5.5.0",
99
94
  "json-loader": "^0.5.7",
100
95
  lodash: "^4.17.21",
101
- "mini-css-extract-plugin": "^2.4.3",
102
- "node-notifier": "^10.0.0",
103
- postcss: "^8.3.11",
104
- "postcss-custom-properties": "^12.0.0",
105
- "postcss-loader": "^6.2.0",
106
- prettier: "^2.4.1",
107
- "react-refresh": "^0.10.0",
96
+ "mini-css-extract-plugin": "^2.5.3",
97
+ "node-notifier": "^10.0.1",
98
+ open: "^8.4.0",
99
+ portfinder: "^1.0.28",
100
+ postcss: "^8.4.6",
101
+ "postcss-custom-properties": "^12.1.4",
102
+ "postcss-loader": "^6.2.1",
103
+ prettier: "^2.5.1",
104
+ "react-refresh": "^0.11.0",
108
105
  "resolve-bin": "^1.0.0",
109
- "resolve-url-loader": "^4.0.0",
110
- sass: "^1.43.3",
111
- "sass-loader": "^12.2.0",
112
- "source-map-loader": "^3.0.0",
106
+ "resolve-url-loader": "^5.0.0",
107
+ sass: "^1.49.7",
108
+ "sass-loader": "^12.4.0",
109
+ "source-map-loader": "^3.0.1",
113
110
  "strip-indent": "^3.0.0",
114
111
  "style-loader": "^3.3.1",
115
- tailwindcss: "^0.7.4",
116
- "tsconfig-paths-webpack-plugin": "^3.5.1",
117
- tsup: "^5.5.0",
118
- typescript: "^4.4.4",
112
+ "tsconfig-paths-webpack-plugin": "^3.5.2",
113
+ tsup: "^5.11.13",
114
+ typescript: "^4.5.5",
119
115
  unfetch: "^4.2.0",
120
116
  "url-loader": "^4.1.1",
121
- webpack: "^5.60.0",
122
- "webpack-cli": "^4.9.1",
117
+ webpack: "^5.68.0",
118
+ "webpack-cli": "^4.9.2",
123
119
  "webpack-config-utils": "^2.3.1",
124
- "webpack-dev-server": "^4.3.1",
120
+ "webpack-dev-server": "^4.7.4",
125
121
  "yaml-loader": "^0.6.0"
126
122
  };
127
123
  var package_default = {
@@ -135,25 +131,21 @@ var package_default = {
135
131
  dependencies
136
132
  };
137
133
 
138
- // src/commands/dev/index.ts
139
- var import_execa = __toModule(require("execa"));
140
-
141
134
  // src/lib/helpers.ts
142
- var import_path = __toModule(require("path"));
143
- var import_fs = __toModule(require("fs"));
144
- var import_chalk = __toModule(require("chalk"));
145
- var import_node_notifier = __toModule(require("node-notifier"));
146
- var import_webpack_config_utils = __toModule(require("webpack-config-utils"));
147
- var import_columnify = __toModule(require("columnify"));
148
- var import_boxen = __toModule(require("boxen"));
149
- var import_dotenv_expand = __toModule(require("dotenv-expand"));
150
- var import_dotenv = __toModule(require("dotenv"));
151
- var import_strip_indent = __toModule(require("strip-indent"));
152
- var TAMARO_CORE_PACKAGE_NAMES = ["@raisenow/tamaro-core", "demo-tamaro-core"];
153
- var TAMARO_CONFIGURATIONS_PACKAGE_NAMES = [
154
- "@raisenow/tamaro-configurations",
155
- "demo-tamaro-configurations"
156
- ];
135
+ var import_path = require("path");
136
+ var import_fs = require("fs");
137
+ var import_chalk = __toESM(require("chalk"));
138
+ var import_node_notifier = __toESM(require("node-notifier"));
139
+ var import_webpack_config_utils = require("webpack-config-utils");
140
+ var import_columnify = __toESM(require("columnify"));
141
+ var import_boxen = __toESM(require("boxen"));
142
+ var import_dotenv_expand = require("dotenv-expand");
143
+ var import_dotenv = require("dotenv");
144
+ var import_open = __toESM(require("open"));
145
+ var import_strip_indent = __toESM(require("strip-indent"));
146
+ var import_execa = require("execa");
147
+ var TAMARO_CORE_PACKAGE_NAMES = ["@raisenow/tamaro-core"];
148
+ var TAMARO_CONFIGURATIONS_PACKAGE_NAMES = ["@raisenow/tamaro-configurations"];
157
149
  var getIfCoreFns = () => {
158
150
  const corePkgPath = resolveApp("package.json");
159
151
  const configsPkgPath = resolveApp("../../package.json");
@@ -169,12 +161,12 @@ var getIfCoreFns = () => {
169
161
  return (0, import_webpack_config_utils.getIfUtils)({ core: false }, ["core"]);
170
162
  }
171
163
  }
172
- 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:
173
165
  1. Root of "${import_chalk.default.bold(TAMARO_CORE_PACKAGE_NAMES[0])}" package folder.
174
166
  2. Root of particular customer configuration folder of "${import_chalk.default.bold(TAMARO_CONFIGURATIONS_PACKAGE_NAMES[0])}" package.
175
167
  You are currently in "${import_chalk.default.bold((0, import_fs.realpathSync)(process.cwd()))}".
176
- `)));
177
- process.exit(0);
168
+ `));
169
+ process.exit(1);
178
170
  };
179
171
  var moduleFileExtensions = ["ts", "tsx", "js", "jsx"];
180
172
  var extensions = moduleFileExtensions.map((v) => `.${v}`);
@@ -209,76 +201,418 @@ var getPaths = (ifCore) => {
209
201
  appTailwindConfig: void 0
210
202
  });
211
203
  };
212
- var logCommand = (...args) => {
213
- 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
+ }));
214
247
  };
215
248
  var notify = (args) => {
216
- const { title, message } = args;
217
- (0, import_node_notifier.notify)({
249
+ const { title, message, target } = args;
250
+ import_node_notifier.default.notify({
218
251
  title,
219
252
  message,
220
- contentImage: resolveOwn("src/assets/rnw-logo.png"),
221
- sound: "Funk"
253
+ contentImage: "https://assets.raisenow.io/favicon.png",
254
+ sound: "Funk",
255
+ timeout: 30
222
256
  });
257
+ if (target) {
258
+ import_node_notifier.default.on("click", () => {
259
+ (0, import_open.default)(target);
260
+ });
261
+ }
223
262
  };
224
263
 
225
- // src/commands/dev/index.ts
226
- var import_resolve_bin = __toModule(require("resolve-bin"));
227
- var prepareDevFlags = (options) => {
228
- const { localCore } = options;
229
- let flags = [];
230
- flags = localCore ? [...flags, "--env localCore"] : flags;
231
- return flags.join(" ");
232
- };
264
+ // src/commands/dev.ts
265
+ var import_resolve_bin = __toESM(require("resolve-bin"));
233
266
  var dev = async (options) => {
234
- 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");
235
271
  const wpBin = import_resolve_bin.default.sync("webpack");
236
272
  const wpConfig = resolveOwn("dist/webpack.config.js");
237
- const cmd = `${wpBin} serve --config ${wpConfig} ${flags}`;
273
+ const cmd = `
274
+ ${wpBin} serve
275
+ --config ${wpConfig}
276
+ ${flags}
277
+ `;
278
+ logTitle(title);
238
279
  logCommand(cmd);
239
- (0, import_execa.commandSync)(cmd, { stdio: "inherit" });
280
+ runCommandSync(cmd, { stdio: "inherit" });
240
281
  };
241
-
242
- // src/commands/build/index.ts
243
- var import_execa2 = __toModule(require("execa"));
244
- var import_resolve_bin2 = __toModule(require("resolve-bin"));
245
- var prepareBuildFlags = (options) => {
246
- const { 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;
247
291
  let flags = [];
248
- flags = analyze ? [...flags, "--env analyze"] : flags;
292
+ flags = localCore ? [...flags, "--env localCore"] : 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 = __toModule(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 = __toModule(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 http-server ${paths.appDist} --cors`;
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 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 Tamaro core or customer configuration for production").option("--analyze", 'Generate some build stats to "reports" folder').option("--deploy", "Deploy to AWS").option("--latest", 'Deploy with tag "latest"').option("--serve", "Run web-server for previously created build").option("--tag <tag>", "Deploy widget with a specific tag").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 Tamaro core or customer configuration fo
301
635
  await serve();
302
636
  }
303
637
  });
304
- cli.command("deploy").description("Deploy Tamaro core or customer configuration to AWS").option("--latest", 'Deploy with tag "latest"').option("--tag <tag>", "Deploy widget with a specific tag").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 previously created build").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
  })();