@raisenow/tamaro-cli 1.5.0 → 1.6.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.
Files changed (123) hide show
  1. package/.history/.eslintignore_20220609190420 +4 -0
  2. package/.history/.eslintignore_20230911190227 +6 -0
  3. package/.history/.eslintignore_20230911211247 +7 -0
  4. package/.history/.eslintignore_20230911211250 +7 -0
  5. package/.history/.eslintrc_20230911201601.js +49 -0
  6. package/.history/.eslintrc_20230911201643.js +49 -0
  7. package/.history/.eslintrc_20230911201735.js +49 -0
  8. package/.history/.eslintrc_20230911201913.js +64 -0
  9. package/.history/.eslintrc_20230911202002.js +62 -0
  10. package/.history/.eslintrc_20230911202138.js +133 -0
  11. package/.history/.eslintrc_20230911202140.js +133 -0
  12. package/.history/.eslintrc_20230911202145.js +133 -0
  13. package/.history/.eslintrc_20230911202147.js +133 -0
  14. package/.history/.eslintrc_20230911202406.js +133 -0
  15. package/.history/.eslintrc_20230911202447.js +133 -0
  16. package/.history/.eslintrc_20230911202453.js +133 -0
  17. package/.history/.eslintrc_20230911202511.js +133 -0
  18. package/.history/.eslintrc_20230911202527.js +133 -0
  19. package/.history/.eslintrc_20230911202639.js +125 -0
  20. package/.history/.eslintrc_20230911202721.js +149 -0
  21. package/.history/.eslintrc_20230911202746.js +149 -0
  22. package/.history/.eslintrc_20240423125702.cjs +148 -0
  23. package/.history/.gitignore_20220609190420 +14 -0
  24. package/.history/.gitignore_20230911185959 +4 -0
  25. package/.history/.gitignore_20230911190006 +4 -0
  26. package/.history/.gitignore_20230911190007 +4 -0
  27. package/.history/.nmprc_20241004144025 +0 -0
  28. package/.history/.nmprc_20241004144041 +1 -0
  29. package/.history/.npmrc_20241004144040 +1 -0
  30. package/.history/.npmrc_20241004144152 +1 -0
  31. package/.history/.npmrc_20241004145639 +2 -0
  32. package/.history/.npmrc_20241004145649 +1 -0
  33. package/.history/.nvmrc_20250729181039 +1 -0
  34. package/.history/.prettierignore_20220609190420 +5 -0
  35. package/.history/.prettierignore_20230911190242 +7 -0
  36. package/.history/.prettierignore_20230911190245 +7 -0
  37. package/.history/.prettierignore_20230911211301 +8 -0
  38. package/.history/CHANGELOG_20250729195139.md +28 -0
  39. package/.history/CHANGELOG_20250729195148.md +29 -0
  40. package/.history/CHANGELOG_20250729195156.md +28 -0
  41. package/.history/CHANGELOG_20250729195218.md +29 -0
  42. package/.history/CHANGELOG_20250729195223.md +27 -0
  43. package/.history/CHANGELOG_20250729195506.md +29 -0
  44. package/.history/CHANGELOG_20250729224404.md +30 -0
  45. package/.history/CHANGELOG_20250729224411.md +30 -0
  46. package/.history/CHANGELOG_20250730124538.md +41 -0
  47. package/.history/CHANGELOG_20250730124603.md +38 -0
  48. package/.history/CHANGELOG_20250730124627.md +36 -0
  49. package/.history/CHANGELOG_20250730124638.md +36 -0
  50. package/.history/CHANGELOG_20250730124640.md +36 -0
  51. package/.history/README_20230911145033.md +245 -0
  52. package/.history/README_20230911151749.md +245 -0
  53. package/.history/README_20230911151844.md +245 -0
  54. package/.history/README_20230911153040.md +245 -0
  55. package/.history/README_20230911202959.md +245 -0
  56. package/.history/bitbucket-pipelines_20250729111540.yml +46 -0
  57. package/.history/bitbucket-pipelines_20250729210338.yml +46 -0
  58. package/.history/bitbucket-pipelines_20250729210340.yml +46 -0
  59. package/.history/bitbucket-pipelines_20250729210342.yml +46 -0
  60. package/.history/bitbucket-pipelines_20250729222234.yml +47 -0
  61. package/.history/bitbucket-pipelines_20250729222554.yml +47 -0
  62. package/.history/bitbucket-pipelines_20250729222555.yml +47 -0
  63. package/.history/bitbucket-pipelines_20250729223022.yml +46 -0
  64. package/.history/bitbucket-pipelines_20250729223024.yml +46 -0
  65. package/.history/cli_20241005014539 +3 -0
  66. package/.history/cli_20241005014542 +3 -0
  67. package/.history/cli_20241005014848 +3 -0
  68. package/.history/dist/chunk-FICM3HUI_20230912183408.js +302 -0
  69. package/{dist/chunk-HGPQTHLY.js → .history/dist/chunk-FICM3HUI_20230912201610.js} +31 -50
  70. package/.history/package_20250729182417.json +111 -0
  71. package/.history/package_20250729182419.json +111 -0
  72. package/.history/package_20250729182618.json +110 -0
  73. package/.history/package_20250729182834.json +110 -0
  74. package/.history/package_20250729183032.json +110 -0
  75. package/.history/package_20250729183033.json +110 -0
  76. package/.history/package_20250729185750.json +110 -0
  77. package/.history/package_20250729185815.json +110 -0
  78. package/.history/package_20250729185846.json +110 -0
  79. package/.history/package_20250729185854.json +110 -0
  80. package/.history/package_20250729185943.json +110 -0
  81. package/.history/package_20250729190645.json +110 -0
  82. package/.history/package_20250729195934.json +110 -0
  83. package/.history/package_20250729200013.json +110 -0
  84. package/.history/package_20250729200056.json +110 -0
  85. package/.history/package_20250729200434.json +110 -0
  86. package/.history/package_20250729200808.json +110 -0
  87. package/.history/package_20250729200944.json +110 -0
  88. package/.history/package_20250729214420.json +114 -0
  89. package/.history/package_20250729223112.json +110 -0
  90. package/.history/package_20250729223127.json +110 -0
  91. package/.history/package_20250729223134.json +110 -0
  92. package/.history/package_20250730124647.json +114 -0
  93. package/.history/tsconfig_20241005001442.json +34 -0
  94. package/.history/tsconfig_20241005001500.json +34 -0
  95. package/.history/tsconfig_20241005001540.json +34 -0
  96. package/.history/tsconfig_20241005014429.json +42 -0
  97. package/.history/tsconfig_20241005014436.json +42 -0
  98. package/.history/tsconfig_20241005014439.json +38 -0
  99. package/.history/tsconfig_20241005014455.json +38 -0
  100. package/.history/tsconfig_20241005014521.json +38 -0
  101. package/.history/vitest.config_20250729214539.ts +0 -0
  102. package/.history/vitest.config_20250729214659.ts +24 -0
  103. package/.history/vitest.config_20250729214748.ts +21 -0
  104. package/.history/vitest.config_20250729214825.ts +21 -0
  105. package/.history/vitest.config_20250729214902.ts +21 -0
  106. package/.history/vitest.config_20250729222125.ts +20 -0
  107. package/.history/vitest.config_20250729222213.ts +20 -0
  108. package/.idea/codeStyles/Project.xml +131 -0
  109. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  110. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  111. package/.idea/misc.xml +17 -0
  112. package/.idea/modules.xml +8 -0
  113. package/.idea/prettier.xml +6 -0
  114. package/.idea/tamaro-cli.iml +12 -0
  115. package/.idea/vcs.xml +6 -0
  116. package/.nvmrc +1 -1
  117. package/bitbucket-pipelines.yml +1 -1
  118. package/dist/cli.js +559 -845
  119. package/dist/env-Cpc7KHou.js +245 -0
  120. package/dist/webpack.config.js +310 -441
  121. package/package.json +37 -41
  122. package/pnpm-workspace.yaml +4 -0
  123. package/tsdown.config.ts +11 -0
package/dist/cli.js CHANGED
@@ -1,367 +1,315 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- AWS_CLOUDFRONT_DISTRIBUTION_ID,
4
- AWS_S3_BUCKET_TAMARO,
5
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD,
6
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
7
- CORE_CONFIG_NAME,
8
- DEFAULT_PORT,
9
- DEFAULT_TAG,
10
- HTTPS_CRT_FILE,
11
- HTTPS_KEY_FILE,
12
- applyEnv,
13
- assertEnvValid,
14
- getIfCoreFns,
15
- getPaths,
16
- getWidgetUuid,
17
- halt,
18
- logCommand,
19
- logDataTable,
20
- logError,
21
- logTitle,
22
- resolveBin,
23
- resolveOwn,
24
- runCommandSync
25
- } from "./chunk-HGPQTHLY.js";
26
-
27
- // src/cli.ts
2
+ import { C as runCommandSync, D as logTitle, E as logError, S as halt, T as logDataTable, _ as CORE_CONFIG_NAME, a as getIfCoreFns, b as HTTPS_CRT_FILE, c as getWidgetUuid, f as resolveOwn, g as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE, h as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD, m as AWS_S3_BUCKET_TAMARO, n as assertEnvValid, o as getPaths, p as AWS_CLOUDFRONT_DISTRIBUTION_ID, t as applyEnv, u as resolveBin, v as DEFAULT_PORT, w as logCommand, x as HTTPS_KEY_FILE, y as DEFAULT_TAG } from "./env-Cpc7KHou.js";
28
3
  import { createCommand } from "commander";
29
-
30
- // src/commands/validate.ts
31
- import { glob } from "glob";
32
-
33
- // src/lib/validators/validateEmailTemplates.ts
34
- import fs from "fs";
4
+ import { globSync } from "glob";
5
+ import { execaCommandSync } from "execa";
6
+ import stripIndent from "strip-indent";
7
+ import fs from "node:fs";
35
8
  import Handlebars from "handlebars";
36
9
  import helpers from "handlebars-helpers";
37
- helpers.comparison({
38
- handlebars: Handlebars
39
- });
40
- var validateEmailTemplates = (templatePaths) => {
41
- const errors = [];
42
- for (const templatePath of templatePaths) {
43
- try {
44
- const template = fs.readFileSync(templatePath, "utf-8");
45
- assureOnlySupportedHelpers(template);
46
- compileEmailTemplate(template);
47
- console.log(`${templatePath} is a valid email template`);
48
- } catch (e) {
49
- errors.push(`${templatePath} is invalid`);
50
- errors.push(e);
51
- }
52
- }
53
- return errors;
54
- };
55
- var assureOnlySupportedHelpers = (template) => {
56
- const extractHelpers = (ast2) => {
57
- const usedHelpers2 = /* @__PURE__ */ new Set();
58
- const extractHelperName = (node) => {
59
- if (node.path?.type === "PathExpression" && (node.params?.length > 0 || node.hash?.pairs?.length > 0)) {
60
- return node.path?.original;
61
- }
62
- };
63
- const visit = (node) => {
64
- if (!node) {
65
- return;
66
- }
67
- switch (node.type) {
68
- case "MustacheStatement":
69
- case "BlockStatement": {
70
- const name = extractHelperName(node);
71
- if (name) {
72
- usedHelpers2.add(name);
73
- }
74
- break;
75
- }
76
- }
77
- for (const key in node) {
78
- const value = node[key];
79
- if (Array.isArray(value)) {
80
- value.forEach(visit);
81
- } else if (value && typeof value === "object" && value.type) {
82
- visit(value);
83
- }
84
- }
85
- };
86
- visit(ast2);
87
- return usedHelpers2;
88
- };
89
- const ast = Handlebars.parse(template);
90
- const usedHelpers = extractHelpers(ast);
91
- const supportedHelpers = /* @__PURE__ */ new Set([
92
- // Built-in Handlebars helpers
93
- "if",
94
- "unless",
95
- "each",
96
- "with",
97
- "log",
98
- "lookup",
99
- // Comparison helpers, provided by "handlebars-helpers" lib
100
- "and",
101
- "compare",
102
- "contains",
103
- "default",
104
- "eq",
105
- "gt",
106
- "gte",
107
- "has",
108
- "isFalsey",
109
- "isTruthy",
110
- "ifEven",
111
- "ifNth",
112
- "ifOdd",
113
- "is",
114
- "isnt",
115
- "lt",
116
- "lte",
117
- "neither",
118
- "not",
119
- "or",
120
- "unlessEq",
121
- "unlessGt",
122
- "unlessLt",
123
- "unlessGteq",
124
- "unlessLteq"
125
- ]);
126
- const unsupportedHelpers = Array.from(usedHelpers).filter(
127
- (h) => !supportedHelpers.has(h)
128
- );
129
- if (unsupportedHelpers.length > 0) {
130
- throw new Error(
131
- `Email template uses unsupported Handlebars helpers: ${unsupportedHelpers.join(", ")}`
132
- );
133
- }
134
- };
135
- var compileEmailTemplate = (template) => {
136
- const compiled = Handlebars.compile(template);
137
- compiled({});
10
+ import prompts from "prompts";
11
+ import { resolve } from "path";
12
+ import { existsSync } from "fs";
13
+ import notifier from "node-notifier";
14
+ import { getPortPromise } from "portfinder";
15
+
16
+ //#region src/lib/validators/validateEmailTemplates.ts
17
+ /**
18
+ * Register custom Handlebars helpers - the same, which are used in the Email Service.
19
+ * Make sure to update it if new helpers are added in the Email Service.
20
+ */
21
+ helpers.comparison({ handlebars: Handlebars });
22
+ /**
23
+ * Recurse through the expected email templates folder and attempt to parse
24
+ * handlebars template to validate their syntax.
25
+ */
26
+ const validateEmailTemplates = (templatePaths) => {
27
+ const errors = [];
28
+ for (const templatePath of templatePaths) try {
29
+ const template = fs.readFileSync(templatePath, "utf-8");
30
+ assureOnlySupportedHelpers(template);
31
+ compileEmailTemplate(template);
32
+ console.log(`${templatePath} is a valid email template`);
33
+ } catch (e) {
34
+ errors.push(`${templatePath} is invalid`);
35
+ errors.push(e);
36
+ }
37
+ return errors;
38
+ };
39
+ /**
40
+ * Validate that only supported Handlebars helpers are used in the template.
41
+ * This function extracts helpers from the template AST and checks them
42
+ * against a predefined set of supported helpers.
43
+ */
44
+ const assureOnlySupportedHelpers = (template) => {
45
+ /**
46
+ * Recursively extract helpers from the AST
47
+ */
48
+ const extractHelpers = (ast) => {
49
+ const usedHelpers = /* @__PURE__ */ new Set();
50
+ const extractHelperName = (node) => {
51
+ if (node.path?.type === "PathExpression" && (node.params?.length > 0 || node.hash?.pairs?.length > 0)) return node.path?.original;
52
+ };
53
+ const visit = (node) => {
54
+ if (!node) return;
55
+ switch (node.type) {
56
+ case "MustacheStatement":
57
+ case "BlockStatement": {
58
+ const name = extractHelperName(node);
59
+ if (name) usedHelpers.add(name);
60
+ break;
61
+ }
62
+ }
63
+ /**
64
+ * Recursively visit children of the AST node.
65
+ */
66
+ for (const key in node) {
67
+ const value = node[key];
68
+ if (Array.isArray(value)) value.forEach(visit);
69
+ else if (value && typeof value === "object" && value.type) visit(value);
70
+ }
71
+ };
72
+ visit(ast);
73
+ return usedHelpers;
74
+ };
75
+ const usedHelpers = extractHelpers(Handlebars.parse(template));
76
+ const supportedHelpers = new Set([
77
+ "if",
78
+ "unless",
79
+ "each",
80
+ "with",
81
+ "log",
82
+ "lookup",
83
+ "and",
84
+ "compare",
85
+ "contains",
86
+ "default",
87
+ "eq",
88
+ "gt",
89
+ "gte",
90
+ "has",
91
+ "isFalsey",
92
+ "isTruthy",
93
+ "ifEven",
94
+ "ifNth",
95
+ "ifOdd",
96
+ "is",
97
+ "isnt",
98
+ "lt",
99
+ "lte",
100
+ "neither",
101
+ "not",
102
+ "or",
103
+ "unlessEq",
104
+ "unlessGt",
105
+ "unlessLt",
106
+ "unlessGteq",
107
+ "unlessLteq"
108
+ ]);
109
+ const unsupportedHelpers = Array.from(usedHelpers).filter((h) => !supportedHelpers.has(h));
110
+ if (unsupportedHelpers.length > 0) throw new Error(`Email template uses unsupported Handlebars helpers: ${unsupportedHelpers.join(", ")}`);
111
+ };
112
+ /**
113
+ * Compile Email template and pass an empty context to validate syntax.
114
+ */
115
+ const compileEmailTemplate = (template) => {
116
+ Handlebars.compile(template)({});
138
117
  };
139
118
 
140
- // src/commands/validate.ts
141
- var validate = async () => {
142
- const errors = validateEmailTemplates(
143
- (await glob("email-config/templates/**/*.hbs")).sort()
144
- );
145
- if (errors.length) {
146
- halt(errors.map((el) => el.toString()).join("\n"));
147
- }
148
- logTitle("Validated successfully");
119
+ //#endregion
120
+ //#region src/commands/validate.ts
121
+ /**
122
+ * Validates the current Tamaro configuration to avoid common errors.
123
+ *
124
+ * The command description is kept generic on purpose. We check for a number
125
+ * of mistakes observed when tamaro configurations are manually edited and
126
+ * deployed.
127
+ */
128
+ const validate = async () => {
129
+ const errors = validateEmailTemplates(globSync("email-config/templates/**/*.hbs").sort());
130
+ if (errors.length) halt(errors.map((el) => el.toString()).join("\n"));
131
+ logTitle("Validated successfully");
149
132
  };
150
133
 
151
- // src/lib/aws.ts
152
- import { execaCommandSync } from "execa";
153
- import prompts from "prompts";
154
- import stripIndent from "strip-indent";
155
- var awsAuthenticate = (options) => {
156
- if (options.ci) {
157
- return;
158
- }
159
- try {
160
- checkIdentity(options);
161
- } catch (error) {
162
- login(options);
163
- }
164
- };
165
- var assertProfilesPresent = () => {
166
- const profiles = getAvailableProfiles();
167
- if (profiles.length === 0) {
168
- halt(
169
- stripIndent(`
134
+ //#endregion
135
+ //#region src/lib/aws.ts
136
+ const awsAuthenticate = (options) => {
137
+ if (options.ci)
138
+ /**
139
+ * Don't try to authenticate the user.
140
+ * This is done when CLI is running within an automated system like pipeline,
141
+ * In this case "AWS_ACCESS_KEY_ID" and "AWS_SECRET_ACCESS_KEY" are used instead of "AWS_PROFILE".
142
+ */
143
+ return;
144
+ try {
145
+ checkIdentity(options);
146
+ } catch (error) {
147
+ login(options);
148
+ }
149
+ };
150
+ const assertProfilesPresent = () => {
151
+ if (getAvailableProfiles().length === 0) halt(stripIndent(`
170
152
  No AWS profiles found.
171
153
  Run "aws configure sso" to set up SSO-enabled profile.
172
154
  Check the wiki for more information:
173
155
  https://raisenow.atlassian.net/wiki/x/lIrWvg
174
- `)
175
- );
176
- }
177
- };
178
- var getAvailableProfiles = () => {
179
- const { stdout } = execaCommandSync("aws configure list-profiles");
180
- return stdout.split("\n");
181
- };
182
- var checkIdentity = (options) => {
183
- const flags = prepareFlags(options);
184
- execaCommandSync(`aws sts get-caller-identity ${flags}`);
185
- };
186
- var login = (options) => {
187
- const flags = prepareFlags(options);
188
- try {
189
- execaCommandSync(`aws sso login ${flags}`, { stdio: "inherit" });
190
- console.log("");
191
- } catch (error) {
192
- halt("Login failed.");
193
- }
194
- };
195
- var prepareFlags = (options) => {
196
- const flags = [];
197
- const { profile } = options;
198
- if (profile) {
199
- flags.push(`--profile ${profile}`);
200
- }
201
- return flags.join(" ");
202
- };
203
- var assertProfileValid = (profile) => {
204
- const profiles = getAvailableProfiles();
205
- if (!profiles.includes(profile)) {
206
- halt(
207
- stripIndent(`
156
+ `));
157
+ };
158
+ const getAvailableProfiles = () => {
159
+ const { stdout } = execaCommandSync("aws configure list-profiles");
160
+ return stdout.split("\n");
161
+ };
162
+ /**
163
+ * Returns caller identity data (output is ignored here).
164
+ * Fails in case of expired SSO session.
165
+ */
166
+ const checkIdentity = (options) => {
167
+ execaCommandSync(`aws sts get-caller-identity ${prepareFlags$3(options)}`);
168
+ };
169
+ /**
170
+ * Opens SSO authentication page in the browser.
171
+ * Fails if user canceled authentication process.
172
+ */
173
+ const login = (options) => {
174
+ const flags = prepareFlags$3(options);
175
+ try {
176
+ execaCommandSync(`aws sso login ${flags}`, { stdio: "inherit" });
177
+ console.log("");
178
+ } catch (error) {
179
+ halt("Login failed.");
180
+ }
181
+ };
182
+ const prepareFlags$3 = (options) => {
183
+ const flags = [];
184
+ const { profile } = options;
185
+ if (profile) flags.push(`--profile ${profile}`);
186
+ return flags.join(" ");
187
+ };
188
+ const assertProfileValid = (profile) => {
189
+ const profiles = getAvailableProfiles();
190
+ if (!profiles.includes(profile)) halt(stripIndent(`
208
191
  AWS profile "${profile}" is not found.
209
192
  Available profiles are: ${profiles.map((v) => `"${v}"`).join(", ")}.
210
- `)
211
- );
212
- }
213
- };
214
- var promptProfile = async () => {
215
- const profiles = getAvailableProfiles().filter((v) => !!v).map((v) => ({ title: v, value: v }));
216
- const { profile } = await prompts(
217
- [
218
- {
219
- type: "select",
220
- name: "profile",
221
- message: "Select AWS profile",
222
- choices: profiles
223
- }
224
- ],
225
- {
226
- onCancel: () => halt()
227
- }
228
- );
229
- return profile;
193
+ `));
194
+ };
195
+ const promptProfile = async () => {
196
+ const { profile } = await prompts([{
197
+ type: "select",
198
+ name: "profile",
199
+ message: "Select AWS profile",
200
+ choices: getAvailableProfiles().filter((v) => !!v).map((v) => ({
201
+ title: v,
202
+ value: v
203
+ }))
204
+ }], { onCancel: () => halt() });
205
+ return profile;
230
206
  };
231
207
 
232
- // src/lib/https.ts
233
- import { existsSync } from "fs";
234
- import { resolve } from "path";
235
- import stripIndent2 from "strip-indent";
236
- var assertCrtExists = () => {
237
- const { ifCore } = getIfCoreFns();
238
- const paths = getPaths(ifCore);
239
- const certFile = resolve(paths.root, HTTPS_CRT_FILE);
240
- const keyFile = resolve(paths.root, HTTPS_KEY_FILE);
241
- if (existsSync(certFile) && existsSync(keyFile)) {
242
- return;
243
- }
244
- halt(
245
- stripIndent2(`
208
+ //#endregion
209
+ //#region src/lib/https.ts
210
+ const assertCrtExists = () => {
211
+ const { ifCore } = getIfCoreFns();
212
+ const paths = getPaths(ifCore);
213
+ const certFile = resolve(paths.root, HTTPS_CRT_FILE);
214
+ const keyFile = resolve(paths.root, HTTPS_KEY_FILE);
215
+ if (existsSync(certFile) && existsSync(keyFile)) return;
216
+ halt(stripIndent(`
246
217
  Flag "--https" is used, but "${HTTPS_CRT_FILE}" and/or "${HTTPS_KEY_FILE}" files are not found.
247
218
  You need to generate certificate first.
248
219
  Check docs: https://unpkg.com/@raisenow/tamaro-cli/readme.html#/?id=use-transport-level-security-https
249
- `)
250
- );
220
+ `));
251
221
  };
252
222
 
253
- // src/lib/notifier.ts
254
- import notifier from "node-notifier";
255
- import stripIndent3 from "strip-indent";
256
- var notify = (args) => {
257
- const { title, message = "" } = args;
258
- notifier.notify({
259
- title,
260
- message: stripIndent3(message).trim(),
261
- contentImage: "https://assets.raisenow.io/favicon.png",
262
- sound: "Funk"
263
- });
223
+ //#endregion
224
+ //#region src/lib/notifier.ts
225
+ const notify = (args) => {
226
+ const { title, message = "" } = args;
227
+ notifier.notify({
228
+ title,
229
+ message: stripIndent(message).trim(),
230
+ contentImage: "https://assets.raisenow.io/favicon.png",
231
+ sound: "Funk"
232
+ });
264
233
  };
265
234
 
266
- // src/commands/build.ts
267
- var build = async (options) => {
268
- const { env } = options;
269
- applyEnv(env);
270
- if (options.deploy && !options.profile && !options.ci) {
271
- assertProfilesPresent();
272
- options.profile = await promptProfile();
273
- }
274
- assertOptionsValid(options);
275
- await validate();
276
- const flags = prepareFlags2(options);
277
- const { ifCore } = getIfCoreFns();
278
- const paths = getPaths(ifCore);
279
- const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
280
- const title = ifCore(
281
- "Building optimised (minified) bundle of Tamaro Core \u2026",
282
- `Building optimised (minified) bundle of "${configName}" customer configuration \u2026`
283
- );
284
- const wpBin = resolveBin("webpack");
285
- const wpConfig = resolveOwn("dist/webpack.config.js");
286
- const cmd = `
287
- ${wpBin}
288
- --config ${wpConfig}
235
+ //#endregion
236
+ //#region src/commands/build.ts
237
+ const build = async (options) => {
238
+ const { env } = options;
239
+ applyEnv(env);
240
+ if (options.deploy && !options.profile && !options.ci) {
241
+ assertProfilesPresent();
242
+ options.profile = await promptProfile();
243
+ }
244
+ assertOptionsValid$5(options);
245
+ await validate();
246
+ const flags = prepareFlags$2(options);
247
+ const { ifCore } = getIfCoreFns();
248
+ const paths = getPaths(ifCore);
249
+ const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
250
+ const title = ifCore("Building optimised (minified) bundle of Tamaro Core ", `Building optimised (minified) bundle of "${configName}" customer configuration …`);
251
+ const cmd = `
252
+ ${resolveBin("webpack")}
253
+ --config ${resolveOwn("dist/webpack.config.js")}
289
254
  --env min
290
255
  ${flags}
291
256
  `;
292
- logTitle(title);
293
- logCommand(cmd);
294
- runCommandSync(cmd, { stdio: "inherit" });
295
- logTitle(`
296
- Bundle for "${configName}" customer configuration is done.`);
297
- console.log(`Path: ${paths.appDist}
298
- `);
299
- process.on("exit", () => {
300
- notify({
301
- title: "build",
302
- message: `Bundle for "${configName}" customer configuration is done.`
303
- });
304
- });
305
- };
306
- var assertOptionsValid = (options) => {
307
- const { localCore, https, deploy: deploy2, env, profile } = options;
308
- const { ifCore } = getIfCoreFns();
309
- if (ifCore() && localCore) {
310
- halt('Flag "--local-core" is redundant if running in Tamaro Core context.');
311
- }
312
- if (localCore && deploy2) {
313
- halt('Flags "--local-core" and "--deploy" must not be used together.');
314
- }
315
- if (https) {
316
- assertCrtExists();
317
- }
318
- if (profile) {
319
- assertProfileValid(profile);
320
- }
321
- assertEnvValid(env);
322
- };
323
- var prepareFlags2 = (options) => {
324
- const flags = [];
325
- const { localCore, analyze, https, nolint } = options;
326
- if (localCore) {
327
- flags.push("--env localCore");
328
- }
329
- if (analyze) {
330
- flags.push("--env analyze");
331
- }
332
- if (https) {
333
- flags.push("--env https");
334
- }
335
- if (nolint) {
336
- flags.push("--env nolint");
337
- }
338
- return flags.join(" ");
257
+ logTitle(title);
258
+ logCommand(cmd);
259
+ runCommandSync(cmd, { stdio: "inherit" });
260
+ logTitle(`\nBundle for "${configName}" customer configuration is done.`);
261
+ console.log(`Path: ${paths.appDist}\n`);
262
+ process.on("exit", () => {
263
+ notify({
264
+ title: "build",
265
+ message: `Bundle for "${configName}" customer configuration is done.`
266
+ });
267
+ });
268
+ };
269
+ const assertOptionsValid$5 = (options) => {
270
+ const { localCore, https, deploy, env, profile } = options;
271
+ const { ifCore } = getIfCoreFns();
272
+ if (ifCore() && localCore) halt("Flag \"--local-core\" is redundant if running in Tamaro Core context.");
273
+ if (localCore && deploy) halt("Flags \"--local-core\" and \"--deploy\" must not be used together.");
274
+ if (https) assertCrtExists();
275
+ if (profile) assertProfileValid(profile);
276
+ assertEnvValid(env);
277
+ };
278
+ const prepareFlags$2 = (options) => {
279
+ const flags = [];
280
+ const { localCore, analyze, https, nolint, debug } = options;
281
+ if (localCore) flags.push("--env localCore");
282
+ if (analyze) flags.push("--env analyze");
283
+ if (https) flags.push("--env https");
284
+ if (nolint) flags.push("--env nolint");
285
+ if (debug) flags.push("--env debug");
286
+ return flags.join(" ");
339
287
  };
340
288
 
341
- // src/commands/deploy.ts
342
- import { existsSync as existsSync2 } from "fs";
343
- import stripIndent4 from "strip-indent";
344
- var deploy = async (options) => {
345
- const { ifCore } = getIfCoreFns();
346
- const paths = getPaths(ifCore);
347
- assertDistPathExists(paths.appDist);
348
- if (!options.profile && !options.ci) {
349
- assertProfilesPresent();
350
- options.profile = await promptProfile();
351
- }
352
- assertOptionsValid2(options);
353
- await validate();
354
- awsAuthenticate(options);
355
- const flags = prepareFlags(options);
356
- const { tag, dryrun } = options;
357
- const dryRunFlag = dryrun ? `--dryrun` : "";
358
- const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
359
- const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}`;
360
- const entryFilename = ifCore("index.js", "widget.js");
361
- if (dryRunFlag) {
362
- logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
363
- }
364
- const cmdSyncAll = `
289
+ //#endregion
290
+ //#region src/commands/deploy.ts
291
+ const deploy = async (options) => {
292
+ const { ifCore } = getIfCoreFns();
293
+ const paths = getPaths(ifCore);
294
+ assertDistPathExists(paths.appDist);
295
+ if (!options.profile && !options.ci) {
296
+ assertProfilesPresent();
297
+ options.profile = await promptProfile();
298
+ }
299
+ assertOptionsValid$4(options);
300
+ await validate();
301
+ awsAuthenticate(options);
302
+ const flags = prepareFlags$3(options);
303
+ const { tag, dryrun } = options;
304
+ const dryRunFlag = dryrun ? `--dryrun` : "";
305
+ const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
306
+ const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}`;
307
+ const entryFilename = ifCore("index.js", "widget.js");
308
+ if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
309
+ /**
310
+ * Sync all files except entrypoint (without deleting old files)
311
+ */
312
+ const cmdSyncAll = `
365
313
  aws s3 sync ${paths.appDist} ${deployUrl}
366
314
  --acl public-read
367
315
  --exclude ${paths.appDist}/${entryFilename}
@@ -369,564 +317,330 @@ var deploy = async (options) => {
369
317
  ${flags}
370
318
  ${dryRunFlag}
371
319
  `;
372
- logTitle("Deploying to AWS S3 \u2026");
373
- logCommand(cmdSyncAll);
374
- try {
375
- runCommandSync(cmdSyncAll, { stdout: "inherit" });
376
- } catch (error) {
377
- halt(error.stderr);
378
- }
379
- const cmdCpEntry = `
320
+ logTitle("Deploying to AWS S3 ");
321
+ logCommand(cmdSyncAll);
322
+ try {
323
+ runCommandSync(cmdSyncAll, { stdout: "inherit" });
324
+ } catch (error) {
325
+ halt(error.stderr);
326
+ }
327
+ /**
328
+ * Copy entrypoint
329
+ */
330
+ const cmdCpEntry = `
380
331
  aws s3 cp ${paths.appDist}/${entryFilename} ${deployUrl}/${entryFilename}
381
332
  --acl public-read
382
333
  --cache-control max-age=64800
383
334
  ${flags}
384
335
  ${dryRunFlag}
385
336
  `;
386
- logCommand(cmdCpEntry);
387
- try {
388
- runCommandSync(cmdCpEntry, { stdout: "inherit" });
389
- } catch (error) {
390
- halt(error.stderr);
391
- }
392
- if (!dryRunFlag) {
393
- const cmdInvalidateCache = `
337
+ logCommand(cmdCpEntry);
338
+ try {
339
+ runCommandSync(cmdCpEntry, { stdout: "inherit" });
340
+ } catch (error) {
341
+ halt(error.stderr);
342
+ }
343
+ if (!dryRunFlag) {
344
+ /**
345
+ * Invalidate cloudfront cache
346
+ */
347
+ const cmdInvalidateCache = `
394
348
  aws cloudfront create-invalidation
395
349
  --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
396
350
  --paths /${configName}/${tag}/*
397
351
  ${flags}
398
352
  `;
399
- logTitle("\nInvalidating edge cache \u2026");
400
- logCommand(cmdInvalidateCache);
401
- try {
402
- runCommandSync(cmdInvalidateCache);
403
- } catch (error) {
404
- halt(error.stderr);
405
- }
406
- }
407
- const demoPage = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`;
408
- const entryPoint = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/${entryFilename}`;
409
- logTitle(`
410
- Bundle for "${configName}" is deployed with tag "${tag}".`);
411
- logDataTable({
412
- "Demo page:": demoPage,
413
- "Entry point:": entryPoint
414
- });
415
- process.on("exit", () => {
416
- notify({
417
- title: "deploy",
418
- message: `
353
+ logTitle("\nInvalidating edge cache ");
354
+ logCommand(cmdInvalidateCache);
355
+ try {
356
+ runCommandSync(cmdInvalidateCache);
357
+ } catch (error) {
358
+ halt(error.stderr);
359
+ }
360
+ }
361
+ const demoPage = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`;
362
+ const entryPoint = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/${entryFilename}`;
363
+ logTitle(`\nBundle for "${configName}" is deployed with tag "${tag}".`);
364
+ logDataTable({
365
+ "Demo page:": demoPage,
366
+ "Entry point:": entryPoint
367
+ });
368
+ process.on("exit", () => {
369
+ notify({
370
+ title: "deploy",
371
+ message: `
419
372
  Bundle for "${configName}" is deployed with tag "${tag}".
420
373
  Demo page: ${demoPage}
421
374
  Entry point: ${entryPoint}
422
375
  `
423
- });
424
- });
425
- };
426
- var assertOptionsValid2 = (options) => {
427
- const { profile, tag } = options;
428
- if (profile) {
429
- assertProfileValid(profile);
430
- }
431
- assertTagValid(tag);
432
- };
433
- var assertDistPathExists = (distPath) => {
434
- if (!existsSync2(distPath)) {
435
- halt(
436
- stripIndent4(`
376
+ });
377
+ });
378
+ };
379
+ const assertOptionsValid$4 = (options) => {
380
+ const { profile, tag } = options;
381
+ if (profile) assertProfileValid(profile);
382
+ assertTagValid(tag);
383
+ };
384
+ const assertDistPathExists = (distPath) => {
385
+ if (!existsSync(distPath)) halt(stripIndent(`
437
386
  Dist folder does not exists.
438
387
  Make sure you have built the bundle before trying to deploy it.
439
- `)
440
- );
441
- }
442
- };
443
- var assertTagValid = (tag) => {
444
- const regex = /^[a-zA-Z0-9-_.]+$/;
445
- if (!regex.test(tag)) {
446
- halt(
447
- `Flag "--tag" has forbidden format. Allowed format: ${regex.toString()}.`
448
- );
449
- }
388
+ `));
389
+ };
390
+ const assertTagValid = (tag) => {
391
+ const regex = /^[a-zA-Z0-9-_.]+$/;
392
+ if (!regex.test(tag)) halt(`Flag "--tag" has forbidden format. Allowed format: ${regex.toString()}.`);
450
393
  };
451
394
 
452
- // src/commands/deploy-email-config.ts
453
- import { existsSync as existsSync3 } from "fs";
454
- import prompts2 from "prompts";
455
- var deployEmailConfig = async (options) => {
456
- const { ifCore } = getIfCoreFns();
457
- const paths = getPaths(ifCore);
458
- const emailConfigPath = `${paths.app}/email-config`;
459
- assertIsNotCore();
460
- assertEmailConfigPathExists(emailConfigPath);
461
- if (!options.profile && !options.ci) {
462
- assertProfilesPresent();
463
- options.profile = await promptProfile();
464
- }
465
- if (!options.bucket) {
466
- options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await promptBucketTamaroEmailConfig();
467
- }
468
- assertOptionsValid3(options);
469
- await validate();
470
- awsAuthenticate(options);
471
- const flags = prepareFlags(options);
472
- const dryRunFlag = options.dryrun ? `--dryrun` : "";
473
- const configName = getWidgetUuid();
474
- const deployUrl = `s3://${options.bucket}/${configName}`;
475
- if (dryRunFlag) {
476
- logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
477
- }
478
- const cmd = `
395
+ //#endregion
396
+ //#region src/commands/deploy-email-config.ts
397
+ const deployEmailConfig = async (options) => {
398
+ const { ifCore } = getIfCoreFns();
399
+ const emailConfigPath = `${getPaths(ifCore).app}/email-config`;
400
+ assertIsNotCore();
401
+ assertEmailConfigPathExists(emailConfigPath);
402
+ if (!options.profile && !options.ci) {
403
+ assertProfilesPresent();
404
+ options.profile = await promptProfile();
405
+ }
406
+ if (!options.bucket) options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await promptBucketTamaroEmailConfig();
407
+ assertOptionsValid$3(options);
408
+ await validate();
409
+ awsAuthenticate(options);
410
+ const flags = prepareFlags$3(options);
411
+ const dryRunFlag = options.dryrun ? `--dryrun` : "";
412
+ const configName = getWidgetUuid();
413
+ const deployUrl = `s3://${options.bucket}/${configName}`;
414
+ if (dryRunFlag) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
415
+ const cmd = `
479
416
  aws s3 sync ${emailConfigPath} ${deployUrl}
480
417
  --delete
481
418
  --exact-timestamps
482
419
  ${flags}
483
420
  ${dryRunFlag}
484
421
  `;
485
- logTitle(
486
- `Deploying email configuration for "${configName}" customer configuration to AWS S3 \u2026`
487
- );
488
- logCommand(cmd);
489
- try {
490
- runCommandSync(cmd, { stdout: "inherit" });
491
- } catch (error) {
492
- halt(error.stderr);
493
- }
494
- logTitle(
495
- `Email configuration for "${configName}" customer configuration is deployed.`
496
- );
497
- logDataTable({ "Deploy URL:": deployUrl });
498
- process.on("exit", () => {
499
- notify({
500
- title: "deploy-email-config",
501
- message: `Email configuration for "${configName}" customer configuration is deployed.`
502
- });
503
- });
504
- };
505
- var assertOptionsValid3 = (options) => {
506
- const { profile, bucket } = options;
507
- if (profile) {
508
- assertProfileValid(profile);
509
- }
510
- if (bucket) {
511
- assertBucketValid(bucket);
512
- }
513
- };
514
- var assertEmailConfigPathExists = (distPath) => {
515
- if (!existsSync3(distPath)) {
516
- halt("Email config folder does not exists. Nothing to deploy.");
517
- }
518
- };
519
- var assertIsNotCore = () => {
520
- const { ifCore } = getIfCoreFns();
521
- if (ifCore()) {
522
- halt("You cannot deploy widget email configuration for Tamaro Core.");
523
- }
524
- };
525
- var assertBucketValid = (bucket) => {
526
- const buckets = [
527
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
528
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
529
- ];
530
- if (!buckets.includes(bucket)) {
531
- halt("Invalid bucket name.");
532
- }
533
- };
534
- var promptBucketTamaroEmailConfig = async () => {
535
- const buckets = [
536
- { title: "stage", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE },
537
- { title: "prod", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD }
538
- ];
539
- const { bucket } = await prompts2(
540
- [
541
- {
542
- type: "select",
543
- name: "bucket",
544
- message: "Select environment",
545
- choices: buckets
546
- }
547
- ],
548
- {
549
- onCancel: () => halt()
550
- }
551
- );
552
- return bucket;
422
+ logTitle(`Deploying email configuration for "${configName}" customer configuration to AWS S3 …`);
423
+ logCommand(cmd);
424
+ try {
425
+ runCommandSync(cmd, { stdout: "inherit" });
426
+ } catch (error) {
427
+ halt(error.stderr);
428
+ }
429
+ logTitle(`Email configuration for "${configName}" customer configuration is deployed.`);
430
+ logDataTable({ "Deploy URL:": deployUrl });
431
+ process.on("exit", () => {
432
+ notify({
433
+ title: "deploy-email-config",
434
+ message: `Email configuration for "${configName}" customer configuration is deployed.`
435
+ });
436
+ });
437
+ };
438
+ const assertOptionsValid$3 = (options) => {
439
+ const { profile, bucket } = options;
440
+ if (profile) assertProfileValid(profile);
441
+ if (bucket) assertBucketValid(bucket);
442
+ };
443
+ const assertEmailConfigPathExists = (distPath) => {
444
+ if (!existsSync(distPath)) halt("Email config folder does not exists. Nothing to deploy.");
445
+ };
446
+ const assertIsNotCore = () => {
447
+ const { ifCore } = getIfCoreFns();
448
+ if (ifCore()) halt("You cannot deploy widget email configuration for Tamaro Core.");
449
+ };
450
+ const assertBucketValid = (bucket) => {
451
+ if (![AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE, AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD].includes(bucket)) halt("Invalid bucket name.");
452
+ };
453
+ const promptBucketTamaroEmailConfig = async () => {
454
+ const { bucket } = await prompts([{
455
+ type: "select",
456
+ name: "bucket",
457
+ message: "Select environment",
458
+ choices: [{
459
+ title: "stage",
460
+ value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE
461
+ }, {
462
+ title: "prod",
463
+ value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
464
+ }]
465
+ }], { onCancel: () => halt() });
466
+ return bucket;
553
467
  };
554
468
 
555
- // src/commands/dev.ts
556
- import { getPortPromise } from "portfinder";
557
- var dev = async (options) => {
558
- const { env } = options;
559
- applyEnv(env);
560
- assertOptionsValid4(options);
561
- const flags = await prepareFlags3(options);
562
- const { ifCore } = getIfCoreFns();
563
- const title = ifCore(
564
- "Running dev web-server for Tamaro Core \u2026",
565
- "Running dev web-server for customer configuration \u2026"
566
- );
567
- const wpBin = resolveBin("webpack");
568
- const wpConfig = resolveOwn("dist/webpack.config.js");
569
- const cmd = `
570
- ${wpBin} serve
571
- --config ${wpConfig}
469
+ //#endregion
470
+ //#region src/commands/dev.ts
471
+ const dev = async (options) => {
472
+ const { env } = options;
473
+ applyEnv(env);
474
+ assertOptionsValid$2(options);
475
+ const flags = await prepareFlags$1(options);
476
+ const { ifCore } = getIfCoreFns();
477
+ const title = ifCore("Running dev web-server for Tamaro Core …", "Running dev web-server for customer configuration …");
478
+ const cmd = `
479
+ ${resolveBin("webpack")} serve
480
+ --config ${resolveOwn("dist/webpack.config.js")}
572
481
  ${flags}
573
482
  `;
574
- logTitle(title);
575
- logCommand(cmd);
576
- runCommandSync(cmd, { stdio: "inherit" });
577
- };
578
- var assertOptionsValid4 = (options) => {
579
- const { localCore, https, port, env } = options;
580
- const { ifCore } = getIfCoreFns();
581
- if (ifCore() && localCore) {
582
- halt('Flag "--local-core" is redundant if running in Tamaro Core context.');
583
- }
584
- if (isNaN(Number(port))) {
585
- halt('Flag "--port" should be a number.');
586
- }
587
- if (https) {
588
- assertCrtExists();
589
- }
590
- assertEnvValid(env);
591
- };
592
- var prepareFlags3 = async (options) => {
593
- const flags = [];
594
- const { localCore, port: defaultPort, https, nolint } = options;
595
- const port = await getPortPromise({ port: Number(defaultPort) });
596
- if (localCore) {
597
- flags.push("--env localCore");
598
- }
599
- flags.push(`--port ${port}`);
600
- if (https) {
601
- flags.push("--env https");
602
- }
603
- if (nolint) {
604
- flags.push("--env nolint");
605
- }
606
- return flags.join(" ");
483
+ logTitle(title);
484
+ logCommand(cmd);
485
+ runCommandSync(cmd, { stdio: "inherit" });
486
+ };
487
+ const assertOptionsValid$2 = (options) => {
488
+ const { localCore, https, port, env } = options;
489
+ const { ifCore } = getIfCoreFns();
490
+ if (ifCore() && localCore) halt("Flag \"--local-core\" is redundant if running in Tamaro Core context.");
491
+ if (isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
492
+ if (https) assertCrtExists();
493
+ assertEnvValid(env);
494
+ };
495
+ const prepareFlags$1 = async (options) => {
496
+ const flags = [];
497
+ const { localCore, port: defaultPort, https, nolint, debug } = options;
498
+ const port = await getPortPromise({ port: Number(defaultPort) });
499
+ if (localCore) flags.push("--env localCore");
500
+ flags.push(`--port ${port}`);
501
+ if (https) flags.push("--env https");
502
+ if (nolint) flags.push("--env nolint");
503
+ if (debug) flags.push("--env debug");
504
+ return flags.join(" ");
607
505
  };
608
506
 
609
- // src/commands/list-deployed.ts
610
- var listDeployed = async (options) => {
611
- if (!options.profile && !options.ci) {
612
- assertProfilesPresent();
613
- options.profile = await promptProfile();
614
- }
615
- assertOptionsValid5(options);
616
- awsAuthenticate(options);
617
- const flags = prepareFlags(options);
618
- const { config } = options;
619
- const { ifCore } = getIfCoreFns();
620
- const configName = config ?? ifCore(CORE_CONFIG_NAME, getWidgetUuid());
621
- const title = !config && ifCore() ? `Listing deployments of Tamaro Core \u2026` : `Listing deployments of "${configName}" customer configuration \u2026`;
622
- const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/`;
623
- const cmd = `aws s3 ls ${deployUrl} ${flags}`;
624
- let out = "";
625
- logTitle(title);
626
- logCommand(cmd);
627
- try {
628
- const result = runCommandSync(cmd);
629
- out = result.stdout;
630
- } catch (error) {
631
- out = error.stdout;
632
- if (error.stderr) {
633
- halt(error.stderr);
634
- }
635
- }
636
- const lines = out.split("\n");
637
- const tags = parseTags(lines);
638
- let text = "";
639
- if (tags.length === 0) {
640
- text = "No deployments found.";
641
- } else {
642
- text = tags.map((tag, idx) => {
643
- return `${idx + 1}. https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`;
644
- }).join("\n");
645
- }
646
- console.log(`${text}
647
- `);
648
- };
649
- var assertOptionsValid5 = (options) => {
650
- const { config, profile } = options;
651
- assertConfigValid(config);
652
- if (profile) {
653
- assertProfileValid(profile);
654
- }
655
- };
656
- var assertConfigValid = (config) => {
657
- if (!config) {
658
- return;
659
- }
660
- const regex = /^[a-zA-Z0-9-_]+$/;
661
- if (!regex.test(config)) {
662
- halt(
663
- `Flag "--config" has forbidden format. Allowed format: ${regex.toString()}.`
664
- );
665
- }
666
- };
667
- var parseTags = (lines) => {
668
- const regex = /^\s*PRE\s*/;
669
- return lines.filter((line) => regex.test(line)).map((line) => line.replace(regex, "").replace(/\/$/, ""));
507
+ //#endregion
508
+ //#region src/commands/list-deployed.ts
509
+ const listDeployed = async (options) => {
510
+ if (!options.profile && !options.ci) {
511
+ assertProfilesPresent();
512
+ options.profile = await promptProfile();
513
+ }
514
+ assertOptionsValid$1(options);
515
+ awsAuthenticate(options);
516
+ const flags = prepareFlags$3(options);
517
+ const { config } = options;
518
+ const { ifCore } = getIfCoreFns();
519
+ const configName = config ?? ifCore(CORE_CONFIG_NAME, getWidgetUuid());
520
+ const title = !config && ifCore() ? `Listing deployments of Tamaro Core …` : `Listing deployments of "${configName}" customer configuration …`;
521
+ const cmd = `aws s3 ls ${`s3://${AWS_S3_BUCKET_TAMARO}/${configName}/`} ${flags}`;
522
+ let out = "";
523
+ logTitle(title);
524
+ logCommand(cmd);
525
+ try {
526
+ out = runCommandSync(cmd).stdout;
527
+ } catch (error) {
528
+ out = error.stdout;
529
+ if (error.stderr) halt(error.stderr);
530
+ }
531
+ const tags = parseTags(out.split("\n"));
532
+ let text = "";
533
+ if (tags.length === 0) text = "No deployments found.";
534
+ else text = tags.map((tag, idx) => {
535
+ return `${idx + 1}. https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`;
536
+ }).join("\n");
537
+ console.log(`${text}\n`);
538
+ };
539
+ const assertOptionsValid$1 = (options) => {
540
+ const { config, profile } = options;
541
+ assertConfigValid(config);
542
+ if (profile) assertProfileValid(profile);
543
+ };
544
+ const assertConfigValid = (config) => {
545
+ if (!config) return;
546
+ const regex = /^[a-zA-Z0-9-_]+$/;
547
+ if (!regex.test(config)) halt(`Flag "--config" has forbidden format. Allowed format: ${regex.toString()}.`);
548
+ };
549
+ const parseTags = (lines) => {
550
+ const regex = /^\s*PRE\s*/;
551
+ return lines.filter((line) => regex.test(line)).map((line) => line.replace(regex, "").replace(/\/$/, ""));
670
552
  };
671
553
 
672
- // src/commands/serve.ts
673
- import { resolve as resolve2 } from "path";
674
- import { getPortPromise as getPortPromise2 } from "portfinder";
675
- var serve = async (options) => {
676
- assertOptionsValid6(options);
677
- const flags = await prepareFlags4(options);
678
- const { ifCore } = getIfCoreFns();
679
- const paths = getPaths(ifCore);
680
- const cmd = `
681
- npx -y serve ${paths.appDist}
554
+ //#endregion
555
+ //#region src/commands/serve.ts
556
+ const serve = async (options) => {
557
+ assertOptionsValid(options);
558
+ const flags = await prepareFlags(options);
559
+ const { ifCore } = getIfCoreFns();
560
+ const cmd = `
561
+ npx -y serve ${getPaths(ifCore).appDist}
682
562
  --cors
683
563
  ${flags}
684
564
  `;
685
- logTitle(`Running web-server for pre-built bundle \u2026`);
686
- logCommand(cmd);
687
- runCommandSync(cmd, { stdio: "inherit" });
688
- };
689
- var assertOptionsValid6 = (options) => {
690
- const { port, https } = options;
691
- if (isNaN(Number(port))) {
692
- halt('Flag "--port" should be a number.');
693
- }
694
- if (https) {
695
- assertCrtExists();
696
- }
697
- };
698
- var prepareFlags4 = async (options) => {
699
- const flags = [];
700
- const { port: defaultPort, https } = options;
701
- const port = await getPortPromise2({ port: Number(defaultPort) });
702
- flags.push(`-p ${port}`);
703
- if (https) {
704
- const { ifCore } = getIfCoreFns();
705
- const paths = getPaths(ifCore);
706
- const certFile = resolve2(paths.root, HTTPS_CRT_FILE);
707
- const keyFile = resolve2(paths.root, HTTPS_KEY_FILE);
708
- flags.push(`--ssl-cert ${certFile}`);
709
- flags.push(`--ssl-key ${keyFile}`);
710
- }
711
- return flags.join(" ");
565
+ logTitle(`Running web-server for pre-built bundle …`);
566
+ logCommand(cmd);
567
+ runCommandSync(cmd, { stdio: "inherit" });
568
+ };
569
+ const assertOptionsValid = (options) => {
570
+ const { port, https } = options;
571
+ if (isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
572
+ if (https) assertCrtExists();
573
+ };
574
+ const prepareFlags = async (options) => {
575
+ const flags = [];
576
+ const { port: defaultPort, https } = options;
577
+ const port = await getPortPromise({ port: Number(defaultPort) });
578
+ flags.push(`-p ${port}`);
579
+ if (https) {
580
+ const { ifCore } = getIfCoreFns();
581
+ const paths = getPaths(ifCore);
582
+ const certFile = resolve(paths.root, HTTPS_CRT_FILE);
583
+ const keyFile = resolve(paths.root, HTTPS_KEY_FILE);
584
+ flags.push(`--ssl-cert ${certFile}`);
585
+ flags.push(`--ssl-key ${keyFile}`);
586
+ }
587
+ return flags.join(" ");
712
588
  };
713
589
 
714
- // package.json
715
- var package_default = {
716
- name: "@raisenow/tamaro-cli",
717
- version: "1.5.0",
718
- author: {
719
- name: "RaiseNow",
720
- email: "development@raisenow.com"
721
- },
722
- type: "module",
723
- bin: "dist/cli.js",
724
- packageManager: "pnpm@10.17.1",
725
- engines: {
726
- node: ">=22",
727
- pnpm: ">=10",
728
- npm: "please-use-pnpm",
729
- yarn: "please-use-pnpm"
730
- },
731
- scripts: {
732
- prepare: "pnpm build",
733
- typecheck: "tsc --noEmit",
734
- build: "tsup src/cli.ts src/webpack.config.ts --clean --shims --format esm",
735
- "build:watch": "pnpm build --watch --ignore-watch .history --ignore-watch .idea",
736
- readme: "pnpx http-server . --cors -o /readme.html",
737
- lint: "DEBUG=eslint:cli-engine eslint .",
738
- "lint:fix": "DEBUG=eslint:cli-engine eslint --fix .",
739
- format: "prettier --write .",
740
- test: "vitest",
741
- "test:watch": "vitest --watch",
742
- "test:coverage": "vitest --coverage"
743
- },
744
- dependencies: {
745
- "@babel/cli": "^7.28.3",
746
- "@babel/core": "^7.28.4",
747
- "@babel/plugin-proposal-decorators": "^7.28.0",
748
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
749
- "@babel/plugin-transform-runtime": "^7.28.3",
750
- "@babel/preset-env": "^7.28.3",
751
- "@babel/preset-react": "^7.27.1",
752
- "@babel/preset-typescript": "^7.27.1",
753
- "@babel/runtime-corejs3": "^7.28.4",
754
- "@pmmmwh/react-refresh-webpack-plugin": "^0.6.1",
755
- "@statoscope/webpack-plugin": "^5.29.0",
756
- "@types/columnify": "^1.5.4",
757
- "@types/handlebars-helpers": "^0.5.6",
758
- "@types/lodash": "^4.17.20",
759
- "@types/node": "^22.18.6",
760
- "@types/node-notifier": "^8.0.5",
761
- "@types/prompts": "^2.4.9",
762
- "@types/resolve-bin": "^0.4.3",
763
- "@types/webpack-config-utils": "^2.3.4",
764
- "@typescript-eslint/eslint-plugin": "^7.18.0",
765
- "@typescript-eslint/parser": "^7.18.0",
766
- autoprefixer: "^10.4.21",
767
- "babel-loader": "^10.0.0",
768
- "babel-plugin-istanbul": "^7.0.1",
769
- "babel-plugin-lodash": "^3.3.4",
770
- chalk: "^5.6.2",
771
- "clean-webpack-plugin": "^4.0.0",
772
- columnify: "^1.6.0",
773
- commander: "^14.0.1",
774
- "copy-webpack-plugin": "^13.0.1",
775
- "core-js": "^3.45.1",
776
- "css-loader": "^7.1.2",
777
- "css-minimizer-webpack-plugin": "^7.0.2",
778
- dotenv: "^17.2.2",
779
- "escape-string-regexp": "^5.0.0",
780
- eslint: "^8.57.1",
781
- "eslint-config-prettier": "^10.1.8",
782
- "eslint-import-resolver-typescript": "^3.6.3",
783
- "eslint-plugin-deprecation": "^3.0.0",
784
- "eslint-plugin-import": "^2.32.0",
785
- "eslint-plugin-markdownlint": "^0.9.0",
786
- "eslint-plugin-promise": "^7.2.1",
787
- "eslint-plugin-unused-imports": "^3.2.0",
788
- "eslint-plugin-yml": "^1.18.0",
789
- "eslint-webpack-plugin": "^5.0.2",
790
- execa: "^9.6.0",
791
- "file-loader": "^6.2.0",
792
- "fork-ts-checker-webpack-plugin": "^9.1.0",
793
- glob: "^11.0.3",
794
- handlebars: "^4.7.8",
795
- "handlebars-helpers": "^0.10.0",
796
- "html-loader": "^5.1.0",
797
- "html-webpack-plugin": "^5.6.4",
798
- "json-loader": "^0.5.7",
799
- lodash: "^4.17.21",
800
- "mini-css-extract-plugin": "^2.9.4",
801
- "node-notifier": "^10.0.1",
802
- portfinder: "^1.0.38",
803
- postcss: "^8.5.6",
804
- "postcss-custom-properties": "^14.0.6",
805
- "postcss-import": "^16.1.1",
806
- "postcss-loader": "^8.2.0",
807
- "postcss-nested": "^7.0.2",
808
- prettier: "^3.6.2",
809
- prompts: "^2.4.2",
810
- "react-refresh": "^0.17.0",
811
- "resolve-url-loader": "^5.0.0",
812
- sass: "^1.93.1",
813
- "sass-loader": "^16.0.5",
814
- "strip-indent": "^4.1.0",
815
- "style-loader": "^4.0.0",
816
- "terser-webpack-plugin": "^5.3.14",
817
- "tsconfig-paths-webpack-plugin": "^4.2.0",
818
- tsup: "^8.5.0",
819
- typescript: "^5.9.2",
820
- "url-loader": "^4.1.1",
821
- vitest: "^3.2.4",
822
- webpack: "^5.101.3",
823
- "webpack-cli": "^6.0.1",
824
- "webpack-config-utils": "^2.3.1",
825
- "webpack-dev-server": "^5.2.2",
826
- "yaml-loader": "^0.8.1"
827
- }
828
- };
590
+ //#endregion
591
+ //#region package.json
592
+ var name = "@raisenow/tamaro-cli";
593
+ var version = "1.6.0-dev.1";
829
594
 
830
- // src/cli.ts
595
+ //#endregion
596
+ //#region src/cli.ts
597
+ /**
598
+ * Makes the script crash on unhandled rejections instead of silently
599
+ * ignoring them. In the future, promise rejections that are not handled will
600
+ * terminate the Node.js process with a non-zero exit code.
601
+ */
831
602
  process.on("unhandledRejection", (error) => {
832
- throw error;
603
+ throw error;
833
604
  });
834
605
  process.on("SIGINT", () => {
835
- halt();
606
+ halt();
836
607
  });
837
- var cli = createCommand().name(package_default.name).version(package_default.version, "-v, --version");
838
- cli.command("dev").description(
839
- "Run the local development server for Tamaro Core or a particular customer configuration"
840
- ).option(
841
- "--local-core",
842
- "Load Tamaro Core from localhost:1234 instead of the CDN",
843
- false
844
- ).option(
845
- "--https",
846
- "Let local web server serve Tamaro with SSL encryption",
847
- false
848
- ).option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option("--env <env>", "Environment (dev, stage, prod)").option("--nolint", "Disable ESLint", false).action(async (options) => {
849
- await dev(options);
608
+ const cli = createCommand().name(name).version(version, "-v, --version");
609
+ 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) => {
610
+ await dev(options);
850
611
  });
851
- cli.command("build").description(
852
- "Build an optimised (minified) bundle of Tamaro Core or a customer configuration"
853
- ).option(
854
- "--local-core",
855
- "Load Tamaro Core from localhost:1234 instead of the CDN",
856
- false
857
- ).option("--analyze", 'Generate bundle statistics to "reports" folder', false).option("--serve", "Run the generated bundle with a local web server", false).option(
858
- "--https",
859
- "Let local web server serve Tamaro with SSL encryption",
860
- false
861
- ).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(
862
- "--deploy",
863
- "Deploy Tamaro Core or a customer configuration bundle to AWS S3",
864
- false
865
- ).option(
866
- "--tag <tag>",
867
- "Tag which should be used for the deployment of the bundle",
868
- DEFAULT_TAG
869
- ).option("--nolint", "Disable ESLint", false).action(async (options) => {
870
- await build(options);
871
- if (options.serve) {
872
- await serve(options);
873
- }
874
- if (options.deploy) {
875
- await deploy(options);
876
- }
612
+ 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("--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) => {
613
+ await build(options);
614
+ if (options.serve) await serve(options);
615
+ if (options.deploy) await deploy(options);
877
616
  });
878
- cli.command("serve").description("Run a local web server for pre-built bundle").option("--port <port>", "Web server port", `${DEFAULT_PORT}`).option(
879
- "--https",
880
- "Let local web server serve Tamaro with SSL encryption",
881
- false
882
- ).action(async (options) => {
883
- await serve(options);
617
+ 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) => {
618
+ await serve(options);
884
619
  });
885
- cli.command("deploy").description(
886
- "Deploy a pre-built Tamaro Core or customer configuration bundle to AWS S3"
887
- ).option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option(
888
- "--tag <tag>",
889
- "Tag which should be used for the deployment of the bundle",
890
- DEFAULT_TAG
891
- ).option(
892
- "--dryrun",
893
- "Displays the operations that would be performed without actually running them",
894
- false
895
- ).action(async (options) => {
896
- await deploy(options);
620
+ 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).action(async (options) => {
621
+ await deploy(options);
897
622
  });
898
- cli.command("list-deployed").description(
899
- "List deployments of Tamaro Core or a particular customer configuration"
900
- ).option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option(
901
- "--config <config>",
902
- "Configuration name (default: current customer configuration)"
903
- ).action(async (options) => {
904
- await listDeployed(options);
623
+ 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) => {
624
+ await listDeployed(options);
905
625
  });
906
- 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(
907
- "--dryrun",
908
- "Displays the operations that would be performed without actually running them",
909
- false
910
- ).action(async (options) => {
911
- await deployEmailConfig(options);
626
+ 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) => {
627
+ await deployEmailConfig(options);
912
628
  });
913
- cli.command("validate").description(
914
- "Validate the current Tamaro configuration to avoid common errors"
915
- ).action(async () => {
916
- await validate();
629
+ cli.command("validate").description("Validate the current Tamaro configuration to avoid common errors").action(async () => {
630
+ await validate();
917
631
  });
918
632
  (async () => {
919
- try {
920
- logTitle(`${package_default.name} ${package_default.version}
921
- `);
922
- await cli.parseAsync(process.argv);
923
- } catch (error) {
924
- if (error.signal === "SIGINT" && error.signalDescription) {
925
- logError(`
926
- ${error.signalDescription}`);
927
- } else {
928
- console.log("");
929
- logError(error.stack);
930
- }
931
- }
633
+ try {
634
+ logTitle(`${name} ${version}\n`);
635
+ await cli.parseAsync(process.argv);
636
+ } catch (error) {
637
+ if (error.signal === "SIGINT" && error.signalDescription) logError(`\n${error.signalDescription}`);
638
+ else {
639
+ console.log("");
640
+ logError(error.stack);
641
+ }
642
+ }
932
643
  })();
644
+
645
+ //#endregion
646
+ export { };