@raisenow/tamaro-cli 1.0.8 → 1.0.11

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