@raisenow/tamaro-cli 1.7.0-dev.2 → 1.8.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -1
- package/bitbucket-pipelines.yml +1 -1
- package/dist/cli.js +79 -73
- package/dist/{env-Bx5mwt8E.js → env-BrLTVK6y.js} +26 -24
- package/dist/webpack.config.js +10 -10
- package/eslint.config.js +17 -0
- package/package.json +17 -25
- package/tsdown.config.ts +5 -5
- package/vitest.config.ts +6 -6
- 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
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-BrLTVK6y.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,15 @@ const unarchive = (options) => {
|
|
|
623
621
|
assertIsArchived();
|
|
624
622
|
const configName = getWidgetUuid();
|
|
625
623
|
const cwd = process.cwd();
|
|
626
|
-
|
|
624
|
+
/**
|
|
625
|
+
* _archived/
|
|
626
|
+
*/
|
|
627
|
+
const archivedDir = path.dirname(cwd);
|
|
628
|
+
/**
|
|
629
|
+
* parent of _archived/
|
|
630
|
+
*/
|
|
631
|
+
const configsDir = path.dirname(archivedDir);
|
|
632
|
+
const restoreTarget = path.resolve(configsDir, configName);
|
|
627
633
|
assertRestoreTargetDoesNotExist(restoreTarget);
|
|
628
634
|
assertOptionsValid$2(options);
|
|
629
635
|
if (options.dryrun) logTitle("🧪 DRY RUN MODE - No actual changes will be made 🧪");
|
|
@@ -634,8 +640,8 @@ const unarchive = (options) => {
|
|
|
634
640
|
logTitle(`✅ "${configName}" has been unarchived and moved to ${restoreTarget}`);
|
|
635
641
|
process.on("exit", () => {
|
|
636
642
|
notify({
|
|
637
|
-
|
|
638
|
-
|
|
643
|
+
message: `"${configName}" has been unarchived.`,
|
|
644
|
+
title: "unarchive"
|
|
639
645
|
});
|
|
640
646
|
});
|
|
641
647
|
};
|
|
@@ -644,7 +650,7 @@ const assertOptionsValid$2 = (options) => {
|
|
|
644
650
|
if (profile) assertProfileValid(profile);
|
|
645
651
|
};
|
|
646
652
|
const assertIsArchived = () => {
|
|
647
|
-
if (basename(dirname(process.cwd())) !== "_archived") halt("This configuration is not archived. Only archived configurations can be unarchived.");
|
|
653
|
+
if (path.basename(path.dirname(process.cwd())) !== "_archived") halt("This configuration is not archived. Only archived configurations can be unarchived.");
|
|
648
654
|
};
|
|
649
655
|
const assertIsNotCore$1 = (ifCore) => {
|
|
650
656
|
if (ifCore()) halt("You cannot unarchive Tamaro Core.");
|
|
@@ -664,7 +670,7 @@ const undeploy = async (options) => {
|
|
|
664
670
|
assertOptionsValid$1(options);
|
|
665
671
|
awsAuthenticate(options);
|
|
666
672
|
const flags = prepareFlags$3(options);
|
|
667
|
-
const { tag = DEFAULT_TAG
|
|
673
|
+
const { all, dryrun, tag = DEFAULT_TAG } = options;
|
|
668
674
|
const dryRunFlag = dryrun ? `--dryrun` : "";
|
|
669
675
|
const deployUrl = all ? `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/` : `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/`;
|
|
670
676
|
const description = all ? `all tags of "${configName}"` : `tag "${tag}" of "${configName}"`;
|
|
@@ -702,13 +708,13 @@ const undeploy = async (options) => {
|
|
|
702
708
|
logDataTable({ "Removed URL:": deployUrl });
|
|
703
709
|
process.on("exit", () => {
|
|
704
710
|
notify({
|
|
705
|
-
|
|
706
|
-
|
|
711
|
+
message: `${description} has been undeployed.`,
|
|
712
|
+
title: "undeploy"
|
|
707
713
|
});
|
|
708
714
|
});
|
|
709
715
|
};
|
|
710
716
|
const assertOptionsValid$1 = (options) => {
|
|
711
|
-
const { profile, tag
|
|
717
|
+
const { all, profile, tag } = options;
|
|
712
718
|
const { ifCore } = getIfCoreFns();
|
|
713
719
|
if (ifCore() && all) halt("Flag \"--all\" must not be used in Tamaro Core context.");
|
|
714
720
|
if (ifCore() && tag === "latest") halt("You cannot undeploy the default tag for Tamaro Core.");
|
|
@@ -755,13 +761,13 @@ const undeployEmailConfig = async (options) => {
|
|
|
755
761
|
logDataTable({ "Removed URL:": deployUrl });
|
|
756
762
|
process.on("exit", () => {
|
|
757
763
|
notify({
|
|
758
|
-
|
|
759
|
-
|
|
764
|
+
message: `Email configuration for "${configName}" has been undeployed.`,
|
|
765
|
+
title: "undeploy-email-config"
|
|
760
766
|
});
|
|
761
767
|
});
|
|
762
768
|
};
|
|
763
769
|
const assertOptionsValid = (options) => {
|
|
764
|
-
const {
|
|
770
|
+
const { bucket, profile } = options;
|
|
765
771
|
if (profile) assertProfileValid(profile);
|
|
766
772
|
if (bucket) assertBucketValid(bucket);
|
|
767
773
|
};
|
|
@@ -773,23 +779,23 @@ const assertBucketValid = (bucket) => {
|
|
|
773
779
|
};
|
|
774
780
|
const promptBucketTamaroEmailConfig = async () => {
|
|
775
781
|
const { bucket } = await prompts([{
|
|
776
|
-
type: "select",
|
|
777
|
-
name: "bucket",
|
|
778
|
-
message: "Select environment",
|
|
779
782
|
choices: [{
|
|
780
783
|
title: "stage",
|
|
781
784
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE
|
|
782
785
|
}, {
|
|
783
786
|
title: "prod",
|
|
784
787
|
value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
785
|
-
}]
|
|
788
|
+
}],
|
|
789
|
+
message: "Select environment",
|
|
790
|
+
name: "bucket",
|
|
791
|
+
type: "select"
|
|
786
792
|
}], { onCancel: () => halt() });
|
|
787
793
|
return bucket;
|
|
788
794
|
};
|
|
789
795
|
//#endregion
|
|
790
796
|
//#region package.json
|
|
791
797
|
var name = "@raisenow/tamaro-cli";
|
|
792
|
-
var version = "1.
|
|
798
|
+
var version = "1.8.0-dev.1";
|
|
793
799
|
//#endregion
|
|
794
800
|
//#region src/cli.ts
|
|
795
801
|
/**
|
|
@@ -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,11 @@ 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
|
-
|
|
70
|
+
const resolveApp = (relativePath) => path.resolve(realpathSync(process.cwd()), relativePath);
|
|
71
|
+
/**
|
|
72
|
+
* __dirname is "dist" in runtime
|
|
73
|
+
*/
|
|
74
|
+
const resolveOwn = (relativePath) => path.resolve(__dirname, "..", relativePath);
|
|
73
75
|
const resolveModule = (resolveFn, filePath) => {
|
|
74
76
|
const extension = moduleFileExtensions.find((extension) => existsSync(resolveFn(`${filePath}.${extension}`)));
|
|
75
77
|
if (extension) return resolveFn(`${filePath}.${extension}`);
|
|
@@ -100,9 +102,11 @@ const resolveEslintPluginConfig = (paths) => {
|
|
|
100
102
|
const resolveBin = (name) => {
|
|
101
103
|
const pkgPath = require$1.resolve(`${name}/package.json`);
|
|
102
104
|
const { bin } = require$1(pkgPath);
|
|
103
|
-
|
|
105
|
+
const dir = path.dirname(pkgPath);
|
|
106
|
+
const binPath = typeof bin === "object" ? bin[name] : bin;
|
|
107
|
+
return path.join(dir, binPath);
|
|
104
108
|
};
|
|
105
|
-
const getWidgetUuid = () => basename(resolveApp("."));
|
|
109
|
+
const getWidgetUuid = () => path.basename(resolveApp("."));
|
|
106
110
|
const getPaths = (ifCore) => {
|
|
107
111
|
return ifCore({
|
|
108
112
|
root: resolveApp("."),
|
|
@@ -128,7 +132,7 @@ const getPaths = (ifCore) => {
|
|
|
128
132
|
};
|
|
129
133
|
const getRelativePaths = (paths) => {
|
|
130
134
|
const relativePaths = {};
|
|
131
|
-
for (const [type, absPath] of Object.entries(paths)) if (absPath) relativePaths[type] = relative("./", absPath) || ".";
|
|
135
|
+
for (const [type, absPath] of Object.entries(paths)) if (absPath) relativePaths[type] = path.relative("./", absPath) || ".";
|
|
132
136
|
return relativePaths;
|
|
133
137
|
};
|
|
134
138
|
const getIfCoreFns = ({ allowArchived = false } = {}) => {
|
|
@@ -164,7 +168,7 @@ const HTTPS_KEY_FILE = "localhost.key";
|
|
|
164
168
|
//#region src/lib/env.ts
|
|
165
169
|
const require = createRequire(import.meta.url);
|
|
166
170
|
const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
167
|
-
const filePath = files.find((file) => basename(file) === ".env");
|
|
171
|
+
const filePath = files.find((file) => path.basename(file) === ".env");
|
|
168
172
|
if (filePath) config({ path: filePath });
|
|
169
173
|
process.env.NODE_ENV ??= ifMin("production", "development");
|
|
170
174
|
process.env.BABEL_ENV ??= ifMin("production", "development");
|
|
@@ -191,7 +195,7 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
191
195
|
process.env.CORE_URL ??= process.env.CORE_URL_PATTERN.replace("{{version}}", version);
|
|
192
196
|
}
|
|
193
197
|
}
|
|
194
|
-
const varNames = [
|
|
198
|
+
const varNames = new Set([
|
|
195
199
|
"NODE_ENV",
|
|
196
200
|
"BABEL_ENV",
|
|
197
201
|
"EXPOSE_VAR",
|
|
@@ -217,8 +221,8 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
217
221
|
"EPMS_PROXY_URL_PROD",
|
|
218
222
|
"EPMS_TWINT_CHECKOUT_URL_STAGE",
|
|
219
223
|
"EPMS_TWINT_CHECKOUT_URL_PROD"
|
|
220
|
-
];
|
|
221
|
-
const raw = Object.keys(process.env).filter((key) => key.startsWith("PUBLIC_") || varNames.
|
|
224
|
+
]);
|
|
225
|
+
const raw = Object.keys(process.env).filter((key) => key.startsWith("PUBLIC_") || varNames.has(key)).reduce((env, key) => {
|
|
222
226
|
env[key] = process.env[key];
|
|
223
227
|
return env;
|
|
224
228
|
}, {});
|
|
@@ -232,11 +236,9 @@ const getEnvVars = (files, ifMin, ifCore, ifLocalCore, ifHttps) => {
|
|
|
232
236
|
};
|
|
233
237
|
const assertEnvValid = (env) => {
|
|
234
238
|
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) {
|
|
239
|
+
const envs = globSync(getPaths(ifCore).appEnv).map((file) => path.basename(file).replace(/^\.env\./, "")).map((file) => path.basename(file).replace(/^\.env$/, "")).filter((v) => !!v);
|
|
240
|
+
if (envs.length === 0 && env) console.log("Flag \"--env\" is ignored.");
|
|
241
|
+
if (envs.length > 0) {
|
|
240
242
|
if (!env) halt("Flag \"--env\" is required.");
|
|
241
243
|
if (env && !envs.includes(env)) halt(stripIndent(`
|
|
242
244
|
Flag "--env" has wrong value.
|
|
@@ -247,7 +249,7 @@ const assertEnvValid = (env) => {
|
|
|
247
249
|
const applyEnv = (env) => {
|
|
248
250
|
if (!env) return;
|
|
249
251
|
const { ifCore } = getIfCoreFns();
|
|
250
|
-
const filePath = globSync(getPaths(ifCore).appEnv).find((file) => basename(file) === `.env.${env}`);
|
|
252
|
+
const filePath = globSync(getPaths(ifCore).appEnv).find((file) => path.basename(file) === `.env.${env}`);
|
|
251
253
|
if (filePath) config({ path: filePath });
|
|
252
254
|
};
|
|
253
255
|
//#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-BrLTVK6y.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
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.replaceAll(new RegExp(`%${escapeStringRegexp(key)}%`, "g"), value ?? "");
|
|
40
40
|
});
|
|
41
41
|
return data;
|
|
42
42
|
});
|
|
@@ -106,10 +106,10 @@ const getWebpackConfig = (env) => {
|
|
|
106
106
|
return removeEmpty({
|
|
107
107
|
mode: ifMin("production", "development"),
|
|
108
108
|
resolve: {
|
|
109
|
-
symlinks:
|
|
109
|
+
symlinks: true,
|
|
110
110
|
extensions: [...extensions, "..."],
|
|
111
111
|
modules: [paths.appNodeModules, "node_modules"],
|
|
112
|
-
alias: { "core-js": dirname(require.resolve("core-js/package.json")) },
|
|
112
|
+
alias: { "core-js": path.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: resolve(paths.root, HTTPS_CRT_FILE),
|
|
262
|
-
key: resolve(paths.root, HTTPS_KEY_FILE)
|
|
261
|
+
cert: path.resolve(paths.root, HTTPS_CRT_FILE),
|
|
262
|
+
key: path.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: basename(file),
|
|
280
|
+
filename: path.basename(file),
|
|
281
281
|
inject: false,
|
|
282
282
|
minify: false
|
|
283
283
|
})),
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import baseConfig from '@rnw-npm/eslint-config'
|
|
3
|
+
import {defineConfig} from 'eslint/config'
|
|
4
|
+
|
|
5
|
+
export default defineConfig([
|
|
6
|
+
...baseConfig,
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* "tamaro-cli" specific overrides.
|
|
10
|
+
*/
|
|
11
|
+
{
|
|
12
|
+
name: 'tamaro-cli/overrides',
|
|
13
|
+
rules: {
|
|
14
|
+
'markdown/no-multiple-h1': 0,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
])
|