@raisenow/tamaro-cli 1.9.0-dev.3 → 3.0.0-dev.1

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,24 +1,92 @@
1
1
  #!/usr/bin/env node
2
- import { A as EPMS_OAUTH_CLIENT_ID, B as logInfo, C as DEFAULT_HTTP_TIMEOUT, D as EPMS_API_BASE_URL_STAGE, E as EPMS_API_BASE_URL_PROD, F as runCommandSync, H as logTitle, I as createTerminalLink, L as logCommand, M as HTTPS_KEY_FILE, N as halt, O as EPMS_AUTH_BASE_URL_PROD, P as promptConfirmation, R as logDataTable, S as CORE_CONFIG_NAME, T as DEFAULT_TAG, V as logSuccess, _ as AWS_CLOUDFRONT_DISTRIBUTION_ID, a as getIfCoreFns, b as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE, c as getWidgetUuid, d as resolveBin, f as resolveCoreVersion, g as AUTH_PORT, h as resolveOwn, j as HTTPS_CRT_FILE, k as EPMS_AUTH_BASE_URL_STAGE, l as resolveAccountUuidFromConfig, m as resolveManagedByFromConfig, n as assertEnvValid, o as getPaths, t as applyEnv, v as AWS_S3_BUCKET_TAMARO, w as DEFAULT_PORT, x as CACHE_DIR, y as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD, z as logError } from "./env-DZ3cWM6p.js";
2
+ import { createRequire } from "node:module";
3
3
  import { createCommand } from "commander";
4
- import fs, { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
4
+ import fs from "node:fs";
5
5
  import path from "node:path";
6
- import stripIndent from "strip-indent";
6
+ import dedent from "dedent";
7
7
  import { S3 } from "@aws-sdk/client-s3";
8
8
  import { execaCommandSync } from "execa";
9
9
  import prompts from "prompts";
10
+ import chalk from "chalk";
10
11
  import columnify from "columnify";
12
+ import envPaths from "env-paths";
11
13
  import * as yaml from "js-yaml";
12
14
  import { z } from "zod";
13
15
  import ky from "ky";
14
16
  import { createServer } from "node:http";
15
17
  import open from "open";
16
18
  import notifier from "node-notifier";
19
+ import console$1 from "node:console";
17
20
  import { globSync } from "glob";
18
21
  import Handlebars from "handlebars";
19
22
  import helpers from "handlebars-helpers";
20
23
  import { config } from "dotenv";
21
24
  import { getPortPromise } from "portfinder";
25
+ //#region src/lib/logging.ts
26
+ const logTitle = (title) => {
27
+ console.log(chalk.bold(title));
28
+ };
29
+ const logError = (message) => {
30
+ if (message) console.log(chalk.red(message));
31
+ };
32
+ const logSuccess = (message) => {
33
+ if (message) console.log(chalk.green(message));
34
+ };
35
+ const logInfo = (message) => {
36
+ if (message) console.log(chalk.blue(message));
37
+ };
38
+ const logCommand = (cmd) => {
39
+ console.log(`\n${chalk.dim(dedent(cmd))}\n`);
40
+ };
41
+ const logDataTable = (data) => {
42
+ console.log(columnify(data, { showHeaders: false }));
43
+ console.log("");
44
+ };
45
+ const createTerminalLink = (text, url) => {
46
+ return `\u001B]8;;${url}\u001B\\${text}\u001B]8;;\u001B\\`;
47
+ };
48
+ //#endregion
49
+ //#region src/lib/command.ts
50
+ const halt = (message) => {
51
+ logError(message);
52
+ process.exit(1);
53
+ };
54
+ const prepareCommand = (cmd) => {
55
+ return cmd.replaceAll("\n", " ").replaceAll(/[ \t]{2,}/g, " ").trim();
56
+ };
57
+ const runCommandSync = (cmd, options) => {
58
+ return execaCommandSync(prepareCommand(cmd), options);
59
+ };
60
+ const promptConfirmation = async (message, skipConfirmation) => {
61
+ if (skipConfirmation) return;
62
+ const { confirmed } = await prompts([{
63
+ initial: false,
64
+ message,
65
+ name: "confirmed",
66
+ type: "confirm"
67
+ }], { onCancel: () => halt() });
68
+ if (!confirmed) halt("Operation cancelled.");
69
+ };
70
+ //#endregion
71
+ //#region src/lib/constants.ts
72
+ const DEFAULT_TAG = "latest";
73
+ const DEFAULT_PORT = 1234;
74
+ const DEFAULT_HTTP_TIMEOUT = 1e4;
75
+ const AWS_S3_BUCKET_TAMARO = "tamaro.raisenow.com";
76
+ const AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE = "rnw-stage-email-service";
77
+ const AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD = "rnw-email-service";
78
+ const EPMS_API_BASE_URL_STAGE = "https://api.stage.mesos.raisenow.net";
79
+ const EPMS_API_BASE_URL_PROD = "https://api.raisenow.io";
80
+ const EPMS_AUTH_BASE_URL_STAGE = "https://login.stage.mesos.raisenow.net";
81
+ const EPMS_AUTH_BASE_URL_PROD = "https://login.raisenow.com";
82
+ const EPMS_OAUTH_CLIENT_ID = "tamaro-cli";
83
+ const AUTH_PORT = 4571;
84
+ const AWS_CLOUDFRONT_DISTRIBUTION_ID = "EHJ1OM458YQ0I";
85
+ const HTTPS_CRT_FILE = "localhost.crt";
86
+ const HTTPS_KEY_FILE = "localhost.key";
87
+ const CACHE_DIR = envPaths("tamaro-cli", { suffix: "" }).cache;
88
+ const TAMARO_VERSION_IN_URL_REGEX = /tamaro-core\/(.*)\/index.js/;
89
+ //#endregion
22
90
  //#region src/lib/aws.ts
23
91
  const awsAuthenticate = (options) => {
24
92
  if (options.ci)
@@ -35,12 +103,12 @@ const awsAuthenticate = (options) => {
35
103
  }
36
104
  };
37
105
  const assertProfilesPresent = () => {
38
- if (getAvailableProfiles().length === 0) halt(stripIndent(`
106
+ if (getAvailableProfiles().length === 0) halt(dedent`
39
107
  No AWS profiles found.
40
108
  Run "aws configure sso" to set up SSO-enabled profile.
41
109
  Check the wiki for more information:
42
110
  https://raisenow.atlassian.net/wiki/x/lIrWvg
43
- `));
111
+ `);
44
112
  };
45
113
  const getAvailableProfiles = () => {
46
114
  const { stdout } = execaCommandSync("aws configure list-profiles");
@@ -51,14 +119,14 @@ const getAvailableProfiles = () => {
51
119
  * Fails in case of expired SSO session.
52
120
  */
53
121
  const checkIdentity = (options) => {
54
- execaCommandSync(`aws sts get-caller-identity ${prepareFlags$3(options)}`);
122
+ execaCommandSync(`aws sts get-caller-identity ${prepareFlags(options)}`);
55
123
  };
56
124
  /**
57
125
  * Opens SSO authentication page in the browser.
58
126
  * Fails if user canceled authentication process.
59
127
  */
60
128
  const login = (options) => {
61
- const flags = prepareFlags$3(options);
129
+ const flags = prepareFlags(options);
62
130
  try {
63
131
  execaCommandSync(`aws sso login ${flags}`, { stdio: "inherit" });
64
132
  console.log("");
@@ -66,7 +134,7 @@ const login = (options) => {
66
134
  halt("Login failed.");
67
135
  }
68
136
  };
69
- const prepareFlags$3 = (options) => {
137
+ const prepareFlags = (options) => {
70
138
  const flags = [];
71
139
  const { profile } = options;
72
140
  if (profile) flags.push(`--profile ${profile}`);
@@ -74,10 +142,10 @@ const prepareFlags$3 = (options) => {
74
142
  };
75
143
  const assertProfileValid = (profile) => {
76
144
  const profiles = getAvailableProfiles();
77
- if (!profiles.includes(profile)) halt(stripIndent(`
145
+ if (!profiles.includes(profile)) halt(dedent`
78
146
  AWS profile "${profile}" is not found.
79
147
  Available profiles are: ${profiles.map((v) => `"${v}"`).join(", ")}.
80
- `));
148
+ `);
81
149
  };
82
150
  const promptProfile = async () => {
83
151
  const { profile } = await prompts([{
@@ -114,6 +182,38 @@ const getConfigDeployments = async (configName) => {
114
182
  return deployments;
115
183
  };
116
184
  //#endregion
185
+ //#region src/lib/resolve.ts
186
+ const resolveAccountUuidFromConfig = (rawConfig, field) => {
187
+ const epmsConfig = z.object({ [field]: z.record(z.string(), z.unknown()) }).safeParse(rawConfig);
188
+ if (!epmsConfig.success) return;
189
+ const configContent = epmsConfig.data[field];
190
+ const accountUuid = configContent.account_mapping ?? configContent.account_uuid;
191
+ const accountUuidValidation = z.uuid().safeParse(accountUuid);
192
+ if (!accountUuidValidation.success) halt(dedent`
193
+ Could not extract EPMS account UUID from config.yml. Please ensure that the "${field}" field is correctly formatted. Expected formats:
194
+ 1. ${field}:
195
+ account_uuid: <UUID>
196
+
197
+ Alternatively, if the account_uuid is conditional using "if" / "then" / "else" statements, it must be provided using the "account_mapping" format:
198
+ 2. ${field}:
199
+ account_mapping: <UUID>
200
+ `);
201
+ return accountUuidValidation.data;
202
+ };
203
+ const resolveManagedByFromConfig = (rawConfig) => {
204
+ const managedByConfig = z.object({ managed_by: z.string().trim().min(1).max(255).optional() }).safeParse(rawConfig);
205
+ if (!managedByConfig.success) halt("Could not extract \"managed_by\" from config.yml. Please ensure it is a non-empty string.");
206
+ return managedByConfig.data?.managed_by ?? "RaiseNow";
207
+ };
208
+ const extractTamaroVersionFromUrl = (url) => {
209
+ const match = url.match(TAMARO_VERSION_IN_URL_REGEX);
210
+ if (match) return match[1].toString();
211
+ };
212
+ const resolveCoreVersion = () => {
213
+ if (process.env.CORE_VERSION) return process.env.CORE_VERSION;
214
+ if (process.env.CORE_URL) return extractTamaroVersionFromUrl(process.env.CORE_URL);
215
+ };
216
+ //#endregion
117
217
  //#region src/lib/epms/auth/util.ts
118
218
  const CachedTokenSchema = z.object({
119
219
  expirationTime: z.number(),
@@ -134,8 +234,8 @@ const getTokenCacheKey = (baseUrl, clientId) => {
134
234
  const readCachedToken = (key) => {
135
235
  try {
136
236
  const filePath = getCacheFilePath(key);
137
- if (!existsSync(filePath)) return;
138
- const data = JSON.parse(readFileSync(filePath, "utf8"));
237
+ if (!fs.existsSync(filePath)) return;
238
+ const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
139
239
  const parsed = CachedTokenSchema.safeParse(data);
140
240
  if (parsed.success) return parsed.data;
141
241
  } catch {}
@@ -143,14 +243,14 @@ const readCachedToken = (key) => {
143
243
  const writeCachedToken = (key, cached) => {
144
244
  try {
145
245
  const filePath = getCacheFilePath(key);
146
- mkdirSync(path.dirname(filePath), { recursive: true });
147
- writeFileSync(filePath, JSON.stringify(cached), { mode: 384 });
246
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
247
+ fs.writeFileSync(filePath, JSON.stringify(cached), { mode: 384 });
148
248
  } catch {}
149
249
  };
150
250
  const removeCachedToken = (key) => {
151
251
  try {
152
252
  const filePath = getCacheFilePath(key);
153
- if (existsSync(filePath)) writeFileSync(filePath, "", { flag: "w" });
253
+ if (fs.existsSync(filePath)) fs.writeFileSync(filePath, "", { flag: "w" });
154
254
  } catch {}
155
255
  };
156
256
  //#endregion
@@ -386,12 +486,12 @@ const epmsAuthenticate = (env) => {
386
486
  if (clientId && clientSecret) return EpmsClient.fromClientCredentials(baseUrl, clientId, clientSecret);
387
487
  return EpmsClient.fromBrowserAuth(baseUrl, authBaseUrl, EPMS_OAUTH_CLIENT_ID);
388
488
  };
389
- const loadTamaroMetadataFromConfig = (paths) => {
390
- if (!("configYml" in paths)) {
391
- halt("Fatal error, this should never happen");
489
+ const loadTamaroMetadataFromConfig = (configYmlPath) => {
490
+ if (!fs.existsSync(configYmlPath)) {
491
+ halt("config.yml not found.");
392
492
  throw new Error("Fatal error");
393
493
  }
394
- const configContent = yaml.load(readFileSync(paths.configYml, "utf8"));
494
+ const configContent = yaml.load(fs.readFileSync(configYmlPath, "utf8"));
395
495
  const accountUuidStage = resolveAccountUuidFromConfig(configContent, "epms_stage");
396
496
  return {
397
497
  accountUuidProd: resolveAccountUuidFromConfig(configContent, "epms"),
@@ -421,7 +521,7 @@ const notify = (args) => {
421
521
  const { message = "", title } = args;
422
522
  notifier.notify({
423
523
  contentImage: "https://assets.raisenow.io/favicon.png",
424
- message: stripIndent(message).trim(),
524
+ message: dedent(message),
425
525
  sound: "Funk",
426
526
  title
427
527
  });
@@ -429,21 +529,19 @@ const notify = (args) => {
429
529
  //#endregion
430
530
  //#region src/commands/archive.ts
431
531
  const archive = async (options) => {
432
- const { ifCore } = getIfCoreFns();
433
- assertIsNotCore$4(ifCore);
434
532
  assertIsNotArchived();
435
- const configName = getWidgetUuid();
533
+ const configName = path.basename(process.cwd());
436
534
  const cwd = process.cwd();
437
535
  const parentDir = path.dirname(cwd);
438
536
  const archiveDir = path.resolve(parentDir, "_archived");
439
537
  const archiveTarget = path.resolve(archiveDir, configName);
440
538
  assertArchiveTargetDoesNotExist(archiveTarget);
441
- assertOptionsValid$9(options);
539
+ assertOptionsValid$7(options);
442
540
  if (options.dryrun) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
443
- if (!ifCore() && !options.forceSkipEpmsSync) await archiveEpms(configName, !!options.dryrun);
541
+ if (!options.forceSkipEpmsSync) await archiveEpms(configName, !!options.dryrun);
444
542
  if (!options.dryrun) {
445
- if (!existsSync(archiveDir)) mkdirSync(archiveDir, { recursive: true });
446
- renameSync(cwd, archiveTarget);
543
+ if (!fs.existsSync(archiveDir)) fs.mkdirSync(archiveDir, { recursive: true });
544
+ fs.renameSync(cwd, archiveTarget);
447
545
  } else logTitle(`Would move ${cwd} → ${archiveTarget}`);
448
546
  logSuccess(`\n✅ "${configName}" has been archived and moved to ${archiveTarget}`);
449
547
  process.on("exit", () => {
@@ -454,9 +552,8 @@ const archive = async (options) => {
454
552
  });
455
553
  };
456
554
  const archiveEpms = async (configName, dryrun) => {
457
- const { ifCore } = getIfCoreFns();
458
- const { accountUuidProd, accountUuidStage } = loadTamaroMetadataFromConfig(getPaths(ifCore));
459
- if (!accountUuidProd && !accountUuidStage) halt(stripIndent(`
555
+ const { accountUuidProd, accountUuidStage } = loadTamaroMetadataFromConfig(path.resolve(process.cwd(), "config.yml"));
556
+ if (!accountUuidProd && !accountUuidStage) halt(dedent`
460
557
  No EPMS account UUIDs found in config.yml.
461
558
  Add them to your config.yml, for example:
462
559
  epms:
@@ -465,7 +562,7 @@ const archiveEpms = async (configName, dryrun) => {
465
562
  account_uuid: <UUID>
466
563
 
467
564
  Or re-run with --force-skip-epms-sync to skip the EPMS sync entirely - ONLY use in emergencies / or if you know what you're doing.
468
- `));
565
+ `);
469
566
  const environments = [{
470
567
  accountUuid: accountUuidStage,
471
568
  env: "stage",
@@ -486,18 +583,15 @@ const archiveEpms = async (configName, dryrun) => {
486
583
  } else logSuccess(`⏭️ EPMS ${label} entry would be archived (dry run).`);
487
584
  }
488
585
  };
489
- const assertOptionsValid$9 = (options) => {
586
+ const assertOptionsValid$7 = (options) => {
490
587
  const { profile } = options;
491
588
  if (profile) assertProfileValid(profile);
492
589
  };
493
- const assertIsNotCore$4 = (ifCore) => {
494
- if (ifCore()) halt("You cannot archive Tamaro Core.");
495
- };
496
590
  const assertIsNotArchived = () => {
497
591
  if (path.basename(path.dirname(process.cwd())) === "_archived") halt("This configuration is already archived.");
498
592
  };
499
593
  const assertArchiveTargetDoesNotExist = (archiveTarget) => {
500
- if (existsSync(archiveTarget)) halt(`Archive target already exists: ${archiveTarget}. Please remove it first.`);
594
+ if (fs.existsSync(archiveTarget)) halt(`Archive target already exists: ${archiveTarget}. Please remove it first.`);
501
595
  };
502
596
  //#endregion
503
597
  //#region src/lib/validators/validateEmailTemplates.ts
@@ -617,71 +711,73 @@ const validate = async () => {
617
711
  logTitle("Validated successfully");
618
712
  };
619
713
  //#endregion
620
- //#region src/lib/https.ts
621
- const assertCrtExists = () => {
622
- const { ifCore } = getIfCoreFns();
623
- const paths = getPaths(ifCore);
624
- const certFile = path.resolve(paths.root, HTTPS_CRT_FILE);
625
- const keyFile = path.resolve(paths.root, HTTPS_KEY_FILE);
626
- if (existsSync(certFile) && existsSync(keyFile)) return;
627
- halt(stripIndent(`
628
- Flag "--https" is used, but "${HTTPS_CRT_FILE}" and/or "${HTTPS_KEY_FILE}" files are not found.
629
- You need to generate certificate first.
630
- Check docs: https://unpkg.com/@raisenow/tamaro-cli/readme.html#/?id=use-transport-level-security-https
631
- `));
714
+ //#region src/lib/paths.ts
715
+ const require = createRequire(import.meta.url);
716
+ /**
717
+ * Assert that the current working directory is a valid config directory (e.g. "configs/epms-demo") and throw an error if not.
718
+ * This is used to ensure that commands that need to be run from a config directory are not run from an invalid location.
719
+ */
720
+ const assertConfigDir = () => {
721
+ const cwd = process.cwd();
722
+ const parentDir = path.basename(path.dirname(cwd));
723
+ const pkgPath = path.resolve(cwd, "../../package.json");
724
+ const message = `Command must be run from a config folder (e.g. configs/epms-demo), not from "${cwd}".`;
725
+ if (!fs.existsSync(pkgPath) || parentDir !== "configs") {
726
+ halt(message);
727
+ return;
728
+ }
729
+ const { name } = require(pkgPath);
730
+ if (name !== "@raisenow/tamaro-configurations") {
731
+ halt(message);
732
+ return;
733
+ }
632
734
  };
633
- //#endregion
634
- //#region src/commands/build.ts
635
- const build = async (options) => {
636
- const { env } = options;
637
- applyEnv(env);
638
- if (options.deploy && !options.profile && !options.ci) {
639
- assertProfilesPresent();
640
- options.profile = await promptProfile();
735
+ /**
736
+ * Assert that the output directory for the given config name exists and throw an error if not.
737
+ * The output directory is where the build artifacts are stored after a successful build.
738
+ * For example, if the config name is "epms-demo", it checks that the "dist/epms-demo" directory exists.
739
+ */
740
+ const assertOutDir = (config) => {
741
+ const outDir = getOutDir(config ?? "");
742
+ if (!config) {
743
+ halt(`Config name is not specified.`);
744
+ return;
745
+ }
746
+ if (!fs.existsSync(outDir)) {
747
+ halt(dedent`
748
+ Build path "${path.relative(getConfigsPackageRoot(), outDir)}" does not exist.
749
+ Ensure that the build was successful and the output directory was created.
750
+ `);
751
+ return;
641
752
  }
642
- assertOptionsValid$8(options);
643
- await validate();
644
- const flags = prepareFlags$2(options);
645
- const { ifCore } = getIfCoreFns();
646
- const paths = getPaths(ifCore);
647
- const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
648
- const title = ifCore("Building optimised (minified) bundle of Tamaro Core …", `Building optimised (minified) bundle of "${configName}" customer configuration …`);
649
- const cmd = `
650
- ${resolveBin("webpack")}
651
- --config ${resolveOwn("dist/webpack.config.js")}
652
- --env min
653
- ${flags}
654
- `;
655
- logTitle(title);
656
- logCommand(cmd);
657
- runCommandSync(cmd, { stdio: "inherit" });
658
- logTitle(`\nBundle for "${configName}" customer configuration is done.`);
659
- console.log(`Path: ${paths.appDist}\n`);
660
- process.on("exit", () => {
661
- notify({
662
- message: `Bundle for "${configName}" customer configuration is done.`,
663
- title: "build"
664
- });
665
- });
666
753
  };
667
- const assertOptionsValid$8 = (options) => {
668
- const { deploy, env, https, localCore, profile } = options;
669
- const { ifCore } = getIfCoreFns();
670
- if (ifCore() && localCore) halt("Flag \"--local-core\" is redundant if running in Tamaro Core context.");
671
- if (localCore && deploy) halt("Flags \"--local-core\" and \"--deploy\" must not be used together.");
672
- if (https) assertCrtExists();
673
- if (profile) assertProfileValid(profile);
674
- assertEnvValid(env);
754
+ /**
755
+ * Returns the name of the current config, which is the name of the current working directory.
756
+ * Asserts that the current working directory is a valid config directory (e.g. "configs/epms-demo") before returning the name.
757
+ */
758
+ const getConfigName = () => {
759
+ assertConfigDir();
760
+ return path.basename(process.cwd());
675
761
  };
676
- const prepareFlags$2 = (options) => {
677
- const flags = [];
678
- const { analyze, debug, https, localCore, nolint } = options;
679
- if (localCore) flags.push("--env localCore");
680
- if (analyze) flags.push("--env analyze");
681
- if (https) flags.push("--env https");
682
- if (nolint) flags.push("--env nolint");
683
- if (debug) flags.push("--env debug");
684
- return flags.join(" ");
762
+ /**
763
+ * Returns the absolute path to the root of the configs package.
764
+ * Asserts that the current working directory is a valid config directory (e.g. "configs/epms-demo") before returning the path.
765
+ */
766
+ const getConfigsPackageRoot = () => {
767
+ assertConfigDir();
768
+ return path.resolve(process.cwd(), "../..");
769
+ };
770
+ /**
771
+ * Returns the absolute path to the input directory for the given config name.
772
+ * For example, if the config name is "epms-demo", it returns the absolute path to "configs/epms-demo" directory.
773
+ */
774
+ const getInputDir = (configName) => path.resolve(getConfigsPackageRoot(), "configs", configName);
775
+ /**
776
+ * Returns the absolute path to the output directory for the build artifacts based on the given config name.
777
+ * For example, if the config name is "epms-demo", it returns the absolute path to "dist/epms-demo" directory.
778
+ */
779
+ const getOutDir = (configName) => {
780
+ return path.resolve(getConfigsPackageRoot(), "dist", configName);
685
781
  };
686
782
  //#endregion
687
783
  //#region src/lib/validators/assertTagValid.ts
@@ -692,8 +788,7 @@ const assertTagValid = (tag) => {
692
788
  //#endregion
693
789
  //#region src/commands/update-epms.ts
694
790
  const updateEpms = async (options) => {
695
- const { ifCore } = getIfCoreFns();
696
- assertIsNotCore$3(ifCore);
791
+ const configName = getConfigName();
697
792
  if (!options.profile && !options.ci) {
698
793
  assertProfilesPresent();
699
794
  options.profile = await promptProfile();
@@ -703,11 +798,12 @@ const updateEpms = async (options) => {
703
798
  process.env.AWS_PROFILE = options.profile;
704
799
  }
705
800
  awsAuthenticate(options);
706
- const paths = getPaths(ifCore);
707
801
  const { dryrun, tag } = options;
708
- const configName = getWidgetUuid();
709
- loadEnv(paths);
710
- const { accountUuidProd, accountUuidStage, managedBy } = loadTamaroMetadataFromConfig(paths);
802
+ const inputDir = getInputDir(configName);
803
+ const dotEnvPath = path.resolve(inputDir, ".env");
804
+ const configYmlPath = path.resolve(inputDir, "config.yml");
805
+ loadEnv(dotEnvPath);
806
+ const { accountUuidProd, accountUuidStage, managedBy } = loadTamaroMetadataFromConfig(configYmlPath);
711
807
  if (!accountUuidProd && !accountUuidStage) {
712
808
  logTitle("No EPMS account UUIDs found in config.yml. Skipping EPMS update.");
713
809
  return;
@@ -755,48 +851,43 @@ const updateEpms = async (options) => {
755
851
  } else logSuccess(`⏭️ EPMS ${label} would be updated (dry run).`);
756
852
  }
757
853
  };
758
- const loadEnv = (paths) => {
759
- const filePath = globSync(paths.appEnv).find((file) => path.basename(file) === ".env");
760
- if (filePath) config({
854
+ const loadEnv = (filePath) => {
855
+ if (fs.existsSync(filePath)) config({
761
856
  path: filePath,
762
857
  quiet: true
763
858
  });
764
859
  };
765
- const assertIsNotCore$3 = (ifCore) => {
766
- if (ifCore()) halt("You cannot update EPMS in the context of Tamaro Core.");
767
- };
768
860
  //#endregion
769
861
  //#region src/commands/deploy.ts
770
862
  const deploy = async (options) => {
771
- const { ifCore } = getIfCoreFns();
772
- const paths = getPaths(ifCore);
773
- assertDistPathExists(paths.appDist);
863
+ const configName = getConfigName();
864
+ const outDir = getOutDir(configName);
865
+ assertOutDir(configName);
774
866
  if (!options.profile && !options.ci) {
775
867
  assertProfilesPresent();
776
868
  options.profile = await promptProfile();
777
869
  }
778
- assertOptionsValid$7(options);
870
+ assertOptionsValid$6(options);
779
871
  await validate();
780
872
  awsAuthenticate(options);
781
- const flags = prepareFlags$3(options);
873
+ const flags = prepareFlags(options);
782
874
  const { dryrun, tag } = options;
783
875
  const dryRunFlag = dryrun ? `--dryrun` : "";
784
- const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
785
876
  const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}`;
786
- const entryFilename = ifCore("index.js", "widget.js");
877
+ const entryFilename = "widget.js";
787
878
  if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
788
879
  /**
789
880
  * Sync all files except entrypoint (without deleting old files)
790
881
  */
791
882
  const cmdSyncAll = `
792
- aws s3 sync ${paths.appDist} ${deployUrl}
883
+ aws s3 sync ${outDir} ${deployUrl}
793
884
  --acl public-read
794
- --exclude ${paths.appDist}/${entryFilename}
885
+ --exclude ${outDir}/${entryFilename}
795
886
  --cache-control max-age=31536000
796
887
  ${flags}
797
888
  ${dryRunFlag}
798
889
  `;
799
- logTitle("Deploying to AWS S3");
890
+ logTitle("Deploying to AWS S3...");
800
891
  logCommand(cmdSyncAll);
801
892
  try {
802
893
  runCommandSync(cmdSyncAll, { stdout: "inherit" });
@@ -807,7 +898,7 @@ const deploy = async (options) => {
807
898
  * Copy entrypoint
808
899
  */
809
900
  const cmdCpEntry = `
810
- aws s3 cp ${paths.appDist}/${entryFilename} ${deployUrl}/${entryFilename}
901
+ aws s3 cp ${outDir}/${entryFilename} ${deployUrl}/${entryFilename}
811
902
  --acl public-read
812
903
  --cache-control max-age=64800
813
904
  ${flags}
@@ -829,7 +920,7 @@ const deploy = async (options) => {
829
920
  --paths /${configName}/${tag}/*
830
921
  ${flags}
831
922
  `;
832
- logTitle("\nInvalidating edge cache");
923
+ logTitle("\nInvalidating edge cache...");
833
924
  logCommand(cmdInvalidateCache);
834
925
  try {
835
926
  runCommandSync(cmdInvalidateCache);
@@ -838,7 +929,7 @@ const deploy = async (options) => {
838
929
  }
839
930
  }
840
931
  if (options.forceSkipEpmsSync) logTitle("⚠️ EPMS sync skipped. You better know what you are doing.");
841
- else if (!ifCore()) await updateEpms(options);
932
+ else await updateEpms(options);
842
933
  const demoPage = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`;
843
934
  const entryPoint = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/${entryFilename}`;
844
935
  logTitle(`\nBundle for "${configName}" is deployed with tag "${tag}".`);
@@ -848,7 +939,7 @@ const deploy = async (options) => {
848
939
  });
849
940
  process.on("exit", () => {
850
941
  notify({
851
- message: `
942
+ message: dedent`
852
943
  Bundle for "${configName}" is deployed with tag "${tag}".
853
944
  Demo page: ${demoPage}
854
945
  Entry point: ${entryPoint}
@@ -857,35 +948,99 @@ const deploy = async (options) => {
857
948
  });
858
949
  });
859
950
  };
860
- const assertOptionsValid$7 = (options) => {
951
+ const assertOptionsValid$6 = (options) => {
861
952
  const { profile, tag } = options;
862
953
  if (profile) assertProfileValid(profile);
863
954
  assertTagValid(tag);
864
955
  };
865
- const assertDistPathExists = (distPath) => {
866
- if (!existsSync(distPath)) halt(stripIndent(`
867
- Dist folder does not exists.
868
- Make sure you have built the bundle before trying to deploy it.
869
- `));
956
+ //#endregion
957
+ //#region src/lib/https.ts
958
+ const assertCrtExists = () => {
959
+ const configsPackageRoot = getConfigsPackageRoot();
960
+ const certFile = path.resolve(configsPackageRoot, HTTPS_CRT_FILE);
961
+ const keyFile = path.resolve(configsPackageRoot, HTTPS_KEY_FILE);
962
+ if (fs.existsSync(certFile) && fs.existsSync(keyFile)) return;
963
+ halt(dedent`
964
+ Files "${HTTPS_CRT_FILE}" and/or "${HTTPS_KEY_FILE}" are not found.
965
+ You need to generate local certificates first.
966
+ 1. Install mkcert:
967
+ brew install mkcert
968
+ 2. Generate the certificate and key in the repository root:
969
+ mkcert -install -cert-file ${HTTPS_CRT_FILE} -key-file ${HTTPS_KEY_FILE} localhost 127.0.0.1 0.0.0.0 ::1
970
+ `);
971
+ };
972
+ //#endregion
973
+ //#region src/commands/preview.ts
974
+ const preview = async () => {
975
+ const configName = getConfigName();
976
+ const configsPackageRoot = getConfigsPackageRoot();
977
+ assertOutDir(configName);
978
+ assertCrtExists();
979
+ const cmd = `pnpm sirv ${path.relative(configsPackageRoot, getOutDir(configName))} --cors --http2 --cert ${HTTPS_CRT_FILE} --key ${HTTPS_KEY_FILE} --port ${await getPortPromise({ port: Number(DEFAULT_PORT) })}`;
980
+ logTitle(`Running web-server for pre-built bundle...`);
981
+ logCommand(cmd);
982
+ runCommandSync(cmd, {
983
+ cwd: configsPackageRoot,
984
+ stdio: "inherit"
985
+ });
986
+ };
987
+ //#endregion
988
+ //#region src/commands/build.ts
989
+ const build = async (options) => {
990
+ const configName = getConfigName();
991
+ const configsPackageRoot = getConfigsPackageRoot();
992
+ const outDir = getOutDir(configName);
993
+ if (options.deploy && !options.profile && !options.ci) {
994
+ assertProfilesPresent();
995
+ options.profile = await promptProfile();
996
+ }
997
+ assertOptionsValid$5(options);
998
+ await validate();
999
+ const cmd = `pnpm vite build`;
1000
+ const env = {
1001
+ ...process.env,
1002
+ BABEL: options.babel ? "true" : "false",
1003
+ CONFIG_NAME: configName,
1004
+ MINIFY: options.minify ? "true" : "false"
1005
+ };
1006
+ logTitle(`Building optimised (minified) bundle of "${configName}" customer configuration...`);
1007
+ logCommand(cmd);
1008
+ runCommandSync(cmd, {
1009
+ cwd: configsPackageRoot,
1010
+ env,
1011
+ stdio: "inherit"
1012
+ });
1013
+ logTitle(`\nBundle for "${configName}" customer configuration is done.`);
1014
+ console$1.log(`Path: ${outDir}\n`);
1015
+ process.on("exit", () => {
1016
+ notify({
1017
+ message: `Bundle for "${configName}" customer configuration is done.`,
1018
+ title: "build"
1019
+ });
1020
+ });
1021
+ if (options.preview) await preview();
1022
+ if (options.deploy) await deploy(options);
1023
+ };
1024
+ const assertOptionsValid$5 = (options) => {
1025
+ const { profile } = options;
1026
+ if (profile) assertProfileValid(profile);
870
1027
  };
871
1028
  //#endregion
872
1029
  //#region src/commands/deploy-email-config.ts
873
1030
  const deployEmailConfig = async (options) => {
874
- const { ifCore } = getIfCoreFns();
875
- const emailConfigPath = `${getPaths(ifCore).app}/email-config`;
876
- assertIsNotCore$2();
1031
+ const configName = getConfigName();
1032
+ const emailConfigPath = `${getInputDir(configName)}/email-config`;
877
1033
  assertEmailConfigPathExists(emailConfigPath);
878
1034
  if (!options.profile && !options.ci) {
879
1035
  assertProfilesPresent();
880
1036
  options.profile = await promptProfile();
881
1037
  }
882
1038
  if (!options.bucket) options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await promptBucketTamaroEmailConfig$1();
883
- assertOptionsValid$6(options);
1039
+ assertOptionsValid$4(options);
884
1040
  await validate();
885
1041
  awsAuthenticate(options);
886
- const flags = prepareFlags$3(options);
1042
+ const flags = prepareFlags(options);
887
1043
  const dryRunFlag = options.dryrun ? `--dryrun` : "";
888
- const configName = getWidgetUuid();
889
1044
  const deployUrl = `s3://${options.bucket}/${configName}`;
890
1045
  if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
891
1046
  const cmd = `
@@ -895,7 +1050,7 @@ const deployEmailConfig = async (options) => {
895
1050
  ${flags}
896
1051
  ${dryRunFlag}
897
1052
  `;
898
- logTitle(`Deploying email configuration for "${configName}" customer configuration to AWS S3 …`);
1053
+ logTitle(`Deploying email configuration for "${configName}" customer configuration to AWS S3...`);
899
1054
  logCommand(cmd);
900
1055
  try {
901
1056
  runCommandSync(cmd, { stdout: "inherit" });
@@ -911,17 +1066,13 @@ const deployEmailConfig = async (options) => {
911
1066
  });
912
1067
  });
913
1068
  };
914
- const assertOptionsValid$6 = (options) => {
1069
+ const assertOptionsValid$4 = (options) => {
915
1070
  const { bucket, profile } = options;
916
1071
  if (profile) assertProfileValid(profile);
917
1072
  if (bucket) assertBucketValid$1(bucket);
918
1073
  };
919
1074
  const assertEmailConfigPathExists = (distPath) => {
920
- if (!existsSync(distPath)) halt("Email config folder does not exists. Nothing to deploy.");
921
- };
922
- const assertIsNotCore$2 = () => {
923
- const { ifCore } = getIfCoreFns();
924
- if (ifCore()) halt("You cannot deploy widget email configuration for Tamaro Core.");
1075
+ if (!fs.existsSync(distPath)) halt("Email config folder does not exists. Nothing to deploy.");
925
1076
  };
926
1077
  const assertBucketValid$1 = (bucket) => {
927
1078
  if (!["rnw-stage-email-service", "rnw-email-service"].includes(bucket)) halt("Invalid bucket name.");
@@ -944,53 +1095,34 @@ const promptBucketTamaroEmailConfig$1 = async () => {
944
1095
  //#endregion
945
1096
  //#region src/commands/dev.ts
946
1097
  const dev = async (options) => {
947
- const { env } = options;
948
- applyEnv(env);
949
- assertOptionsValid$5(options);
950
- const flags = await prepareFlags$1(options);
951
- const { ifCore } = getIfCoreFns();
952
- const title = ifCore("Running dev web-server for Tamaro Core …", "Running dev web-server for customer configuration …");
953
- const cmd = `
954
- ${resolveBin("webpack")} serve
955
- --config ${resolveOwn("dist/webpack.config.js")}
956
- ${flags}
957
- `;
958
- logTitle(title);
1098
+ const configName = getConfigName();
1099
+ const configsPackageRoot = getConfigsPackageRoot();
1100
+ const cmd = `pnpm vite dev --port ${await getPortPromise({ port: Number(DEFAULT_PORT) })}`;
1101
+ const env = {
1102
+ ...process.env,
1103
+ CONFIG_NAME: configName,
1104
+ LOCAL_CORE: options.localCore ? "true" : "false"
1105
+ };
1106
+ logTitle(`\nStarting Vite dev server for "${configName}" configuration...`);
959
1107
  logCommand(cmd);
960
- runCommandSync(cmd, { stdio: "inherit" });
961
- };
962
- const assertOptionsValid$5 = (options) => {
963
- const { env, https, localCore, port } = options;
964
- const { ifCore } = getIfCoreFns();
965
- if (ifCore() && localCore) halt("Flag \"--local-core\" is redundant if running in Tamaro Core context.");
966
- if (Number.isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
967
- if (https) assertCrtExists();
968
- assertEnvValid(env);
969
- };
970
- const prepareFlags$1 = async (options) => {
971
- const flags = [];
972
- const { debug, https, localCore, nolint, port: defaultPort } = options;
973
- const port = await getPortPromise({ port: Number(defaultPort) });
974
- if (localCore) flags.push("--env localCore");
975
- flags.push(`--port ${port}`);
976
- if (https) flags.push("--env https");
977
- if (nolint) flags.push("--env nolint");
978
- if (debug) flags.push("--env debug");
979
- return flags.join(" ");
1108
+ runCommandSync(cmd, {
1109
+ cwd: configsPackageRoot,
1110
+ env,
1111
+ stdio: "inherit"
1112
+ });
980
1113
  };
981
1114
  //#endregion
982
1115
  //#region src/commands/list-deployed.ts
983
1116
  const listDeployed = async (options) => {
1117
+ const configName = getConfigName();
984
1118
  if (!options.profile && !options.ci) {
985
1119
  assertProfilesPresent();
986
1120
  options.profile = await promptProfile();
987
1121
  }
988
- assertOptionsValid$4(options);
1122
+ assertOptionsValid$3(options);
989
1123
  awsAuthenticate(options);
990
- const { config, profile } = options;
991
- const { ifCore } = getIfCoreFns();
992
- const configName = config ?? ifCore("tamaro-core", getWidgetUuid());
993
- logTitle(!config && ifCore() ? `Listing deployments of Tamaro Core …` : `Listing deployments of "${configName}" customer configuration …`);
1124
+ const { profile } = options;
1125
+ logTitle(`Listing deployments of "${configName}" customer configuration...`);
994
1126
  if (profile) process.env.AWS_PROFILE = profile;
995
1127
  const deployments = await getConfigDeployments(configName);
996
1128
  if (deployments.length === 0) {
@@ -1014,68 +1146,25 @@ const listDeployed = async (options) => {
1014
1146
  });
1015
1147
  console.log(`\n${table}\n`);
1016
1148
  };
1017
- const assertOptionsValid$4 = (options) => {
1018
- const { config, profile } = options;
1019
- assertConfigValid(config);
1020
- if (profile) assertProfileValid(profile);
1021
- };
1022
- const assertConfigValid = (config) => {
1023
- if (!config) return;
1024
- const regex = /^[\w-]+$/;
1025
- if (!regex.test(config)) halt(`Flag "--config" has forbidden format. Allowed format: ${regex.toString()}.`);
1026
- };
1027
- //#endregion
1028
- //#region src/commands/serve.ts
1029
- const serve = async (options) => {
1030
- assertOptionsValid$3(options);
1031
- const flags = await prepareFlags(options);
1032
- const { ifCore } = getIfCoreFns();
1033
- const cmd = `
1034
- npx -y serve ${getPaths(ifCore).appDist}
1035
- --cors
1036
- ${flags}
1037
- `;
1038
- logTitle(`Running web-server for pre-built bundle …`);
1039
- logCommand(cmd);
1040
- runCommandSync(cmd, { stdio: "inherit" });
1041
- };
1042
1149
  const assertOptionsValid$3 = (options) => {
1043
- const { https, port } = options;
1044
- if (Number.isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
1045
- if (https) assertCrtExists();
1046
- };
1047
- const prepareFlags = async (options) => {
1048
- const flags = [];
1049
- const { https, port: defaultPort } = options;
1050
- const port = await getPortPromise({ port: Number(defaultPort) });
1051
- flags.push(`-p ${port}`);
1052
- if (https) {
1053
- const { ifCore } = getIfCoreFns();
1054
- const paths = getPaths(ifCore);
1055
- const certFile = path.resolve(paths.root, HTTPS_CRT_FILE);
1056
- const keyFile = path.resolve(paths.root, HTTPS_KEY_FILE);
1057
- flags.push(`--ssl-cert ${certFile}`);
1058
- flags.push(`--ssl-key ${keyFile}`);
1059
- }
1060
- return flags.join(" ");
1150
+ const { profile } = options;
1151
+ if (profile) assertProfileValid(profile);
1061
1152
  };
1062
1153
  //#endregion
1063
1154
  //#region src/commands/unarchive.ts
1064
1155
  const unarchive = async (options) => {
1065
- const { ifCore } = getIfCoreFns({ allowArchived: true });
1066
- assertIsNotCore$1(ifCore);
1067
1156
  assertIsArchived();
1068
- const configName = getWidgetUuid();
1157
+ const configName = path.basename(process.cwd());
1069
1158
  const cwd = process.cwd();
1070
1159
  const archivedDir = path.dirname(cwd);
1071
1160
  const configsDir = path.dirname(archivedDir);
1072
1161
  const restoreTarget = path.resolve(configsDir, configName);
1073
1162
  assertRestoreTargetDoesNotExist(restoreTarget);
1074
1163
  assertOptionsValid$2(options);
1075
- if (!ifCore() && !options.forceSkipEpmsSync) await unarchiveEpms(configName, !!options.dryrun);
1164
+ if (!options.forceSkipEpmsSync) await unarchiveEpms(configName, !!options.dryrun);
1076
1165
  if (options.dryrun) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
1077
1166
  if (!options.dryrun) {
1078
- renameSync(cwd, restoreTarget);
1167
+ fs.renameSync(cwd, restoreTarget);
1079
1168
  process.chdir(restoreTarget);
1080
1169
  } else logTitle(`Would move ${cwd} → ${restoreTarget}`);
1081
1170
  logSuccess(`\n✅ "${configName}" has been unarchived and moved to ${restoreTarget}`);
@@ -1087,9 +1176,8 @@ const unarchive = async (options) => {
1087
1176
  });
1088
1177
  };
1089
1178
  const unarchiveEpms = async (configName, dryrun) => {
1090
- const { ifCore } = getIfCoreFns({ allowArchived: true });
1091
- const { accountUuidProd, accountUuidStage } = loadTamaroMetadataFromConfig(getPaths(ifCore));
1092
- if (!accountUuidProd && !accountUuidStage) halt(stripIndent(`
1179
+ const { accountUuidProd, accountUuidStage } = loadTamaroMetadataFromConfig(path.resolve(process.cwd(), "config.yml"));
1180
+ if (!accountUuidProd && !accountUuidStage) halt(dedent`
1093
1181
  No EPMS account UUIDs found in config.yml.
1094
1182
  Add them to your config.yml, for example:
1095
1183
  epms:
@@ -1098,7 +1186,7 @@ const unarchiveEpms = async (configName, dryrun) => {
1098
1186
  account_uuid: <UUID>
1099
1187
 
1100
1188
  Or re-run with --force-skip-epms-sync to skip the EPMS sync entirely - ONLY use in emergencies / or if you know what you're doing.
1101
- `));
1189
+ `);
1102
1190
  const environments = [{
1103
1191
  accountUuid: accountUuidStage,
1104
1192
  env: "stage",
@@ -1126,24 +1214,20 @@ const assertOptionsValid$2 = (options) => {
1126
1214
  const assertIsArchived = () => {
1127
1215
  if (path.basename(path.dirname(process.cwd())) !== "_archived") halt("This configuration is not archived. Only archived configurations can be unarchived.");
1128
1216
  };
1129
- const assertIsNotCore$1 = (ifCore) => {
1130
- if (ifCore()) halt("You cannot unarchive Tamaro Core.");
1131
- };
1132
1217
  const assertRestoreTargetDoesNotExist = (restoreTarget) => {
1133
- if (existsSync(restoreTarget)) halt(`Restore target already exists: ${restoreTarget}. Please remove it first.`);
1218
+ if (fs.existsSync(restoreTarget)) halt(`Restore target already exists: ${restoreTarget}. Please remove it first.`);
1134
1219
  };
1135
1220
  //#endregion
1136
1221
  //#region src/commands/undeploy.ts
1137
1222
  const undeploy = async (options) => {
1138
- const { ifCore } = getIfCoreFns();
1139
- const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
1223
+ const configName = getConfigName();
1140
1224
  if (!options.profile && !options.ci) {
1141
1225
  assertProfilesPresent();
1142
1226
  options.profile = await promptProfile();
1143
1227
  }
1144
1228
  assertOptionsValid$1(options);
1145
1229
  awsAuthenticate(options);
1146
- const flags = prepareFlags$3(options);
1230
+ const flags = prepareFlags(options);
1147
1231
  const { all, dryrun, tag = DEFAULT_TAG } = options;
1148
1232
  const dryRunFlag = dryrun ? `--dryrun` : "";
1149
1233
  const deployUrl = all ? `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/` : `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/`;
@@ -1156,7 +1240,7 @@ const undeploy = async (options) => {
1156
1240
  ${flags}
1157
1241
  ${dryRunFlag}
1158
1242
  `;
1159
- logTitle(`Undeploying ${description} from AWS S3 …`);
1243
+ logTitle(`Undeploying ${description} from AWS S3...`);
1160
1244
  logCommand(cmd);
1161
1245
  try {
1162
1246
  runCommandSync(cmd, { stdout: "inherit" });
@@ -1170,7 +1254,7 @@ const undeploy = async (options) => {
1170
1254
  --paths ${all ? `/${configName}/*` : `/${configName}/${tag}/*`}
1171
1255
  ${flags}
1172
1256
  `;
1173
- logTitle("\nInvalidating edge cache");
1257
+ logTitle("\nInvalidating edge cache...");
1174
1258
  logCommand(cmdInvalidateCache);
1175
1259
  try {
1176
1260
  runCommandSync(cmdInvalidateCache);
@@ -1189,9 +1273,6 @@ const undeploy = async (options) => {
1189
1273
  };
1190
1274
  const assertOptionsValid$1 = (options) => {
1191
1275
  const { all, profile, tag } = options;
1192
- const { ifCore } = getIfCoreFns();
1193
- if (ifCore() && all) halt("Flag \"--all\" must not be used in Tamaro Core context.");
1194
- if (ifCore() && tag === "latest") halt("You cannot undeploy the default tag for Tamaro Core.");
1195
1276
  if (profile) assertProfileValid(profile);
1196
1277
  if (all && tag) halt("Flags \"--tag\" and \"--all\" must not be used together.");
1197
1278
  if (!all && tag) assertTagValid(tag);
@@ -1199,8 +1280,7 @@ const assertOptionsValid$1 = (options) => {
1199
1280
  //#endregion
1200
1281
  //#region src/commands/undeploy-email-config.ts
1201
1282
  const undeployEmailConfig = async (options) => {
1202
- const { ifCore } = getIfCoreFns();
1203
- assertIsNotCore(ifCore);
1283
+ const configName = getConfigName();
1204
1284
  if (!options.profile && !options.ci) {
1205
1285
  assertProfilesPresent();
1206
1286
  options.profile = await promptProfile();
@@ -1212,9 +1292,8 @@ const undeployEmailConfig = async (options) => {
1212
1292
  else options.bucket = await promptBucketTamaroEmailConfig();
1213
1293
  assertOptionsValid(options);
1214
1294
  awsAuthenticate(options);
1215
- const flags = prepareFlags$3(options);
1295
+ const flags = prepareFlags(options);
1216
1296
  const dryRunFlag = options.dryrun ? `--dryrun` : "";
1217
- const configName = getWidgetUuid();
1218
1297
  const deployUrl = `s3://${options.bucket}/${configName}/`;
1219
1298
  await promptConfirmation(`Are you sure you want to undeploy the email configuration for "${configName}" from "${options.bucket}"?`, options.ci);
1220
1299
  if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
@@ -1224,7 +1303,7 @@ const undeployEmailConfig = async (options) => {
1224
1303
  ${flags}
1225
1304
  ${dryRunFlag}
1226
1305
  `;
1227
- logTitle(`Undeploying email configuration for "${configName}" from AWS S3 …`);
1306
+ logTitle(`Undeploying email configuration for "${configName}" from AWS S3...`);
1228
1307
  logCommand(cmd);
1229
1308
  try {
1230
1309
  runCommandSync(cmd, { stdout: "inherit" });
@@ -1245,9 +1324,6 @@ const assertOptionsValid = (options) => {
1245
1324
  if (profile) assertProfileValid(profile);
1246
1325
  if (bucket) assertBucketValid(bucket);
1247
1326
  };
1248
- const assertIsNotCore = (ifCore) => {
1249
- if (ifCore()) halt("You cannot undeploy widget email configuration for Tamaro Core.");
1250
- };
1251
1327
  const assertBucketValid = (bucket) => {
1252
1328
  if (!["rnw-stage-email-service", "rnw-email-service"].includes(bucket)) halt("Invalid bucket name.");
1253
1329
  };
@@ -1269,7 +1345,7 @@ const promptBucketTamaroEmailConfig = async () => {
1269
1345
  //#endregion
1270
1346
  //#region package.json
1271
1347
  var name = "@raisenow/tamaro-cli";
1272
- var version = "1.9.0-dev.3";
1348
+ var version = "3.0.0-dev.1";
1273
1349
  //#endregion
1274
1350
  //#region src/cli.ts
1275
1351
  /**
@@ -1280,59 +1356,25 @@ var version = "1.9.0-dev.3";
1280
1356
  process.on("unhandledRejection", (error) => {
1281
1357
  throw error;
1282
1358
  });
1283
- process.on("SIGINT", () => {
1284
- halt();
1285
- });
1286
- const cli = createCommand().name(name).version(version, "-v, --version");
1287
- 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("--https", "Let local web server serve Tamaro with SSL encryption", false).option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option("--env <env>", "Environment (dev, stage, prod)").option("--nolint", "Disable ESLint", false).option("--debug", "Enable debug mode", false).action(async (options) => {
1288
- await dev(options);
1289
- });
1290
- 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("--https", "Let local web server serve Tamaro with SSL encryption", false).option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option("--env <env>", "Environment (dev, stage, prod)").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--deploy", "Deploy Tamaro Core or a customer configuration bundle to AWS S3", false).option("--force-skip-epms-sync", "Skip the EPMS sync entirely. Only use this in emergencies.", false).option("--tag <tag>", "Tag which should be used for the deployment of the bundle", DEFAULT_TAG).option("--nolint", "Disable ESLint", false).option("--debug", "Enable debug mode", false).action(async (options) => {
1291
- await build(options);
1292
- if (options.serve) await serve(options);
1293
- if (options.deploy) await deploy(options);
1294
- });
1295
- cli.command("serve").description("Run a local web server for pre-built bundle").option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option("--https", "Let local web server serve Tamaro with SSL encryption", false).action(async (options) => {
1296
- await serve(options);
1297
- });
1298
- cli.command("deploy").description("Deploy a pre-built Tamaro Core or customer configuration bundle to AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--tag <tag>", "Tag which should be used for the deployment of the bundle", DEFAULT_TAG).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--force-skip-epms-sync", "Skip the EPMS sync entirely. Only use this in emergencies.", false).action(async (options) => {
1299
- await deploy(options);
1300
- });
1301
- cli.command("list-deployed").description("List deployments of Tamaro Core or a particular customer configuration").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--config <config>", "Configuration name (default: current customer configuration)").action(async (options) => {
1302
- await listDeployed(options);
1303
- });
1304
- cli.command("deploy-email-config").description("Deploy a widget's email configuration to AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--bucket <bucket>", "AWS bucket for email configs").option("--dryrun", "Displays the operations that would be performed without actually running them", false).action(async (options) => {
1305
- await deployEmailConfig(options);
1306
- });
1307
- cli.command("undeploy").description("Undeploy a Tamaro Core or customer configuration bundle from AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--tag <tag>", "Tag which should be undeployed").option("--all", "Undeploy all tags", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).action(async (options) => {
1308
- await undeploy(options);
1309
- });
1310
- cli.command("undeploy-email-config").description("Undeploy a widget's email configuration from AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--bucket <bucket>", "AWS bucket for email configs").option("--stage", "Undeploy from stage environment (alternative to --bucket)").option("--prod", "Undeploy from prod environment (alternative to --bucket)").option("--dryrun", "Displays the operations that would be performed without actually running them", false).action(async (options) => {
1311
- await undeployEmailConfig(options);
1312
- });
1313
- cli.command("archive").description("Archive a customer configuration by moving it to the _archived folder").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--force-skip-epms-sync", "Skip EPMS archive sync (emergency use only)", false).action(async (options) => {
1314
- await archive(options);
1315
- });
1316
- cli.command("unarchive").description("Unarchive a customer configuration by restoring it from the _archived folder").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--force-skip-epms-sync", "Skip EPMS unarchive sync (emergency use only)", false).action(async (options) => {
1317
- await unarchive(options);
1318
- });
1319
- cli.command("update-epms").description("Update EPMS with the currently deployed widget tags.").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--tag <tag>", "Tag which should be set for the deployment", DEFAULT_TAG).action(async (options) => {
1320
- await updateEpms(options);
1321
- });
1322
- cli.command("validate").description("Validate the current Tamaro configuration to avoid common errors").action(async () => {
1323
- await validate();
1324
- });
1325
- (async () => {
1326
- try {
1327
- logTitle(`${name} ${version}\n`);
1328
- await cli.parseAsync(process.argv);
1329
- } catch (error) {
1330
- if (error.signal === "SIGINT" && error.signalDescription) logError(`\n${error.signalDescription}`);
1331
- else {
1332
- console.log("");
1333
- logError(error.stack);
1334
- }
1335
- }
1336
- })();
1359
+ const cli = createCommand().name(name).description("CLI for Tamaro Customer Configurations development").version(version, "-v, --version");
1360
+ cli.command("dev").description("Run the local dev-server").option("--local-core", "Load Tamaro Core from \"https://localhost:1234/src/index.ts\" rather than from CDN", false).action(dev);
1361
+ cli.command("build").description("Build an optimised (minified) bundle").option("--preview", "Run a local web server for pre-built bundle", false).option("--babel", "Use Babel for transpilation", true).option("--no-babel", "Do not use Babel for transpilation").option("--minify", "Minify the bundle", true).option("--no-minify", "Do not minify the bundle").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--deploy", "Deploy customer configuration bundle to AWS S3", false).option("--force-skip-epms-sync", "Skip the EPMS sync entirely. Only use this in emergencies.", false).option("--tag <tag>", "Tag which should be used for the deployment of the bundle", DEFAULT_TAG).action(build);
1362
+ cli.command("preview").description("Run a local web server for pre-built bundle").action(preview);
1363
+ cli.command("deploy").description("Deploy a pre-built Tamaro Core or customer configuration bundle to AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--tag <tag>", "Tag which should be used for the deployment of the bundle", DEFAULT_TAG).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--force-skip-epms-sync", "Skip the EPMS sync entirely. Only use this in emergencies.", false).action(deploy);
1364
+ cli.command("list-deployed").description("List deployments of customer configuration").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).action(listDeployed);
1365
+ cli.command("deploy-email-config").description("Deploy a widget's email configuration to AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--bucket <bucket>", "AWS bucket for email configs").option("--dryrun", "Displays the operations that would be performed without actually running them", false).action(deployEmailConfig);
1366
+ cli.command("undeploy").description("Undeploy a Tamaro Core or customer configuration bundle from AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--tag <tag>", "Tag which should be undeployed").option("--all", "Undeploy all tags", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).action(undeploy);
1367
+ cli.command("undeploy-email-config").description("Undeploy a widget's email configuration from AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--bucket <bucket>", "AWS bucket for email configs").option("--stage", "Undeploy from stage environment (alternative to --bucket)").option("--prod", "Undeploy from prod environment (alternative to --bucket)").option("--dryrun", "Displays the operations that would be performed without actually running them", false).action(undeployEmailConfig);
1368
+ cli.command("archive").description("Archive a customer configuration by moving it to the _archived folder").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--force-skip-epms-sync", "Skip EPMS archive sync (emergency use only)", false).action(archive);
1369
+ cli.command("unarchive").description("Unarchive a customer configuration by restoring it from the _archived folder").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--force-skip-epms-sync", "Skip EPMS unarchive sync (emergency use only)", false).action(unarchive);
1370
+ cli.command("update-epms").description("Update EPMS with the currently deployed widget tags.").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--dryrun", "Displays the operations that would be performed without actually running them", false).option("--tag <tag>", "Tag which should be set for the deployment", DEFAULT_TAG).action(updateEpms);
1371
+ cli.command("validate").description("Validate the current Tamaro configuration to avoid common errors").action(validate);
1372
+ try {
1373
+ logTitle(`${name} ${version}\n`);
1374
+ await cli.parseAsync(process.argv);
1375
+ } catch (error) {
1376
+ if (error.signal === "SIGINT" && error.signalDescription) logError(`\n${error.signalDescription}`);
1377
+ else logError(`\n${error}`);
1378
+ }
1337
1379
  //#endregion
1338
1380
  export {};