@raisenow/tamaro-cli 1.8.0-dev.2 ā 1.8.0-dev.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +73 -73
- package/dist/{env-B20cxmcB.js ā env-LI5tXjy4.js} +23 -22
- package/dist/webpack.config.js +9 -9
- package/eslint.config.ts +30 -0
- package/out-tsc/lib/tsconfig.lib.tsbuildinfo +1 -0
- package/out-tsc/node/tsconfig.node.tsbuildinfo +1 -0
- package/out-tsc/node/tsdown.config.d.ts +3 -0
- package/out-tsc/node/tsdown.config.d.ts.map +1 -0
- package/out-tsc/node/vitest.config.d.ts +3 -0
- package/out-tsc/node/vitest.config.d.ts.map +1 -0
- package/out-tsc/spec/tsconfig.spec.tsbuildinfo +1 -0
- package/package.json +7 -8
- package/tsconfig.base.json +25 -0
- package/tsconfig.lib.json +25 -0
- package/tsconfig.node.json +18 -0
- package/tsconfig.spec.json +29 -0
- package/vitest.config.ts +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
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-LI5tXjy4.js";
|
|
3
3
|
import { createCommand } from "commander";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import { existsSync, mkdirSync, renameSync } from "fs";
|
|
5
|
+
import { basename, dirname, resolve } from "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";
|
|
11
12
|
import Handlebars from "handlebars";
|
|
12
13
|
import helpers from "handlebars-helpers";
|
|
13
14
|
import { getPortPromise } from "portfinder";
|
|
@@ -22,7 +23,7 @@ const awsAuthenticate = (options) => {
|
|
|
22
23
|
return;
|
|
23
24
|
try {
|
|
24
25
|
checkIdentity(options);
|
|
25
|
-
} catch {
|
|
26
|
+
} catch (error) {
|
|
26
27
|
login(options);
|
|
27
28
|
}
|
|
28
29
|
};
|
|
@@ -54,7 +55,7 @@ const login = (options) => {
|
|
|
54
55
|
try {
|
|
55
56
|
execaCommandSync(`aws sso login ${flags}`, { stdio: "inherit" });
|
|
56
57
|
console.log("");
|
|
57
|
-
} catch {
|
|
58
|
+
} catch (error) {
|
|
58
59
|
halt("Login failed.");
|
|
59
60
|
}
|
|
60
61
|
};
|
|
@@ -73,25 +74,25 @@ const assertProfileValid = (profile) => {
|
|
|
73
74
|
};
|
|
74
75
|
const promptProfile = async () => {
|
|
75
76
|
const { profile } = await prompts([{
|
|
77
|
+
type: "select",
|
|
78
|
+
name: "profile",
|
|
79
|
+
message: "Select AWS profile",
|
|
76
80
|
choices: getAvailableProfiles().filter((v) => !!v).map((v) => ({
|
|
77
81
|
title: v,
|
|
78
82
|
value: v
|
|
79
|
-
}))
|
|
80
|
-
message: "Select AWS profile",
|
|
81
|
-
name: "profile",
|
|
82
|
-
type: "select"
|
|
83
|
+
}))
|
|
83
84
|
}], { onCancel: () => halt() });
|
|
84
85
|
return profile;
|
|
85
86
|
};
|
|
86
87
|
//#endregion
|
|
87
88
|
//#region src/lib/notifier.ts
|
|
88
89
|
const notify = (args) => {
|
|
89
|
-
const { message = ""
|
|
90
|
+
const { title, message = "" } = args;
|
|
90
91
|
notifier.notify({
|
|
91
|
-
|
|
92
|
+
title,
|
|
92
93
|
message: stripIndent(message).trim(),
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
contentImage: "https://assets.raisenow.io/favicon.png",
|
|
95
|
+
sound: "Funk"
|
|
95
96
|
});
|
|
96
97
|
};
|
|
97
98
|
//#endregion
|
|
@@ -102,9 +103,8 @@ const archive = (options) => {
|
|
|
102
103
|
assertIsNotArchived();
|
|
103
104
|
const configName = getWidgetUuid();
|
|
104
105
|
const cwd = process.cwd();
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
const archiveTarget = path.resolve(archiveDir, configName);
|
|
106
|
+
const archiveDir = resolve(dirname(cwd), "_archived");
|
|
107
|
+
const archiveTarget = 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
|
+
title: "archive",
|
|
119
|
+
message: `"${configName}" has been archived.`
|
|
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 (
|
|
131
|
+
if (basename(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, "utf-8");
|
|
151
151
|
assureOnlySupportedHelpers(template);
|
|
152
152
|
compileEmailTemplate(template);
|
|
153
153
|
console.log(`${templatePath} is a valid email template`);
|
|
154
|
-
} catch (
|
|
154
|
+
} catch (e) {
|
|
155
155
|
errors.push(`${templatePath} is invalid`);
|
|
156
|
-
errors.push(
|
|
156
|
+
errors.push(e);
|
|
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 "MustacheStatement":
|
|
178
|
+
case "BlockStatement": {
|
|
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(
|
|
189
|
+
if (Array.isArray(value)) value.forEach(visit);
|
|
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 = Array.from(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
|
|
249
|
+
const errors = validateEmailTemplates(globSync("email-config/templates/**/*.hbs").sort());
|
|
250
|
+
if (errors.length) 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 =
|
|
259
|
-
const keyFile =
|
|
258
|
+
const certFile = resolve(paths.root, HTTPS_CRT_FILE);
|
|
259
|
+
const keyFile = 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
|
+
title: "build",
|
|
297
|
+
message: `Bundle for "${configName}" customer configuration is done.`
|
|
298
298
|
});
|
|
299
299
|
});
|
|
300
300
|
};
|
|
301
301
|
const assertOptionsValid$8 = (options) => {
|
|
302
|
-
const {
|
|
302
|
+
const { localCore, https, deploy, env, 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 { localCore, analyze, https, nolint, debug } = 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 = /^[a-zA-Z0-9-_.]+$/;
|
|
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 { tag, dryrun } = 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",
|
|
407
408
|
message: `
|
|
408
409
|
Bundle for "${configName}" is deployed with tag "${tag}".
|
|
409
410
|
Demo page: ${demoPage}
|
|
410
411
|
Entry point: ${entryPoint}
|
|
411
|
-
|
|
412
|
-
title: "deploy"
|
|
412
|
+
`
|
|
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
|
+
title: "deploy-email-config",
|
|
466
|
+
message: `Email configuration for "${configName}" customer configuration is deployed.`
|
|
467
467
|
});
|
|
468
468
|
});
|
|
469
469
|
};
|
|
470
470
|
const assertOptionsValid$6 = (options) => {
|
|
471
|
-
const {
|
|
471
|
+
const { profile, bucket } = 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",
|
|
487
490
|
choices: [{
|
|
488
491
|
title: "stage",
|
|
489
492
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE
|
|
490
493
|
}, {
|
|
491
494
|
title: "prod",
|
|
492
495
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
493
|
-
}]
|
|
494
|
-
message: "Select environment",
|
|
495
|
-
name: "bucket",
|
|
496
|
-
type: "select"
|
|
496
|
+
}]
|
|
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 { localCore, https, port, env } = 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 (
|
|
522
|
+
if (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 { localCore, port: defaultPort, https, nolint, debug } = 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,7 +559,9 @@ const listDeployed = async (options) => {
|
|
|
559
559
|
if (error.stderr) halt(error.stderr);
|
|
560
560
|
}
|
|
561
561
|
const tags = parseTags(out.split("\n"));
|
|
562
|
-
|
|
562
|
+
let text = "";
|
|
563
|
+
if (tags.length === 0) text = "No deployments found.";
|
|
564
|
+
else text = tags.map((tag, idx) => {
|
|
563
565
|
return `${idx + 1}. https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`;
|
|
564
566
|
}).join("\n");
|
|
565
567
|
console.log(`${text}\n`);
|
|
@@ -571,7 +573,7 @@ const assertOptionsValid$4 = (options) => {
|
|
|
571
573
|
};
|
|
572
574
|
const assertConfigValid = (config) => {
|
|
573
575
|
if (!config) return;
|
|
574
|
-
const regex = /^[
|
|
576
|
+
const regex = /^[a-zA-Z0-9-_]+$/;
|
|
575
577
|
if (!regex.test(config)) halt(`Flag "--config" has forbidden format. Allowed format: ${regex.toString()}.`);
|
|
576
578
|
};
|
|
577
579
|
const parseTags = (lines) => {
|
|
@@ -594,20 +596,20 @@ const serve = async (options) => {
|
|
|
594
596
|
runCommandSync(cmd, { stdio: "inherit" });
|
|
595
597
|
};
|
|
596
598
|
const assertOptionsValid$3 = (options) => {
|
|
597
|
-
const {
|
|
598
|
-
if (
|
|
599
|
+
const { port, https } = options;
|
|
600
|
+
if (isNaN(Number(port))) halt("Flag \"--port\" should be a number.");
|
|
599
601
|
if (https) assertCrtExists();
|
|
600
602
|
};
|
|
601
603
|
const prepareFlags = async (options) => {
|
|
602
604
|
const flags = [];
|
|
603
|
-
const {
|
|
605
|
+
const { port: defaultPort, https } = options;
|
|
604
606
|
const port = await getPortPromise({ port: Number(defaultPort) });
|
|
605
607
|
flags.push(`-p ${port}`);
|
|
606
608
|
if (https) {
|
|
607
609
|
const { ifCore } = getIfCoreFns();
|
|
608
610
|
const paths = getPaths(ifCore);
|
|
609
|
-
const certFile =
|
|
610
|
-
const keyFile =
|
|
611
|
+
const certFile = resolve(paths.root, HTTPS_CRT_FILE);
|
|
612
|
+
const keyFile = resolve(paths.root, HTTPS_KEY_FILE);
|
|
611
613
|
flags.push(`--ssl-cert ${certFile}`);
|
|
612
614
|
flags.push(`--ssl-key ${keyFile}`);
|
|
613
615
|
}
|
|
@@ -621,9 +623,7 @@ const unarchive = (options) => {
|
|
|
621
623
|
assertIsArchived();
|
|
622
624
|
const configName = getWidgetUuid();
|
|
623
625
|
const cwd = process.cwd();
|
|
624
|
-
const
|
|
625
|
-
const configsDir = path.dirname(archivedDir);
|
|
626
|
-
const restoreTarget = path.resolve(configsDir, configName);
|
|
626
|
+
const restoreTarget = resolve(dirname(dirname(cwd)), 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
|
+
title: "unarchive",
|
|
638
|
+
message: `"${configName}" has been unarchived.`
|
|
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 (
|
|
647
|
+
if (basename(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 {
|
|
667
|
+
const { tag = DEFAULT_TAG, all, dryrun } = 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
|
+
title: "undeploy",
|
|
706
|
+
message: `${description} has been undeployed.`
|
|
707
707
|
});
|
|
708
708
|
});
|
|
709
709
|
};
|
|
710
710
|
const assertOptionsValid$1 = (options) => {
|
|
711
|
-
const {
|
|
711
|
+
const { profile, tag, all } = 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
|
+
title: "undeploy-email-config",
|
|
759
|
+
message: `Email configuration for "${configName}" has been undeployed.`
|
|
760
760
|
});
|
|
761
761
|
});
|
|
762
762
|
};
|
|
763
763
|
const assertOptionsValid = (options) => {
|
|
764
|
-
const {
|
|
764
|
+
const { profile, bucket } = 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",
|
|
776
779
|
choices: [{
|
|
777
780
|
title: "stage",
|
|
778
781
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE
|
|
779
782
|
}, {
|
|
780
783
|
title: "prod",
|
|
781
784
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
782
|
-
}]
|
|
783
|
-
message: "Select environment",
|
|
784
|
-
name: "bucket",
|
|
785
|
-
type: "select"
|
|
785
|
+
}]
|
|
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.8.0-dev.
|
|
792
|
+
var version = "1.8.0-dev.3";
|
|
793
793
|
//#endregion
|
|
794
794
|
//#region src/cli.ts
|
|
795
795
|
/**
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import path from "node:path";
|
|
1
|
+
import { existsSync, realpathSync } from "fs";
|
|
2
|
+
import { basename, dirname, join, relative, resolve } from "path";
|
|
4
3
|
import { execaCommandSync } from "execa";
|
|
5
4
|
import prompts from "prompts";
|
|
6
5
|
import stripIndent from "strip-indent";
|
|
7
6
|
import chalk from "chalk";
|
|
8
7
|
import columnify from "columnify";
|
|
8
|
+
import path from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { createRequire } from "module";
|
|
10
11
|
import { getIfUtils } from "webpack-config-utils";
|
|
11
12
|
import { globSync } from "glob";
|
|
12
13
|
import { config } from "dotenv";
|
|
@@ -34,7 +35,7 @@ const halt = (message) => {
|
|
|
34
35
|
process.exit(1);
|
|
35
36
|
};
|
|
36
37
|
const prepareCommand = (cmd) => {
|
|
37
|
-
return cmd.
|
|
38
|
+
return cmd.replace(/\n/gm, " ").replace(/[ \t]{2,}/gm, " ").trim();
|
|
38
39
|
};
|
|
39
40
|
const runCommandSync = (cmd, options) => {
|
|
40
41
|
return execaCommandSync(prepareCommand(cmd), options);
|
|
@@ -42,10 +43,10 @@ const runCommandSync = (cmd, options) => {
|
|
|
42
43
|
const promptConfirmation = async (message, skipConfirmation) => {
|
|
43
44
|
if (skipConfirmation) return;
|
|
44
45
|
const { confirmed } = await prompts([{
|
|
45
|
-
|
|
46
|
-
message,
|
|
46
|
+
type: "confirm",
|
|
47
47
|
name: "confirmed",
|
|
48
|
-
|
|
48
|
+
message,
|
|
49
|
+
initial: false
|
|
49
50
|
}], { onCancel: () => halt() });
|
|
50
51
|
if (!confirmed) halt("Operation cancelled.");
|
|
51
52
|
};
|
|
@@ -67,8 +68,8 @@ const extensions = moduleFileExtensions.map((v) => `.${v}`);
|
|
|
67
68
|
const TAMARO_CORE_PACKAGE_NAMES = ["@raisenow/tamaro-core"];
|
|
68
69
|
const TAMARO_CONFIGURATIONS_PACKAGE_NAMES = ["@raisenow/tamaro-configurations"];
|
|
69
70
|
const TAMARO_SELF_SERVICE_PACKAGE_NAMES = ["@raisenow/tamaro-self-service"];
|
|
70
|
-
const resolveApp = (relativePath) =>
|
|
71
|
-
const resolveOwn = (relativePath) =>
|
|
71
|
+
const resolveApp = (relativePath) => resolve(realpathSync(process.cwd()), relativePath);
|
|
72
|
+
const resolveOwn = (relativePath) => resolve(__dirname, "..", relativePath);
|
|
72
73
|
const resolveModule = (resolveFn, filePath) => {
|
|
73
74
|
const extension = moduleFileExtensions.find((extension) => existsSync(resolveFn(`${filePath}.${extension}`)));
|
|
74
75
|
if (extension) return resolveFn(`${filePath}.${extension}`);
|
|
@@ -99,11 +100,9 @@ const resolveEslintPluginConfig = (paths) => {
|
|
|
99
100
|
const resolveBin = (name) => {
|
|
100
101
|
const pkgPath = require$1.resolve(`${name}/package.json`);
|
|
101
102
|
const { bin } = require$1(pkgPath);
|
|
102
|
-
|
|
103
|
-
const binPath = typeof bin === "object" ? bin[name] : bin;
|
|
104
|
-
return path.join(dir, binPath);
|
|
103
|
+
return join(dirname(pkgPath), typeof bin === "object" ? bin[name] : bin);
|
|
105
104
|
};
|
|
106
|
-
const getWidgetUuid = () =>
|
|
105
|
+
const getWidgetUuid = () => basename(resolveApp("."));
|
|
107
106
|
/**
|
|
108
107
|
* Get the appropriate tsconfig file.
|
|
109
108
|
* Prefers tsconfig.app.json (composite config structure) but falls back to
|
|
@@ -150,7 +149,7 @@ const getPaths = (ifCore) => {
|
|
|
150
149
|
};
|
|
151
150
|
const getRelativePaths = (paths) => {
|
|
152
151
|
const relativePaths = {};
|
|
153
|
-
for (const [type, absPath] of Object.entries(paths)) if (absPath) relativePaths[type] =
|
|
152
|
+
for (const [type, absPath] of Object.entries(paths)) if (absPath) relativePaths[type] = relative("./", absPath) || ".";
|
|
154
153
|
return relativePaths;
|
|
155
154
|
};
|
|
156
155
|
const getIfCoreFns = ({ allowArchived = false } = {}) => {
|
|
@@ -186,7 +185,7 @@ const HTTPS_KEY_FILE = "localhost.key";
|
|
|
186
185
|
//#region src/lib/env.ts
|
|
187
186
|
const require = createRequire(import.meta.url);
|
|
188
187
|
const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
189
|
-
const filePath = files.find((file) =>
|
|
188
|
+
const filePath = files.find((file) => basename(file) === ".env");
|
|
190
189
|
if (filePath) config({ path: filePath });
|
|
191
190
|
process.env.NODE_ENV ??= ifMin("production", "development");
|
|
192
191
|
process.env.BABEL_ENV ??= ifMin("production", "development");
|
|
@@ -213,7 +212,7 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
213
212
|
process.env.CORE_URL ??= process.env.CORE_URL_PATTERN.replace("{{version}}", version);
|
|
214
213
|
}
|
|
215
214
|
}
|
|
216
|
-
const varNames =
|
|
215
|
+
const varNames = [
|
|
217
216
|
"NODE_ENV",
|
|
218
217
|
"BABEL_ENV",
|
|
219
218
|
"EXPOSE_VAR",
|
|
@@ -239,8 +238,8 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
239
238
|
"EPMS_PROXY_URL_PROD",
|
|
240
239
|
"EPMS_TWINT_CHECKOUT_URL_STAGE",
|
|
241
240
|
"EPMS_TWINT_CHECKOUT_URL_PROD"
|
|
242
|
-
]
|
|
243
|
-
const raw = Object.keys(process.env).filter((key) => key.startsWith("PUBLIC_") || varNames.
|
|
241
|
+
];
|
|
242
|
+
const raw = Object.keys(process.env).filter((key) => key.startsWith("PUBLIC_") || varNames.includes(key)).reduce((env, key) => {
|
|
244
243
|
env[key] = process.env[key];
|
|
245
244
|
return env;
|
|
246
245
|
}, {});
|
|
@@ -254,9 +253,11 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
254
253
|
};
|
|
255
254
|
const assertEnvValid = (env) => {
|
|
256
255
|
const { ifCore } = getIfCoreFns();
|
|
257
|
-
const envs = globSync(getPaths(ifCore).appEnv).map((file) =>
|
|
258
|
-
if (envs.length === 0
|
|
259
|
-
|
|
256
|
+
const envs = globSync(getPaths(ifCore).appEnv).map((file) => basename(file).replace(/^\.env\./, "")).map((file) => basename(file).replace(/^\.env$/, "")).filter((v) => !!v);
|
|
257
|
+
if (envs.length === 0) {
|
|
258
|
+
if (env) console.log("Flag \"--env\" is ignored.");
|
|
259
|
+
}
|
|
260
|
+
if (envs.length !== 0) {
|
|
260
261
|
if (!env) halt("Flag \"--env\" is required.");
|
|
261
262
|
if (env && !envs.includes(env)) halt(stripIndent(`
|
|
262
263
|
Flag "--env" has wrong value.
|
|
@@ -267,7 +268,7 @@ const assertEnvValid = (env) => {
|
|
|
267
268
|
const applyEnv = (env) => {
|
|
268
269
|
if (!env) return;
|
|
269
270
|
const { ifCore } = getIfCoreFns();
|
|
270
|
-
const filePath = globSync(getPaths(ifCore).appEnv).find((file) =>
|
|
271
|
+
const filePath = globSync(getPaths(ifCore).appEnv).find((file) => basename(file) === `.env.${env}`);
|
|
271
272
|
if (filePath) config({ path: filePath });
|
|
272
273
|
};
|
|
273
274
|
//#endregion
|
package/dist/webpack.config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as logDataTable, b as resolveEslintPluginConfig, d as HTTPS_CRT_FILE, f as HTTPS_KEY_FILE, g as getRelativePaths, h as getPaths, k as logTitle, m as getIfCoreFns, p as extensions, r as getEnvVars, v as resolveApp } from "./env-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
1
|
+
import { E as logDataTable, b as resolveEslintPluginConfig, d as HTTPS_CRT_FILE, f as HTTPS_KEY_FILE, g as getRelativePaths, h as getPaths, k as logTitle, m as getIfCoreFns, p as extensions, r as getEnvVars, v as resolveApp } from "./env-LI5tXjy4.js";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { basename, dirname, resolve } from "path";
|
|
4
|
+
import { createRequire } from "module";
|
|
5
5
|
import { getIfUtils, removeEmpty } from "webpack-config-utils";
|
|
6
6
|
import { globSync } from "glob";
|
|
7
7
|
import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin";
|
|
@@ -36,7 +36,7 @@ var InterpolateHtmlPlugin = class {
|
|
|
36
36
|
});
|
|
37
37
|
hooks.afterTemplateExecution.tap(PLUGIN_NAME, (data) => {
|
|
38
38
|
Object.entries(this.replacements).forEach(([key, value]) => {
|
|
39
|
-
data.html = data.html.
|
|
39
|
+
data.html = data.html.replace(new RegExp(`%${escapeStringRegexp(key)}%`, "g"), value ?? "");
|
|
40
40
|
});
|
|
41
41
|
return data;
|
|
42
42
|
});
|
|
@@ -109,7 +109,7 @@ const getWebpackConfig = (env) => {
|
|
|
109
109
|
symlinks: true,
|
|
110
110
|
extensions: [...extensions, "..."],
|
|
111
111
|
modules: [paths.appNodeModules, "node_modules"],
|
|
112
|
-
alias: { "core-js":
|
|
112
|
+
alias: { "core-js": dirname(require.resolve("core-js/package.json")) },
|
|
113
113
|
plugins: [new TsconfigPathsPlugin({
|
|
114
114
|
configFile: paths.appTsConfig,
|
|
115
115
|
extensions
|
|
@@ -258,8 +258,8 @@ const getWebpackConfig = (env) => {
|
|
|
258
258
|
server: ifHttps({
|
|
259
259
|
type: "https",
|
|
260
260
|
options: {
|
|
261
|
-
cert:
|
|
262
|
-
key:
|
|
261
|
+
cert: resolve(paths.root, HTTPS_CRT_FILE),
|
|
262
|
+
key: resolve(paths.root, HTTPS_KEY_FILE)
|
|
263
263
|
}
|
|
264
264
|
})
|
|
265
265
|
},
|
|
@@ -277,7 +277,7 @@ const getWebpackConfig = (env) => {
|
|
|
277
277
|
ifMin(new CleanWebpackPlugin({})),
|
|
278
278
|
...appHtmlFiles.map((file) => new HtmlWebpackPlugin({
|
|
279
279
|
template: file,
|
|
280
|
-
filename:
|
|
280
|
+
filename: basename(file),
|
|
281
281
|
inject: false,
|
|
282
282
|
minify: false
|
|
283
283
|
})),
|
package/eslint.config.ts
CHANGED
|
@@ -18,6 +18,36 @@ export default defineConfig([
|
|
|
18
18
|
rules: {
|
|
19
19
|
'jsdoc/convert-to-jsdoc-comments': OFF,
|
|
20
20
|
'no-useless-assignment': OFF,
|
|
21
|
+
|
|
22
|
+
// todo: remove these rules
|
|
23
|
+
'@typescript-eslint/restrict-template-expressions': OFF,
|
|
24
|
+
'perfectionist/sort-objects': OFF,
|
|
25
|
+
'perfectionist/sort-object-types': OFF,
|
|
26
|
+
'perfectionist/sort-intersection-types': OFF,
|
|
27
|
+
'perfectionist/sort-switch-case': OFF,
|
|
28
|
+
'unicorn/prefer-top-level-await': OFF,
|
|
29
|
+
'unicorn/prefer-node-protocol': OFF,
|
|
30
|
+
'unicorn/import-style': OFF,
|
|
31
|
+
'unicorn/no-process-exit': OFF,
|
|
32
|
+
'unicorn/consistent-function-scoping': OFF,
|
|
33
|
+
'unicorn/prefer-spread': OFF,
|
|
34
|
+
'unicorn/no-array-callback-reference': OFF,
|
|
35
|
+
'unicorn/catch-error-name': OFF,
|
|
36
|
+
'unicorn/text-encoding-identifier-case': OFF,
|
|
37
|
+
'unicorn/explicit-length-check': OFF,
|
|
38
|
+
'unicorn/no-lonely-if': OFF,
|
|
39
|
+
'unicorn/prefer-set-has': OFF,
|
|
40
|
+
'unicorn/prefer-string-replace-all': OFF,
|
|
41
|
+
'unicorn/prefer-optional-catch-binding': OFF,
|
|
42
|
+
'unicorn/no-array-sort': OFF,
|
|
43
|
+
'unicorn/prefer-number-properties': OFF,
|
|
44
|
+
'unicorn/prefer-ternary': OFF,
|
|
45
|
+
'import-x/consistent-type-specifier-style': OFF,
|
|
46
|
+
'regexp/no-useless-flag': OFF,
|
|
47
|
+
'regexp/use-ignore-case': OFF,
|
|
48
|
+
'regexp/prefer-w': OFF,
|
|
49
|
+
'@typescript-eslint/no-var-requires': OFF,
|
|
50
|
+
'@typescript-eslint/no-unused-vars': OFF,
|
|
21
51
|
},
|
|
22
52
|
},
|
|
23
53
|
{
|