@raisenow/tamaro-cli 1.0.21 → 1.0.22

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/.nvmrc CHANGED
@@ -1 +1 @@
1
- 16.15.0
1
+ 16.17.0
package/README.md CHANGED
@@ -38,6 +38,7 @@ Runs the local development server for _Tamaro Core_ or a particular customer con
38
38
  ### Options
39
39
 
40
40
  - `--local-core` – Load _Tamaro Core_ from localhost:1234 instead of the CDN
41
+ - `--https` – Let local web server serve Tamaro with SSL encryption
41
42
  - `--port <port>` – Web server port (default: 1234)
42
43
  - `--env <env>` – Environment (dev, stage, prod)
43
44
 
@@ -66,6 +67,26 @@ npx -y @raisenow/tamaro-cli dev
66
67
  npx -y @raisenow/tamaro-cli dev --local-core
67
68
  ```
68
69
 
70
+ ### Use Transport Level Security (HTTPS)
71
+
72
+ You might want to the local web server to serve Tamaro over HTTPS, for example for testing wallet payments over Google Pay. For that, you have to install [mkcert](https://mkcert.org/), then generate a local certificate and key file and install it into your local trust stores using this command in the root directory of the Tamaro configuration repository (or Tamaro Core):
73
+
74
+ Install `mkcert`:
75
+
76
+ ```bash
77
+ brew install mkcert
78
+ ```
79
+
80
+ Generate certificate:
81
+
82
+ ```bash
83
+ mkcert -install -cert-file localhost.crt -key-file localhost.key localhost 127.0.0.1 0.0.0.0 ::1
84
+ ```
85
+
86
+ You will see that the certificate and key files are created. Keep them for yourself. Do not share them or commit them. (They should be ignored by Git.)
87
+
88
+ You can then use the flag `--https` with the CLI. If you are using the local Tamaro Core, you also have to serve that over HTTPS. Certificate and key files must be copied to Tamaro Core folder as well.
89
+
69
90
  ## `build`
70
91
 
71
92
  Build an optimised (minified) bundle of _Tamaro Core_ or a customer configuration.
@@ -75,6 +96,7 @@ Build an optimised (minified) bundle of _Tamaro Core_ or a customer configuratio
75
96
  - `--local-core` – Load _Tamaro Core_ from localhost:1234 instead of the CDN
76
97
  - `--analyze` – Generate bundle statistics to `reports` folder
77
98
  - `--serve` – Run the generated bundle with a local web server
99
+ - `--https` – Let local web server serve Tamaro with SSL encryption
78
100
  - `--port <port>` – Web server port (default: 1234)
79
101
  - `--env <env>` – Environment (dev, stage, prod)
80
102
  - `--deploy` – Deploy _Tamaro Core_ or a customer configuration bundle to AWS S3
@@ -5,6 +5,17 @@ var getFilename = () => fileURLToPath(import.meta.url);
5
5
  var getDirname = () => path.dirname(getFilename());
6
6
  var __dirname = /* @__PURE__ */ getDirname();
7
7
 
8
+ // src/lib/constants.ts
9
+ var DEFAULT_TAG = "latest";
10
+ var DEFAULT_PORT = 1234;
11
+ var DEFAULT_AWS_PROFILE = "payments-prod-cs-deployer";
12
+ var DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET = "rnw-email-service";
13
+ var AWS_S3_BUCKET = "tamaro.raisenow.com";
14
+ var CORE_CONFIG_NAME = "tamaro-core";
15
+ var AWS_CLOUDFRONT_DISTRIBUTION_ID = "EHJ1OM458YQ0I";
16
+ var HTTPS_CRT_FILE = "localhost.crt";
17
+ var HTTPS_KEY_FILE = "localhost.key";
18
+
8
19
  // src/lib/logging.ts
9
20
  import chalk from "chalk";
10
21
  import stripIndent from "strip-indent";
@@ -62,6 +73,7 @@ var getWidgetUuid = () => basename(resolveApp("."));
62
73
  var getPaths = (ifCore) => {
63
74
  return ifCore(
64
75
  {
76
+ root: resolveApp("."),
65
77
  app: resolveApp("."),
66
78
  appEntry: resolveModule(resolveApp, "src/index"),
67
79
  appDist: resolveApp("dist"),
@@ -72,6 +84,7 @@ var getPaths = (ifCore) => {
72
84
  appTailwindConfig: resolveApp("tailwind.config.js")
73
85
  },
74
86
  {
87
+ root: resolveApp("../.."),
75
88
  app: resolveApp("."),
76
89
  appEntry: resolveModule(resolveApp, "widget"),
77
90
  appDist: resolveApp(`../../dist/${getWidgetUuid()}`),
@@ -144,7 +157,7 @@ var runCommandSync = (cmd, options) => {
144
157
 
145
158
  // src/lib/env.ts
146
159
  var require3 = createRequire2(import.meta.url);
147
- var getEnvVars = (files, ifMin, ifCore, ifLocalCore) => {
160
+ var getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
148
161
  var _a, _b, _c, _d, _e, _f, _g, _h;
149
162
  const filePath = files.find((file) => basename2(file) === ".env");
150
163
  dotenvExpand(dotenvConfig({ path: filePath }));
@@ -168,7 +181,8 @@ var getEnvVars = (files, ifMin, ifCore, ifLocalCore) => {
168
181
  if (!ifCore()) {
169
182
  process.env.WIDGET_UUID = getWidgetUuid();
170
183
  if (ifLocalCore()) {
171
- process.env.CORE_URL = `http://0.0.0.0:1234/index.js`;
184
+ const protocol = ifHttps() ? "https" : "http";
185
+ process.env.CORE_URL = `${protocol}://0.0.0.0:1234/index.js`;
172
186
  } else {
173
187
  let version = process.env.CORE_VERSION;
174
188
  version = version ? `@${version}` : "";
@@ -238,6 +252,15 @@ var assertEnvValid = (env) => {
238
252
  };
239
253
 
240
254
  export {
255
+ DEFAULT_TAG,
256
+ DEFAULT_PORT,
257
+ DEFAULT_AWS_PROFILE,
258
+ DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET,
259
+ AWS_S3_BUCKET,
260
+ CORE_CONFIG_NAME,
261
+ AWS_CLOUDFRONT_DISTRIBUTION_ID,
262
+ HTTPS_CRT_FILE,
263
+ HTTPS_KEY_FILE,
241
264
  logTitle,
242
265
  logError,
243
266
  logCommand,
package/dist/cli.js CHANGED
@@ -1,5 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ AWS_CLOUDFRONT_DISTRIBUTION_ID,
4
+ AWS_S3_BUCKET,
5
+ CORE_CONFIG_NAME,
6
+ DEFAULT_AWS_PROFILE,
7
+ DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET,
8
+ DEFAULT_PORT,
9
+ DEFAULT_TAG,
10
+ HTTPS_CRT_FILE,
11
+ HTTPS_KEY_FILE,
3
12
  assertEnvValid,
4
13
  getIfCoreFns,
5
14
  getPaths,
@@ -12,7 +21,7 @@ import {
12
21
  resolveBin,
13
22
  resolveOwn,
14
23
  runCommandSync
15
- } from "./chunk-MVLEHXBO.js";
24
+ } from "./chunk-2HKMDCAH.js";
16
25
 
17
26
  // src/cli.ts
18
27
  import { createCommand } from "commander";
@@ -20,7 +29,7 @@ import { createCommand } from "commander";
20
29
  // package.json
21
30
  var package_default = {
22
31
  name: "@raisenow/tamaro-cli",
23
- version: "1.0.21",
32
+ version: "1.0.22",
24
33
  author: {
25
34
  name: "RaiseNow",
26
35
  email: "development@raisenow.com"
@@ -40,25 +49,25 @@ var package_default = {
40
49
  npm: ">=8"
41
50
  },
42
51
  dependencies: {
43
- "@babel/cli": "^7.18.9",
44
- "@babel/core": "^7.18.9",
45
- "@babel/plugin-proposal-decorators": "^7.18.9",
52
+ "@babel/cli": "^7.18.10",
53
+ "@babel/core": "^7.19.0",
54
+ "@babel/plugin-proposal-decorators": "^7.19.0",
46
55
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
47
- "@babel/plugin-transform-runtime": "^7.18.9",
48
- "@babel/preset-env": "^7.18.9",
56
+ "@babel/plugin-transform-runtime": "^7.18.10",
57
+ "@babel/preset-env": "^7.19.0",
49
58
  "@babel/preset-react": "^7.18.6",
50
59
  "@babel/preset-typescript": "^7.18.6",
51
- "@babel/runtime-corejs3": "^7.18.9",
60
+ "@babel/runtime-corejs3": "^7.19.0",
52
61
  "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
53
62
  "@statoscope/webpack-plugin": "^5.24.0",
54
63
  "@types/columnify": "^1.5.1",
55
- "@types/lodash": "^4.14.182",
56
- "@types/node": "^18.6.3",
64
+ "@types/lodash": "^4.14.184",
65
+ "@types/node": "^18.7.15",
57
66
  "@types/node-notifier": "^8.0.2",
58
67
  "@types/resolve-bin": "^0.4.1",
59
68
  "@types/webpack-config-utils": "^2.3.1",
60
- "@typescript-eslint/eslint-plugin": "^5.31.0",
61
- "@typescript-eslint/parser": "^5.31.0",
69
+ "@typescript-eslint/eslint-plugin": "^5.36.2",
70
+ "@typescript-eslint/parser": "^5.36.2",
62
71
  autoprefixer: "^10.4.8",
63
72
  "babel-loader": "^8.2.5",
64
73
  "babel-plugin-istanbul": "^6.1.1",
@@ -68,16 +77,16 @@ var package_default = {
68
77
  columnify: "^1.6.0",
69
78
  commander: "^9.4.0",
70
79
  "copy-webpack-plugin": "^11.0.0",
71
- "core-js": "^3.24.1",
80
+ "core-js": "^3.25.0",
72
81
  "css-loader": "^6.7.1",
73
82
  "css-minimizer-webpack-plugin": "^4.0.0",
74
- dotenv: "^16.0.1",
75
- "dotenv-expand": "^8.0.3",
83
+ dotenv: "^16.0.2",
84
+ "dotenv-expand": "^9.0.0",
76
85
  "escape-string-regexp": "^5.0.0",
77
- eslint: "^8.20.0",
86
+ eslint: "^8.23.0",
78
87
  "eslint-config-prettier": "^8.5.0",
79
88
  "eslint-plugin-node": "^11.1.0",
80
- "eslint-plugin-promise": "^6.0.0",
89
+ "eslint-plugin-promise": "^6.0.1",
81
90
  "eslint-webpack-plugin": "^3.2.0",
82
91
  execa: "^6.1.0",
83
92
  "file-loader": "^6.2.0",
@@ -89,41 +98,55 @@ var package_default = {
89
98
  lodash: "^4.17.21",
90
99
  "mini-css-extract-plugin": "^2.6.1",
91
100
  "node-notifier": "^10.0.1",
92
- portfinder: "^1.0.28",
93
- postcss: "^8.4.14",
101
+ portfinder: "^1.0.32",
102
+ postcss: "^8.4.16",
94
103
  "postcss-custom-properties": "^12.1.7",
95
104
  "postcss-loader": "^7.0.1",
96
105
  prettier: "^2.7.1",
97
106
  "react-refresh": "^0.14.0",
98
107
  "resolve-url-loader": "^5.0.0",
99
- sass: "^1.54.0",
108
+ sass: "^1.54.8",
100
109
  "sass-loader": "^13.0.2",
101
110
  "source-map-loader": "^4.0.0",
102
111
  "strip-indent": "^4.0.0",
103
112
  "style-loader": "^3.3.1",
104
113
  "tsconfig-paths-webpack-plugin": "^4.0.0",
105
- tsup: "^6.2.1",
106
- typescript: "^4.7.4",
114
+ tsup: "^6.2.3",
115
+ typescript: "^4.8.2",
107
116
  "url-loader": "^4.1.1",
108
117
  webpack: "^5.74.0",
109
118
  "webpack-cli": "^4.10.0",
110
119
  "webpack-config-utils": "^2.3.1",
111
- "webpack-dev-server": "^4.9.3",
120
+ "webpack-dev-server": "^4.10.1",
112
121
  "yaml-loader": "^0.8.0"
113
122
  }
114
123
  };
115
124
 
116
- // src/lib/constants.ts
117
- var DEFAULT_TAG = "latest";
118
- var DEFAULT_PORT = 1234;
119
- var DEFAULT_AWS_PROFILE = "payments-prod-cs-deployer";
120
- var DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET = "rnw-email-service";
121
- var AWS_S3_BUCKET = "tamaro.raisenow.com";
122
- var CORE_CONFIG_NAME = "tamaro-core";
123
- var AWS_CLOUDFRONT_DISTRIBUTION_ID = "EHJ1OM458YQ0I";
124
-
125
125
  // src/commands/dev.ts
126
126
  import { getPortPromise } from "portfinder";
127
+
128
+ // src/lib/https.ts
129
+ import { existsSync } from "fs";
130
+ import { resolve } from "path";
131
+ import stripIndent from "strip-indent";
132
+ var assertCrtExists = () => {
133
+ const { ifCore } = getIfCoreFns();
134
+ const paths = getPaths(ifCore);
135
+ const certFile = resolve(paths.root, HTTPS_CRT_FILE);
136
+ const keyFile = resolve(paths.root, HTTPS_KEY_FILE);
137
+ if (existsSync(certFile) && existsSync(keyFile)) {
138
+ return;
139
+ }
140
+ halt(
141
+ stripIndent(`
142
+ Flag \u201C--https\u201D is used, but \u201C${HTTPS_CRT_FILE}\u201D and/or \u201C${HTTPS_KEY_FILE}\u201D files are not found.
143
+ You need to generate certificate first.
144
+ Check docs: https://unpkg.com/@raisenow/tamaro-cli/readme.html#/?id=use-transport-level-security-https
145
+ `)
146
+ );
147
+ };
148
+
149
+ // src/commands/dev.ts
127
150
  var dev = async (options) => {
128
151
  assertOptionsValid(options);
129
152
  const flags = (await prepareFlags([], options)).join(" ");
@@ -144,7 +167,7 @@ var dev = async (options) => {
144
167
  runCommandSync(cmd, { stdio: "inherit" });
145
168
  };
146
169
  var assertOptionsValid = (options) => {
147
- const { localCore, port, env } = options;
170
+ const { localCore, https, port, env } = options;
148
171
  const { ifCore } = getIfCoreFns();
149
172
  if (ifCore() && localCore) {
150
173
  halt("Flag \u201C--local-core\u201D is redundant if running in Tamaro Core context.");
@@ -152,21 +175,27 @@ var assertOptionsValid = (options) => {
152
175
  if (isNaN(Number(port))) {
153
176
  halt("Flag \u201C--port\u201D should be a number.");
154
177
  }
178
+ if (https) {
179
+ assertCrtExists();
180
+ }
155
181
  assertEnvValid(env);
156
182
  };
157
183
  var prepareFlags = async (flags, options) => {
158
- const { localCore, port: defaultPort } = options;
184
+ const { localCore, port: defaultPort, https } = options;
159
185
  const port = await getPortPromise({ port: Number(defaultPort) });
160
186
  if (localCore) {
161
187
  flags.push("--env localCore");
162
188
  }
163
189
  flags.push(`--port ${port}`);
190
+ if (https) {
191
+ flags.push("--env https");
192
+ }
164
193
  return flags;
165
194
  };
166
195
 
167
196
  // src/lib/aws.ts
168
197
  import { execaCommandSync } from "execa";
169
- import stripIndent from "strip-indent";
198
+ import stripIndent2 from "strip-indent";
170
199
  var withAwsAuthenticate = (fn, options) => {
171
200
  awsAuthenticate(options);
172
201
  return fn();
@@ -193,16 +222,16 @@ var assertProfileValid = (profile) => {
193
222
  console.log(`Using AWS profile: \u201C${profile}\u201D`);
194
223
  let message;
195
224
  if (profiles.length === 0) {
196
- message = stripIndent(`
225
+ message = stripIndent2(`
197
226
  No AWS profiles found.
198
227
  `);
199
228
  } else {
200
- message = stripIndent(`
229
+ message = stripIndent2(`
201
230
  AWS profile \u201C${profile}\u201D has not been found.
202
231
  Available profiles are: ${profiles.map((v) => `\u201C${v}\u201D`).join(", ")}.
203
232
  `);
204
233
  }
205
- message += stripIndent(`
234
+ message += stripIndent2(`
206
235
  Run \u201Caws configure sso\u201D to set up SSO-enabled profile.
207
236
  Check the wiki for more information:
208
237
  https://raisenow.atlassian.net/wiki/x/lIrWvg
@@ -237,12 +266,12 @@ var prepareFlags2 = (flags, options) => {
237
266
 
238
267
  // src/lib/notifier.ts
239
268
  import notifier from "node-notifier";
240
- import stripIndent2 from "strip-indent";
269
+ import stripIndent3 from "strip-indent";
241
270
  var notify = (args) => {
242
271
  const { title, message = "" } = args;
243
272
  notifier.notify({
244
273
  title,
245
- message: stripIndent2(message).trim(),
274
+ message: stripIndent3(message).trim(),
246
275
  contentImage: "https://assets.raisenow.io/favicon.png",
247
276
  sound: "Funk"
248
277
  });
@@ -282,7 +311,7 @@ Bundle for \u201C${configName}\u201D customer configuration is done.`);
282
311
  });
283
312
  };
284
313
  var assertOptionsValid2 = (options) => {
285
- const { localCore, deploy: deploy2, profile, env } = options;
314
+ const { localCore, https, deploy: deploy2, profile, env } = options;
286
315
  const { ifCore } = getIfCoreFns();
287
316
  if (ifCore() && localCore) {
288
317
  halt("Flag \u201C--local-core\u201D is redundant if running in Tamaro Core context.");
@@ -290,23 +319,29 @@ var assertOptionsValid2 = (options) => {
290
319
  if (localCore && deploy2) {
291
320
  halt("Flags \u201C--local-core\u201D and \u201C--deploy\u201D must not be used together.");
292
321
  }
322
+ if (https) {
323
+ assertCrtExists();
324
+ }
293
325
  assertProfileValid(profile);
294
326
  assertEnvValid(env);
295
327
  };
296
328
  var prepareFlags3 = (flags, options) => {
297
- const { localCore, analyze } = options;
329
+ const { localCore, analyze, https } = options;
298
330
  if (localCore) {
299
331
  flags.push("--env localCore");
300
332
  }
301
333
  if (analyze) {
302
334
  flags.push("--env analyze");
303
335
  }
336
+ if (https) {
337
+ flags.push("--env https");
338
+ }
304
339
  return flags;
305
340
  };
306
341
 
307
342
  // src/commands/deploy.ts
308
- import { existsSync } from "fs";
309
- import stripIndent3 from "strip-indent";
343
+ import { existsSync as existsSync2 } from "fs";
344
+ import stripIndent4 from "strip-indent";
310
345
  var deploy = async (options) => {
311
346
  const { ifCore } = getIfCoreFns();
312
347
  const paths = getPaths(ifCore);
@@ -387,9 +422,9 @@ var assertOptionsValid3 = (options) => {
387
422
  assertProfileValid(profile);
388
423
  };
389
424
  var assertDistPathExists = (distPath) => {
390
- if (!existsSync(distPath)) {
425
+ if (!existsSync2(distPath)) {
391
426
  halt(
392
- stripIndent3(`
427
+ stripIndent4(`
393
428
  Dist folder does not exists.
394
429
  Make sure you have built the bundle before trying to deploy it.
395
430
  `)
@@ -409,6 +444,7 @@ var prepareFlags4 = (flags, options) => {
409
444
  };
410
445
 
411
446
  // src/commands/serve.ts
447
+ import { resolve as resolve2 } from "path";
412
448
  import { getPortPromise as getPortPromise2 } from "portfinder";
413
449
  var serve = async (options) => {
414
450
  assertOptionsValid4(options);
@@ -425,15 +461,26 @@ var serve = async (options) => {
425
461
  runCommandSync(cmd, { stdio: "inherit" });
426
462
  };
427
463
  var assertOptionsValid4 = (options) => {
428
- const { port } = options;
464
+ const { port, https } = options;
429
465
  if (isNaN(Number(port))) {
430
466
  halt('Flag "--port" should be a number.');
431
467
  }
468
+ if (https) {
469
+ assertCrtExists();
470
+ }
432
471
  };
433
472
  var prepareFlags5 = async (flags, options) => {
434
- const { port: defaultPort } = options;
473
+ const { port: defaultPort, https } = options;
435
474
  const port = await getPortPromise2({ port: Number(defaultPort) });
436
475
  flags.push(`-p ${port}`);
476
+ if (https) {
477
+ const { ifCore } = getIfCoreFns();
478
+ const paths = getPaths(ifCore);
479
+ const certFile = resolve2(paths.root, HTTPS_CRT_FILE);
480
+ const keyFile = resolve2(paths.root, HTTPS_KEY_FILE);
481
+ flags.push(`--ssl-cert ${certFile}`);
482
+ flags.push(`--ssl-key ${keyFile}`);
483
+ }
437
484
  return flags;
438
485
  };
439
486
 
@@ -497,7 +544,7 @@ var parseTags = (lines) => {
497
544
  };
498
545
 
499
546
  // src/commands/deploy-email-config.ts
500
- import { existsSync as existsSync2 } from "fs";
547
+ import { existsSync as existsSync3 } from "fs";
501
548
  var deployEmailConfig = async (options) => {
502
549
  const { ifCore } = getIfCoreFns();
503
550
  const paths = getPaths(ifCore);
@@ -541,7 +588,7 @@ var assertOptionsValid6 = (options) => {
541
588
  assertProfileValid(profile);
542
589
  };
543
590
  var assertEmailConfigPathExists = (distPath) => {
544
- if (!existsSync2(distPath)) {
591
+ if (!existsSync3(distPath)) {
545
592
  halt("Email config folder does not exists. Nothing to deploy.", 0);
546
593
  }
547
594
  };
@@ -577,6 +624,10 @@ cli.command("dev").description(
577
624
  "--local-core",
578
625
  "Load Tamaro Core from localhost:1234 instead of the CDN",
579
626
  false
627
+ ).option(
628
+ "--https",
629
+ "Let local web server serve Tamaro with SSL encryption",
630
+ false
580
631
  ).option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option("--env <env>", "Environment (dev, stage, prod)").action(async (options) => {
581
632
  await dev(options);
582
633
  });
@@ -586,7 +637,11 @@ cli.command("build").description(
586
637
  "--local-core",
587
638
  "Load Tamaro Core from localhost:1234 instead of the CDN",
588
639
  false
589
- ).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("--env <env>", "Environment (dev, stage, prod)").option(
640
+ ).option("--analyze", 'Generate bundle statistics to "reports" folder', false).option("--serve", "Run the generated bundle with a local web server", false).option(
641
+ "--https",
642
+ "Let local web server serve Tamaro with SSL encryption",
643
+ false
644
+ ).option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option("--env <env>", "Environment (dev, stage, prod)").option(
590
645
  "--deploy",
591
646
  "Deploy Tamaro Core or a customer configuration bundle to AWS S3",
592
647
  false
@@ -607,7 +662,11 @@ cli.command("build").description(
607
662
  await deploy(options);
608
663
  }
609
664
  });
610
- cli.command("serve").description("Run a local web server for pre-built bundle").option("--port <port>", "Web server port", `${DEFAULT_PORT}`).action(async (options) => {
665
+ cli.command("serve").description("Run a local web server for pre-built bundle").option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option(
666
+ "--https",
667
+ "Let local web server serve Tamaro with SSL encryption",
668
+ false
669
+ ).action(async (options) => {
611
670
  await serve(options);
612
671
  });
613
672
  cli.command("deploy").description(
@@ -1,4 +1,6 @@
1
1
  import {
2
+ HTTPS_CRT_FILE,
3
+ HTTPS_KEY_FILE,
2
4
  extensions,
3
5
  getEnvVars,
4
6
  getIfCoreFns,
@@ -8,11 +10,11 @@ import {
8
10
  logTitle,
9
11
  moduleFileExtensions,
10
12
  resolveApp
11
- } from "./chunk-MVLEHXBO.js";
13
+ } from "./chunk-2HKMDCAH.js";
12
14
 
13
15
  // src/webpack.config.ts
14
16
  import { createRequire } from "module";
15
- import { basename, dirname } from "path";
17
+ import { basename, dirname, resolve } from "path";
16
18
  import { existsSync } from "fs";
17
19
  import glob from "glob";
18
20
  import { getIfUtils, removeEmpty } from "webpack-config-utils";
@@ -65,12 +67,13 @@ var imageInlineSizeLimit = 0;
65
67
  var getWebpackConfig = async (env) => {
66
68
  const { ifMin, ifNotMin } = getIfUtils(env, ["min"]);
67
69
  const { ifAnalyze } = getIfUtils(env, ["analyze"]);
70
+ const { ifHttps } = getIfUtils(env, ["https"]);
68
71
  const { ifLocalCore } = getIfUtils(env, ["localCore"]);
69
72
  const { ifCore } = getIfCoreFns();
70
73
  const paths = getPaths(ifCore);
71
74
  const appHtmlFiles = glob.sync(paths.appHtml);
72
75
  const appEnvFiles = glob.sync(paths.appEnv);
73
- const envVars = getEnvVars(appEnvFiles, ifMin, ifCore, ifLocalCore);
76
+ const envVars = getEnvVars(appEnvFiles, ifMin, ifCore, ifLocalCore, ifHttps);
74
77
  const { ifHmr } = getIfUtils({ hmr: process.env.HMR_ENABLED === "true" }, ["hmr"]);
75
78
  const useTailwind = ifCore() && paths.appTailwindConfig && existsSync(paths.appTailwindConfig);
76
79
  logTitle("Paths:");
@@ -288,7 +291,14 @@ var getWebpackConfig = async (env) => {
288
291
  warnings: false,
289
292
  errors: true
290
293
  }
291
- }
294
+ },
295
+ server: ifHttps({
296
+ type: "https",
297
+ options: {
298
+ cert: resolve(paths.root, HTTPS_CRT_FILE),
299
+ key: resolve(paths.root, HTTPS_KEY_FILE)
300
+ }
301
+ })
292
302
  },
293
303
  optimization: {
294
304
  removeEmptyChunks: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raisenow/tamaro-cli",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "author": {
5
5
  "name": "RaiseNow",
6
6
  "email": "development@raisenow.com"
@@ -20,25 +20,25 @@
20
20
  "npm": ">=8"
21
21
  },
22
22
  "dependencies": {
23
- "@babel/cli": "^7.18.9",
24
- "@babel/core": "^7.18.9",
25
- "@babel/plugin-proposal-decorators": "^7.18.9",
23
+ "@babel/cli": "^7.18.10",
24
+ "@babel/core": "^7.19.0",
25
+ "@babel/plugin-proposal-decorators": "^7.19.0",
26
26
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
27
- "@babel/plugin-transform-runtime": "^7.18.9",
28
- "@babel/preset-env": "^7.18.9",
27
+ "@babel/plugin-transform-runtime": "^7.18.10",
28
+ "@babel/preset-env": "^7.19.0",
29
29
  "@babel/preset-react": "^7.18.6",
30
30
  "@babel/preset-typescript": "^7.18.6",
31
- "@babel/runtime-corejs3": "^7.18.9",
31
+ "@babel/runtime-corejs3": "^7.19.0",
32
32
  "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
33
33
  "@statoscope/webpack-plugin": "^5.24.0",
34
34
  "@types/columnify": "^1.5.1",
35
- "@types/lodash": "^4.14.182",
36
- "@types/node": "^18.6.3",
35
+ "@types/lodash": "^4.14.184",
36
+ "@types/node": "^18.7.15",
37
37
  "@types/node-notifier": "^8.0.2",
38
38
  "@types/resolve-bin": "^0.4.1",
39
39
  "@types/webpack-config-utils": "^2.3.1",
40
- "@typescript-eslint/eslint-plugin": "^5.31.0",
41
- "@typescript-eslint/parser": "^5.31.0",
40
+ "@typescript-eslint/eslint-plugin": "^5.36.2",
41
+ "@typescript-eslint/parser": "^5.36.2",
42
42
  "autoprefixer": "^10.4.8",
43
43
  "babel-loader": "^8.2.5",
44
44
  "babel-plugin-istanbul": "^6.1.1",
@@ -48,16 +48,16 @@
48
48
  "columnify": "^1.6.0",
49
49
  "commander": "^9.4.0",
50
50
  "copy-webpack-plugin": "^11.0.0",
51
- "core-js": "^3.24.1",
51
+ "core-js": "^3.25.0",
52
52
  "css-loader": "^6.7.1",
53
53
  "css-minimizer-webpack-plugin": "^4.0.0",
54
- "dotenv": "^16.0.1",
55
- "dotenv-expand": "^8.0.3",
54
+ "dotenv": "^16.0.2",
55
+ "dotenv-expand": "^9.0.0",
56
56
  "escape-string-regexp": "^5.0.0",
57
- "eslint": "^8.20.0",
57
+ "eslint": "^8.23.0",
58
58
  "eslint-config-prettier": "^8.5.0",
59
59
  "eslint-plugin-node": "^11.1.0",
60
- "eslint-plugin-promise": "^6.0.0",
60
+ "eslint-plugin-promise": "^6.0.1",
61
61
  "eslint-webpack-plugin": "^3.2.0",
62
62
  "execa": "^6.1.0",
63
63
  "file-loader": "^6.2.0",
@@ -69,26 +69,26 @@
69
69
  "lodash": "^4.17.21",
70
70
  "mini-css-extract-plugin": "^2.6.1",
71
71
  "node-notifier": "^10.0.1",
72
- "portfinder": "^1.0.28",
73
- "postcss": "^8.4.14",
72
+ "portfinder": "^1.0.32",
73
+ "postcss": "^8.4.16",
74
74
  "postcss-custom-properties": "^12.1.7",
75
75
  "postcss-loader": "^7.0.1",
76
76
  "prettier": "^2.7.1",
77
77
  "react-refresh": "^0.14.0",
78
78
  "resolve-url-loader": "^5.0.0",
79
- "sass": "^1.54.0",
79
+ "sass": "^1.54.8",
80
80
  "sass-loader": "^13.0.2",
81
81
  "source-map-loader": "^4.0.0",
82
82
  "strip-indent": "^4.0.0",
83
83
  "style-loader": "^3.3.1",
84
84
  "tsconfig-paths-webpack-plugin": "^4.0.0",
85
- "tsup": "^6.2.1",
86
- "typescript": "^4.7.4",
85
+ "tsup": "^6.2.3",
86
+ "typescript": "^4.8.2",
87
87
  "url-loader": "^4.1.1",
88
88
  "webpack": "^5.74.0",
89
89
  "webpack-cli": "^4.10.0",
90
90
  "webpack-config-utils": "^2.3.1",
91
- "webpack-dev-server": "^4.9.3",
91
+ "webpack-dev-server": "^4.10.1",
92
92
  "yaml-loader": "^0.8.0"
93
93
  }
94
94
  }
package/src/cli.ts CHANGED
@@ -49,6 +49,11 @@ cli
49
49
  'Load Tamaro Core from localhost:1234 instead of the CDN',
50
50
  false,
51
51
  )
52
+ .option(
53
+ '--https',
54
+ 'Let local web server serve Tamaro with SSL encryption',
55
+ false,
56
+ )
52
57
  .option('--port <port>', 'Web server port', `${DEFAULT_PORT}`)
53
58
  .option('--env <env>', 'Environment (dev, stage, prod)')
54
59
  .action(async (options: DevOptions) => {
@@ -67,6 +72,11 @@ cli
67
72
  )
68
73
  .option('--analyze', 'Generate bundle statistics to "reports" folder', false)
69
74
  .option('--serve', 'Run the generated bundle with a local web server', false)
75
+ .option(
76
+ '--https',
77
+ 'Let local web server serve Tamaro with SSL encryption',
78
+ false,
79
+ )
70
80
  .option('--port <port>', 'Web server port', `${DEFAULT_PORT}`)
71
81
  .option('--env <env>', 'Environment (dev, stage, prod)')
72
82
  .option(
@@ -100,6 +110,11 @@ cli
100
110
  .command('serve')
101
111
  .description('Run a local web server for pre-built bundle')
102
112
  .option('--port <port>', 'Web server port', `${DEFAULT_PORT}`)
113
+ .option(
114
+ '--https',
115
+ 'Let local web server serve Tamaro with SSL encryption',
116
+ false,
117
+ )
103
118
  .action(async (options: ServeOptions) => {
104
119
  await serve(options)
105
120
  })
@@ -8,6 +8,7 @@ import {
8
8
  resolveOwn,
9
9
  } from 'lib/resolve'
10
10
  import {assertEnvValid} from 'lib/env'
11
+ import {assertCrtExists} from 'lib/https'
11
12
  import {logCommand, logTitle} from 'lib/logging'
12
13
  import {notify} from 'lib/notifier'
13
14
  import {halt, runCommandSync} from 'lib/command'
@@ -18,6 +19,7 @@ import {DeployOptions} from 'commands/deploy'
18
19
  export type BuildOptions = {
19
20
  localCore: boolean
20
21
  analyze: boolean
22
+ https: boolean
21
23
  serve: boolean
22
24
  deploy: boolean
23
25
  env: string
@@ -70,7 +72,7 @@ export const build = async (
70
72
  ///////////////////////////////////////////////////////////////////////////////
71
73
 
72
74
  const assertOptionsValid = (options: BuildOptions & DeployOptions) => {
73
- const {localCore, deploy, profile, env} = options
75
+ const {localCore, https, deploy, profile, env} = options
74
76
  const {ifCore} = getIfCoreFns()
75
77
 
76
78
  if (ifCore() && localCore) {
@@ -81,6 +83,10 @@ const assertOptionsValid = (options: BuildOptions & DeployOptions) => {
81
83
  halt('Flags “--local-core” and “--deploy” must not be used together.')
82
84
  }
83
85
 
86
+ if (https) {
87
+ assertCrtExists()
88
+ }
89
+
84
90
  assertProfileValid(profile)
85
91
  assertEnvValid(env)
86
92
  }
@@ -88,7 +94,7 @@ const assertOptionsValid = (options: BuildOptions & DeployOptions) => {
88
94
  ///////////////////////////////////////////////////////////////////////////////
89
95
 
90
96
  const prepareFlags = (flags: string[], options: BuildOptions): string[] => {
91
- const {localCore, analyze} = options
97
+ const {localCore, analyze, https} = options
92
98
 
93
99
  if (localCore) {
94
100
  flags.push('--env localCore')
@@ -98,5 +104,9 @@ const prepareFlags = (flags: string[], options: BuildOptions): string[] => {
98
104
  flags.push('--env analyze')
99
105
  }
100
106
 
107
+ if (https) {
108
+ flags.push('--env https')
109
+ }
110
+
101
111
  return flags
102
112
  }
@@ -3,11 +3,13 @@ import {getIfCoreFns, resolveBin, resolveOwn} from 'lib/resolve'
3
3
  import {logCommand, logTitle} from 'lib/logging'
4
4
  import {halt, runCommandSync} from 'lib/command'
5
5
  import {assertEnvValid} from 'lib/env'
6
+ import {assertCrtExists} from 'lib/https'
6
7
 
7
8
  ///////////////////////////////////////////////////////////////////////////////
8
9
 
9
10
  export type DevOptions = {
10
11
  localCore: boolean
12
+ https: boolean
11
13
  port: string
12
14
  env: string
13
15
  }
@@ -39,7 +41,7 @@ export const dev = async (options: DevOptions): Promise<void> => {
39
41
  ///////////////////////////////////////////////////////////////////////////////
40
42
 
41
43
  const assertOptionsValid = (options: DevOptions) => {
42
- const {localCore, port, env} = options
44
+ const {localCore, https, port, env} = options
43
45
  const {ifCore} = getIfCoreFns()
44
46
 
45
47
  if (ifCore() && localCore) {
@@ -50,6 +52,10 @@ const assertOptionsValid = (options: DevOptions) => {
50
52
  halt('Flag “--port” should be a number.')
51
53
  }
52
54
 
55
+ if (https) {
56
+ assertCrtExists()
57
+ }
58
+
53
59
  assertEnvValid(env)
54
60
  }
55
61
 
@@ -59,7 +65,7 @@ const prepareFlags = async (
59
65
  flags: string[],
60
66
  options: DevOptions,
61
67
  ): Promise<string[]> => {
62
- const {localCore, port: defaultPort} = options
68
+ const {localCore, port: defaultPort, https} = options
63
69
  const port = await getPortPromise({port: Number(defaultPort)})
64
70
 
65
71
  if (localCore) {
@@ -68,5 +74,9 @@ const prepareFlags = async (
68
74
 
69
75
  flags.push(`--port ${port}`)
70
76
 
77
+ if (https) {
78
+ flags.push('--env https')
79
+ }
80
+
71
81
  return flags
72
82
  }
@@ -1,12 +1,16 @@
1
+ import {resolve} from 'path'
1
2
  import {getPortPromise} from 'portfinder'
2
3
  import {getIfCoreFns, getPaths} from 'lib/resolve'
3
4
  import {logCommand, logTitle} from 'lib/logging'
4
5
  import {halt, runCommandSync} from 'lib/command'
6
+ import {assertCrtExists} from 'lib/https'
7
+ import {HTTPS_CRT_FILE, HTTPS_KEY_FILE} from 'lib/constants'
5
8
 
6
9
  ///////////////////////////////////////////////////////////////////////////////
7
10
 
8
11
  export type ServeOptions = {
9
12
  port: string
13
+ https: boolean
10
14
  }
11
15
 
12
16
  ///////////////////////////////////////////////////////////////////////////////
@@ -31,11 +35,15 @@ export const serve = async (options: ServeOptions): Promise<void> => {
31
35
  ///////////////////////////////////////////////////////////////////////////////
32
36
 
33
37
  const assertOptionsValid = (options: ServeOptions) => {
34
- const {port} = options
38
+ const {port, https} = options
35
39
 
36
40
  if (isNaN(Number(port))) {
37
41
  halt('Flag "--port" should be a number.')
38
42
  }
43
+
44
+ if (https) {
45
+ assertCrtExists()
46
+ }
39
47
  }
40
48
 
41
49
  ///////////////////////////////////////////////////////////////////////////////
@@ -44,10 +52,20 @@ const prepareFlags = async (
44
52
  flags: string[],
45
53
  options: ServeOptions,
46
54
  ): Promise<string[]> => {
47
- const {port: defaultPort} = options
55
+ const {port: defaultPort, https} = options
48
56
  const port = await getPortPromise({port: Number(defaultPort)})
49
57
 
50
58
  flags.push(`-p ${port}`)
51
59
 
60
+ if (https) {
61
+ const {ifCore} = getIfCoreFns()
62
+ const paths = getPaths(ifCore)
63
+ const certFile = resolve(paths.root, HTTPS_CRT_FILE)
64
+ const keyFile = resolve(paths.root, HTTPS_KEY_FILE)
65
+
66
+ flags.push(`--ssl-cert ${certFile}`)
67
+ flags.push(`--ssl-key ${keyFile}`)
68
+ }
69
+
52
70
  return flags
53
71
  }
@@ -5,3 +5,5 @@ export const DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET = 'rnw-email-service'
5
5
  export const AWS_S3_BUCKET = 'tamaro.raisenow.com'
6
6
  export const CORE_CONFIG_NAME = 'tamaro-core'
7
7
  export const AWS_CLOUDFRONT_DISTRIBUTION_ID = 'EHJ1OM458YQ0I'
8
+ export const HTTPS_CRT_FILE = 'localhost.crt'
9
+ export const HTTPS_KEY_FILE = 'localhost.key'
package/src/lib/env.ts CHANGED
@@ -25,6 +25,7 @@ export const getEnvVars = (
25
25
  ifMin: IfUtilsFn,
26
26
  ifCore: IfUtilsFn,
27
27
  ifLocalCore: IfUtilsFn,
28
+ ifHttps: IfUtilsFn,
28
29
  ) => {
29
30
  const filePath = files.find((file) => basename(file) === '.env')
30
31
 
@@ -59,7 +60,8 @@ export const getEnvVars = (
59
60
  process.env.WIDGET_UUID = getWidgetUuid()
60
61
 
61
62
  if (ifLocalCore()) {
62
- process.env.CORE_URL = `http://0.0.0.0:1234/index.js`
63
+ const protocol = ifHttps() ? 'https' : 'http'
64
+ process.env.CORE_URL = `${protocol}://0.0.0.0:1234/index.js`
63
65
  } else {
64
66
  let version = process.env.CORE_VERSION
65
67
  version = version ? `@${version}` : ''
@@ -0,0 +1,27 @@
1
+ import {existsSync} from 'fs'
2
+ import {resolve} from 'path'
3
+ import stripIndent from 'strip-indent'
4
+ import {halt} from 'lib/command'
5
+ import {getIfCoreFns, getPaths} from 'lib/resolve'
6
+ import {HTTPS_CRT_FILE, HTTPS_KEY_FILE} from 'lib/constants'
7
+
8
+ ///////////////////////////////////////////////////////////////////////////////
9
+
10
+ export const assertCrtExists = () => {
11
+ const {ifCore} = getIfCoreFns()
12
+ const paths = getPaths(ifCore)
13
+ const certFile = resolve(paths.root, HTTPS_CRT_FILE)
14
+ const keyFile = resolve(paths.root, HTTPS_KEY_FILE)
15
+
16
+ if (existsSync(certFile) && existsSync(keyFile)) {
17
+ return
18
+ }
19
+
20
+ halt(
21
+ stripIndent(`
22
+ Flag “--https” is used, but “${HTTPS_CRT_FILE}” and/or “${HTTPS_KEY_FILE}” files are not found.
23
+ You need to generate certificate first.
24
+ Check docs: https://unpkg.com/@raisenow/tamaro-cli/readme.html#/?id=use-transport-level-security-https
25
+ `),
26
+ )
27
+ }
@@ -67,6 +67,7 @@ export const getWidgetUuid = () => basename(resolveApp('.'))
67
67
  export const getPaths = (ifCore: IfUtilsFn) => {
68
68
  return ifCore(
69
69
  {
70
+ root: resolveApp('.'),
70
71
  app: resolveApp('.'),
71
72
  appEntry: resolveModule(resolveApp, 'src/index'),
72
73
  appDist: resolveApp('dist'),
@@ -77,6 +78,7 @@ export const getPaths = (ifCore: IfUtilsFn) => {
77
78
  appTailwindConfig: resolveApp('tailwind.config.js'),
78
79
  },
79
80
  {
81
+ root: resolveApp('../..'),
80
82
  app: resolveApp('.'),
81
83
  appEntry: resolveModule(resolveApp, 'widget'),
82
84
  appDist: resolveApp(`../../dist/${getWidgetUuid()}`),
@@ -1,5 +1,5 @@
1
1
  import {createRequire} from 'module'
2
- import {basename, dirname} from 'path'
2
+ import {basename, dirname, resolve} from 'path'
3
3
  import {existsSync} from 'fs'
4
4
  import glob from 'glob'
5
5
  import {getIfUtils, removeEmpty} from 'webpack-config-utils'
@@ -28,6 +28,7 @@ import {
28
28
  } from 'lib/resolve'
29
29
  import {getEnvVars} from 'lib/env'
30
30
  import {logDataTable, logTitle} from 'lib/logging'
31
+ import {HTTPS_CRT_FILE, HTTPS_KEY_FILE} from 'lib/constants'
31
32
 
32
33
  ///////////////////////////////////////////////////////////////////////////////
33
34
 
@@ -40,12 +41,13 @@ const imageInlineSizeLimit = 0
40
41
  const getWebpackConfig = async (env: any): Promise<Configuration> => {
41
42
  const {ifMin, ifNotMin} = getIfUtils(env, ['min'])
42
43
  const {ifAnalyze} = getIfUtils(env, ['analyze'])
44
+ const {ifHttps} = getIfUtils(env, ['https'])
43
45
  const {ifLocalCore} = getIfUtils(env, ['localCore'])
44
46
  const {ifCore} = getIfCoreFns()
45
47
  const paths = getPaths(ifCore)
46
48
  const appHtmlFiles = glob.sync(paths.appHtml)
47
49
  const appEnvFiles = glob.sync(paths.appEnv)
48
- const envVars = getEnvVars(appEnvFiles, ifMin, ifCore, ifLocalCore)
50
+ const envVars = getEnvVars(appEnvFiles, ifMin, ifCore, ifLocalCore, ifHttps)
49
51
  const {ifHmr} = getIfUtils({hmr: process.env.HMR_ENABLED === 'true'}, ['hmr'])
50
52
  const useTailwind =
51
53
  ifCore() && paths.appTailwindConfig && existsSync(paths.appTailwindConfig)
@@ -294,6 +296,13 @@ const getWebpackConfig = async (env: any): Promise<Configuration> => {
294
296
  errors: true,
295
297
  },
296
298
  },
299
+ server: ifHttps({
300
+ type: 'https',
301
+ options: {
302
+ cert: resolve(paths.root, HTTPS_CRT_FILE),
303
+ key: resolve(paths.root, HTTPS_KEY_FILE),
304
+ },
305
+ }),
297
306
  },
298
307
 
299
308
  optimization: {