@raisenow/tamaro-cli 3.0.0-dev.2 → 3.0.0-dev.4

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.
@@ -1,7 +1,49 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
3
  <component name="ChangeListManager">
4
- <list default="true" id="03cc3f97-55ca-4737-9fe2-779ac8457ab2" name="Changes" comment="" />
4
+ <list default="true" id="03cc3f97-55ca-4737-9fe2-779ac8457ab2" name="Changes" comment="">
5
+ <change afterPath="$PROJECT_DIR$/src/commands/format.ts" afterDir="false" />
6
+ <change afterPath="$PROJECT_DIR$/src/commands/lint.ts" afterDir="false" />
7
+ <change afterPath="$PROJECT_DIR$/src/commands/preview.ts" afterDir="false" />
8
+ <change afterPath="$PROJECT_DIR$/src/commands/typecheck.ts" afterDir="false" />
9
+ <change afterPath="$PROJECT_DIR$/src/lib/paths.ts" afterDir="false" />
10
+ <change beforePath="$PROJECT_DIR$/.nvmrc" beforeDir="false" afterPath="$PROJECT_DIR$/.nvmrc" afterDir="false" />
11
+ <change beforePath="$PROJECT_DIR$/CHANGELOG.md" beforeDir="false" afterPath="$PROJECT_DIR$/CHANGELOG.md" afterDir="false" />
12
+ <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
13
+ <change beforePath="$PROJECT_DIR$/bitbucket-pipelines.yml" beforeDir="false" afterPath="$PROJECT_DIR$/bitbucket-pipelines.yml" afterDir="false" />
14
+ <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
15
+ <change beforePath="$PROJECT_DIR$/pnpm-lock.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pnpm-lock.yaml" afterDir="false" />
16
+ <change beforePath="$PROJECT_DIR$/pnpm-workspace.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pnpm-workspace.yaml" afterDir="false" />
17
+ <change beforePath="$PROJECT_DIR$/src/cli.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/cli.ts" afterDir="false" />
18
+ <change beforePath="$PROJECT_DIR$/src/commands/archive.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/archive.ts" afterDir="false" />
19
+ <change beforePath="$PROJECT_DIR$/src/commands/build.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/build.ts" afterDir="false" />
20
+ <change beforePath="$PROJECT_DIR$/src/commands/deploy-email-config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/deploy-email-config.ts" afterDir="false" />
21
+ <change beforePath="$PROJECT_DIR$/src/commands/deploy.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/deploy.ts" afterDir="false" />
22
+ <change beforePath="$PROJECT_DIR$/src/commands/dev.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/dev.ts" afterDir="false" />
23
+ <change beforePath="$PROJECT_DIR$/src/commands/list-deployed.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/list-deployed.ts" afterDir="false" />
24
+ <change beforePath="$PROJECT_DIR$/src/commands/serve.ts" beforeDir="false" />
25
+ <change beforePath="$PROJECT_DIR$/src/commands/unarchive.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/unarchive.ts" afterDir="false" />
26
+ <change beforePath="$PROJECT_DIR$/src/commands/undeploy-email-config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/undeploy-email-config.ts" afterDir="false" />
27
+ <change beforePath="$PROJECT_DIR$/src/commands/undeploy.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/undeploy.ts" afterDir="false" />
28
+ <change beforePath="$PROJECT_DIR$/src/commands/update-epms.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/update-epms.ts" afterDir="false" />
29
+ <change beforePath="$PROJECT_DIR$/src/commands/validate.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/commands/validate.ts" afterDir="false" />
30
+ <change beforePath="$PROJECT_DIR$/src/lib/InterpolateHtmlPlugin.ts" beforeDir="false" />
31
+ <change beforePath="$PROJECT_DIR$/src/lib/aws.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/aws.ts" afterDir="false" />
32
+ <change beforePath="$PROJECT_DIR$/src/lib/command.ts" beforeDir="false" />
33
+ <change beforePath="$PROJECT_DIR$/src/lib/constants.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/constants.ts" afterDir="false" />
34
+ <change beforePath="$PROJECT_DIR$/src/lib/env.ts" beforeDir="false" />
35
+ <change beforePath="$PROJECT_DIR$/src/lib/epms/auth/browser.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/epms/auth/browser.ts" afterDir="false" />
36
+ <change beforePath="$PROJECT_DIR$/src/lib/epms/auth/util.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/epms/auth/util.ts" afterDir="false" />
37
+ <change beforePath="$PROJECT_DIR$/src/lib/epms/helpers.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/epms/helpers.ts" afterDir="false" />
38
+ <change beforePath="$PROJECT_DIR$/src/lib/https.ts" beforeDir="false" />
39
+ <change beforePath="$PROJECT_DIR$/src/lib/logging.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/logging.ts" afterDir="false" />
40
+ <change beforePath="$PROJECT_DIR$/src/lib/notifier.ts" beforeDir="false" />
41
+ <change beforePath="$PROJECT_DIR$/src/lib/resolve.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/resolve.ts" afterDir="false" />
42
+ <change beforePath="$PROJECT_DIR$/src/lib/validators/assertTagValid.ts" beforeDir="false" />
43
+ <change beforePath="$PROJECT_DIR$/src/webpack.config.ts" beforeDir="false" />
44
+ <change beforePath="$PROJECT_DIR$/tsconfig.base.json" beforeDir="false" afterPath="$PROJECT_DIR$/tsconfig.base.json" afterDir="false" />
45
+ <change beforePath="$PROJECT_DIR$/tsdown.config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/tsdown.config.ts" afterDir="false" />
46
+ </list>
5
47
  <option name="SHOW_DIALOG" value="false" />
6
48
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
7
49
  <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -49,6 +91,7 @@
49
91
  <workItem from="1777936008103" duration="88000" />
50
92
  <workItem from="1778477038620" duration="2530000" />
51
93
  <workItem from="1780398242165" duration="1962000" />
94
+ <workItem from="1781661280180" duration="949000" />
52
95
  </task>
53
96
  <servers />
54
97
  </component>
package/dist/cli.js CHANGED
@@ -1,73 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
+ import { assertAwsProfileValid, assertAwsProfilesPresent, assertCrtExists, assertTagValid, awsAuthenticate, halt, logDataTable, logError, logInfo, logSuccess, logTitle, notify, prepareAwsCliFlags, promptAwsProfile, promptConfirmation, runCommandSync } from "@rnw-npm/cli-helpers";
3
4
  import { createCommand } from "commander";
4
5
  import fs from "node:fs";
5
6
  import path from "node:path";
6
7
  import dedent from "dedent";
7
- import { S3 } from "@aws-sdk/client-s3";
8
- import { execaCommandSync } from "execa";
9
- import prompts from "prompts";
10
- import chalk from "chalk";
11
- import columnify from "columnify";
12
- import envPaths from "env-paths";
13
8
  import * as yaml from "js-yaml";
9
+ import envPaths from "env-paths";
14
10
  import { z } from "zod";
15
11
  import ky from "ky";
16
12
  import { createServer } from "node:http";
17
13
  import open from "open";
18
- import notifier from "node-notifier";
19
- import console$1 from "node:console";
20
14
  import { globSync } from "glob";
21
15
  import Handlebars from "handlebars";
22
16
  import helpers from "handlebars-helpers";
23
17
  import { config } from "dotenv";
24
18
  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
19
+ import prompts from "prompts";
20
+ import columnify from "columnify";
21
+ import { S3 } from "@aws-sdk/client-s3";
71
22
  //#region src/lib/constants.ts
72
23
  const DEFAULT_TAG = "latest";
73
24
  const DEFAULT_PORT = 1234;
@@ -75,113 +26,16 @@ const DEFAULT_HTTP_TIMEOUT = 1e4;
75
26
  const AWS_S3_BUCKET_TAMARO = "tamaro.raisenow.com";
76
27
  const AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE = "rnw-stage-email-service";
77
28
  const AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD = "rnw-email-service";
29
+ const AWS_CLOUDFRONT_DISTRIBUTION_ID = "EHJ1OM458YQ0I";
78
30
  const EPMS_API_BASE_URL_STAGE = "https://api.stage.mesos.raisenow.net";
79
31
  const EPMS_API_BASE_URL_PROD = "https://api.raisenow.io";
80
32
  const EPMS_AUTH_BASE_URL_STAGE = "https://login.stage.mesos.raisenow.net";
81
33
  const EPMS_AUTH_BASE_URL_PROD = "https://login.raisenow.com";
82
34
  const EPMS_OAUTH_CLIENT_ID = "tamaro-cli";
83
35
  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
36
  const CACHE_DIR = envPaths("tamaro-cli", { suffix: "" }).cache;
88
37
  const TAMARO_VERSION_IN_URL_REGEX = /tamaro-core\/(.*)\/index.js/;
89
38
  //#endregion
90
- //#region src/lib/aws.ts
91
- const awsAuthenticate = (options) => {
92
- if (options.ci)
93
- /**
94
- * Don't try to authenticate the user.
95
- * This is done when CLI is running within an automated system like pipeline,
96
- * In this case "AWS_ACCESS_KEY_ID" and "AWS_SECRET_ACCESS_KEY" are used instead of "AWS_PROFILE".
97
- */
98
- return;
99
- try {
100
- checkIdentity(options);
101
- } catch {
102
- login(options);
103
- }
104
- };
105
- const assertProfilesPresent = () => {
106
- if (getAvailableProfiles().length === 0) halt(dedent`
107
- No AWS profiles found.
108
- Run "aws configure sso" to set up SSO-enabled profile.
109
- Check the wiki for more information:
110
- https://raisenow.atlassian.net/wiki/x/lIrWvg
111
- `);
112
- };
113
- const getAvailableProfiles = () => {
114
- const { stdout } = execaCommandSync("aws configure list-profiles");
115
- return stdout.split("\n");
116
- };
117
- /**
118
- * Returns caller identity data (output is ignored here).
119
- * Fails in case of expired SSO session.
120
- */
121
- const checkIdentity = (options) => {
122
- execaCommandSync(`aws sts get-caller-identity ${prepareFlags(options)}`);
123
- };
124
- /**
125
- * Opens SSO authentication page in the browser.
126
- * Fails if user canceled authentication process.
127
- */
128
- const login = (options) => {
129
- const flags = prepareFlags(options);
130
- try {
131
- execaCommandSync(`aws sso login ${flags}`, { stdio: "inherit" });
132
- console.log("");
133
- } catch {
134
- halt("Login failed.");
135
- }
136
- };
137
- const prepareFlags = (options) => {
138
- const flags = [];
139
- const { profile } = options;
140
- if (profile) flags.push(`--profile ${profile}`);
141
- return flags.join(" ");
142
- };
143
- const assertProfileValid = (profile) => {
144
- const profiles = getAvailableProfiles();
145
- if (!profiles.includes(profile)) halt(dedent`
146
- AWS profile "${profile}" is not found.
147
- Available profiles are: ${profiles.map((v) => `"${v}"`).join(", ")}.
148
- `);
149
- };
150
- const promptProfile = async () => {
151
- const { profile } = await prompts([{
152
- choices: getAvailableProfiles().filter((v) => !!v).map((v) => ({
153
- title: v,
154
- value: v
155
- })),
156
- message: "Select AWS profile",
157
- name: "profile",
158
- type: "select"
159
- }], { onCancel: () => halt() });
160
- return profile;
161
- };
162
- const s3 = new S3({});
163
- const getConfigDeployments = async (configName) => {
164
- const widgetJs = (await s3.listObjectsV2({
165
- Bucket: "tamaro.raisenow.com",
166
- Prefix: `${configName}/`
167
- })).Contents?.filter((file) => file.Key?.endsWith(`/index.html`)) ?? [];
168
- const deployments = [];
169
- for (const file of widgetJs) {
170
- const key = file.Key ?? "";
171
- const parts = key.split("/");
172
- if (parts.length < 2 || !file.LastModified) continue;
173
- const tag = parts.at(-2);
174
- const date = file.LastModified.toISOString();
175
- const fullUrl = `https://${AWS_S3_BUCKET_TAMARO}/${key}`;
176
- deployments.push({
177
- date,
178
- fullUrl,
179
- tag
180
- });
181
- }
182
- return deployments;
183
- };
184
- //#endregion
185
39
  //#region src/lib/resolve.ts
186
40
  const resolveAccountUuidFromConfig = (rawConfig, field) => {
187
41
  const epmsConfig = z.object({ [field]: z.record(z.string(), z.unknown()) }).safeParse(rawConfig);
@@ -292,6 +146,11 @@ const createAuthorizer = (baseUrl, clientId, clientSecret) => {
292
146
  }] } });
293
147
  };
294
148
  //#endregion
149
+ //#region src/lib/logging.ts
150
+ const createTerminalLink = (text, url) => {
151
+ return `\u001B]8;;${url}\u001B\\${text}\u001B]8;;\u001B\\`;
152
+ };
153
+ //#endregion
295
154
  //#region src/lib/epms/auth/authCallback.html
296
155
  var authCallback_default = "<!doctype html>\n<html>\n <head\n ><title>Authenticating</title></head\n >\n <body>\n <p>Authenticating</p>\n <script>\n const hash = window.location.hash.substring(1)\n const params = new URLSearchParams(hash)\n const data = {\n access_token: params.get('access_token'),\n token_type: params.get('token_type'),\n expires_in: parseInt(params.get('expires_in') || '0', 10),\n }\n fetch('/token', {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify(data),\n })\n .then(() => {\n document.querySelector('p').textContent =\n 'Authentication successful! You can close this tab.'\n })\n .catch(() => {\n document.querySelector('p').textContent =\n 'Authentication failed. Please try again.'\n })\n <\/script>\n </body>\n</html>\n";
297
156
  //#endregion
@@ -516,17 +375,6 @@ const assertUserIsSuperAdmin = async (epmsClient) => {
516
375
  }
517
376
  };
518
377
  //#endregion
519
- //#region src/lib/notifier.ts
520
- const notify = (args) => {
521
- const { message = "", title } = args;
522
- notifier.notify({
523
- contentImage: "https://assets.raisenow.io/favicon.png",
524
- message: dedent(message),
525
- sound: "Funk",
526
- title
527
- });
528
- };
529
- //#endregion
530
378
  //#region src/commands/archive.ts
531
379
  const archive = async (options) => {
532
380
  assertIsNotArchived();
@@ -585,7 +433,7 @@ const archiveEpms = async (configName, dryrun) => {
585
433
  };
586
434
  const assertOptionsValid$7 = (options) => {
587
435
  const { profile } = options;
588
- if (profile) assertProfileValid(profile);
436
+ if (profile) assertAwsProfileValid(profile);
589
437
  };
590
438
  const assertIsNotArchived = () => {
591
439
  if (path.basename(path.dirname(process.cwd())) === "_archived") halt("This configuration is already archived.");
@@ -780,21 +628,15 @@ const getOutDir = (configName) => {
780
628
  return path.resolve(getConfigsPackageRoot(), "dist", configName);
781
629
  };
782
630
  //#endregion
783
- //#region src/lib/validators/assertTagValid.ts
784
- const assertTagValid = (tag) => {
785
- const regex = /^[\w.-]+$/;
786
- if (!regex.test(tag)) halt(`Flag "--tag" has forbidden format. Allowed format: ${regex.toString()}.`);
787
- };
788
- //#endregion
789
631
  //#region src/commands/update-epms.ts
790
632
  const updateEpms = async (options) => {
791
633
  const configName = getConfigName();
792
634
  if (!options.profile && !options.ci) {
793
- assertProfilesPresent();
794
- options.profile = await promptProfile();
635
+ assertAwsProfilesPresent();
636
+ options.profile = await promptAwsProfile();
795
637
  }
796
638
  if (options.profile) {
797
- assertProfileValid(options.profile);
639
+ assertAwsProfileValid(options.profile);
798
640
  process.env.AWS_PROFILE = options.profile;
799
641
  }
800
642
  awsAuthenticate(options);
@@ -864,13 +706,13 @@ const deploy = async (options) => {
864
706
  const outDir = getOutDir(configName);
865
707
  assertOutDir(configName);
866
708
  if (!options.profile && !options.ci) {
867
- assertProfilesPresent();
868
- options.profile = await promptProfile();
709
+ assertAwsProfilesPresent();
710
+ options.profile = await promptAwsProfile();
869
711
  }
870
712
  assertOptionsValid$6(options);
871
713
  await validate();
872
714
  awsAuthenticate(options);
873
- const flags = prepareFlags(options);
715
+ const flags = prepareAwsCliFlags(options);
874
716
  const { dryrun, tag } = options;
875
717
  const dryRunFlag = dryrun ? `--dryrun` : "";
876
718
  const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}`;
@@ -879,54 +721,47 @@ const deploy = async (options) => {
879
721
  /**
880
722
  * Sync all files except entrypoint (without deleting old files)
881
723
  */
882
- const cmdSyncAll = `
883
- aws s3 sync ${outDir} ${deployUrl}
884
- --acl public-read
885
- --exclude ${outDir}/${entryFilename}
886
- --cache-control max-age=31536000
887
- ${flags}
888
- ${dryRunFlag}
889
- `;
890
- logTitle("Deploying to AWS S3...");
891
- logCommand(cmdSyncAll);
892
724
  try {
893
- runCommandSync(cmdSyncAll, { stdout: "inherit" });
725
+ logTitle("Deploying to AWS S3...");
726
+ runCommandSync(dedent`
727
+ aws s3 sync ${outDir} ${deployUrl}
728
+ --acl public-read
729
+ --exclude ${outDir}/${entryFilename}
730
+ --cache-control max-age=31536000
731
+ ${flags}
732
+ ${dryRunFlag}
733
+ `, { stdout: "inherit" });
894
734
  } catch (error) {
895
735
  halt(error.stderr);
896
736
  }
897
737
  /**
898
738
  * Copy entrypoint
899
739
  */
900
- const cmdCpEntry = `
901
- aws s3 cp ${outDir}/${entryFilename} ${deployUrl}/${entryFilename}
902
- --acl public-read
903
- --cache-control max-age=64800
904
- ${flags}
905
- ${dryRunFlag}
906
- `;
907
- logCommand(cmdCpEntry);
908
740
  try {
909
- runCommandSync(cmdCpEntry, { stdout: "inherit" });
741
+ runCommandSync(dedent`
742
+ aws s3 cp ${outDir}/${entryFilename} ${deployUrl}/${entryFilename}
743
+ --acl public-read
744
+ --cache-control max-age=64800
745
+ ${flags}
746
+ ${dryRunFlag}
747
+ `, { stdout: "inherit" });
910
748
  } catch (error) {
911
749
  halt(error.stderr);
912
750
  }
913
- if (!dryRunFlag) {
914
- /**
915
- * Invalidate cloudfront cache
916
- */
917
- const cmdInvalidateCache = `
918
- aws cloudfront create-invalidation
919
- --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
920
- --paths /${configName}/${tag}/*
921
- ${flags}
922
- `;
751
+ if (!dryRunFlag)
752
+ /**
753
+ * Invalidate cloudfront cache
754
+ */
755
+ try {
923
756
  logTitle("\nInvalidating edge cache...");
924
- logCommand(cmdInvalidateCache);
925
- try {
926
- runCommandSync(cmdInvalidateCache);
927
- } catch (error) {
928
- halt(error.stderr);
929
- }
757
+ runCommandSync(dedent`
758
+ aws cloudfront create-invalidation
759
+ --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
760
+ --paths /${configName}/${tag}/*
761
+ ${flags}
762
+ `);
763
+ } catch (error) {
764
+ halt(error.stderr);
930
765
  }
931
766
  if (options.forceSkipEpmsSync) logTitle("⚠️ EPMS sync skipped. You better know what you are doing.");
932
767
  else await updateEpms(options);
@@ -939,7 +774,7 @@ const deploy = async (options) => {
939
774
  });
940
775
  process.on("exit", () => {
941
776
  notify({
942
- message: dedent`
777
+ message: `
943
778
  Bundle for "${configName}" is deployed with tag "${tag}".
944
779
  Demo page: ${demoPage}
945
780
  Entry point: ${entryPoint}
@@ -950,36 +785,20 @@ const deploy = async (options) => {
950
785
  };
951
786
  const assertOptionsValid$6 = (options) => {
952
787
  const { profile, tag } = options;
953
- if (profile) assertProfileValid(profile);
788
+ if (profile) assertAwsProfileValid(profile);
954
789
  assertTagValid(tag);
955
790
  };
956
791
  //#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
792
  //#region src/commands/preview.ts
974
793
  const preview = async () => {
975
794
  const configName = getConfigName();
976
795
  const configsPackageRoot = getConfigsPackageRoot();
796
+ const relativeOutDir = path.relative(configsPackageRoot, getOutDir(configName));
977
797
  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, {
798
+ assertCrtExists(configsPackageRoot);
799
+ const port = await getPortPromise({ port: Number(DEFAULT_PORT) });
800
+ logTitle("\nRunning web-server for pre-built bundle...");
801
+ runCommandSync(`pnpm sirv ${relativeOutDir} --cors --http2 --cert localhost.crt --key localhost.key --port ${port}`, {
983
802
  cwd: configsPackageRoot,
984
803
  stdio: "inherit"
985
804
  });
@@ -991,27 +810,23 @@ const build = async (options) => {
991
810
  const configsPackageRoot = getConfigsPackageRoot();
992
811
  const outDir = getOutDir(configName);
993
812
  if (options.deploy && !options.profile && !options.ci) {
994
- assertProfilesPresent();
995
- options.profile = await promptProfile();
813
+ assertAwsProfilesPresent();
814
+ options.profile = await promptAwsProfile();
996
815
  }
997
816
  assertOptionsValid$5(options);
998
817
  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
818
  logTitle(`Building optimised (minified) bundle of "${configName}" customer configuration...`);
1007
- logCommand(cmd);
1008
- runCommandSync(cmd, {
819
+ runCommandSync(`pnpm vite build`, {
1009
820
  cwd: configsPackageRoot,
1010
- env,
821
+ env: {
822
+ BABEL: options.babel ? "true" : "false",
823
+ CONFIG_NAME: configName,
824
+ MINIFY: options.minify ? "true" : "false"
825
+ },
1011
826
  stdio: "inherit"
1012
827
  });
1013
828
  logTitle(`\nBundle for "${configName}" customer configuration is done.`);
1014
- console$1.log(`Path: ${outDir}\n`);
829
+ console.log(`Path: ${outDir}\n`);
1015
830
  process.on("exit", () => {
1016
831
  notify({
1017
832
  message: `Bundle for "${configName}" customer configuration is done.`,
@@ -1022,8 +837,9 @@ const build = async (options) => {
1022
837
  if (options.deploy) await deploy(options);
1023
838
  };
1024
839
  const assertOptionsValid$5 = (options) => {
1025
- const { profile } = options;
1026
- if (profile) assertProfileValid(profile);
840
+ const { preview, profile } = options;
841
+ if (preview) assertCrtExists(getConfigsPackageRoot());
842
+ if (profile) assertAwsProfileValid(profile);
1027
843
  };
1028
844
  //#endregion
1029
845
  //#region src/commands/deploy-email-config.ts
@@ -1032,28 +848,26 @@ const deployEmailConfig = async (options) => {
1032
848
  const emailConfigPath = `${getInputDir(configName)}/email-config`;
1033
849
  assertEmailConfigPathExists(emailConfigPath);
1034
850
  if (!options.profile && !options.ci) {
1035
- assertProfilesPresent();
1036
- options.profile = await promptProfile();
851
+ assertAwsProfilesPresent();
852
+ options.profile = await promptAwsProfile();
1037
853
  }
1038
854
  if (!options.bucket) options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await promptBucketTamaroEmailConfig$1();
1039
855
  assertOptionsValid$4(options);
1040
856
  await validate();
1041
857
  awsAuthenticate(options);
1042
- const flags = prepareFlags(options);
858
+ const flags = prepareAwsCliFlags(options);
1043
859
  const dryRunFlag = options.dryrun ? `--dryrun` : "";
1044
860
  const deployUrl = `s3://${options.bucket}/${configName}`;
1045
861
  if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
1046
- const cmd = `
1047
- aws s3 sync ${emailConfigPath} ${deployUrl}
1048
- --delete
1049
- --exact-timestamps
1050
- ${flags}
1051
- ${dryRunFlag}
1052
- `;
1053
- logTitle(`Deploying email configuration for "${configName}" customer configuration to AWS S3...`);
1054
- logCommand(cmd);
1055
862
  try {
1056
- runCommandSync(cmd, { stdout: "inherit" });
863
+ logTitle(`Deploying email configuration for "${configName}" customer configuration to AWS S3...`);
864
+ runCommandSync(dedent`
865
+ aws s3 sync ${emailConfigPath} ${deployUrl}
866
+ --delete
867
+ --exact-timestamps
868
+ ${flags}
869
+ ${dryRunFlag}
870
+ `, { stdout: "inherit" });
1057
871
  } catch (error) {
1058
872
  halt(error.stderr);
1059
873
  }
@@ -1068,7 +882,7 @@ const deployEmailConfig = async (options) => {
1068
882
  };
1069
883
  const assertOptionsValid$4 = (options) => {
1070
884
  const { bucket, profile } = options;
1071
- if (profile) assertProfileValid(profile);
885
+ if (profile) assertAwsProfileValid(profile);
1072
886
  if (bucket) assertBucketValid$1(bucket);
1073
887
  };
1074
888
  const assertEmailConfigPathExists = (distPath) => {
@@ -1097,17 +911,15 @@ const promptBucketTamaroEmailConfig$1 = async () => {
1097
911
  const dev = async (options) => {
1098
912
  const configName = getConfigName();
1099
913
  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
- };
914
+ assertCrtExists(configsPackageRoot);
915
+ const port = await getPortPromise({ port: Number(DEFAULT_PORT) });
1106
916
  logTitle(`\nStarting Vite dev server for "${configName}" configuration...`);
1107
- logCommand(cmd);
1108
- runCommandSync(cmd, {
917
+ runCommandSync(`pnpm vite dev --port ${port}`, {
1109
918
  cwd: configsPackageRoot,
1110
- env,
919
+ env: {
920
+ CONFIG_NAME: configName,
921
+ LOCAL_CORE: options.localCore ? "true" : "false"
922
+ },
1111
923
  stdio: "inherit"
1112
924
  });
1113
925
  };
@@ -1116,18 +928,14 @@ const dev = async (options) => {
1116
928
  const format = () => {
1117
929
  const configsPackageRoot = getConfigsPackageRoot();
1118
930
  const relativeCwd = path.relative(configsPackageRoot, process.cwd());
1119
- const cmd1 = "pnpm prettier --write . \"!configs/**\"";
1120
931
  logTitle("Formatting root with Prettier...");
1121
- logCommand(cmd1);
1122
- runCommandSync(cmd1, {
932
+ runCommandSync("pnpm prettier --write . \"!configs/**\"", {
1123
933
  cwd: configsPackageRoot,
1124
934
  shell: true,
1125
935
  stdio: "inherit"
1126
936
  });
1127
- const cmd2 = `pnpm prettier --write ${relativeCwd}`;
1128
937
  logTitle(`\nFormatting config folder "${relativeCwd}" with Prettier...`);
1129
- logCommand(cmd2);
1130
- runCommandSync(cmd2, {
938
+ runCommandSync(`pnpm prettier --write ${relativeCwd}`, {
1131
939
  cwd: configsPackageRoot,
1132
940
  shell: true,
1133
941
  stdio: "inherit"
@@ -1138,23 +946,16 @@ const format = () => {
1138
946
  const lint = () => {
1139
947
  const configsPackageRoot = getConfigsPackageRoot();
1140
948
  const relativeCwd = path.relative(configsPackageRoot, process.cwd());
1141
- const env = {
1142
- ...process.env,
1143
- DEBUG: "eslint:eslint-helpers"
1144
- };
1145
- const cmd1 = "pnpm eslint --ignore-pattern \"configs/\" .";
949
+ const env = { DEBUG: "eslint:eslint-helpers" };
1146
950
  logTitle("Linting root with ESLint...");
1147
- logCommand(cmd1);
1148
- runCommandSync(cmd1, {
951
+ runCommandSync("pnpm eslint --ignore-pattern \"configs/\" .", {
1149
952
  cwd: configsPackageRoot,
1150
953
  env,
1151
954
  shell: true,
1152
955
  stdio: "inherit"
1153
956
  });
1154
- const cmd2 = `pnpm eslint ${relativeCwd}`;
1155
957
  logTitle(`\nLinting config folder "${relativeCwd}" with ESLint...`);
1156
- logCommand(cmd2);
1157
- runCommandSync(cmd2, {
958
+ runCommandSync(`pnpm eslint ${relativeCwd}`, {
1158
959
  cwd: configsPackageRoot,
1159
960
  env,
1160
961
  shell: true,
@@ -1162,12 +963,35 @@ const lint = () => {
1162
963
  });
1163
964
  };
1164
965
  //#endregion
966
+ //#region src/lib/aws.ts
967
+ const getConfigDeployments = async (configName) => {
968
+ const widgetJs = (await new S3({}).listObjectsV2({
969
+ Bucket: "tamaro.raisenow.com",
970
+ Prefix: `${configName}/`
971
+ })).Contents?.filter((file) => file.Key?.endsWith(`/index.html`)) ?? [];
972
+ const deployments = [];
973
+ for (const file of widgetJs) {
974
+ const key = file.Key ?? "";
975
+ const parts = key.split("/");
976
+ if (parts.length < 2 || !file.LastModified) continue;
977
+ const tag = parts.at(-2);
978
+ const date = file.LastModified.toISOString();
979
+ const fullUrl = `https://${AWS_S3_BUCKET_TAMARO}/${key}`;
980
+ deployments.push({
981
+ date,
982
+ fullUrl,
983
+ tag
984
+ });
985
+ }
986
+ return deployments;
987
+ };
988
+ //#endregion
1165
989
  //#region src/commands/list-deployed.ts
1166
990
  const listDeployed = async (options) => {
1167
991
  const configName = getConfigName();
1168
992
  if (!options.profile && !options.ci) {
1169
- assertProfilesPresent();
1170
- options.profile = await promptProfile();
993
+ assertAwsProfilesPresent();
994
+ options.profile = await promptAwsProfile();
1171
995
  }
1172
996
  assertOptionsValid$3(options);
1173
997
  awsAuthenticate(options);
@@ -1198,16 +1022,15 @@ const listDeployed = async (options) => {
1198
1022
  };
1199
1023
  const assertOptionsValid$3 = (options) => {
1200
1024
  const { profile } = options;
1201
- if (profile) assertProfileValid(profile);
1025
+ if (profile) assertAwsProfileValid(profile);
1202
1026
  };
1203
1027
  //#endregion
1204
1028
  //#region src/commands/typecheck.ts
1205
1029
  const typecheck = () => {
1206
1030
  const configsPackageRoot = getConfigsPackageRoot();
1207
- const cmd = `pnpm tsc --project ${path.relative(configsPackageRoot, process.cwd())}/tsconfig.json`;
1031
+ const relativeCwd = path.relative(configsPackageRoot, process.cwd());
1208
1032
  logTitle("Running TypeScript type-checking...");
1209
- logCommand(cmd);
1210
- runCommandSync(cmd, {
1033
+ runCommandSync(`pnpm tsc --project ${relativeCwd}/tsconfig.json`, {
1211
1034
  cwd: configsPackageRoot,
1212
1035
  stdio: "inherit"
1213
1036
  });
@@ -1271,7 +1094,7 @@ const unarchiveEpms = async (configName, dryrun) => {
1271
1094
  };
1272
1095
  const assertOptionsValid$2 = (options) => {
1273
1096
  const { profile } = options;
1274
- if (profile) assertProfileValid(profile);
1097
+ if (profile) assertAwsProfileValid(profile);
1275
1098
  };
1276
1099
  const assertIsArchived = () => {
1277
1100
  if (path.basename(path.dirname(process.cwd())) !== "_archived") halt("This configuration is not archived. Only archived configurations can be unarchived.");
@@ -1284,42 +1107,39 @@ const assertRestoreTargetDoesNotExist = (restoreTarget) => {
1284
1107
  const undeploy = async (options) => {
1285
1108
  const configName = getConfigName();
1286
1109
  if (!options.profile && !options.ci) {
1287
- assertProfilesPresent();
1288
- options.profile = await promptProfile();
1110
+ assertAwsProfilesPresent();
1111
+ options.profile = await promptAwsProfile();
1289
1112
  }
1290
1113
  assertOptionsValid$1(options);
1291
1114
  awsAuthenticate(options);
1292
- const flags = prepareFlags(options);
1115
+ const flags = prepareAwsCliFlags(options);
1293
1116
  const { all, dryrun, tag = DEFAULT_TAG } = options;
1294
1117
  const dryRunFlag = dryrun ? `--dryrun` : "";
1295
1118
  const deployUrl = all ? `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/` : `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/`;
1296
1119
  const description = all ? `all tags of "${configName}"` : `tag "${tag}" of "${configName}"`;
1297
1120
  if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
1298
- await promptConfirmation(`Are you sure you want to undeploy ${description}?`, options.ci);
1299
- const cmd = `
1300
- aws s3 rm ${deployUrl}
1301
- --recursive
1302
- ${flags}
1303
- ${dryRunFlag}
1304
- `;
1305
- logTitle(`Undeploying ${description} from AWS S3...`);
1306
- logCommand(cmd);
1121
+ if (!options.ci) await promptConfirmation(`Are you sure you want to undeploy ${description}?`);
1307
1122
  try {
1308
- runCommandSync(cmd, { stdout: "inherit" });
1123
+ logTitle(`Undeploying ${description} from AWS S3...`);
1124
+ runCommandSync(dedent`
1125
+ aws s3 rm ${deployUrl}
1126
+ --recursive
1127
+ ${flags}
1128
+ ${dryRunFlag}
1129
+ `, { stdout: "inherit" });
1309
1130
  } catch (error) {
1310
1131
  halt(error.stderr);
1311
1132
  }
1312
1133
  if (!dryRunFlag) {
1313
- const cmdInvalidateCache = `
1314
- aws cloudfront create-invalidation
1315
- --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
1316
- --paths ${all ? `/${configName}/*` : `/${configName}/${tag}/*`}
1317
- ${flags}
1318
- `;
1319
- logTitle("\nInvalidating edge cache...");
1320
- logCommand(cmdInvalidateCache);
1134
+ const invalidationPath = all ? `/${configName}/*` : `/${configName}/${tag}/*`;
1321
1135
  try {
1322
- runCommandSync(cmdInvalidateCache);
1136
+ logTitle("\nInvalidating edge cache...");
1137
+ runCommandSync(dedent`
1138
+ aws cloudfront create-invalidation
1139
+ --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
1140
+ --paths ${invalidationPath}
1141
+ ${flags}
1142
+ `);
1323
1143
  } catch (error) {
1324
1144
  halt(error.stderr);
1325
1145
  }
@@ -1335,7 +1155,7 @@ const undeploy = async (options) => {
1335
1155
  };
1336
1156
  const assertOptionsValid$1 = (options) => {
1337
1157
  const { all, profile, tag } = options;
1338
- if (profile) assertProfileValid(profile);
1158
+ if (profile) assertAwsProfileValid(profile);
1339
1159
  if (all && tag) halt("Flags \"--tag\" and \"--all\" must not be used together.");
1340
1160
  if (!all && tag) assertTagValid(tag);
1341
1161
  };
@@ -1344,8 +1164,8 @@ const assertOptionsValid$1 = (options) => {
1344
1164
  const undeployEmailConfig = async (options) => {
1345
1165
  const configName = getConfigName();
1346
1166
  if (!options.profile && !options.ci) {
1347
- assertProfilesPresent();
1348
- options.profile = await promptProfile();
1167
+ assertAwsProfilesPresent();
1168
+ options.profile = await promptAwsProfile();
1349
1169
  }
1350
1170
  if (options.ci) options.bucket = AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD;
1351
1171
  if (!options.bucket) if (options.ci) options.bucket = AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD;
@@ -1354,21 +1174,19 @@ const undeployEmailConfig = async (options) => {
1354
1174
  else options.bucket = await promptBucketTamaroEmailConfig();
1355
1175
  assertOptionsValid(options);
1356
1176
  awsAuthenticate(options);
1357
- const flags = prepareFlags(options);
1177
+ const flags = prepareAwsCliFlags(options);
1358
1178
  const dryRunFlag = options.dryrun ? `--dryrun` : "";
1359
1179
  const deployUrl = `s3://${options.bucket}/${configName}/`;
1360
- await promptConfirmation(`Are you sure you want to undeploy the email configuration for "${configName}" from "${options.bucket}"?`, options.ci);
1180
+ if (!options.ci) await promptConfirmation(`Are you sure you want to undeploy the email configuration for "${configName}" from "${options.bucket}"?`);
1361
1181
  if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
1362
- const cmd = `
1363
- aws s3 rm ${deployUrl}
1364
- --recursive
1365
- ${flags}
1366
- ${dryRunFlag}
1367
- `;
1368
- logTitle(`Undeploying email configuration for "${configName}" from AWS S3...`);
1369
- logCommand(cmd);
1370
1182
  try {
1371
- runCommandSync(cmd, { stdout: "inherit" });
1183
+ logTitle(`Undeploying email configuration for "${configName}" from AWS S3...`);
1184
+ runCommandSync(dedent`
1185
+ aws s3 rm ${deployUrl}
1186
+ --recursive
1187
+ ${flags}
1188
+ ${dryRunFlag}
1189
+ `, { stdout: "inherit" });
1372
1190
  } catch (error) {
1373
1191
  halt(error.stderr);
1374
1192
  }
@@ -1383,7 +1201,7 @@ const undeployEmailConfig = async (options) => {
1383
1201
  };
1384
1202
  const assertOptionsValid = (options) => {
1385
1203
  const { bucket, profile } = options;
1386
- if (profile) assertProfileValid(profile);
1204
+ if (profile) assertAwsProfileValid(profile);
1387
1205
  if (bucket) assertBucketValid(bucket);
1388
1206
  };
1389
1207
  const assertBucketValid = (bucket) => {
@@ -1407,25 +1225,17 @@ const promptBucketTamaroEmailConfig = async () => {
1407
1225
  //#endregion
1408
1226
  //#region package.json
1409
1227
  var name = "@raisenow/tamaro-cli";
1410
- var version = "3.0.0-dev.2";
1228
+ var version = "3.0.0-dev.4";
1411
1229
  //#endregion
1412
1230
  //#region src/cli.ts
1413
- /**
1414
- * Makes the script crash on unhandled rejections instead of silently
1415
- * ignoring them. In the future, promise rejections that are not handled will
1416
- * terminate the Node.js process with a non-zero exit code.
1417
- */
1418
- process.on("unhandledRejection", (error) => {
1419
- throw error;
1420
- });
1421
1231
  const cli = createCommand().name(name).description("CLI for Tamaro Customer Configurations development").version(version, "-v, --version");
1422
1232
  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);
1423
1233
  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);
1424
1234
  cli.command("preview").description("Run a local web server for pre-built bundle").action(preview);
1425
- 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);
1235
+ cli.command("deploy").description("Deploy a pre-built 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);
1426
1236
  cli.command("list-deployed").description("List deployments of customer configuration").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).action(listDeployed);
1427
1237
  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);
1428
- 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);
1238
+ cli.command("undeploy").description("Undeploy a 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);
1429
1239
  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);
1430
1240
  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);
1431
1241
  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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raisenow/tamaro-cli",
3
- "version": "3.0.0-dev.2",
3
+ "version": "3.0.0-dev.4",
4
4
  "author": {
5
5
  "name": "RaiseNow",
6
6
  "email": "development@raisenow.com"
@@ -13,20 +13,19 @@
13
13
  "yarn": "please-use-pnpm"
14
14
  },
15
15
  "dependencies": {
16
- "@aws-sdk/client-s3": "^3.1068.0",
17
- "chalk": "^5.6.2",
16
+ "@aws-sdk/client-s3": "^3.1070.0",
17
+ "@rnw-npm/cli-helpers": "^2.0.0",
18
18
  "columnify": "^1.6.0",
19
- "commander": "^14.0.3",
19
+ "commander": "^15.0.0",
20
20
  "dedent": "^1.7.2",
21
21
  "dotenv": "^17.4.2",
22
22
  "env-paths": "^4.0.0",
23
23
  "execa": "^9.6.1",
24
24
  "glob": "^13.0.6",
25
- "handlebars-helpers": "^0.10.0",
26
25
  "handlebars": "^4.7.9",
26
+ "handlebars-helpers": "^0.10.0",
27
27
  "js-yaml": "^4.2.0",
28
28
  "ky": "^1.14.3",
29
- "node-notifier": "^10.0.1",
30
29
  "open": "^11.0.0",
31
30
  "portfinder": "^1.0.38",
32
31
  "prompts": "^2.4.2",
@@ -38,16 +37,15 @@
38
37
  "@types/columnify": "^1.5.4",
39
38
  "@types/handlebars-helpers": "^0.5.6",
40
39
  "@types/js-yaml": "^4.0.9",
41
- "@types/node-notifier": "^8.0.5",
42
40
  "@types/node": "^24.13.2",
43
41
  "@types/prompts": "^2.4.9",
44
42
  "eslint": "^10.5.0",
45
43
  "husky": "^9.1.7",
46
- "lint-staged": "^16.4.0",
44
+ "lint-staged": "^17.0.7",
47
45
  "prettier": "^3.8.4",
48
46
  "tsdown": "^0.22.2",
49
47
  "typescript": "^6.0.3",
50
- "vitest": "^4.1.7"
48
+ "vitest": "^4.1.9"
51
49
  },
52
50
  "prettier": "@rnw-npm/prettier-config",
53
51
  "lint-staged": {