@raisenow/tamaro-cli 1.7.0 → 1.8.0-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +6 -0
- package/.nvmrc +1 -1
- package/bitbucket-pipelines.yml +3 -10
- package/dist/cli.js +73 -73
- package/dist/{env-Bx5mwt8E.js → env-B20cxmcB.js} +46 -26
- package/dist/webpack.config.js +10 -10
- package/eslint.config.ts +30 -0
- package/package.json +26 -26
- package/tsdown.config.ts +5 -5
- package/vitest.config.ts +8 -8
- package/.eslintignore +0 -7
- package/.eslintrc.cjs +0 -148
- package/.history/.eslintignore_20220609190420 +0 -4
- package/.history/.eslintignore_20230911190227 +0 -6
- package/.history/.eslintignore_20230911211247 +0 -7
- package/.history/.eslintignore_20230911211250 +0 -7
- package/.history/.eslintrc_20230911201601.js +0 -49
- package/.history/.eslintrc_20230911201643.js +0 -49
- package/.history/.eslintrc_20230911201735.js +0 -49
- package/.history/.eslintrc_20230911201913.js +0 -64
- package/.history/.eslintrc_20230911202002.js +0 -62
- package/.history/.eslintrc_20230911202138.js +0 -133
- package/.history/.eslintrc_20230911202140.js +0 -133
- package/.history/.eslintrc_20230911202145.js +0 -133
- package/.history/.eslintrc_20230911202147.js +0 -133
- package/.history/.eslintrc_20230911202406.js +0 -133
- package/.history/.eslintrc_20230911202447.js +0 -133
- package/.history/.eslintrc_20230911202453.js +0 -133
- package/.history/.eslintrc_20230911202511.js +0 -133
- package/.history/.eslintrc_20230911202527.js +0 -133
- package/.history/.eslintrc_20230911202639.js +0 -125
- package/.history/.eslintrc_20230911202721.js +0 -149
- package/.history/.eslintrc_20230911202746.js +0 -149
- package/.history/.eslintrc_20240423125702.cjs +0 -148
- package/.history/.gitignore_20220609190420 +0 -14
- package/.history/.gitignore_20230911185959 +0 -4
- package/.history/.gitignore_20230911190006 +0 -4
- package/.history/.gitignore_20230911190007 +0 -4
- package/.history/.nmprc_20241004144025 +0 -0
- package/.history/.nmprc_20241004144041 +0 -1
- package/.history/.npmrc_20241004144040 +0 -1
- package/.history/.npmrc_20241004144152 +0 -1
- package/.history/.npmrc_20241004145639 +0 -2
- package/.history/.npmrc_20241004145649 +0 -1
- package/.history/.nvmrc_20250729181039 +0 -1
- package/.history/.prettierignore_20220609190420 +0 -5
- package/.history/.prettierignore_20230911190242 +0 -7
- package/.history/.prettierignore_20230911190245 +0 -7
- package/.history/.prettierignore_20230911211301 +0 -8
- package/.history/CHANGELOG_20250729195139.md +0 -28
- package/.history/CHANGELOG_20250729195148.md +0 -29
- package/.history/CHANGELOG_20250729195156.md +0 -28
- package/.history/CHANGELOG_20250729195218.md +0 -29
- package/.history/CHANGELOG_20250729195223.md +0 -27
- package/.history/CHANGELOG_20250729195506.md +0 -29
- package/.history/CHANGELOG_20250729224404.md +0 -30
- package/.history/CHANGELOG_20250729224411.md +0 -30
- package/.history/CHANGELOG_20250730124538.md +0 -41
- package/.history/CHANGELOG_20250730124603.md +0 -38
- package/.history/CHANGELOG_20250730124627.md +0 -36
- package/.history/CHANGELOG_20250730124638.md +0 -36
- package/.history/CHANGELOG_20250730124640.md +0 -36
- package/.history/README_20230911145033.md +0 -245
- package/.history/README_20230911151749.md +0 -245
- package/.history/README_20230911151844.md +0 -245
- package/.history/README_20230911153040.md +0 -245
- package/.history/README_20230911202959.md +0 -245
- package/.history/bitbucket-pipelines_20250729111540.yml +0 -46
- package/.history/bitbucket-pipelines_20250729210338.yml +0 -46
- package/.history/bitbucket-pipelines_20250729210340.yml +0 -46
- package/.history/bitbucket-pipelines_20250729210342.yml +0 -46
- package/.history/bitbucket-pipelines_20250729222234.yml +0 -47
- package/.history/bitbucket-pipelines_20250729222554.yml +0 -47
- package/.history/bitbucket-pipelines_20250729222555.yml +0 -47
- package/.history/bitbucket-pipelines_20250729223022.yml +0 -46
- package/.history/bitbucket-pipelines_20250729223024.yml +0 -46
- package/.history/cli_20241005014539 +0 -3
- package/.history/cli_20241005014542 +0 -3
- package/.history/cli_20241005014848 +0 -3
- package/.history/dist/chunk-FICM3HUI_20230912183408.js +0 -302
- package/.history/dist/chunk-FICM3HUI_20230912201610.js +0 -302
- package/.history/package_20250729182417.json +0 -111
- package/.history/package_20250729182419.json +0 -111
- package/.history/package_20250729182618.json +0 -110
- package/.history/package_20250729182834.json +0 -110
- package/.history/package_20250729183032.json +0 -110
- package/.history/package_20250729183033.json +0 -110
- package/.history/package_20250729185750.json +0 -110
- package/.history/package_20250729185815.json +0 -110
- package/.history/package_20250729185846.json +0 -110
- package/.history/package_20250729185854.json +0 -110
- package/.history/package_20250729185943.json +0 -110
- package/.history/package_20250729190645.json +0 -110
- package/.history/package_20250729195934.json +0 -110
- package/.history/package_20250729200013.json +0 -110
- package/.history/package_20250729200056.json +0 -110
- package/.history/package_20250729200434.json +0 -110
- package/.history/package_20250729200808.json +0 -110
- package/.history/package_20250729200944.json +0 -110
- package/.history/package_20250729214420.json +0 -114
- package/.history/package_20250729223112.json +0 -110
- package/.history/package_20250729223127.json +0 -110
- package/.history/package_20250729223134.json +0 -110
- package/.history/package_20250730124647.json +0 -114
- package/.history/tsconfig_20241005001442.json +0 -34
- package/.history/tsconfig_20241005001500.json +0 -34
- package/.history/tsconfig_20241005001540.json +0 -34
- package/.history/tsconfig_20241005014429.json +0 -42
- package/.history/tsconfig_20241005014436.json +0 -42
- package/.history/tsconfig_20241005014439.json +0 -38
- package/.history/tsconfig_20241005014455.json +0 -38
- package/.history/tsconfig_20241005014521.json +0 -38
- package/.history/vitest.config_20250729214539.ts +0 -0
- package/.history/vitest.config_20250729214659.ts +0 -24
- package/.history/vitest.config_20250729214748.ts +0 -21
- package/.history/vitest.config_20250729214825.ts +0 -21
- package/.history/vitest.config_20250729214902.ts +0 -21
- package/.history/vitest.config_20250729222125.ts +0 -20
- package/.history/vitest.config_20250729222213.ts +0 -20
- package/.idea/codeStyles/Project.xml +0 -131
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/misc.xml +0 -17
- package/.idea/modules.xml +0 -8
- package/.idea/prettier.xml +0 -6
- package/.idea/tamaro-cli.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/.prettierrc.cjs +0 -19
package/.nvmrc
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
22.22.
|
|
1
|
+
22.22.2
|
package/bitbucket-pipelines.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
image: node:22.22.
|
|
1
|
+
image: node:22.22.2
|
|
2
2
|
|
|
3
3
|
definitions:
|
|
4
4
|
caches:
|
|
@@ -18,15 +18,9 @@ definitions:
|
|
|
18
18
|
initialize: &initialize |-
|
|
19
19
|
corepack enable pnpm
|
|
20
20
|
corepack prepare --activate
|
|
21
|
+
npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN_READ_ONLY
|
|
22
|
+
pnpm install --prefer-offline
|
|
21
23
|
steps:
|
|
22
|
-
- step: &install
|
|
23
|
-
name: Install dependencies
|
|
24
|
-
caches:
|
|
25
|
-
- node
|
|
26
|
-
- pnpm
|
|
27
|
-
script:
|
|
28
|
-
- *initialize
|
|
29
|
-
- pnpm install --prefer-offline
|
|
30
24
|
- step: &check
|
|
31
25
|
name: Check
|
|
32
26
|
caches:
|
|
@@ -43,5 +37,4 @@ definitions:
|
|
|
43
37
|
|
|
44
38
|
pipelines:
|
|
45
39
|
default:
|
|
46
|
-
- step: *install
|
|
47
40
|
- step: *check
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as promptConfirmation, D as logError, E as logDataTable, O as logSuccess, S as halt, T as logCommand, _ as getWidgetUuid, a as AWS_S3_BUCKET_TAMARO, c as CORE_CONFIG_NAME, d as HTTPS_CRT_FILE, f as HTTPS_KEY_FILE, h as getPaths, i as AWS_CLOUDFRONT_DISTRIBUTION_ID, k as logTitle, l as DEFAULT_PORT, m as getIfCoreFns, n as assertEnvValid, o as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD, s as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE, t as applyEnv, u as DEFAULT_TAG, w as runCommandSync, x as resolveOwn, y as resolveBin } from "./env-
|
|
2
|
+
import { C as promptConfirmation, D as logError, E as logDataTable, O as logSuccess, S as halt, T as logCommand, _ as getWidgetUuid, a as AWS_S3_BUCKET_TAMARO, c as CORE_CONFIG_NAME, d as HTTPS_CRT_FILE, f as HTTPS_KEY_FILE, h as getPaths, i as AWS_CLOUDFRONT_DISTRIBUTION_ID, k as logTitle, l as DEFAULT_PORT, m as getIfCoreFns, n as assertEnvValid, o as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD, s as AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE, t as applyEnv, u as DEFAULT_TAG, w as runCommandSync, x as resolveOwn, y as resolveBin } from "./env-B20cxmcB.js";
|
|
3
3
|
import { createCommand } from "commander";
|
|
4
|
-
import { existsSync, mkdirSync, renameSync } from "fs";
|
|
5
|
-
import
|
|
4
|
+
import fs, { existsSync, mkdirSync, renameSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
6
|
import { execaCommandSync } from "execa";
|
|
7
7
|
import prompts from "prompts";
|
|
8
8
|
import stripIndent from "strip-indent";
|
|
9
9
|
import notifier from "node-notifier";
|
|
10
10
|
import { globSync } from "glob";
|
|
11
|
-
import fs from "node:fs";
|
|
12
11
|
import Handlebars from "handlebars";
|
|
13
12
|
import helpers from "handlebars-helpers";
|
|
14
13
|
import { getPortPromise } from "portfinder";
|
|
@@ -23,7 +22,7 @@ const awsAuthenticate = (options) => {
|
|
|
23
22
|
return;
|
|
24
23
|
try {
|
|
25
24
|
checkIdentity(options);
|
|
26
|
-
} catch
|
|
25
|
+
} catch {
|
|
27
26
|
login(options);
|
|
28
27
|
}
|
|
29
28
|
};
|
|
@@ -55,7 +54,7 @@ const login = (options) => {
|
|
|
55
54
|
try {
|
|
56
55
|
execaCommandSync(`aws sso login ${flags}`, { stdio: "inherit" });
|
|
57
56
|
console.log("");
|
|
58
|
-
} catch
|
|
57
|
+
} catch {
|
|
59
58
|
halt("Login failed.");
|
|
60
59
|
}
|
|
61
60
|
};
|
|
@@ -74,25 +73,25 @@ const assertProfileValid = (profile) => {
|
|
|
74
73
|
};
|
|
75
74
|
const promptProfile = async () => {
|
|
76
75
|
const { profile } = await prompts([{
|
|
77
|
-
type: "select",
|
|
78
|
-
name: "profile",
|
|
79
|
-
message: "Select AWS profile",
|
|
80
76
|
choices: getAvailableProfiles().filter((v) => !!v).map((v) => ({
|
|
81
77
|
title: v,
|
|
82
78
|
value: v
|
|
83
|
-
}))
|
|
79
|
+
})),
|
|
80
|
+
message: "Select AWS profile",
|
|
81
|
+
name: "profile",
|
|
82
|
+
type: "select"
|
|
84
83
|
}], { onCancel: () => halt() });
|
|
85
84
|
return profile;
|
|
86
85
|
};
|
|
87
86
|
//#endregion
|
|
88
87
|
//#region src/lib/notifier.ts
|
|
89
88
|
const notify = (args) => {
|
|
90
|
-
const {
|
|
89
|
+
const { message = "", title } = args;
|
|
91
90
|
notifier.notify({
|
|
92
|
-
title,
|
|
93
|
-
message: stripIndent(message).trim(),
|
|
94
91
|
contentImage: "https://assets.raisenow.io/favicon.png",
|
|
95
|
-
|
|
92
|
+
message: stripIndent(message).trim(),
|
|
93
|
+
sound: "Funk",
|
|
94
|
+
title
|
|
96
95
|
});
|
|
97
96
|
};
|
|
98
97
|
//#endregion
|
|
@@ -103,8 +102,9 @@ const archive = (options) => {
|
|
|
103
102
|
assertIsNotArchived();
|
|
104
103
|
const configName = getWidgetUuid();
|
|
105
104
|
const cwd = process.cwd();
|
|
106
|
-
const
|
|
107
|
-
const
|
|
105
|
+
const parentDir = path.dirname(cwd);
|
|
106
|
+
const archiveDir = path.resolve(parentDir, "_archived");
|
|
107
|
+
const archiveTarget = path.resolve(archiveDir, configName);
|
|
108
108
|
assertArchiveTargetDoesNotExist(archiveTarget);
|
|
109
109
|
assertOptionsValid$9(options);
|
|
110
110
|
if (options.dryrun) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
|
|
@@ -115,8 +115,8 @@ const archive = (options) => {
|
|
|
115
115
|
logSuccess(`\n✅ "${configName}" has been archived and moved to ${archiveTarget}`);
|
|
116
116
|
process.on("exit", () => {
|
|
117
117
|
notify({
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
message: `"${configName}" has been archived.`,
|
|
119
|
+
title: "archive"
|
|
120
120
|
});
|
|
121
121
|
});
|
|
122
122
|
};
|
|
@@ -128,7 +128,7 @@ const assertIsNotCore$3 = (ifCore) => {
|
|
|
128
128
|
if (ifCore()) halt("You cannot archive Tamaro Core.");
|
|
129
129
|
};
|
|
130
130
|
const assertIsNotArchived = () => {
|
|
131
|
-
if (basename(dirname(process.cwd())) === "_archived") halt("This configuration is already archived.");
|
|
131
|
+
if (path.basename(path.dirname(process.cwd())) === "_archived") halt("This configuration is already archived.");
|
|
132
132
|
};
|
|
133
133
|
const assertArchiveTargetDoesNotExist = (archiveTarget) => {
|
|
134
134
|
if (existsSync(archiveTarget)) halt(`Archive target already exists: ${archiveTarget}. Please remove it first.`);
|
|
@@ -147,13 +147,13 @@ helpers.comparison({ handlebars: Handlebars });
|
|
|
147
147
|
const validateEmailTemplates = (templatePaths) => {
|
|
148
148
|
const errors = [];
|
|
149
149
|
for (const templatePath of templatePaths) try {
|
|
150
|
-
const template = fs.readFileSync(templatePath, "
|
|
150
|
+
const template = fs.readFileSync(templatePath, "utf8");
|
|
151
151
|
assureOnlySupportedHelpers(template);
|
|
152
152
|
compileEmailTemplate(template);
|
|
153
153
|
console.log(`${templatePath} is a valid email template`);
|
|
154
|
-
} catch (
|
|
154
|
+
} catch (error) {
|
|
155
155
|
errors.push(`${templatePath} is invalid`);
|
|
156
|
-
errors.push(
|
|
156
|
+
errors.push(error);
|
|
157
157
|
}
|
|
158
158
|
return errors;
|
|
159
159
|
};
|
|
@@ -174,8 +174,8 @@ const assureOnlySupportedHelpers = (template) => {
|
|
|
174
174
|
const visit = (node) => {
|
|
175
175
|
if (!node) return;
|
|
176
176
|
switch (node.type) {
|
|
177
|
-
case "
|
|
178
|
-
case "
|
|
177
|
+
case "BlockStatement":
|
|
178
|
+
case "MustacheStatement": {
|
|
179
179
|
const name = extractHelperName(node);
|
|
180
180
|
if (name) usedHelpers.add(name);
|
|
181
181
|
break;
|
|
@@ -186,7 +186,7 @@ const assureOnlySupportedHelpers = (template) => {
|
|
|
186
186
|
*/
|
|
187
187
|
for (const key in node) {
|
|
188
188
|
const value = node[key];
|
|
189
|
-
if (Array.isArray(value)) value.forEach(visit);
|
|
189
|
+
if (Array.isArray(value)) value.forEach((v) => visit(v));
|
|
190
190
|
else if (value && typeof value === "object" && value.type) visit(value);
|
|
191
191
|
}
|
|
192
192
|
};
|
|
@@ -227,7 +227,7 @@ const assureOnlySupportedHelpers = (template) => {
|
|
|
227
227
|
"unlessGteq",
|
|
228
228
|
"unlessLteq"
|
|
229
229
|
]);
|
|
230
|
-
const unsupportedHelpers =
|
|
230
|
+
const unsupportedHelpers = [...usedHelpers].filter((h) => !supportedHelpers.has(h));
|
|
231
231
|
if (unsupportedHelpers.length > 0) throw new Error(`Email template uses unsupported Handlebars helpers: ${unsupportedHelpers.join(", ")}`);
|
|
232
232
|
};
|
|
233
233
|
/**
|
|
@@ -246,8 +246,8 @@ const compileEmailTemplate = (template) => {
|
|
|
246
246
|
* deployed.
|
|
247
247
|
*/
|
|
248
248
|
const validate = async () => {
|
|
249
|
-
const errors = validateEmailTemplates(globSync("email-config/templates/**/*.hbs").
|
|
250
|
-
if (errors.length) halt(errors.map((el) => el.toString()).join("\n"));
|
|
249
|
+
const errors = validateEmailTemplates(globSync("email-config/templates/**/*.hbs").toSorted());
|
|
250
|
+
if (errors.length > 0) halt(errors.map((el) => el.toString()).join("\n"));
|
|
251
251
|
logTitle("Validated successfully");
|
|
252
252
|
};
|
|
253
253
|
//#endregion
|
|
@@ -255,8 +255,8 @@ const validate = async () => {
|
|
|
255
255
|
const assertCrtExists = () => {
|
|
256
256
|
const { ifCore } = getIfCoreFns();
|
|
257
257
|
const paths = getPaths(ifCore);
|
|
258
|
-
const certFile = resolve(paths.root, HTTPS_CRT_FILE);
|
|
259
|
-
const keyFile = resolve(paths.root, HTTPS_KEY_FILE);
|
|
258
|
+
const certFile = path.resolve(paths.root, HTTPS_CRT_FILE);
|
|
259
|
+
const keyFile = path.resolve(paths.root, HTTPS_KEY_FILE);
|
|
260
260
|
if (existsSync(certFile) && existsSync(keyFile)) return;
|
|
261
261
|
halt(stripIndent(`
|
|
262
262
|
Flag "--https" is used, but "${HTTPS_CRT_FILE}" and/or "${HTTPS_KEY_FILE}" files are not found.
|
|
@@ -293,13 +293,13 @@ const build = async (options) => {
|
|
|
293
293
|
console.log(`Path: ${paths.appDist}\n`);
|
|
294
294
|
process.on("exit", () => {
|
|
295
295
|
notify({
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
message: `Bundle for "${configName}" customer configuration is done.`,
|
|
297
|
+
title: "build"
|
|
298
298
|
});
|
|
299
299
|
});
|
|
300
300
|
};
|
|
301
301
|
const assertOptionsValid$8 = (options) => {
|
|
302
|
-
const {
|
|
302
|
+
const { deploy, env, https, localCore, profile } = options;
|
|
303
303
|
const { ifCore } = getIfCoreFns();
|
|
304
304
|
if (ifCore() && localCore) halt("Flag \"--local-core\" is redundant if running in Tamaro Core context.");
|
|
305
305
|
if (localCore && deploy) halt("Flags \"--local-core\" and \"--deploy\" must not be used together.");
|
|
@@ -309,7 +309,7 @@ const assertOptionsValid$8 = (options) => {
|
|
|
309
309
|
};
|
|
310
310
|
const prepareFlags$2 = (options) => {
|
|
311
311
|
const flags = [];
|
|
312
|
-
const {
|
|
312
|
+
const { analyze, debug, https, localCore, nolint } = options;
|
|
313
313
|
if (localCore) flags.push("--env localCore");
|
|
314
314
|
if (analyze) flags.push("--env analyze");
|
|
315
315
|
if (https) flags.push("--env https");
|
|
@@ -320,7 +320,7 @@ const prepareFlags$2 = (options) => {
|
|
|
320
320
|
//#endregion
|
|
321
321
|
//#region src/lib/validators/assertTagValid.ts
|
|
322
322
|
const assertTagValid = (tag) => {
|
|
323
|
-
const regex = /^[
|
|
323
|
+
const regex = /^[\w.-]+$/;
|
|
324
324
|
if (!regex.test(tag)) halt(`Flag "--tag" has forbidden format. Allowed format: ${regex.toString()}.`);
|
|
325
325
|
};
|
|
326
326
|
//#endregion
|
|
@@ -337,7 +337,7 @@ const deploy = async (options) => {
|
|
|
337
337
|
await validate();
|
|
338
338
|
awsAuthenticate(options);
|
|
339
339
|
const flags = prepareFlags$3(options);
|
|
340
|
-
const {
|
|
340
|
+
const { dryrun, tag } = options;
|
|
341
341
|
const dryRunFlag = dryrun ? `--dryrun` : "";
|
|
342
342
|
const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
|
|
343
343
|
const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}`;
|
|
@@ -404,12 +404,12 @@ const deploy = async (options) => {
|
|
|
404
404
|
});
|
|
405
405
|
process.on("exit", () => {
|
|
406
406
|
notify({
|
|
407
|
-
title: "deploy",
|
|
408
407
|
message: `
|
|
409
408
|
Bundle for "${configName}" is deployed with tag "${tag}".
|
|
410
409
|
Demo page: ${demoPage}
|
|
411
410
|
Entry point: ${entryPoint}
|
|
412
|
-
|
|
411
|
+
`,
|
|
412
|
+
title: "deploy"
|
|
413
413
|
});
|
|
414
414
|
});
|
|
415
415
|
};
|
|
@@ -462,13 +462,13 @@ const deployEmailConfig = async (options) => {
|
|
|
462
462
|
logDataTable({ "Deploy URL:": deployUrl });
|
|
463
463
|
process.on("exit", () => {
|
|
464
464
|
notify({
|
|
465
|
-
|
|
466
|
-
|
|
465
|
+
message: `Email configuration for "${configName}" customer configuration is deployed.`,
|
|
466
|
+
title: "deploy-email-config"
|
|
467
467
|
});
|
|
468
468
|
});
|
|
469
469
|
};
|
|
470
470
|
const assertOptionsValid$6 = (options) => {
|
|
471
|
-
const {
|
|
471
|
+
const { bucket, profile } = options;
|
|
472
472
|
if (profile) assertProfileValid(profile);
|
|
473
473
|
if (bucket) assertBucketValid$1(bucket);
|
|
474
474
|
};
|
|
@@ -484,16 +484,16 @@ const assertBucketValid$1 = (bucket) => {
|
|
|
484
484
|
};
|
|
485
485
|
const promptBucketTamaroEmailConfig$1 = async () => {
|
|
486
486
|
const { bucket } = await prompts([{
|
|
487
|
-
type: "select",
|
|
488
|
-
name: "bucket",
|
|
489
|
-
message: "Select environment",
|
|
490
487
|
choices: [{
|
|
491
488
|
title: "stage",
|
|
492
489
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE
|
|
493
490
|
}, {
|
|
494
491
|
title: "prod",
|
|
495
492
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
496
|
-
}]
|
|
493
|
+
}],
|
|
494
|
+
message: "Select environment",
|
|
495
|
+
name: "bucket",
|
|
496
|
+
type: "select"
|
|
497
497
|
}], { onCancel: () => halt() });
|
|
498
498
|
return bucket;
|
|
499
499
|
};
|
|
@@ -516,16 +516,16 @@ const dev = async (options) => {
|
|
|
516
516
|
runCommandSync(cmd, { stdio: "inherit" });
|
|
517
517
|
};
|
|
518
518
|
const assertOptionsValid$5 = (options) => {
|
|
519
|
-
const {
|
|
519
|
+
const { env, https, localCore, port } = options;
|
|
520
520
|
const { ifCore } = getIfCoreFns();
|
|
521
521
|
if (ifCore() && localCore) halt("Flag \"--local-core\" is redundant if running in Tamaro Core context.");
|
|
522
|
-
if (isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
|
|
522
|
+
if (Number.isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
|
|
523
523
|
if (https) assertCrtExists();
|
|
524
524
|
assertEnvValid(env);
|
|
525
525
|
};
|
|
526
526
|
const prepareFlags$1 = async (options) => {
|
|
527
527
|
const flags = [];
|
|
528
|
-
const {
|
|
528
|
+
const { debug, https, localCore, nolint, port: defaultPort } = options;
|
|
529
529
|
const port = await getPortPromise({ port: Number(defaultPort) });
|
|
530
530
|
if (localCore) flags.push("--env localCore");
|
|
531
531
|
flags.push(`--port ${port}`);
|
|
@@ -559,9 +559,7 @@ const listDeployed = async (options) => {
|
|
|
559
559
|
if (error.stderr) halt(error.stderr);
|
|
560
560
|
}
|
|
561
561
|
const tags = parseTags(out.split("\n"));
|
|
562
|
-
|
|
563
|
-
if (tags.length === 0) text = "No deployments found.";
|
|
564
|
-
else text = tags.map((tag, idx) => {
|
|
562
|
+
const text = tags.length === 0 ? "No deployments found." : tags.map((tag, idx) => {
|
|
565
563
|
return `${idx + 1}. https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`;
|
|
566
564
|
}).join("\n");
|
|
567
565
|
console.log(`${text}\n`);
|
|
@@ -573,7 +571,7 @@ const assertOptionsValid$4 = (options) => {
|
|
|
573
571
|
};
|
|
574
572
|
const assertConfigValid = (config) => {
|
|
575
573
|
if (!config) return;
|
|
576
|
-
const regex = /^[
|
|
574
|
+
const regex = /^[\w-]+$/;
|
|
577
575
|
if (!regex.test(config)) halt(`Flag "--config" has forbidden format. Allowed format: ${regex.toString()}.`);
|
|
578
576
|
};
|
|
579
577
|
const parseTags = (lines) => {
|
|
@@ -596,20 +594,20 @@ const serve = async (options) => {
|
|
|
596
594
|
runCommandSync(cmd, { stdio: "inherit" });
|
|
597
595
|
};
|
|
598
596
|
const assertOptionsValid$3 = (options) => {
|
|
599
|
-
const {
|
|
600
|
-
if (isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
|
|
597
|
+
const { https, port } = options;
|
|
598
|
+
if (Number.isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
|
|
601
599
|
if (https) assertCrtExists();
|
|
602
600
|
};
|
|
603
601
|
const prepareFlags = async (options) => {
|
|
604
602
|
const flags = [];
|
|
605
|
-
const { port: defaultPort
|
|
603
|
+
const { https, port: defaultPort } = options;
|
|
606
604
|
const port = await getPortPromise({ port: Number(defaultPort) });
|
|
607
605
|
flags.push(`-p ${port}`);
|
|
608
606
|
if (https) {
|
|
609
607
|
const { ifCore } = getIfCoreFns();
|
|
610
608
|
const paths = getPaths(ifCore);
|
|
611
|
-
const certFile = resolve(paths.root, HTTPS_CRT_FILE);
|
|
612
|
-
const keyFile = resolve(paths.root, HTTPS_KEY_FILE);
|
|
609
|
+
const certFile = path.resolve(paths.root, HTTPS_CRT_FILE);
|
|
610
|
+
const keyFile = path.resolve(paths.root, HTTPS_KEY_FILE);
|
|
613
611
|
flags.push(`--ssl-cert ${certFile}`);
|
|
614
612
|
flags.push(`--ssl-key ${keyFile}`);
|
|
615
613
|
}
|
|
@@ -623,7 +621,9 @@ const unarchive = (options) => {
|
|
|
623
621
|
assertIsArchived();
|
|
624
622
|
const configName = getWidgetUuid();
|
|
625
623
|
const cwd = process.cwd();
|
|
626
|
-
const
|
|
624
|
+
const archivedDir = path.dirname(cwd);
|
|
625
|
+
const configsDir = path.dirname(archivedDir);
|
|
626
|
+
const restoreTarget = path.resolve(configsDir, configName);
|
|
627
627
|
assertRestoreTargetDoesNotExist(restoreTarget);
|
|
628
628
|
assertOptionsValid$2(options);
|
|
629
629
|
if (options.dryrun) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
|
|
@@ -634,8 +634,8 @@ const unarchive = (options) => {
|
|
|
634
634
|
logTitle(`✅ "${configName}" has been unarchived and moved to ${restoreTarget}`);
|
|
635
635
|
process.on("exit", () => {
|
|
636
636
|
notify({
|
|
637
|
-
|
|
638
|
-
|
|
637
|
+
message: `"${configName}" has been unarchived.`,
|
|
638
|
+
title: "unarchive"
|
|
639
639
|
});
|
|
640
640
|
});
|
|
641
641
|
};
|
|
@@ -644,7 +644,7 @@ const assertOptionsValid$2 = (options) => {
|
|
|
644
644
|
if (profile) assertProfileValid(profile);
|
|
645
645
|
};
|
|
646
646
|
const assertIsArchived = () => {
|
|
647
|
-
if (basename(dirname(process.cwd())) !== "_archived") halt("This configuration is not archived. Only archived configurations can be unarchived.");
|
|
647
|
+
if (path.basename(path.dirname(process.cwd())) !== "_archived") halt("This configuration is not archived. Only archived configurations can be unarchived.");
|
|
648
648
|
};
|
|
649
649
|
const assertIsNotCore$1 = (ifCore) => {
|
|
650
650
|
if (ifCore()) halt("You cannot unarchive Tamaro Core.");
|
|
@@ -664,7 +664,7 @@ const undeploy = async (options) => {
|
|
|
664
664
|
assertOptionsValid$1(options);
|
|
665
665
|
awsAuthenticate(options);
|
|
666
666
|
const flags = prepareFlags$3(options);
|
|
667
|
-
const { tag = DEFAULT_TAG
|
|
667
|
+
const { all, dryrun, tag = DEFAULT_TAG } = options;
|
|
668
668
|
const dryRunFlag = dryrun ? `--dryrun` : "";
|
|
669
669
|
const deployUrl = all ? `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/` : `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/`;
|
|
670
670
|
const description = all ? `all tags of "${configName}"` : `tag "${tag}" of "${configName}"`;
|
|
@@ -702,13 +702,13 @@ const undeploy = async (options) => {
|
|
|
702
702
|
logDataTable({ "Removed URL:": deployUrl });
|
|
703
703
|
process.on("exit", () => {
|
|
704
704
|
notify({
|
|
705
|
-
|
|
706
|
-
|
|
705
|
+
message: `${description} has been undeployed.`,
|
|
706
|
+
title: "undeploy"
|
|
707
707
|
});
|
|
708
708
|
});
|
|
709
709
|
};
|
|
710
710
|
const assertOptionsValid$1 = (options) => {
|
|
711
|
-
const { profile, tag
|
|
711
|
+
const { all, profile, tag } = options;
|
|
712
712
|
const { ifCore } = getIfCoreFns();
|
|
713
713
|
if (ifCore() && all) halt("Flag \"--all\" must not be used in Tamaro Core context.");
|
|
714
714
|
if (ifCore() && tag === "latest") halt("You cannot undeploy the default tag for Tamaro Core.");
|
|
@@ -755,13 +755,13 @@ const undeployEmailConfig = async (options) => {
|
|
|
755
755
|
logDataTable({ "Removed URL:": deployUrl });
|
|
756
756
|
process.on("exit", () => {
|
|
757
757
|
notify({
|
|
758
|
-
|
|
759
|
-
|
|
758
|
+
message: `Email configuration for "${configName}" has been undeployed.`,
|
|
759
|
+
title: "undeploy-email-config"
|
|
760
760
|
});
|
|
761
761
|
});
|
|
762
762
|
};
|
|
763
763
|
const assertOptionsValid = (options) => {
|
|
764
|
-
const {
|
|
764
|
+
const { bucket, profile } = options;
|
|
765
765
|
if (profile) assertProfileValid(profile);
|
|
766
766
|
if (bucket) assertBucketValid(bucket);
|
|
767
767
|
};
|
|
@@ -773,23 +773,23 @@ const assertBucketValid = (bucket) => {
|
|
|
773
773
|
};
|
|
774
774
|
const promptBucketTamaroEmailConfig = async () => {
|
|
775
775
|
const { bucket } = await prompts([{
|
|
776
|
-
type: "select",
|
|
777
|
-
name: "bucket",
|
|
778
|
-
message: "Select environment",
|
|
779
776
|
choices: [{
|
|
780
777
|
title: "stage",
|
|
781
778
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE
|
|
782
779
|
}, {
|
|
783
780
|
title: "prod",
|
|
784
781
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
785
|
-
}]
|
|
782
|
+
}],
|
|
783
|
+
message: "Select environment",
|
|
784
|
+
name: "bucket",
|
|
785
|
+
type: "select"
|
|
786
786
|
}], { onCancel: () => halt() });
|
|
787
787
|
return bucket;
|
|
788
788
|
};
|
|
789
789
|
//#endregion
|
|
790
790
|
//#region package.json
|
|
791
791
|
var name = "@raisenow/tamaro-cli";
|
|
792
|
-
var version = "1.
|
|
792
|
+
var version = "1.8.0-dev.2";
|
|
793
793
|
//#endregion
|
|
794
794
|
//#region src/cli.ts
|
|
795
795
|
/**
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import { execaCommandSync } from "execa";
|
|
4
5
|
import prompts from "prompts";
|
|
5
6
|
import stripIndent from "strip-indent";
|
|
6
7
|
import chalk from "chalk";
|
|
7
8
|
import columnify from "columnify";
|
|
8
|
-
import path from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { createRequire } from "module";
|
|
11
10
|
import { getIfUtils } from "webpack-config-utils";
|
|
12
11
|
import { globSync } from "glob";
|
|
13
12
|
import { config } from "dotenv";
|
|
@@ -35,7 +34,7 @@ const halt = (message) => {
|
|
|
35
34
|
process.exit(1);
|
|
36
35
|
};
|
|
37
36
|
const prepareCommand = (cmd) => {
|
|
38
|
-
return cmd.
|
|
37
|
+
return cmd.replaceAll("\n", " ").replaceAll(/[ \t]{2,}/g, " ").trim();
|
|
39
38
|
};
|
|
40
39
|
const runCommandSync = (cmd, options) => {
|
|
41
40
|
return execaCommandSync(prepareCommand(cmd), options);
|
|
@@ -43,15 +42,15 @@ const runCommandSync = (cmd, options) => {
|
|
|
43
42
|
const promptConfirmation = async (message, skipConfirmation) => {
|
|
44
43
|
if (skipConfirmation) return;
|
|
45
44
|
const { confirmed } = await prompts([{
|
|
46
|
-
|
|
47
|
-
name: "confirmed",
|
|
45
|
+
initial: false,
|
|
48
46
|
message,
|
|
49
|
-
|
|
47
|
+
name: "confirmed",
|
|
48
|
+
type: "confirm"
|
|
50
49
|
}], { onCancel: () => halt() });
|
|
51
50
|
if (!confirmed) halt("Operation cancelled.");
|
|
52
51
|
};
|
|
53
52
|
//#endregion
|
|
54
|
-
//#region node_modules/.pnpm/tsdown@0.21.
|
|
53
|
+
//#region node_modules/.pnpm/tsdown@0.21.7_synckit@0.11.11_typescript@6.0.2/node_modules/tsdown/esm-shims.js
|
|
55
54
|
const getFilename = () => fileURLToPath(import.meta.url);
|
|
56
55
|
const getDirname = () => path.dirname(getFilename());
|
|
57
56
|
const __dirname = /* @__PURE__ */ getDirname();
|
|
@@ -68,8 +67,8 @@ const extensions = moduleFileExtensions.map((v) => `.${v}`);
|
|
|
68
67
|
const TAMARO_CORE_PACKAGE_NAMES = ["@raisenow/tamaro-core"];
|
|
69
68
|
const TAMARO_CONFIGURATIONS_PACKAGE_NAMES = ["@raisenow/tamaro-configurations"];
|
|
70
69
|
const TAMARO_SELF_SERVICE_PACKAGE_NAMES = ["@raisenow/tamaro-self-service"];
|
|
71
|
-
const resolveApp = (relativePath) => resolve(realpathSync(process.cwd()), relativePath);
|
|
72
|
-
const resolveOwn = (relativePath) => resolve(__dirname, "..", relativePath);
|
|
70
|
+
const resolveApp = (relativePath) => path.resolve(realpathSync(process.cwd()), relativePath);
|
|
71
|
+
const resolveOwn = (relativePath) => path.resolve(__dirname, "..", relativePath);
|
|
73
72
|
const resolveModule = (resolveFn, filePath) => {
|
|
74
73
|
const extension = moduleFileExtensions.find((extension) => existsSync(resolveFn(`${filePath}.${extension}`)));
|
|
75
74
|
if (extension) return resolveFn(`${filePath}.${extension}`);
|
|
@@ -100,9 +99,32 @@ const resolveEslintPluginConfig = (paths) => {
|
|
|
100
99
|
const resolveBin = (name) => {
|
|
101
100
|
const pkgPath = require$1.resolve(`${name}/package.json`);
|
|
102
101
|
const { bin } = require$1(pkgPath);
|
|
103
|
-
|
|
102
|
+
const dir = path.dirname(pkgPath);
|
|
103
|
+
const binPath = typeof bin === "object" ? bin[name] : bin;
|
|
104
|
+
return path.join(dir, binPath);
|
|
105
|
+
};
|
|
106
|
+
const getWidgetUuid = () => path.basename(resolveApp("."));
|
|
107
|
+
/**
|
|
108
|
+
* Get the appropriate tsconfig file.
|
|
109
|
+
* Prefers tsconfig.app.json (composite config structure) but falls back to
|
|
110
|
+
* tsconfig.json for backwards compatibility with older versions.
|
|
111
|
+
*/
|
|
112
|
+
const getTsConfigPath = () => {
|
|
113
|
+
const appTsConfig = resolveApp("tsconfig.app.json");
|
|
114
|
+
if (existsSync(appTsConfig)) return appTsConfig;
|
|
115
|
+
return resolveApp("tsconfig.json");
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Get the appropriate tailwind config file.
|
|
119
|
+
* Prefers tailwind.config.cjs (for ESM compatibility) but falls back to
|
|
120
|
+
* tailwind.config.js for backwards compatibility.
|
|
121
|
+
*/
|
|
122
|
+
const getTailwindConfigPath = () => {
|
|
123
|
+
const cjsConfig = resolveApp("tailwind.config.cjs");
|
|
124
|
+
if (existsSync(cjsConfig)) return cjsConfig;
|
|
125
|
+
const jsConfig = resolveApp("tailwind.config.js");
|
|
126
|
+
if (existsSync(jsConfig)) return jsConfig;
|
|
104
127
|
};
|
|
105
|
-
const getWidgetUuid = () => basename(resolveApp("."));
|
|
106
128
|
const getPaths = (ifCore) => {
|
|
107
129
|
return ifCore({
|
|
108
130
|
root: resolveApp("."),
|
|
@@ -110,10 +132,10 @@ const getPaths = (ifCore) => {
|
|
|
110
132
|
appEntry: resolveModule(resolveApp, "src/index"),
|
|
111
133
|
appDist: resolveApp("dist"),
|
|
112
134
|
appNodeModules: resolveApp("node_modules"),
|
|
113
|
-
appTsConfig:
|
|
135
|
+
appTsConfig: getTsConfigPath(),
|
|
114
136
|
appHtml: resolveApp("src/*.html"),
|
|
115
137
|
appEnv: resolveApp(".env*"),
|
|
116
|
-
appTailwindConfig:
|
|
138
|
+
appTailwindConfig: getTailwindConfigPath()
|
|
117
139
|
}, {
|
|
118
140
|
root: resolveApp("../.."),
|
|
119
141
|
app: resolveApp("."),
|
|
@@ -128,7 +150,7 @@ const getPaths = (ifCore) => {
|
|
|
128
150
|
};
|
|
129
151
|
const getRelativePaths = (paths) => {
|
|
130
152
|
const relativePaths = {};
|
|
131
|
-
for (const [type, absPath] of Object.entries(paths)) if (absPath) relativePaths[type] = relative("./", absPath) || ".";
|
|
153
|
+
for (const [type, absPath] of Object.entries(paths)) if (absPath) relativePaths[type] = path.relative("./", absPath) || ".";
|
|
132
154
|
return relativePaths;
|
|
133
155
|
};
|
|
134
156
|
const getIfCoreFns = ({ allowArchived = false } = {}) => {
|
|
@@ -164,7 +186,7 @@ const HTTPS_KEY_FILE = "localhost.key";
|
|
|
164
186
|
//#region src/lib/env.ts
|
|
165
187
|
const require = createRequire(import.meta.url);
|
|
166
188
|
const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
167
|
-
const filePath = files.find((file) => basename(file) === ".env");
|
|
189
|
+
const filePath = files.find((file) => path.basename(file) === ".env");
|
|
168
190
|
if (filePath) config({ path: filePath });
|
|
169
191
|
process.env.NODE_ENV ??= ifMin("production", "development");
|
|
170
192
|
process.env.BABEL_ENV ??= ifMin("production", "development");
|
|
@@ -191,7 +213,7 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
191
213
|
process.env.CORE_URL ??= process.env.CORE_URL_PATTERN.replace("{{version}}", version);
|
|
192
214
|
}
|
|
193
215
|
}
|
|
194
|
-
const varNames = [
|
|
216
|
+
const varNames = new Set([
|
|
195
217
|
"NODE_ENV",
|
|
196
218
|
"BABEL_ENV",
|
|
197
219
|
"EXPOSE_VAR",
|
|
@@ -217,8 +239,8 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
217
239
|
"EPMS_PROXY_URL_PROD",
|
|
218
240
|
"EPMS_TWINT_CHECKOUT_URL_STAGE",
|
|
219
241
|
"EPMS_TWINT_CHECKOUT_URL_PROD"
|
|
220
|
-
];
|
|
221
|
-
const raw = Object.keys(process.env).filter((key) => key.startsWith("PUBLIC_") || varNames.
|
|
242
|
+
]);
|
|
243
|
+
const raw = Object.keys(process.env).filter((key) => key.startsWith("PUBLIC_") || varNames.has(key)).reduce((env, key) => {
|
|
222
244
|
env[key] = process.env[key];
|
|
223
245
|
return env;
|
|
224
246
|
}, {});
|
|
@@ -232,11 +254,9 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
232
254
|
};
|
|
233
255
|
const assertEnvValid = (env) => {
|
|
234
256
|
const { ifCore } = getIfCoreFns();
|
|
235
|
-
const envs = globSync(getPaths(ifCore).appEnv).map((file) => basename(file).replace(/^\.env\./, "")).map((file) => basename(file).replace(/^\.env$/, "")).filter((v) => !!v);
|
|
236
|
-
if (envs.length === 0)
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
if (envs.length !== 0) {
|
|
257
|
+
const envs = globSync(getPaths(ifCore).appEnv).map((file) => path.basename(file).replace(/^\.env\./, "")).map((file) => path.basename(file).replace(/^\.env$/, "")).filter((v) => !!v);
|
|
258
|
+
if (envs.length === 0 && env) console.log("Flag \"--env\" is ignored.");
|
|
259
|
+
if (envs.length > 0) {
|
|
240
260
|
if (!env) halt("Flag \"--env\" is required.");
|
|
241
261
|
if (env && !envs.includes(env)) halt(stripIndent(`
|
|
242
262
|
Flag "--env" has wrong value.
|
|
@@ -247,7 +267,7 @@ const assertEnvValid = (env) => {
|
|
|
247
267
|
const applyEnv = (env) => {
|
|
248
268
|
if (!env) return;
|
|
249
269
|
const { ifCore } = getIfCoreFns();
|
|
250
|
-
const filePath = globSync(getPaths(ifCore).appEnv).find((file) => basename(file) === `.env.${env}`);
|
|
270
|
+
const filePath = globSync(getPaths(ifCore).appEnv).find((file) => path.basename(file) === `.env.${env}`);
|
|
251
271
|
if (filePath) config({ path: filePath });
|
|
252
272
|
};
|
|
253
273
|
//#endregion
|