alex-c-line 2.7.0 → 2.7.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/dist/configs/index.cjs +1 -1
- package/dist/index.cjs +65 -64
- package/dist/index.js +24 -23
- package/package.json +14 -14
package/dist/configs/index.cjs
CHANGED
|
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
require("@alextheman/utility");
|
|
25
25
|
let zod = require("zod");
|
|
26
|
-
zod = __toESM(zod);
|
|
26
|
+
zod = __toESM(zod, 1);
|
|
27
27
|
let _alextheman_utility_internal = require("@alextheman/utility/internal");
|
|
28
28
|
//#region src/configs/helpers/preCommit/definePreCommitConfig.ts
|
|
29
29
|
const preCommitStepOptionsSchema = zod.default.strictObject({ arguments: zod.default.array(zod.default.string()).optional() });
|
package/dist/index.cjs
CHANGED
|
@@ -22,17 +22,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
24
|
let commander = require("commander");
|
|
25
|
-
let
|
|
25
|
+
let _alextheman_utility_v6 = require("@alextheman/utility/v6");
|
|
26
26
|
let chalk = require("chalk");
|
|
27
|
-
chalk = __toESM(chalk);
|
|
27
|
+
chalk = __toESM(chalk, 1);
|
|
28
28
|
let boxen = require("boxen");
|
|
29
|
-
boxen = __toESM(boxen);
|
|
29
|
+
boxen = __toESM(boxen, 1);
|
|
30
30
|
let figlet = require("figlet");
|
|
31
|
-
figlet = __toESM(figlet);
|
|
31
|
+
figlet = __toESM(figlet, 1);
|
|
32
32
|
let env_paths = require("env-paths");
|
|
33
|
-
env_paths = __toESM(env_paths);
|
|
33
|
+
env_paths = __toESM(env_paths, 1);
|
|
34
34
|
let node_path = require("node:path");
|
|
35
|
-
node_path = __toESM(node_path);
|
|
35
|
+
node_path = __toESM(node_path, 1);
|
|
36
|
+
let _alextheman_utility = require("@alextheman/utility");
|
|
36
37
|
let _inquirer_prompts = require("@inquirer/prompts");
|
|
37
38
|
let node_fs_promises = require("node:fs/promises");
|
|
38
39
|
let dotenv = require("dotenv");
|
|
@@ -40,16 +41,16 @@ let execa = require("execa");
|
|
|
40
41
|
let node_url = require("node:url");
|
|
41
42
|
let _alextheman_utility_internal = require("@alextheman/utility/internal");
|
|
42
43
|
let zod = require("zod");
|
|
43
|
-
zod = __toESM(zod);
|
|
44
|
+
zod = __toESM(zod, 1);
|
|
44
45
|
let node_module = require("node:module");
|
|
45
46
|
let toml = require("toml");
|
|
46
47
|
let gray_matter = require("gray-matter");
|
|
47
|
-
gray_matter = __toESM(gray_matter);
|
|
48
|
+
gray_matter = __toESM(gray_matter, 1);
|
|
48
49
|
let _alextheman_utility_node = require("@alextheman/utility/node");
|
|
49
50
|
let axios = require("axios");
|
|
50
|
-
axios = __toESM(axios);
|
|
51
|
+
axios = __toESM(axios, 1);
|
|
51
52
|
let supports_color = require("supports-color");
|
|
52
|
-
supports_color = __toESM(supports_color);
|
|
53
|
+
supports_color = __toESM(supports_color, 1);
|
|
53
54
|
let node_crypto = require("node:crypto");
|
|
54
55
|
let semver = require("semver");
|
|
55
56
|
//#region src/utility/miscellaneous/centerLine.ts
|
|
@@ -83,7 +84,7 @@ async function createAlexCLineArtwork(options) {
|
|
|
83
84
|
//#region src/cli/commands/artwork/log.ts
|
|
84
85
|
function artworkLog(program) {
|
|
85
86
|
program.command("log").description("Log the alex-c-line artwork to the console.").option("--subtitle-text <subtitleText>", "Customise the subtitle text.").option("--subtitle-color <subtitleColor>", "Customise the subtitle color.").action(async ({ subtitleText, subtitleColor = "green" }) => {
|
|
86
|
-
if (subtitleColor !== "green" && subtitleColor !== "white") throw new
|
|
87
|
+
if (subtitleColor !== "green" && subtitleColor !== "white") throw new _alextheman_utility_v6.DataError({ subtitleColor }, "INVALID_SUBTITLE_COLOR", "Subtitle color must either be green or white.");
|
|
87
88
|
const chalkColour = {
|
|
88
89
|
green: chalk.default.green,
|
|
89
90
|
white: chalk.default.white
|
|
@@ -402,7 +403,7 @@ async function findPackageRoot(startDirectory, packageName) {
|
|
|
402
403
|
if (parent === directory) break;
|
|
403
404
|
directory = parent;
|
|
404
405
|
}
|
|
405
|
-
throw new
|
|
406
|
+
throw new _alextheman_utility_v6.DataError({ packageName }, "PACKAGE_ROOT_NOT_FOUND", `Could not find package root for ${packageName}`);
|
|
406
407
|
}
|
|
407
408
|
//#endregion
|
|
408
409
|
//#region src/utility/constants/ALEX_C_LINE_PACKAGE_ROOT.ts
|
|
@@ -475,7 +476,7 @@ const templatePullRequestSchema = zod.default.discriminatedUnion("category", [te
|
|
|
475
476
|
requireConfirmationFrom: zod.default.string()
|
|
476
477
|
})]);
|
|
477
478
|
function parseTemplatePullRequestConfig(input) {
|
|
478
|
-
return
|
|
479
|
+
return _alextheman_utility.az.with(templatePullRequestSchema).parse(input);
|
|
479
480
|
}
|
|
480
481
|
//#endregion
|
|
481
482
|
//#region src/configs/helpers/defineAlexCLineConfig.ts
|
|
@@ -484,7 +485,7 @@ const alexCLineConfigSchema = zod.default.strictObject({
|
|
|
484
485
|
template: zod.default.object({ pullRequest: templatePullRequestSchema })
|
|
485
486
|
}).partial();
|
|
486
487
|
async function parseAlexCLineConfig(input) {
|
|
487
|
-
return await
|
|
488
|
+
return await _alextheman_utility.az.with(alexCLineConfigSchema).parseAsync(input);
|
|
488
489
|
}
|
|
489
490
|
//#endregion
|
|
490
491
|
//#region src/configs/types/ConfigFileName.ts
|
|
@@ -517,7 +518,7 @@ const alexCLinePrivateConfigSchema = zod.default.object({ localPackage: zod.defa
|
|
|
517
518
|
}))
|
|
518
519
|
}) });
|
|
519
520
|
function parseAlexCLinePrivateConfig(data) {
|
|
520
|
-
return
|
|
521
|
+
return _alextheman_utility.az.with(alexCLinePrivateConfigSchema).parse(data);
|
|
521
522
|
}
|
|
522
523
|
//#endregion
|
|
523
524
|
//#region src/cache/project/types/AlexCLineProjectCache.ts
|
|
@@ -531,7 +532,7 @@ const alexCLineProjectCacheSchema = zod.default.object({ useLocalPackage: zod.de
|
|
|
531
532
|
//#endregion
|
|
532
533
|
//#region src/cache/project/parseAlexCLineProjectCache.ts
|
|
533
534
|
function parseAlexCLineProjectCache(data) {
|
|
534
|
-
return
|
|
535
|
+
return _alextheman_utility.az.with(alexCLineProjectCacheSchema).parse(data);
|
|
535
536
|
}
|
|
536
537
|
//#endregion
|
|
537
538
|
//#region src/cache/project/loadAlexCLineProjectCache.ts
|
|
@@ -584,16 +585,16 @@ async function findTgzFile(packagePath, packageManager) {
|
|
|
584
585
|
const tgzFiles = (await (0, node_fs_promises.readdir)(packagePath)).filter((fileName) => {
|
|
585
586
|
return fileName.endsWith(".tgz");
|
|
586
587
|
});
|
|
587
|
-
if (tgzFiles.length === 0) throw new
|
|
588
|
+
if (tgzFiles.length === 0) throw new _alextheman_utility_v6.DataError({ tgzFiles }, "TGZ_FILE_NOT_FOUND", "Could not find any .tgz files");
|
|
588
589
|
const expectedTgzFileName = await (0, _alextheman_utility_internal.getExpectedTgzName)(packagePath, packageManager);
|
|
589
590
|
const amountOfMatchingFiles = tgzFiles.filter((fileName) => {
|
|
590
591
|
return fileName === expectedTgzFileName;
|
|
591
592
|
}).length;
|
|
592
|
-
if (amountOfMatchingFiles === 0) throw new
|
|
593
|
+
if (amountOfMatchingFiles === 0) throw new _alextheman_utility_v6.DataError({
|
|
593
594
|
expectedTgzFileName,
|
|
594
595
|
amountOfMatchingFiles
|
|
595
596
|
}, "EXPECTED_FILE_NOT_FOUND", "Could not find a .tgz file with the expected file name.");
|
|
596
|
-
if (amountOfMatchingFiles > 1) throw new
|
|
597
|
+
if (amountOfMatchingFiles > 1) throw new _alextheman_utility_v6.DataError({
|
|
597
598
|
expectedTgzFileName,
|
|
598
599
|
amountOfMatchingFiles
|
|
599
600
|
}, "AMBIGUOUS_RESOLUTION", "There are too many .tgz files with the expected file name.");
|
|
@@ -619,27 +620,27 @@ function localPackageUse(program) {
|
|
|
619
620
|
PrivateConfigFileName.ES_MODULES_JAVASCRIPT,
|
|
620
621
|
PrivateConfigFileName.STANDARD_JAVASCRIPT
|
|
621
622
|
]);
|
|
622
|
-
if (!configPath) throw new
|
|
623
|
+
if (!configPath) throw new _alextheman_utility_v6.DataError({ configPath }, "ALEX_C_LINE_PRIVATE_CONFIG_NOT_FOUND", "Could not find the path to the alex-c-line private config file (should be `.alex-c-line.private.config.js`). Does it exist?");
|
|
623
624
|
const { localPackage: { enableCache, localPackages } } = await loadAlexCLinePrivateConfig(configPath);
|
|
624
625
|
const localPackage = localPackages[packageName];
|
|
625
|
-
if (!localPackage) throw new
|
|
626
|
+
if (!localPackage) throw new _alextheman_utility_v6.DataError({
|
|
626
627
|
packageName,
|
|
627
628
|
configPath
|
|
628
629
|
}, "PACKAGE_NOT_FOUND", `Could not find ${packageName} in your private config.`);
|
|
629
630
|
const { packageManager, prepareScript = "build", dependencyGroup = "dependencies", keepOldTarballs } = localPackage;
|
|
630
631
|
const packageInfo = await (0, _alextheman_utility_internal.getPackageJsonContents)(process.cwd());
|
|
631
|
-
if (packageInfo === null) throw new
|
|
632
|
+
if (packageInfo === null) throw new _alextheman_utility_v6.DataError({ currentDirectory: process.cwd() }, "MISSING_CURRENT_REPOSITORY_PACKAGE_JSON", "Could not find package.json in the current location");
|
|
632
633
|
const dependencies = (0, _alextheman_utility_internal.getDependenciesFromGroup)(packageInfo, dependencyGroup);
|
|
633
|
-
if (!(packageName in dependencies) && packageName !== "alex-c-line") throw new
|
|
634
|
+
if (!(packageName in dependencies) && packageName !== "alex-c-line") throw new _alextheman_utility_v6.DataError({
|
|
634
635
|
packageName,
|
|
635
636
|
dependencyGroup,
|
|
636
637
|
packagePath: process.cwd()
|
|
637
638
|
}, "PACKAGE_NOT_FOUND", `Could not find ${packageName} in the ${dependencyGroup} of your package.json.`);
|
|
638
639
|
const localPackagePath = node_path.default.resolve(process.cwd(), localPackage.path);
|
|
639
640
|
const localPackageInfo = await (0, _alextheman_utility_internal.getPackageJsonContents)(localPackagePath);
|
|
640
|
-
if (localPackageInfo === null) throw new
|
|
641
|
-
const localPackageRepositoryName =
|
|
642
|
-
if (localPackageRepositoryName !== packageName) throw new
|
|
641
|
+
if (localPackageInfo === null) throw new _alextheman_utility_v6.DataError({ localPackagePath }, "MISSING_PACKAGE_REPOSITORY_PACKAGE_JSON", "Could not find package.json in the package repository.");
|
|
642
|
+
const localPackageRepositoryName = _alextheman_utility.az.with(zod.default.string()).parse(localPackageInfo.name);
|
|
643
|
+
if (localPackageRepositoryName !== packageName) throw new _alextheman_utility_v6.DataError({
|
|
643
644
|
providedPackageName: packageName,
|
|
644
645
|
localPackagePath,
|
|
645
646
|
localPackageRepositoryName
|
|
@@ -728,7 +729,7 @@ const pyprojectSchema = zod.default.object({
|
|
|
728
729
|
"dependency-groups": zod.default.object({ dev: zod.default.array(zod.default.string()).optional() })
|
|
729
730
|
}).partial();
|
|
730
731
|
async function preferExactDependencyVersions(program) {
|
|
731
|
-
const data =
|
|
732
|
+
const data = _alextheman_utility.az.with(pyprojectSchema).parse((0, toml.parse)(await (0, node_fs_promises.readFile)("pyproject.toml", "utf-8")));
|
|
732
733
|
const sections = [data.project?.dependencies ?? [], data["dependency-groups"]?.dev ?? []];
|
|
733
734
|
const violations = [];
|
|
734
735
|
for (const dependencies of sections) for (const dependency of dependencies) if (!dependency.includes("==")) violations.push(dependency);
|
|
@@ -744,7 +745,7 @@ const RuleName$1 = { PREFER_EXACT_DEPENDENCY_VERSIONS: "prefer-exact-dependency-
|
|
|
744
745
|
function pyprojectCheck(program) {
|
|
745
746
|
program.command("check").description("Run checks on your pyproject.toml file").option("--rules <rules>", "The name of the rule to check", (rawRules) => {
|
|
746
747
|
const rawRuleNamesArray = rawRules.split(",");
|
|
747
|
-
return
|
|
748
|
+
return _alextheman_utility.az.with(zod.default.array(zod.default.enum(RuleName$1))).parse(rawRuleNamesArray);
|
|
748
749
|
}).action(async ({ rules }) => {
|
|
749
750
|
if (rules?.includes("prefer-exact-dependency-versions")) await preferExactDependencyVersions(program);
|
|
750
751
|
console.info(`${SUCCESS_PREFIX} Success! All checks passed!`);
|
|
@@ -817,9 +818,9 @@ async function loadAlexCLineConfig(filePath) {
|
|
|
817
818
|
function preCommit(program) {
|
|
818
819
|
program.command("pre-commit").description("Run the pre-commit scripts specified in the alex-c-line config (v2 experiment).").option("--allow-no-staged-changes", "Run even if nothing is staged").option("--no-update-index").option("--update-index", "Update the git index after the run").action(async (options) => {
|
|
819
820
|
const configPath = await findAlexCLineConfig(process.cwd());
|
|
820
|
-
if (!configPath) throw new
|
|
821
|
+
if (!configPath) throw new _alextheman_utility_v6.DataError({ configPath }, "ALEX_C_LINE_CONFIG_NOT_FOUND", "Could not find the path to the alex-c-line config file. Does it exist?");
|
|
821
822
|
const { preCommit: preCommitConfig } = await loadAlexCLineConfig(configPath);
|
|
822
|
-
if (!preCommitConfig) throw new
|
|
823
|
+
if (!preCommitConfig) throw new _alextheman_utility_v6.DataError({
|
|
823
824
|
configPath,
|
|
824
825
|
preCommitConfig
|
|
825
826
|
}, "PRE_COMMIT_CONFIG_NOT_FOUND", "Could not find the pre-commit config in alex-c-line config.");
|
|
@@ -837,7 +838,7 @@ function preCommit(program) {
|
|
|
837
838
|
}
|
|
838
839
|
const { packageManager: packagePackageManager, scripts } = JSON.parse(await (0, node_fs_promises.readFile)(node_path.default.join(process.cwd(), "package.json"), "utf8"));
|
|
839
840
|
const rawPackageManager = preCommitConfig.packageManager ?? (typeof packagePackageManager === "string" ? packagePackageManager.split("@")[0] : void 0);
|
|
840
|
-
const packageManager =
|
|
841
|
+
const packageManager = _alextheman_utility.az.with(zod.default.enum(_alextheman_utility_internal.PackageManager)).parse(rawPackageManager, new _alextheman_utility_v6.DataError({ packageManager: rawPackageManager }, "UNSUPPORTED_PACKAGE_MANAGER", `This package manager is not currently supported. Only the following are supported: ${Object.values(_alextheman_utility_internal.PackageManager).join(", ")}`));
|
|
841
842
|
const stepRunner = createStepRunner(program);
|
|
842
843
|
for (const step of preCommitConfig.steps) if (typeof step === "function") await step(stepRunner);
|
|
843
844
|
else if (typeof step === "string") await stepRunner(packageManager, getCommandArguments(program, step, scripts));
|
|
@@ -881,7 +882,7 @@ async function createPullRequestTemplatesFromTemplates(config) {
|
|
|
881
882
|
const templateVariables = getTemplateVariables$1(config);
|
|
882
883
|
const { category } = config;
|
|
883
884
|
const templatesPath = node_path.default.join(await findPackageRoot(node_path.default.dirname(__filename$2), "alex-c-line"), "templates", "pullRequest");
|
|
884
|
-
if (!(await (0, node_fs_promises.readdir)(templatesPath)).includes(category)) throw new
|
|
885
|
+
if (!(await (0, node_fs_promises.readdir)(templatesPath)).includes(category)) throw new _alextheman_utility_v6.DataError({ category }, "CATEGORY_NOT_FOUND", "Category folder not found in the templates folder.");
|
|
885
886
|
const categoryPath = node_path.default.join(templatesPath, category);
|
|
886
887
|
const allCategoryTemplateNames = (await (0, node_fs_promises.readdir)(categoryPath)).filter((name) => {
|
|
887
888
|
return name.endsWith(".md");
|
|
@@ -889,11 +890,11 @@ async function createPullRequestTemplatesFromTemplates(config) {
|
|
|
889
890
|
const allTemplates = {};
|
|
890
891
|
for (const templateFileName of allCategoryTemplateNames) {
|
|
891
892
|
const { content, data } = (0, gray_matter.default)(await (0, node_fs_promises.readFile)(node_path.default.join(categoryPath, templateFileName), "utf-8"));
|
|
892
|
-
const templateName =
|
|
893
|
-
const placeholders =
|
|
893
|
+
const templateName = _alextheman_utility.az.with(zod.default.string()).parse(data.id === "base" ? "pull_request_template" : data.id);
|
|
894
|
+
const placeholders = _alextheman_utility.az.with(zod.default.array(zod.default.string()).default([])).parse(data.placeholders);
|
|
894
895
|
let finalContent = content;
|
|
895
896
|
for (const placeholder of placeholders) {
|
|
896
|
-
if (!(placeholder in templateVariables)) throw new
|
|
897
|
+
if (!(placeholder in templateVariables)) throw new _alextheman_utility_v6.DataError({ placeholder }, "INVALID_PLACEHOLDER", "The placeholder found in frontmatter can not be found in the metadata.");
|
|
897
898
|
finalContent = finalContent.replaceAll(`{{${placeholder}}}`, templateVariables[placeholder]);
|
|
898
899
|
}
|
|
899
900
|
allTemplates[templateName] = finalContent;
|
|
@@ -904,15 +905,15 @@ async function createPullRequestTemplatesFromTemplates(config) {
|
|
|
904
905
|
//#region src/cli/commands/template/pullRequest/create.ts
|
|
905
906
|
function templatePullRequestCreate(program) {
|
|
906
907
|
program.command("create").option("--category <category>", "The category of pull request templates to get (can be either `general` or `infrastructure`)", (rawValue) => {
|
|
907
|
-
return
|
|
908
|
+
return _alextheman_utility.az.with(zod.default.enum(PullRequestTemplateCategory)).parse(rawValue, () => {
|
|
908
909
|
program.error(`Invalid template category ${rawValue}. The category must be one of \`general\` or \`infrastructure\``);
|
|
909
910
|
});
|
|
910
911
|
}).option("--project-name <projectName>", "The name of the package to use in the templates (leave blank to default to name found in package.json)").option("--project-type <projectType>", "The type of project, used in phrases such as 'adds a new feature to the {{projectType}}'. This option must not be specified if category is `infrastructure`").option("--infrastructure-provider <infrastructureProvider>", "If category is `infrastructure`, this would be the name of the Infrastructure provider (e.g. Terraform)").option("--require-confirmation-from <requireConfirmationFrom>", "If category is `infrastructure`, this would be the name of the user to get approval from if a manual change was required").description("Create pull request template files for a category (currently generates all templates in that category).").action(async (commandLineOptions) => {
|
|
911
912
|
const configPath = await findAlexCLineConfig(process.cwd());
|
|
912
913
|
const { template: { pullRequest: config } = {} } = configPath ? await loadAlexCLineConfig(configPath) : {};
|
|
913
914
|
const packageInfo = await (0, _alextheman_utility_internal.getPackageJsonContents)(process.cwd());
|
|
914
|
-
const { name: projectName } = commandLineOptions.projectName || config?.projectName ? { name: commandLineOptions.projectName ?? config?.projectName } :
|
|
915
|
-
if (!projectName) throw new
|
|
915
|
+
const { name: projectName } = commandLineOptions.projectName || config?.projectName ? { name: commandLineOptions.projectName ?? config?.projectName } : _alextheman_utility.az.with(zod.default.object({ name: zod.default.string() })).parse(packageInfo);
|
|
916
|
+
if (!projectName) throw new _alextheman_utility_v6.DataError({ projectName }, "PROJECT_NAME_NOT_FOUND", "Could not resolve project name.");
|
|
916
917
|
const parsedOptions = parseTemplatePullRequestConfig((0, _alextheman_utility.removeUndefinedFromObject)({
|
|
917
918
|
category: commandLineOptions.category ?? config?.category ?? "general",
|
|
918
919
|
projectType: commandLineOptions.projectType ?? (config?.category === "general" ? config?.projectType : void 0),
|
|
@@ -955,7 +956,7 @@ const ReleaseStatus = {
|
|
|
955
956
|
//#region src/utility/markdownTemplates/releaseNote/parseReleaseStatus.ts
|
|
956
957
|
function parseReleaseStatus(data) {
|
|
957
958
|
const normalisedStringifiedData = (typeof data === "string" ? data : String(data)).toUpperCase().replaceAll(" ", "_");
|
|
958
|
-
if (!Object.keys(ReleaseStatus).includes(normalisedStringifiedData)) new
|
|
959
|
+
if (!Object.keys(ReleaseStatus).includes(normalisedStringifiedData)) new _alextheman_utility_v6.DataError({ data }, "INVALID_RELEASE_STATUS", "Invalid release status. The release status must be one of \"In progress\" or \"Released\"");
|
|
959
960
|
return ReleaseStatus[normalisedStringifiedData];
|
|
960
961
|
}
|
|
961
962
|
//#endregion
|
|
@@ -988,8 +989,8 @@ function normaliseMarkdown(markdownString) {
|
|
|
988
989
|
//#region src/utility/markdownTemplates/releaseNote/getReleaseStatus.ts
|
|
989
990
|
function getReleaseStatus(content) {
|
|
990
991
|
const releaseStatus = getMarkdownBlock(content, ...getMarkdownCommentPair("alex-c-line-release-status"));
|
|
991
|
-
if (releaseStatus === null) throw new
|
|
992
|
-
return
|
|
992
|
+
if (releaseStatus === null) throw new _alextheman_utility_v6.DataError({ releaseStatus }, "RELEASE_STATUS_NOT_FOUND", "Could not find release status in document.");
|
|
993
|
+
return _alextheman_utility.az.with(zod.default.enum(ReleaseStatus)).parse(normaliseMarkdown(releaseStatus.split(":")[1]));
|
|
993
994
|
}
|
|
994
995
|
//#endregion
|
|
995
996
|
//#region src/utility/markdownTemplates/releaseNote/validateReleaseDocument.ts
|
|
@@ -997,14 +998,14 @@ const __filename$1 = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__
|
|
|
997
998
|
async function validateReleaseDocument(projectName, version, content, allowedReleaseStatus = ["In progress", "Released"]) {
|
|
998
999
|
if (!normaliseMarkdown(content).startsWith(normaliseMarkdown(_alextheman_utility.normaliseIndents`
|
|
999
1000
|
# ${version} (${(0, _alextheman_utility.kebabToCamel)(version.type, { startWithUpper: true })} Release)
|
|
1000
|
-
`))) throw new
|
|
1001
|
+
`))) throw new _alextheman_utility_v6.DataError({ heading: content.split("\n").slice(0, 3).join("\n") }, "INVALID_HEADING", _alextheman_utility.normaliseIndents`
|
|
1001
1002
|
Expected heading to be:
|
|
1002
1003
|
|
|
1003
1004
|
# ${version} (${(0, _alextheman_utility.kebabToCamel)(version.type, { startWithUpper: true })} Release)
|
|
1004
1005
|
`);
|
|
1005
1006
|
const releaseStatus = getReleaseStatus(content);
|
|
1006
1007
|
const allowedReleaseStatuses = (0, _alextheman_utility.removeDuplicates)(Array.isArray(allowedReleaseStatus) ? allowedReleaseStatus : [allowedReleaseStatus]);
|
|
1007
|
-
if (!allowedReleaseStatuses.includes(releaseStatus)) throw new
|
|
1008
|
+
if (!allowedReleaseStatuses.includes(releaseStatus)) throw new _alextheman_utility_v6.DataError({ releaseStatus }, "INVALID_RELEASE_STATUS", _alextheman_utility.normaliseIndents`
|
|
1008
1009
|
Invalid release status.
|
|
1009
1010
|
Current: "${releaseStatus}"
|
|
1010
1011
|
Expected: ${allowedReleaseStatuses.length === 1 ? `"${allowedReleaseStatus}"` : `one of: ${allowedReleaseStatuses.map((status) => {
|
|
@@ -1014,26 +1015,26 @@ async function validateReleaseDocument(projectName, version, content, allowedRel
|
|
|
1014
1015
|
const summary = getMarkdownBlock(content, ...releaseSummaryHeaders);
|
|
1015
1016
|
const templateContent = await (0, node_fs_promises.readFile)(node_path.default.join(await findPackageRoot(node_path.default.dirname(__filename$1), "alex-c-line"), "templates", "releases", `${version.type}.md`), "utf-8");
|
|
1016
1017
|
const templateSummary = getMarkdownBlock(templateContent, ...releaseSummaryHeaders)?.replaceAll(`{{projectName}}`, projectName);
|
|
1017
|
-
if (!templateSummary) throw new
|
|
1018
|
-
if (!summary) throw new
|
|
1018
|
+
if (!templateSummary) throw new _alextheman_utility_v6.DataError({ templateContent }, "SUMMARY_NOT_FOUND", "Expected to find a release summary but it was not found.");
|
|
1019
|
+
if (!summary) throw new _alextheman_utility_v6.DataError({ content }, "SUMMARY_NOT_FOUND", _alextheman_utility.normaliseIndents`
|
|
1019
1020
|
Expected to find a release summary but it was not found. Expected release summary to be:
|
|
1020
1021
|
|
|
1021
1022
|
${templateSummary}
|
|
1022
1023
|
`);
|
|
1023
|
-
if (normaliseMarkdown(summary) !== normaliseMarkdown(templateSummary)) throw new
|
|
1024
|
+
if (normaliseMarkdown(summary) !== normaliseMarkdown(templateSummary)) throw new _alextheman_utility_v6.DataError({ summary }, "INVALID_SUMMARY", _alextheman_utility.normaliseIndents`
|
|
1024
1025
|
Summary does not match what was expected. Expected release summary to be:
|
|
1025
1026
|
|
|
1026
1027
|
${templateSummary}
|
|
1027
1028
|
`);
|
|
1028
|
-
if (!content.includes("## Description of Changes")) throw new
|
|
1029
|
-
if (version.type === "major" && !content.includes("## Migration Notes")) throw new
|
|
1029
|
+
if (!content.includes("## Description of Changes")) throw new _alextheman_utility_v6.DataError({ content }, "DESCRIPTION_NOT_FOUND", "Expected to find a description of changes but it was not found.");
|
|
1030
|
+
if (version.type === "major" && !content.includes("## Migration Notes")) throw new _alextheman_utility_v6.DataError({ content }, "MIGRATION_NOTES_NOT_FOUND", "Major version notes must have migration notes as major versions are expected to be breaking changes that require users to migrate and refactor their code.");
|
|
1030
1031
|
}
|
|
1031
1032
|
//#endregion
|
|
1032
1033
|
//#region src/cli/commands/template/releaseNote/check.ts
|
|
1033
1034
|
function templateReleaseNoteCheck(program) {
|
|
1034
1035
|
program.command("check").argument("<documentPath>", "The path to the document", _alextheman_utility_node.parseFilePath).option("--expected-release-status <expectedReleaseStatus>", "The expected release status of the document once we read it in.", parseReleaseStatus).description("Check whether a given release note is valid according to the templates or not. Returns exit code 0 for valid release note and non-zero otherwise.").action(async (documentPath, { expectedReleaseStatus }) => {
|
|
1035
1036
|
const fileContents = await (0, node_fs_promises.readFile)(node_path.default.join(process.cwd(), documentPath.fullPath), "utf-8");
|
|
1036
|
-
const { name } =
|
|
1037
|
+
const { name } = _alextheman_utility.az.with(zod.default.object({ name: zod.default.string() })).parse(await (0, _alextheman_utility_internal.getPackageJsonContents)(process.cwd()), () => {
|
|
1037
1038
|
program.error("Your package.json is invalid");
|
|
1038
1039
|
});
|
|
1039
1040
|
const documentVersion = new _alextheman_utility.VersionNumber(documentPath.base.split(".").filter((part) => {
|
|
@@ -1043,7 +1044,7 @@ function templateReleaseNoteCheck(program) {
|
|
|
1043
1044
|
await validateReleaseDocument(name, documentVersion, fileContents, expectedReleaseStatus);
|
|
1044
1045
|
console.info(`${SUCCESS_PREFIX} Release document is valid!`);
|
|
1045
1046
|
} catch (error) {
|
|
1046
|
-
if (
|
|
1047
|
+
if (_alextheman_utility_v6.DataError.check(error)) convertDataErrorToProgramError(error, program, { exitCode: 2 });
|
|
1047
1048
|
else throw error;
|
|
1048
1049
|
}
|
|
1049
1050
|
});
|
|
@@ -1063,10 +1064,10 @@ async function getEditableSectionFromTemplate(version) {
|
|
|
1063
1064
|
//#region src/utility/markdownTemplates/replaceMarkdownPlaceholders.ts
|
|
1064
1065
|
function replaceMarkdownPlaceholders(rawContent, templateVariables) {
|
|
1065
1066
|
const { content, data } = (0, gray_matter.default)(rawContent);
|
|
1066
|
-
const placeholders =
|
|
1067
|
+
const placeholders = _alextheman_utility.az.with(zod.default.array(zod.default.string()).default([])).parse(data.placeholders);
|
|
1067
1068
|
let finalContent = content;
|
|
1068
1069
|
for (const placeholder of placeholders) {
|
|
1069
|
-
if (!(placeholder in templateVariables)) throw new
|
|
1070
|
+
if (!(placeholder in templateVariables)) throw new _alextheman_utility_v6.DataError({ placeholder }, "INVALID_PLACEHOLDER", "The placeholder found in frontmatter can not be found in the metadata.");
|
|
1070
1071
|
finalContent = finalContent.replaceAll(`{{${placeholder}}}`, templateVariables[placeholder]);
|
|
1071
1072
|
}
|
|
1072
1073
|
return finalContent;
|
|
@@ -1117,15 +1118,15 @@ function templateReleaseNoteCreate(program) {
|
|
|
1117
1118
|
try {
|
|
1118
1119
|
return new _alextheman_utility.VersionNumber(rawValue);
|
|
1119
1120
|
} catch (error) {
|
|
1120
|
-
if (
|
|
1121
|
+
if (_alextheman_utility_v6.DataError.check(error) && error.code === "INVALID_VERSION") return (0, _alextheman_utility.parseVersionType)(rawValue);
|
|
1121
1122
|
throw error;
|
|
1122
1123
|
}
|
|
1123
1124
|
}).description("Create release notes based on the current version in package.json.").action(async (target) => {
|
|
1124
1125
|
const packageInfo = await (0, _alextheman_utility_internal.getPackageJsonContents)(process.cwd());
|
|
1125
|
-
const { name, version: packageVersion } =
|
|
1126
|
+
const { name, version: packageVersion } = _alextheman_utility.az.with(zod.default.object({
|
|
1126
1127
|
name: zod.default.string(),
|
|
1127
1128
|
version: zod.default.string()
|
|
1128
|
-
})
|
|
1129
|
+
})).parse(packageInfo);
|
|
1129
1130
|
const versionNumber = target instanceof _alextheman_utility.VersionNumber ? target : target ? new _alextheman_utility.VersionNumber(packageVersion).increment(target) : new _alextheman_utility.VersionNumber(packageVersion);
|
|
1130
1131
|
const releaseNotePath = getReleaseNotePath(versionNumber);
|
|
1131
1132
|
const releaseNoteTemplate = await createReleaseNoteFromTemplates(name, versionNumber, { status: "In progress" });
|
|
@@ -1161,8 +1162,8 @@ function templateReleaseNotePath(program) {
|
|
|
1161
1162
|
function templateReleaseNoteSetStatus(program) {
|
|
1162
1163
|
program.command("set-status").description("Change the release status on a given release document initially generated from the `create-release-note` command.").argument("<documentPath>", "The path to the document").argument("[status]", "The status to set the document to", parseReleaseStatus, ReleaseStatus.RELEASED).action(async (documentPath, status) => {
|
|
1163
1164
|
const packageInfo = await (0, _alextheman_utility_internal.getPackageJsonContents)(process.cwd());
|
|
1164
|
-
const { name } =
|
|
1165
|
-
if (!documentPath.endsWith("md")) throw new
|
|
1165
|
+
const { name } = _alextheman_utility.az.with(zod.default.object({ name: zod.default.string() })).parse(packageInfo, new _alextheman_utility_v6.DataError({ name: packageInfo?.name }, "INVALID_PACKAGE_JSON", "Invalid package.json - expected package.json to contain a `name` property."));
|
|
1166
|
+
if (!documentPath.endsWith("md")) throw new _alextheman_utility_v6.DataError({ documentPath }, "INVALID_FILE_PATH", "Invalid file path. Path must lead to a .md file.");
|
|
1166
1167
|
const versionNumber = new _alextheman_utility.VersionNumber(node_path.default.basename(documentPath).split(".").filter((part) => {
|
|
1167
1168
|
return part !== "md";
|
|
1168
1169
|
}).join("."));
|
|
@@ -1171,7 +1172,7 @@ function templateReleaseNoteSetStatus(program) {
|
|
|
1171
1172
|
await validateReleaseDocument(name, versionNumber, initialDocument);
|
|
1172
1173
|
const [userEditableSectionStart, userEditableSectionEnd] = getMarkdownCommentPair("user-editable-section");
|
|
1173
1174
|
const editableSection = getMarkdownBlock(initialDocument, userEditableSectionStart, userEditableSectionEnd);
|
|
1174
|
-
if (editableSection === null) throw new
|
|
1175
|
+
if (editableSection === null) throw new _alextheman_utility_v6.DataError({
|
|
1175
1176
|
startMarker: userEditableSectionStart,
|
|
1176
1177
|
endMarker: userEditableSectionEnd
|
|
1177
1178
|
}, "EDITABLE_SECTION_NOT_FOUND", "Could not find editable section in the provided document.");
|
|
@@ -1203,7 +1204,7 @@ function template(program) {
|
|
|
1203
1204
|
//#endregion
|
|
1204
1205
|
//#region package.json
|
|
1205
1206
|
var name = "alex-c-line";
|
|
1206
|
-
var version$1 = "2.7.
|
|
1207
|
+
var version$1 = "2.7.2";
|
|
1207
1208
|
var description = "Command-line tool with commands to streamline the developer workflow.";
|
|
1208
1209
|
//#endregion
|
|
1209
1210
|
//#region src/utility/updates/checkUpdate.ts
|
|
@@ -1270,9 +1271,9 @@ function uuid(program) {
|
|
|
1270
1271
|
//#region src/utility/miscellaneous/parseZodSchemaForProgram.ts
|
|
1271
1272
|
function parseZodSchemaForProgram(program, schema, data) {
|
|
1272
1273
|
try {
|
|
1273
|
-
return
|
|
1274
|
+
return _alextheman_utility.az.with(schema).parse(data);
|
|
1274
1275
|
} catch (error) {
|
|
1275
|
-
if (
|
|
1276
|
+
if (_alextheman_utility_v6.DataError.check(error)) convertDataErrorToProgramError(error, program);
|
|
1276
1277
|
throw error;
|
|
1277
1278
|
}
|
|
1278
1279
|
}
|
|
@@ -1395,7 +1396,7 @@ const RuleName = {
|
|
|
1395
1396
|
function packageJsonCheck(program) {
|
|
1396
1397
|
program.command("check").description("Run checks on your package.json file").option("--rules <rules>", "The name of the rule to check", (rawRules) => {
|
|
1397
1398
|
const rawRuleNamesArray = rawRules.split(",");
|
|
1398
|
-
return
|
|
1399
|
+
return _alextheman_utility.az.with(zod.default.array(zod.default.enum(RuleName))).parse(rawRuleNamesArray);
|
|
1399
1400
|
}).action(async ({ rules }) => {
|
|
1400
1401
|
if (rules?.includes("no-pre-release-dependencies")) await noPreReleaseDependencies(program);
|
|
1401
1402
|
if (rules?.includes("no-file-dependencies")) await noFileDependencies(program);
|
|
@@ -1429,7 +1430,7 @@ function createCommands(program) {
|
|
|
1429
1430
|
//#region src/utility/errors/formatError.ts
|
|
1430
1431
|
function formatError(error) {
|
|
1431
1432
|
if (error instanceof execa.ExecaError) {
|
|
1432
|
-
const dataError = new
|
|
1433
|
+
const dataError = new _alextheman_utility_v6.DataError({
|
|
1433
1434
|
cwd: error.cwd,
|
|
1434
1435
|
command: error.command,
|
|
1435
1436
|
exitCode: error.exitCode,
|
|
@@ -1480,7 +1481,7 @@ const alexCLineGlobalCacheSchema = zod.default.looseObject({ updateChecks: zod.d
|
|
|
1480
1481
|
//#endregion
|
|
1481
1482
|
//#region src/cache/global/parseAlexCLineGlobalCache.ts
|
|
1482
1483
|
function parseAlexCLineGlobalCache(input) {
|
|
1483
|
-
return
|
|
1484
|
+
return _alextheman_utility.az.with(alexCLineGlobalCacheSchema).parse(input);
|
|
1484
1485
|
}
|
|
1485
1486
|
//#endregion
|
|
1486
1487
|
//#region src/cache/global/loadAlexCLineGlobalCache.ts
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { Command } from "commander";
|
|
4
|
-
import { DataError
|
|
4
|
+
import { DataError } from "@alextheman/utility/v6";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import boxen from "boxen";
|
|
7
7
|
import figlet from "figlet";
|
|
8
8
|
import envPaths from "env-paths";
|
|
9
9
|
import path from "node:path";
|
|
10
|
+
import { ONE_DAY_IN_MILLISECONDS, VersionNumber, az, fillArray, getStringsAndInterpolations, interpolate, isTemplateStringsArray, kebabToCamel, normaliseIndents, omitProperties, parseBoolean, parseVersionType, removeDuplicates, removeUndefinedFromObject, stringifyDotenv } from "@alextheman/utility";
|
|
10
11
|
import { confirm, input, password, select } from "@inquirer/prompts";
|
|
11
12
|
import { access, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
12
13
|
import { parse } from "dotenv";
|
|
@@ -444,7 +445,7 @@ const templatePullRequestSchema = z.discriminatedUnion("category", [templatePull
|
|
|
444
445
|
requireConfirmationFrom: z.string()
|
|
445
446
|
})]);
|
|
446
447
|
function parseTemplatePullRequestConfig(input) {
|
|
447
|
-
return
|
|
448
|
+
return az.with(templatePullRequestSchema).parse(input);
|
|
448
449
|
}
|
|
449
450
|
//#endregion
|
|
450
451
|
//#region src/configs/helpers/defineAlexCLineConfig.ts
|
|
@@ -453,7 +454,7 @@ const alexCLineConfigSchema = z.strictObject({
|
|
|
453
454
|
template: z.object({ pullRequest: templatePullRequestSchema })
|
|
454
455
|
}).partial();
|
|
455
456
|
async function parseAlexCLineConfig(input) {
|
|
456
|
-
return await
|
|
457
|
+
return await az.with(alexCLineConfigSchema).parseAsync(input);
|
|
457
458
|
}
|
|
458
459
|
//#endregion
|
|
459
460
|
//#region src/configs/types/ConfigFileName.ts
|
|
@@ -486,7 +487,7 @@ const alexCLinePrivateConfigSchema = z.object({ localPackage: z.strictObject({
|
|
|
486
487
|
}))
|
|
487
488
|
}) });
|
|
488
489
|
function parseAlexCLinePrivateConfig(data) {
|
|
489
|
-
return
|
|
490
|
+
return az.with(alexCLinePrivateConfigSchema).parse(data);
|
|
490
491
|
}
|
|
491
492
|
//#endregion
|
|
492
493
|
//#region src/cache/project/types/AlexCLineProjectCache.ts
|
|
@@ -500,7 +501,7 @@ const alexCLineProjectCacheSchema = z.object({ useLocalPackage: z.object({ depen
|
|
|
500
501
|
//#endregion
|
|
501
502
|
//#region src/cache/project/parseAlexCLineProjectCache.ts
|
|
502
503
|
function parseAlexCLineProjectCache(data) {
|
|
503
|
-
return
|
|
504
|
+
return az.with(alexCLineProjectCacheSchema).parse(data);
|
|
504
505
|
}
|
|
505
506
|
//#endregion
|
|
506
507
|
//#region src/cache/project/loadAlexCLineProjectCache.ts
|
|
@@ -607,7 +608,7 @@ function localPackageUse(program) {
|
|
|
607
608
|
const localPackagePath = path.resolve(process.cwd(), localPackage.path);
|
|
608
609
|
const localPackageInfo = await getPackageJsonContents(localPackagePath);
|
|
609
610
|
if (localPackageInfo === null) throw new DataError({ localPackagePath }, "MISSING_PACKAGE_REPOSITORY_PACKAGE_JSON", "Could not find package.json in the package repository.");
|
|
610
|
-
const localPackageRepositoryName =
|
|
611
|
+
const localPackageRepositoryName = az.with(z.string()).parse(localPackageInfo.name);
|
|
611
612
|
if (localPackageRepositoryName !== packageName) throw new DataError({
|
|
612
613
|
providedPackageName: packageName,
|
|
613
614
|
localPackagePath,
|
|
@@ -697,7 +698,7 @@ const pyprojectSchema = z.object({
|
|
|
697
698
|
"dependency-groups": z.object({ dev: z.array(z.string()).optional() })
|
|
698
699
|
}).partial();
|
|
699
700
|
async function preferExactDependencyVersions(program) {
|
|
700
|
-
const data =
|
|
701
|
+
const data = az.with(pyprojectSchema).parse(parse$1(await readFile("pyproject.toml", "utf-8")));
|
|
701
702
|
const sections = [data.project?.dependencies ?? [], data["dependency-groups"]?.dev ?? []];
|
|
702
703
|
const violations = [];
|
|
703
704
|
for (const dependencies of sections) for (const dependency of dependencies) if (!dependency.includes("==")) violations.push(dependency);
|
|
@@ -713,7 +714,7 @@ const RuleName$1 = { PREFER_EXACT_DEPENDENCY_VERSIONS: "prefer-exact-dependency-
|
|
|
713
714
|
function pyprojectCheck(program) {
|
|
714
715
|
program.command("check").description("Run checks on your pyproject.toml file").option("--rules <rules>", "The name of the rule to check", (rawRules) => {
|
|
715
716
|
const rawRuleNamesArray = rawRules.split(",");
|
|
716
|
-
return
|
|
717
|
+
return az.with(z.array(z.enum(RuleName$1))).parse(rawRuleNamesArray);
|
|
717
718
|
}).action(async ({ rules }) => {
|
|
718
719
|
if (rules?.includes("prefer-exact-dependency-versions")) await preferExactDependencyVersions(program);
|
|
719
720
|
console.info(`${SUCCESS_PREFIX} Success! All checks passed!`);
|
|
@@ -806,7 +807,7 @@ function preCommit(program) {
|
|
|
806
807
|
}
|
|
807
808
|
const { packageManager: packagePackageManager, scripts } = JSON.parse(await readFile(path.join(process.cwd(), "package.json"), "utf8"));
|
|
808
809
|
const rawPackageManager = preCommitConfig.packageManager ?? (typeof packagePackageManager === "string" ? packagePackageManager.split("@")[0] : void 0);
|
|
809
|
-
const packageManager =
|
|
810
|
+
const packageManager = az.with(z.enum(PackageManager)).parse(rawPackageManager, new DataError({ packageManager: rawPackageManager }, "UNSUPPORTED_PACKAGE_MANAGER", `This package manager is not currently supported. Only the following are supported: ${Object.values(PackageManager).join(", ")}`));
|
|
810
811
|
const stepRunner = createStepRunner(program);
|
|
811
812
|
for (const step of preCommitConfig.steps) if (typeof step === "function") await step(stepRunner);
|
|
812
813
|
else if (typeof step === "string") await stepRunner(packageManager, getCommandArguments(program, step, scripts));
|
|
@@ -858,8 +859,8 @@ async function createPullRequestTemplatesFromTemplates(config) {
|
|
|
858
859
|
const allTemplates = {};
|
|
859
860
|
for (const templateFileName of allCategoryTemplateNames) {
|
|
860
861
|
const { content, data } = matter(await readFile(path.join(categoryPath, templateFileName), "utf-8"));
|
|
861
|
-
const templateName =
|
|
862
|
-
const placeholders =
|
|
862
|
+
const templateName = az.with(z.string()).parse(data.id === "base" ? "pull_request_template" : data.id);
|
|
863
|
+
const placeholders = az.with(z.array(z.string()).default([])).parse(data.placeholders);
|
|
863
864
|
let finalContent = content;
|
|
864
865
|
for (const placeholder of placeholders) {
|
|
865
866
|
if (!(placeholder in templateVariables)) throw new DataError({ placeholder }, "INVALID_PLACEHOLDER", "The placeholder found in frontmatter can not be found in the metadata.");
|
|
@@ -873,14 +874,14 @@ async function createPullRequestTemplatesFromTemplates(config) {
|
|
|
873
874
|
//#region src/cli/commands/template/pullRequest/create.ts
|
|
874
875
|
function templatePullRequestCreate(program) {
|
|
875
876
|
program.command("create").option("--category <category>", "The category of pull request templates to get (can be either `general` or `infrastructure`)", (rawValue) => {
|
|
876
|
-
return
|
|
877
|
+
return az.with(z.enum(PullRequestTemplateCategory)).parse(rawValue, () => {
|
|
877
878
|
program.error(`Invalid template category ${rawValue}. The category must be one of \`general\` or \`infrastructure\``);
|
|
878
879
|
});
|
|
879
880
|
}).option("--project-name <projectName>", "The name of the package to use in the templates (leave blank to default to name found in package.json)").option("--project-type <projectType>", "The type of project, used in phrases such as 'adds a new feature to the {{projectType}}'. This option must not be specified if category is `infrastructure`").option("--infrastructure-provider <infrastructureProvider>", "If category is `infrastructure`, this would be the name of the Infrastructure provider (e.g. Terraform)").option("--require-confirmation-from <requireConfirmationFrom>", "If category is `infrastructure`, this would be the name of the user to get approval from if a manual change was required").description("Create pull request template files for a category (currently generates all templates in that category).").action(async (commandLineOptions) => {
|
|
880
881
|
const configPath = await findAlexCLineConfig(process.cwd());
|
|
881
882
|
const { template: { pullRequest: config } = {} } = configPath ? await loadAlexCLineConfig(configPath) : {};
|
|
882
883
|
const packageInfo = await getPackageJsonContents(process.cwd());
|
|
883
|
-
const { name: projectName } = commandLineOptions.projectName || config?.projectName ? { name: commandLineOptions.projectName ?? config?.projectName } :
|
|
884
|
+
const { name: projectName } = commandLineOptions.projectName || config?.projectName ? { name: commandLineOptions.projectName ?? config?.projectName } : az.with(z.object({ name: z.string() })).parse(packageInfo);
|
|
884
885
|
if (!projectName) throw new DataError({ projectName }, "PROJECT_NAME_NOT_FOUND", "Could not resolve project name.");
|
|
885
886
|
const parsedOptions = parseTemplatePullRequestConfig(removeUndefinedFromObject({
|
|
886
887
|
category: commandLineOptions.category ?? config?.category ?? "general",
|
|
@@ -958,7 +959,7 @@ function normaliseMarkdown(markdownString) {
|
|
|
958
959
|
function getReleaseStatus(content) {
|
|
959
960
|
const releaseStatus = getMarkdownBlock(content, ...getMarkdownCommentPair("alex-c-line-release-status"));
|
|
960
961
|
if (releaseStatus === null) throw new DataError({ releaseStatus }, "RELEASE_STATUS_NOT_FOUND", "Could not find release status in document.");
|
|
961
|
-
return
|
|
962
|
+
return az.with(z.enum(ReleaseStatus)).parse(normaliseMarkdown(releaseStatus.split(":")[1]));
|
|
962
963
|
}
|
|
963
964
|
//#endregion
|
|
964
965
|
//#region src/utility/markdownTemplates/releaseNote/validateReleaseDocument.ts
|
|
@@ -1002,7 +1003,7 @@ async function validateReleaseDocument(projectName, version, content, allowedRel
|
|
|
1002
1003
|
function templateReleaseNoteCheck(program) {
|
|
1003
1004
|
program.command("check").argument("<documentPath>", "The path to the document", parseFilePath).option("--expected-release-status <expectedReleaseStatus>", "The expected release status of the document once we read it in.", parseReleaseStatus).description("Check whether a given release note is valid according to the templates or not. Returns exit code 0 for valid release note and non-zero otherwise.").action(async (documentPath, { expectedReleaseStatus }) => {
|
|
1004
1005
|
const fileContents = await readFile(path.join(process.cwd(), documentPath.fullPath), "utf-8");
|
|
1005
|
-
const { name } =
|
|
1006
|
+
const { name } = az.with(z.object({ name: z.string() })).parse(await getPackageJsonContents(process.cwd()), () => {
|
|
1006
1007
|
program.error("Your package.json is invalid");
|
|
1007
1008
|
});
|
|
1008
1009
|
const documentVersion = new VersionNumber(documentPath.base.split(".").filter((part) => {
|
|
@@ -1032,7 +1033,7 @@ async function getEditableSectionFromTemplate(version) {
|
|
|
1032
1033
|
//#region src/utility/markdownTemplates/replaceMarkdownPlaceholders.ts
|
|
1033
1034
|
function replaceMarkdownPlaceholders(rawContent, templateVariables) {
|
|
1034
1035
|
const { content, data } = matter(rawContent);
|
|
1035
|
-
const placeholders =
|
|
1036
|
+
const placeholders = az.with(z.array(z.string()).default([])).parse(data.placeholders);
|
|
1036
1037
|
let finalContent = content;
|
|
1037
1038
|
for (const placeholder of placeholders) {
|
|
1038
1039
|
if (!(placeholder in templateVariables)) throw new DataError({ placeholder }, "INVALID_PLACEHOLDER", "The placeholder found in frontmatter can not be found in the metadata.");
|
|
@@ -1091,10 +1092,10 @@ function templateReleaseNoteCreate(program) {
|
|
|
1091
1092
|
}
|
|
1092
1093
|
}).description("Create release notes based on the current version in package.json.").action(async (target) => {
|
|
1093
1094
|
const packageInfo = await getPackageJsonContents(process.cwd());
|
|
1094
|
-
const { name, version: packageVersion } =
|
|
1095
|
+
const { name, version: packageVersion } = az.with(z.object({
|
|
1095
1096
|
name: z.string(),
|
|
1096
1097
|
version: z.string()
|
|
1097
|
-
})
|
|
1098
|
+
})).parse(packageInfo);
|
|
1098
1099
|
const versionNumber = target instanceof VersionNumber ? target : target ? new VersionNumber(packageVersion).increment(target) : new VersionNumber(packageVersion);
|
|
1099
1100
|
const releaseNotePath = getReleaseNotePath(versionNumber);
|
|
1100
1101
|
const releaseNoteTemplate = await createReleaseNoteFromTemplates(name, versionNumber, { status: "In progress" });
|
|
@@ -1130,7 +1131,7 @@ function templateReleaseNotePath(program) {
|
|
|
1130
1131
|
function templateReleaseNoteSetStatus(program) {
|
|
1131
1132
|
program.command("set-status").description("Change the release status on a given release document initially generated from the `create-release-note` command.").argument("<documentPath>", "The path to the document").argument("[status]", "The status to set the document to", parseReleaseStatus, ReleaseStatus.RELEASED).action(async (documentPath, status) => {
|
|
1132
1133
|
const packageInfo = await getPackageJsonContents(process.cwd());
|
|
1133
|
-
const { name } =
|
|
1134
|
+
const { name } = az.with(z.object({ name: z.string() })).parse(packageInfo, new DataError({ name: packageInfo?.name }, "INVALID_PACKAGE_JSON", "Invalid package.json - expected package.json to contain a `name` property."));
|
|
1134
1135
|
if (!documentPath.endsWith("md")) throw new DataError({ documentPath }, "INVALID_FILE_PATH", "Invalid file path. Path must lead to a .md file.");
|
|
1135
1136
|
const versionNumber = new VersionNumber(path.basename(documentPath).split(".").filter((part) => {
|
|
1136
1137
|
return part !== "md";
|
|
@@ -1172,7 +1173,7 @@ function template(program) {
|
|
|
1172
1173
|
//#endregion
|
|
1173
1174
|
//#region package.json
|
|
1174
1175
|
var name = "alex-c-line";
|
|
1175
|
-
var version$1 = "2.7.
|
|
1176
|
+
var version$1 = "2.7.2";
|
|
1176
1177
|
var description = "Command-line tool with commands to streamline the developer workflow.";
|
|
1177
1178
|
//#endregion
|
|
1178
1179
|
//#region src/utility/updates/checkUpdate.ts
|
|
@@ -1239,7 +1240,7 @@ function uuid(program) {
|
|
|
1239
1240
|
//#region src/utility/miscellaneous/parseZodSchemaForProgram.ts
|
|
1240
1241
|
function parseZodSchemaForProgram(program, schema, data) {
|
|
1241
1242
|
try {
|
|
1242
|
-
return
|
|
1243
|
+
return az.with(schema).parse(data);
|
|
1243
1244
|
} catch (error) {
|
|
1244
1245
|
if (DataError.check(error)) convertDataErrorToProgramError(error, program);
|
|
1245
1246
|
throw error;
|
|
@@ -1364,7 +1365,7 @@ const RuleName = {
|
|
|
1364
1365
|
function packageJsonCheck(program) {
|
|
1365
1366
|
program.command("check").description("Run checks on your package.json file").option("--rules <rules>", "The name of the rule to check", (rawRules) => {
|
|
1366
1367
|
const rawRuleNamesArray = rawRules.split(",");
|
|
1367
|
-
return
|
|
1368
|
+
return az.with(z.array(z.enum(RuleName))).parse(rawRuleNamesArray);
|
|
1368
1369
|
}).action(async ({ rules }) => {
|
|
1369
1370
|
if (rules?.includes("no-pre-release-dependencies")) await noPreReleaseDependencies(program);
|
|
1370
1371
|
if (rules?.includes("no-file-dependencies")) await noFileDependencies(program);
|
|
@@ -1449,7 +1450,7 @@ const alexCLineGlobalCacheSchema = z.looseObject({ updateChecks: z.record(z.stri
|
|
|
1449
1450
|
//#endregion
|
|
1450
1451
|
//#region src/cache/global/parseAlexCLineGlobalCache.ts
|
|
1451
1452
|
function parseAlexCLineGlobalCache(input) {
|
|
1452
|
-
return
|
|
1453
|
+
return az.with(alexCLineGlobalCacheSchema).parse(input);
|
|
1453
1454
|
}
|
|
1454
1455
|
//#endregion
|
|
1455
1456
|
//#region src/cache/global/loadAlexCLineGlobalCache.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alex-c-line",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.2",
|
|
4
4
|
"description": "Command-line tool with commands to streamline the developer workflow.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
"templates"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@alextheman/utility": "5.
|
|
38
|
-
"@inquirer/prompts": "8.4.
|
|
39
|
-
"axios": "1.15.
|
|
37
|
+
"@alextheman/utility": "5.14.0",
|
|
38
|
+
"@inquirer/prompts": "8.4.2",
|
|
39
|
+
"axios": "1.15.2",
|
|
40
40
|
"boxen": "8.0.1",
|
|
41
41
|
"chalk": "5.6.2",
|
|
42
42
|
"commander": "14.0.3",
|
|
43
|
-
"dotenv": "17.4.
|
|
43
|
+
"dotenv": "17.4.2",
|
|
44
44
|
"dotenv-stringify": "3.0.1",
|
|
45
45
|
"env-paths": "4.0.0",
|
|
46
46
|
"execa": "9.6.1",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"zod": "4.3.6"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@alextheman/eslint-plugin": "5.
|
|
55
|
+
"@alextheman/eslint-plugin": "5.13.1",
|
|
56
56
|
"@commander-js/extra-typings": "14.0.0",
|
|
57
57
|
"@types/eslint": "9.6.1",
|
|
58
58
|
"@types/node": "25.6.0",
|
|
@@ -60,17 +60,17 @@
|
|
|
60
60
|
"@types/update-notifier": "6.0.8",
|
|
61
61
|
"cross-env": "10.1.0",
|
|
62
62
|
"dotenv-cli": "11.0.0",
|
|
63
|
-
"eslint": "10.2.
|
|
63
|
+
"eslint": "10.2.1",
|
|
64
64
|
"husky": "9.1.7",
|
|
65
|
-
"markdownlint-cli2": "0.22.
|
|
66
|
-
"prettier": "3.8.
|
|
65
|
+
"markdownlint-cli2": "0.22.1",
|
|
66
|
+
"prettier": "3.8.3",
|
|
67
67
|
"tempy": "3.2.0",
|
|
68
68
|
"ts-node": "10.9.2",
|
|
69
|
-
"tsdown": "0.21.
|
|
70
|
-
"typescript": "6.0.
|
|
71
|
-
"typescript-eslint": "8.
|
|
72
|
-
"vite
|
|
73
|
-
"vitest": "4.1.
|
|
69
|
+
"tsdown": "0.21.10",
|
|
70
|
+
"typescript": "6.0.3",
|
|
71
|
+
"typescript-eslint": "8.59.0",
|
|
72
|
+
"vite": "8.0.10",
|
|
73
|
+
"vitest": "4.1.5"
|
|
74
74
|
},
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=22.0.0"
|