alex-c-line 1.30.2 → 1.32.0

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.
@@ -23,7 +23,7 @@ interface CreatePullRequestTemplateInfrastructureConfig extends CreatePullReques
23
23
  }
24
24
  type CreatePullRequestTemplateConfig = CreatePullRequestTemplateGeneralConfig | CreatePullRequestTemplateInfrastructureConfig;
25
25
  //#endregion
26
- //#region src/commands/pre-commit/createStepRunner.d.ts
26
+ //#region src/cli/commands/pre-commit/createStepRunner.d.ts
27
27
  interface BaseOptions {
28
28
  stdio: "inherit";
29
29
  reject: false;
@@ -24,7 +24,7 @@ interface CreatePullRequestTemplateInfrastructureConfig extends CreatePullReques
24
24
  }
25
25
  type CreatePullRequestTemplateConfig = CreatePullRequestTemplateGeneralConfig | CreatePullRequestTemplateInfrastructureConfig;
26
26
  //#endregion
27
- //#region src/commands/pre-commit/createStepRunner.d.ts
27
+ //#region src/cli/commands/pre-commit/createStepRunner.d.ts
28
28
  interface BaseOptions {
29
29
  stdio: "inherit";
30
30
  reject: false;
@@ -22,7 +22,7 @@ interface CreatePullRequestTemplateInfrastructureConfig extends CreatePullReques
22
22
  }
23
23
  type CreatePullRequestTemplateConfig = CreatePullRequestTemplateGeneralConfig | CreatePullRequestTemplateInfrastructureConfig;
24
24
  //#endregion
25
- //#region src/commands/pre-commit/createStepRunner.d.ts
25
+ //#region src/cli/commands/pre-commit/createStepRunner.d.ts
26
26
  interface BaseOptions {
27
27
  stdio: "inherit";
28
28
  reject: false;
@@ -22,7 +22,7 @@ interface CreatePullRequestTemplateInfrastructureConfig extends CreatePullReques
22
22
  }
23
23
  type CreatePullRequestTemplateConfig = CreatePullRequestTemplateGeneralConfig | CreatePullRequestTemplateInfrastructureConfig;
24
24
  //#endregion
25
- //#region src/commands/pre-commit/createStepRunner.d.ts
25
+ //#region src/cli/commands/pre-commit/createStepRunner.d.ts
26
26
  interface BaseOptions {
27
27
  stdio: "inherit";
28
28
  reject: false;
package/dist/index.cjs CHANGED
@@ -58,6 +58,8 @@ gray_matter = __toESM(gray_matter);
58
58
  let _alextheman_utility_node = require("@alextheman/utility/node");
59
59
  let supports_color = require("supports-color");
60
60
  supports_color = __toESM(supports_color);
61
+ let node_crypto = require("node:crypto");
62
+ let semver = require("semver");
61
63
 
62
64
  //#region src/utility/miscellaneous/asciiToPng.ts
63
65
  async function asciiToPng(ascii, options) {
@@ -122,7 +124,7 @@ async function createAlexCLineArtwork(options) {
122
124
  }
123
125
 
124
126
  //#endregion
125
- //#region src/commands/artwork.ts
127
+ //#region src/cli/commands/artwork.ts
126
128
  function artwork(program) {
127
129
  program.command("artwork").description("Create the artwork for alex-c-line").option("--subtitle-text <subtitleText>", "Customise the subtitle text").option("--subtitle-color <subtitleColor>", "Customise the subtitle color").option("--save-png [fileName]", "Save the artwork as a PNG file, optionally specifying the path").action(async ({ savePng: fileName, subtitleText, subtitleColor = "green" }) => {
128
130
  if (subtitleColor !== "green" && subtitleColor !== "white") throw new _alextheman_utility.DataError({ subtitleColor }, "INVALID_SUBTITLE_COLOR", "Subtitle color must either be green or white.");
@@ -156,7 +158,7 @@ const { cache: ALEX_C_LINE_GLOBAL_CACHE_DIRECTORY } = alexCLineEnvPaths;
156
158
  const ALEX_C_LINE_GLOBAL_CACHE_PATH = node_path.default.join(ALEX_C_LINE_GLOBAL_CACHE_DIRECTORY, "cache.json");
157
159
 
158
160
  //#endregion
159
- //#region src/commands/cache-path.ts
161
+ //#region src/cli/commands/cache-path.ts
160
162
  function cachePath(program) {
161
163
  program.command("cache-path").description("Log the path to the alex-c-line cache files.").action(() => {
162
164
  console.info(ALEX_C_LINE_GLOBAL_CACHE_PATH);
@@ -164,7 +166,7 @@ function cachePath(program) {
164
166
  }
165
167
 
166
168
  //#endregion
167
- //#region src/commands/check-for-file-dependencies.ts
169
+ //#region src/cli/commands/check-for-file-dependencies.ts
168
170
  function findFileDependencies(dependencies) {
169
171
  const fileDependencies = {};
170
172
  if (!dependencies) return {};
@@ -193,7 +195,7 @@ function checkForFileDependencies(program) {
193
195
  }
194
196
 
195
197
  //#endregion
196
- //#region src/commands/check-lockfile-version-discrepancy.ts
198
+ //#region src/cli/commands/check-lockfile-version-discrepancy.ts
197
199
  function checkLockfileVersionDiscrepancy(program) {
198
200
  program.command("check-lockfile-version-discrepancy").description("Check that version numbers in package.json and package-lock.json match").action(async () => {
199
201
  console.info("Checking for package.json and package-lock.json discrepancies...");
@@ -209,7 +211,7 @@ function checkLockfileVersionDiscrepancy(program) {
209
211
  }
210
212
 
211
213
  //#endregion
212
- //#region src/commands/deprecated/check-version-number-change.ts
214
+ //#region src/cli/commands/deprecated/check-version-number-change.ts
213
215
  function checkVersionNumberChange(program) {
214
216
  program.command("check-version-number-change").description("Check that version number on branch has changed if source code differs between main and current branch").action(async () => {
215
217
  console.info("Checking for version change...");
@@ -305,7 +307,7 @@ function getPullRequestTemplates(packageName) {
305
307
  }
306
308
 
307
309
  //#endregion
308
- //#region src/commands/deprecated/create-pull-request-templates.ts
310
+ //#region src/cli/commands/deprecated/create-pull-request-templates.ts
309
311
  const deprecationMessage$2 = "[DEPRECATED]: This command does not support the new markdown-native templates and alex-c-line config system. Please use `pre-commit-2` instead.";
310
312
  function createPullRequestTemplates(program) {
311
313
  program.command("create-pull-request-templates").description(_alextheman_utility.normaliseIndents`
@@ -401,7 +403,7 @@ function getReleaseNoteTemplate(packageName, version, status = "In progress", co
401
403
  }
402
404
 
403
405
  //#endregion
404
- //#region src/commands/deprecated/create-release-note.ts
406
+ //#region src/cli/commands/deprecated/create-release-note.ts
405
407
  function createReleaseNote(program) {
406
408
  program.command("create-release-note").argument("[versionType]", "The version type to increment by (`major|minor|patch`). Note that this performs the version calculation without changing package.json. If left blank it will use the version in package.json", _alextheman_utility.parseVersionType).description("Create release notes based on the current version in package.json.").action(async (versionType) => {
407
409
  const { name, version } = JSON.parse(await (0, node_fs_promises.readFile)(node_path.default.join(process.cwd(), "package.json"), "utf-8"));
@@ -424,7 +426,7 @@ function createReleaseNote(program) {
424
426
  }
425
427
 
426
428
  //#endregion
427
- //#region src/commands/deprecated/edit-env.ts
429
+ //#region src/cli/commands/deprecated/edit-env.ts
428
430
  const deprecationMessage$1 = "[DEPRECATED]: Please use `edit-env-2` instead.";
429
431
  function editEnv(program) {
430
432
  program.command("edit-env <key> [value]").description(_alextheman_utility.normaliseIndents`
@@ -447,7 +449,7 @@ function editEnv(program) {
447
449
  }
448
450
 
449
451
  //#endregion
450
- //#region src/commands/deprecated/pre-commit.ts
452
+ //#region src/cli/commands/deprecated/pre-commit.ts
451
453
  const deprecationMessage = "[DEPRECATED]: This command does not support the new alex-c-line config system. Please use `pre-commit-2` instead.";
452
454
  function preCommit(program) {
453
455
  program.command("pre-commit").description(_alextheman_utility.normaliseIndents`
@@ -496,7 +498,7 @@ function isValidReleaseDocument(packageName, version, initialDocument) {
496
498
  }
497
499
 
498
500
  //#endregion
499
- //#region src/commands/deprecated/set-release-status.ts
501
+ //#region src/cli/commands/deprecated/set-release-status.ts
500
502
  function setReleaseStatus(program) {
501
503
  program.command("set-release-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").action(async (documentPath) => {
502
504
  const { name: packageName } = JSON.parse(await (0, node_fs_promises.readFile)(node_path.default.join(process.cwd(), "package.json"), "utf-8"));
@@ -530,7 +532,7 @@ async function upsertDotenvFile(contents, envFilePath) {
530
532
  }
531
533
 
532
534
  //#endregion
533
- //#region src/commands/edit-env-file/addVariable.ts
535
+ //#region src/cli/commands/edit-env-file/addVariable.ts
534
536
  async function addVariable(program, envFileContents, file) {
535
537
  const newVariableName = await (0, _inquirer_prompts.input)({ message: "Please enter the name of the environment variable you would like to add." });
536
538
  if (newVariableName in envFileContents) program.error(`
@@ -556,7 +558,7 @@ async function addVariable(program, envFileContents, file) {
556
558
  }
557
559
 
558
560
  //#endregion
559
- //#region src/commands/edit-env-file/deleteVariable.ts
561
+ //#region src/cli/commands/edit-env-file/deleteVariable.ts
560
562
  async function deleteVariable(envFileContents, variableToEdit, file) {
561
563
  if (!await (0, _inquirer_prompts.confirm)({ message: `Are you sure you want to delete \`${String(variableToEdit)}\`?` })) {
562
564
  console.info("Deletion aborted");
@@ -567,7 +569,7 @@ async function deleteVariable(envFileContents, variableToEdit, file) {
567
569
  }
568
570
 
569
571
  //#endregion
570
- //#region src/commands/edit-env-file/editVariable.ts
572
+ //#region src/cli/commands/edit-env-file/editVariable.ts
571
573
  async function editVariable(envFileContents, variableToEdit, file) {
572
574
  const newValue = await (0, _inquirer_prompts.password)({ message: `Please enter new value for \`${String(variableToEdit)}\`` });
573
575
  await upsertDotenvFile({
@@ -586,7 +588,7 @@ function redact(secretString) {
586
588
  }
587
589
 
588
590
  //#endregion
589
- //#region src/commands/edit-env-file/changeExistingVariable.ts
591
+ //#region src/cli/commands/edit-env-file/changeExistingVariable.ts
590
592
  async function changeExistingVariable(envFileContents, variableToEdit, file) {
591
593
  switch (await (0, _inquirer_prompts.select)({
592
594
  message: _alextheman_utility.normaliseIndents`
@@ -624,7 +626,7 @@ async function parseDotenvFile(envFilePath) {
624
626
  }
625
627
 
626
628
  //#endregion
627
- //#region src/commands/edit-env-file/index.ts
629
+ //#region src/cli/commands/edit-env-file/index.ts
628
630
  function editEnvFile(program) {
629
631
  program.command("edit-env-file").description("Edit properties in a .env file").option("--interactive", "Enable interactive mode", true).option("--file <filePath>", "The path to the .env file you want to edit, relative to the working directory this command is run", ".env").action(async ({ interactive, file }) => {
630
632
  if (interactive) {
@@ -671,7 +673,7 @@ function editEnvFile(program) {
671
673
  }
672
674
 
673
675
  //#endregion
674
- //#region src/commands/encrypt-with-key.ts
676
+ //#region src/cli/commands/encrypt-with-key.ts
675
677
  function encryptWithKey(program) {
676
678
  program.command("encrypt-with-key").alias("encrypt").description("Encrypt a secret given the public base64 key and the thing you want to encrypt.").argument("<publicKey>", "The public base64 key to encrypt with").argument("<plaintextValue>", "The value to encrypt in plaintext").action(async (publicKey, plaintextValue) => {
677
679
  try {
@@ -686,7 +688,7 @@ function encryptWithKey(program) {
686
688
  }
687
689
 
688
690
  //#endregion
689
- //#region src/commands/git-post-merge-cleanup.ts
691
+ //#region src/cli/commands/git-post-merge-cleanup.ts
690
692
  function gitPostMergeCleanup(program) {
691
693
  program.command("git-post-merge-cleanup").alias("git-cleanup").description("Run after merging into a given branch to quickly clean up").argument("[branch]", "The branch you want to merge into", "main").option("--rebase", "Enable if your repository mainly rebases into main").action(async (branch, { rebase: rebaseOption }) => {
692
694
  let alexCLineConfigJSON;
@@ -735,7 +737,7 @@ function gitPostMergeCleanup(program) {
735
737
  }
736
738
 
737
739
  //#endregion
738
- //#region src/commands/pre-commit/createStepRunner.ts
740
+ //#region src/cli/commands/pre-commit/createStepRunner.ts
739
741
  const runCommandAndLogToConsole = (0, execa.execa)({
740
742
  stdio: "inherit",
741
743
  reject: false
@@ -771,7 +773,7 @@ function createStepRunner(program) {
771
773
  }
772
774
 
773
775
  //#endregion
774
- //#region src/commands/pre-commit/getCommandArguments.ts
776
+ //#region src/cli/commands/pre-commit/getCommandArguments.ts
775
777
  function getCommandArguments(program, script, scripts, args) {
776
778
  if (!(script in (scripts ?? {}))) program.error(`Could not find script \`${script}\` in package.json.`, {
777
779
  exitCode: 1,
@@ -875,7 +877,7 @@ async function loadAlexCLineConfig(filePath) {
875
877
  }
876
878
 
877
879
  //#endregion
878
- //#region src/commands/pre-commit/pre-commit-2.ts
880
+ //#region src/cli/commands/pre-commit/pre-commit-2.ts
879
881
  function preCommit2(program) {
880
882
  program.command("pre-commit-2").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) => {
881
883
  const configPath = await findAlexCLineConfig(process.cwd());
@@ -915,7 +917,7 @@ function preCommit2(program) {
915
917
  }
916
918
 
917
919
  //#endregion
918
- //#region src/commands/say-hello.ts
920
+ //#region src/cli/commands/say-hello.ts
919
921
  function sayHello(program) {
920
922
  program.command("say-hello").description("Quick test command").action(() => {
921
923
  console.info("Hello!");
@@ -1007,7 +1009,7 @@ async function getPullRequestTemplatesFromMarkdown(config) {
1007
1009
  }
1008
1010
 
1009
1011
  //#endregion
1010
- //#region src/commands/template/pullRequest/create-pull-request-template-2.ts
1012
+ //#region src/cli/commands/template/pullRequest/create-pull-request-template-2.ts
1011
1013
  function createPullRequestTemplate(program) {
1012
1014
  program.command("create-pull-request-template").alias("create-pull-request-template-2").option("--category <category>", "The category of pull request templates to get (can be either `general` or `infrastructure`)", (rawValue) => {
1013
1015
  return (0, _alextheman_utility.parseZodSchema)(zod.default.enum(PullRequestTemplateCategory), rawValue, () => {
@@ -1119,7 +1121,7 @@ async function validateReleaseDocument(projectName, version, content, allowedRel
1119
1121
  }
1120
1122
 
1121
1123
  //#endregion
1122
- //#region src/commands/template/releaseNote/check-release-note.ts
1124
+ //#region src/cli/commands/template/releaseNote/check-release-note.ts
1123
1125
  function checkReleaseNote(program) {
1124
1126
  program.command("check-release-note").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 }) => {
1125
1127
  const fileContents = await (0, node_fs_promises.readFile)(node_path.default.join(process.cwd(), documentPath.fullPath), "utf-8");
@@ -1169,7 +1171,7 @@ async function getReleaseNoteTemplateFromMarkdown(projectName, version, metadata
1169
1171
  }
1170
1172
 
1171
1173
  //#endregion
1172
- //#region src/commands/template/releaseNote/create-release-note-2.ts
1174
+ //#region src/cli/commands/template/releaseNote/create-release-note-2.ts
1173
1175
  function createReleaseNote2(program) {
1174
1176
  program.command("create-release-note-2").argument("[createFor]", _alextheman_utility.normaliseIndents`
1175
1177
  Decide what version to create a release note for exactly:
@@ -1211,7 +1213,7 @@ function createReleaseNote2(program) {
1211
1213
  }
1212
1214
 
1213
1215
  //#endregion
1214
- //#region src/commands/template/releaseNote/migrate-release-notes.ts
1216
+ //#region src/cli/commands/template/releaseNote/migrate-release-notes.ts
1215
1217
  function migrateReleaseNotes(program) {
1216
1218
  program.command("migrate-release-notes").description(_alextheman_utility.normaliseIndents`
1217
1219
  Migrate the docs/releases folder generated from \`create-release-note\` to be more compatible with v2.
@@ -1267,7 +1269,7 @@ function migrateReleaseNotes(program) {
1267
1269
  }
1268
1270
 
1269
1271
  //#endregion
1270
- //#region src/commands/template/releaseNote/set-release-status-2.ts
1272
+ //#region src/cli/commands/template/releaseNote/set-release-status-2.ts
1271
1273
  function setReleaseStatus2(program) {
1272
1274
  program.command("set-release-status-2").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) => {
1273
1275
  const packageInfo = JSON.parse(await (0, node_fs_promises.readFile)(node_path.default.join(process.cwd(), "package.json"), "utf-8"));
@@ -1315,7 +1317,7 @@ function parseZodSchemaForProgram(programError, schema, data) {
1315
1317
  //#endregion
1316
1318
  //#region package.json
1317
1319
  var name = "alex-c-line";
1318
- var version = "1.30.2";
1320
+ var version = "1.32.0";
1319
1321
  var description = "Command-line tool with commands to streamline the developer workflow.";
1320
1322
 
1321
1323
  //#endregion
@@ -1351,7 +1353,7 @@ async function checkUpdate(options) {
1351
1353
  }
1352
1354
 
1353
1355
  //#endregion
1354
- //#region src/commands/update.ts
1356
+ //#region src/cli/commands/update.ts
1355
1357
  const optionsSchema = zod.default.object({ check: zod.default.boolean().optional() });
1356
1358
  function update(program) {
1357
1359
  program.command("update").description("Handle updates of the currently installed alex-c-line").option("--check", "Check for available updates").option("--apply", "Apply the latest update").action(async (rawOptions) => {
@@ -1450,7 +1452,7 @@ async function removeAllTarballs(packagePath, packageName) {
1450
1452
  }
1451
1453
 
1452
1454
  //#endregion
1453
- //#region src/commands/use-local-package.ts
1455
+ //#region src/cli/commands/use-local-package.ts
1454
1456
  function useLocalPackage(program) {
1455
1457
  program.command("use-local-package").description(_alextheman_utility.normaliseIndents`
1456
1458
  ${experimentalHeader}
@@ -1553,7 +1555,27 @@ function useLocalPackage(program) {
1553
1555
  }
1554
1556
 
1555
1557
  //#endregion
1556
- //#region src/commands/versioning/get-major-version.ts
1558
+ //#region src/cli/commands/uuid/generate.ts
1559
+ function generateUUID(program) {
1560
+ program.command("generate").description("Generate a random UUID").action(() => {
1561
+ console.info((0, node_crypto.randomUUID)());
1562
+ });
1563
+ }
1564
+
1565
+ //#endregion
1566
+ //#region src/utility/miscellaneous/loadCommands.ts
1567
+ function loadCommands(program, commandMap) {
1568
+ for (const loader of Object.values(commandMap)) loader(program);
1569
+ }
1570
+
1571
+ //#endregion
1572
+ //#region src/cli/commands/uuid/index.ts
1573
+ function uuid(program) {
1574
+ loadCommands(program.command("uuid").description("Commands to help manage UUIDs"), { generateUUID });
1575
+ }
1576
+
1577
+ //#endregion
1578
+ //#region src/cli/commands/versioning/get-major-version.ts
1557
1579
  function getMajorVersion(program) {
1558
1580
  program.command("get-major-version").description("Get the major representation of a version number (e.g. v2, v3 etc...)").argument("<version>", "The version to get the major representation of", (rawValue) => {
1559
1581
  return new _alextheman_utility.VersionNumber(rawValue);
@@ -1563,7 +1585,7 @@ function getMajorVersion(program) {
1563
1585
  }
1564
1586
 
1565
1587
  //#endregion
1566
- //#region src/commands/versioning/get-minor-version.ts
1588
+ //#region src/cli/commands/versioning/get-minor-version.ts
1567
1589
  function getMinorVersion(program) {
1568
1590
  program.command("get-minor-version").description("Get the minor representation of a version number (e.g. v2.1, v3.1 etc...)").argument("<version>", "The version to get the minor representation of", (rawValue) => {
1569
1591
  return new _alextheman_utility.VersionNumber(rawValue);
@@ -1573,7 +1595,7 @@ function getMinorVersion(program) {
1573
1595
  }
1574
1596
 
1575
1597
  //#endregion
1576
- //#region src/commands/versioning/get-version-type.ts
1598
+ //#region src/cli/commands/versioning/get-version-type.ts
1577
1599
  function getVersionType(program) {
1578
1600
  program.command("get-version-type").description("Gets the version type of the given version number.").argument("<version>", "The version to get the version type from", (rawVersion) => {
1579
1601
  return new _alextheman_utility.VersionNumber(rawVersion);
@@ -1583,7 +1605,7 @@ function getVersionType(program) {
1583
1605
  }
1584
1606
 
1585
1607
  //#endregion
1586
- //#region src/commands/versioning/increment-version.ts
1608
+ //#region src/cli/commands/versioning/increment-version.ts
1587
1609
  function incrementVersion(program) {
1588
1610
  program.command("increment-version").description("Increments the given input version depending on the given increment type.").argument("<version>", "The version to increment", (rawVersion) => {
1589
1611
  return new _alextheman_utility.VersionNumber(rawVersion);
@@ -1599,13 +1621,51 @@ function incrementVersion(program) {
1599
1621
  }
1600
1622
 
1601
1623
  //#endregion
1602
- //#region src/utility/miscellaneous/loadCommands.ts
1603
- function loadCommands(program, commandMap) {
1604
- for (const loader of Object.values(commandMap)) loader(program);
1624
+ //#region src/utility/constants/successPrefix.ts
1625
+ const successPrefix = chalk.default.green("✓");
1626
+
1627
+ //#endregion
1628
+ //#region src/cli/commands/package-json/noPreReleaseDependencies.ts
1629
+ function isPreRelease(dependencyVersionRange) {
1630
+ const minimumFromRange = (0, semver.minVersion)(dependencyVersionRange);
1631
+ return minimumFromRange !== null && (0, semver.prerelease)(minimumFromRange) !== null;
1632
+ }
1633
+ async function noPreReleaseDependencies(program) {
1634
+ const packageJson = await (0, _alextheman_utility_internal.getPackageJsonContents)(process.cwd());
1635
+ if (packageJson === null) throw (0, _alextheman_utility_internal.packageJsonNotFoundError)(process.cwd());
1636
+ const dependencies = (0, _alextheman_utility_internal.getDependenciesFromGroup)(packageJson, "dependencies");
1637
+ const devDependencies = (0, _alextheman_utility_internal.getDependenciesFromGroup)(packageJson, "devDependencies");
1638
+ const preReleaseDependencies = {};
1639
+ const preReleaseDevDependencies = {};
1640
+ for (const [dependencyName, dependencyVersionRange] of Object.entries(dependencies)) if (isPreRelease(dependencyVersionRange)) preReleaseDependencies[dependencyName] = dependencyVersionRange;
1641
+ for (const [dependencyName, dependencyVersionRange] of Object.entries(devDependencies)) if (isPreRelease(dependencyVersionRange)) preReleaseDevDependencies[dependencyName] = dependencyVersionRange;
1642
+ if (Object.keys(preReleaseDependencies).length !== 0 || Object.keys(preReleaseDevDependencies).length !== 0) program.error(_alextheman_utility.normaliseIndents`
1643
+ ${errorPrefix}: Pre-release version pinning is not allowed. Found the following violations:
1644
+
1645
+ ${JSON.stringify({
1646
+ dependencies: preReleaseDependencies,
1647
+ devDependencies: preReleaseDevDependencies
1648
+ }, null, 2)}
1649
+ `, {
1650
+ exitCode: 2,
1651
+ code: "UNEXPECTED_PRE_RELEASE_VERSION"
1652
+ });
1653
+ console.info(`${successPrefix} No pre-release versions found!`);
1654
+ }
1655
+
1656
+ //#endregion
1657
+ //#region src/cli/commands/package-json/index.ts
1658
+ const RuleName = { NO_PRE_RELEASE_DEPENDENCIES: "no-pre-release-dependencies" };
1659
+ function packageJson(program) {
1660
+ program.command("package-json").description("Run checks on your package.json file").argument("[ruleName]", "The name of the rule to check", (rawRuleName) => {
1661
+ return (0, _alextheman_utility.parseZodSchema)(zod.default.enum(RuleName), rawRuleName);
1662
+ }).action(async (ruleName) => {
1663
+ if (ruleName === "no-pre-release-dependencies") return await noPreReleaseDependencies(program);
1664
+ });
1605
1665
  }
1606
1666
 
1607
1667
  //#endregion
1608
- //#region src/commands/index.ts
1668
+ //#region src/cli/commands/index.ts
1609
1669
  function createCommands(program) {
1610
1670
  loadCommands(program, {
1611
1671
  artwork,
@@ -1633,7 +1693,9 @@ function createCommands(program) {
1633
1693
  setReleaseStatus,
1634
1694
  setReleaseStatus2,
1635
1695
  update,
1636
- useLocalPackage
1696
+ useLocalPackage,
1697
+ uuid,
1698
+ packageJson
1637
1699
  });
1638
1700
  }
1639
1701
 
@@ -1709,7 +1771,7 @@ async function runAutomatedUpdateCheck() {
1709
1771
  }
1710
1772
 
1711
1773
  //#endregion
1712
- //#region src/index.ts
1774
+ //#region src/cli/index.ts
1713
1775
  (async () => {
1714
1776
  try {
1715
1777
  const program = new commander.Command();
package/dist/index.js CHANGED
@@ -15,11 +15,13 @@ import dotenvStringify from "dotenv-stringify";
15
15
  import z from "zod";
16
16
  import { confirm, input, password, select } from "@inquirer/prompts";
17
17
  import os from "node:os";
18
- import { PackageManager, getDependenciesFromGroup, getExpectedTgzName, getPackageJsonContents } from "@alextheman/utility/internal";
18
+ import { PackageManager, getDependenciesFromGroup, getExpectedTgzName, getPackageJsonContents, packageJsonNotFoundError } from "@alextheman/utility/internal";
19
19
  import { fileURLToPath, pathToFileURL } from "node:url";
20
20
  import matter from "gray-matter";
21
21
  import { parseFilePath } from "@alextheman/utility/node";
22
22
  import supportsColor from "supports-color";
23
+ import { randomUUID } from "node:crypto";
24
+ import { minVersion, prerelease } from "semver";
23
25
 
24
26
  //#region src/utility/miscellaneous/asciiToPng.ts
25
27
  async function asciiToPng(ascii, options) {
@@ -84,7 +86,7 @@ async function createAlexCLineArtwork(options) {
84
86
  }
85
87
 
86
88
  //#endregion
87
- //#region src/commands/artwork.ts
89
+ //#region src/cli/commands/artwork.ts
88
90
  function artwork(program) {
89
91
  program.command("artwork").description("Create the artwork for alex-c-line").option("--subtitle-text <subtitleText>", "Customise the subtitle text").option("--subtitle-color <subtitleColor>", "Customise the subtitle color").option("--save-png [fileName]", "Save the artwork as a PNG file, optionally specifying the path").action(async ({ savePng: fileName, subtitleText, subtitleColor = "green" }) => {
90
92
  if (subtitleColor !== "green" && subtitleColor !== "white") throw new DataError({ subtitleColor }, "INVALID_SUBTITLE_COLOR", "Subtitle color must either be green or white.");
@@ -118,7 +120,7 @@ const { cache: ALEX_C_LINE_GLOBAL_CACHE_DIRECTORY } = alexCLineEnvPaths;
118
120
  const ALEX_C_LINE_GLOBAL_CACHE_PATH = path.join(ALEX_C_LINE_GLOBAL_CACHE_DIRECTORY, "cache.json");
119
121
 
120
122
  //#endregion
121
- //#region src/commands/cache-path.ts
123
+ //#region src/cli/commands/cache-path.ts
122
124
  function cachePath(program) {
123
125
  program.command("cache-path").description("Log the path to the alex-c-line cache files.").action(() => {
124
126
  console.info(ALEX_C_LINE_GLOBAL_CACHE_PATH);
@@ -126,7 +128,7 @@ function cachePath(program) {
126
128
  }
127
129
 
128
130
  //#endregion
129
- //#region src/commands/check-for-file-dependencies.ts
131
+ //#region src/cli/commands/check-for-file-dependencies.ts
130
132
  function findFileDependencies(dependencies) {
131
133
  const fileDependencies = {};
132
134
  if (!dependencies) return {};
@@ -155,7 +157,7 @@ function checkForFileDependencies(program) {
155
157
  }
156
158
 
157
159
  //#endregion
158
- //#region src/commands/check-lockfile-version-discrepancy.ts
160
+ //#region src/cli/commands/check-lockfile-version-discrepancy.ts
159
161
  function checkLockfileVersionDiscrepancy(program) {
160
162
  program.command("check-lockfile-version-discrepancy").description("Check that version numbers in package.json and package-lock.json match").action(async () => {
161
163
  console.info("Checking for package.json and package-lock.json discrepancies...");
@@ -171,7 +173,7 @@ function checkLockfileVersionDiscrepancy(program) {
171
173
  }
172
174
 
173
175
  //#endregion
174
- //#region src/commands/deprecated/check-version-number-change.ts
176
+ //#region src/cli/commands/deprecated/check-version-number-change.ts
175
177
  function checkVersionNumberChange(program) {
176
178
  program.command("check-version-number-change").description("Check that version number on branch has changed if source code differs between main and current branch").action(async () => {
177
179
  console.info("Checking for version change...");
@@ -267,7 +269,7 @@ function getPullRequestTemplates(packageName) {
267
269
  }
268
270
 
269
271
  //#endregion
270
- //#region src/commands/deprecated/create-pull-request-templates.ts
272
+ //#region src/cli/commands/deprecated/create-pull-request-templates.ts
271
273
  const deprecationMessage$2 = "[DEPRECATED]: This command does not support the new markdown-native templates and alex-c-line config system. Please use `pre-commit-2` instead.";
272
274
  function createPullRequestTemplates(program) {
273
275
  program.command("create-pull-request-templates").description(normaliseIndents`
@@ -363,7 +365,7 @@ function getReleaseNoteTemplate(packageName, version, status = "In progress", co
363
365
  }
364
366
 
365
367
  //#endregion
366
- //#region src/commands/deprecated/create-release-note.ts
368
+ //#region src/cli/commands/deprecated/create-release-note.ts
367
369
  function createReleaseNote(program) {
368
370
  program.command("create-release-note").argument("[versionType]", "The version type to increment by (`major|minor|patch`). Note that this performs the version calculation without changing package.json. If left blank it will use the version in package.json", parseVersionType).description("Create release notes based on the current version in package.json.").action(async (versionType) => {
369
371
  const { name, version } = JSON.parse(await readFile(path.join(process.cwd(), "package.json"), "utf-8"));
@@ -386,7 +388,7 @@ function createReleaseNote(program) {
386
388
  }
387
389
 
388
390
  //#endregion
389
- //#region src/commands/deprecated/edit-env.ts
391
+ //#region src/cli/commands/deprecated/edit-env.ts
390
392
  const deprecationMessage$1 = "[DEPRECATED]: Please use `edit-env-2` instead.";
391
393
  function editEnv(program) {
392
394
  program.command("edit-env <key> [value]").description(normaliseIndents`
@@ -409,7 +411,7 @@ function editEnv(program) {
409
411
  }
410
412
 
411
413
  //#endregion
412
- //#region src/commands/deprecated/pre-commit.ts
414
+ //#region src/cli/commands/deprecated/pre-commit.ts
413
415
  const deprecationMessage = "[DEPRECATED]: This command does not support the new alex-c-line config system. Please use `pre-commit-2` instead.";
414
416
  function preCommit(program) {
415
417
  program.command("pre-commit").description(normaliseIndents`
@@ -458,7 +460,7 @@ function isValidReleaseDocument(packageName, version, initialDocument) {
458
460
  }
459
461
 
460
462
  //#endregion
461
- //#region src/commands/deprecated/set-release-status.ts
463
+ //#region src/cli/commands/deprecated/set-release-status.ts
462
464
  function setReleaseStatus(program) {
463
465
  program.command("set-release-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").action(async (documentPath) => {
464
466
  const { name: packageName } = JSON.parse(await readFile(path.join(process.cwd(), "package.json"), "utf-8"));
@@ -492,7 +494,7 @@ async function upsertDotenvFile(contents, envFilePath) {
492
494
  }
493
495
 
494
496
  //#endregion
495
- //#region src/commands/edit-env-file/addVariable.ts
497
+ //#region src/cli/commands/edit-env-file/addVariable.ts
496
498
  async function addVariable(program, envFileContents, file) {
497
499
  const newVariableName = await input({ message: "Please enter the name of the environment variable you would like to add." });
498
500
  if (newVariableName in envFileContents) program.error(`
@@ -518,7 +520,7 @@ async function addVariable(program, envFileContents, file) {
518
520
  }
519
521
 
520
522
  //#endregion
521
- //#region src/commands/edit-env-file/deleteVariable.ts
523
+ //#region src/cli/commands/edit-env-file/deleteVariable.ts
522
524
  async function deleteVariable(envFileContents, variableToEdit, file) {
523
525
  if (!await confirm({ message: `Are you sure you want to delete \`${String(variableToEdit)}\`?` })) {
524
526
  console.info("Deletion aborted");
@@ -529,7 +531,7 @@ async function deleteVariable(envFileContents, variableToEdit, file) {
529
531
  }
530
532
 
531
533
  //#endregion
532
- //#region src/commands/edit-env-file/editVariable.ts
534
+ //#region src/cli/commands/edit-env-file/editVariable.ts
533
535
  async function editVariable(envFileContents, variableToEdit, file) {
534
536
  const newValue = await password({ message: `Please enter new value for \`${String(variableToEdit)}\`` });
535
537
  await upsertDotenvFile({
@@ -548,7 +550,7 @@ function redact(secretString) {
548
550
  }
549
551
 
550
552
  //#endregion
551
- //#region src/commands/edit-env-file/changeExistingVariable.ts
553
+ //#region src/cli/commands/edit-env-file/changeExistingVariable.ts
552
554
  async function changeExistingVariable(envFileContents, variableToEdit, file) {
553
555
  switch (await select({
554
556
  message: normaliseIndents`
@@ -586,7 +588,7 @@ async function parseDotenvFile(envFilePath) {
586
588
  }
587
589
 
588
590
  //#endregion
589
- //#region src/commands/edit-env-file/index.ts
591
+ //#region src/cli/commands/edit-env-file/index.ts
590
592
  function editEnvFile(program) {
591
593
  program.command("edit-env-file").description("Edit properties in a .env file").option("--interactive", "Enable interactive mode", true).option("--file <filePath>", "The path to the .env file you want to edit, relative to the working directory this command is run", ".env").action(async ({ interactive, file }) => {
592
594
  if (interactive) {
@@ -633,7 +635,7 @@ function editEnvFile(program) {
633
635
  }
634
636
 
635
637
  //#endregion
636
- //#region src/commands/encrypt-with-key.ts
638
+ //#region src/cli/commands/encrypt-with-key.ts
637
639
  function encryptWithKey$1(program) {
638
640
  program.command("encrypt-with-key").alias("encrypt").description("Encrypt a secret given the public base64 key and the thing you want to encrypt.").argument("<publicKey>", "The public base64 key to encrypt with").argument("<plaintextValue>", "The value to encrypt in plaintext").action(async (publicKey, plaintextValue) => {
639
641
  try {
@@ -648,7 +650,7 @@ function encryptWithKey$1(program) {
648
650
  }
649
651
 
650
652
  //#endregion
651
- //#region src/commands/git-post-merge-cleanup.ts
653
+ //#region src/cli/commands/git-post-merge-cleanup.ts
652
654
  function gitPostMergeCleanup(program) {
653
655
  program.command("git-post-merge-cleanup").alias("git-cleanup").description("Run after merging into a given branch to quickly clean up").argument("[branch]", "The branch you want to merge into", "main").option("--rebase", "Enable if your repository mainly rebases into main").action(async (branch, { rebase: rebaseOption }) => {
654
656
  let alexCLineConfigJSON;
@@ -697,7 +699,7 @@ function gitPostMergeCleanup(program) {
697
699
  }
698
700
 
699
701
  //#endregion
700
- //#region src/commands/pre-commit/createStepRunner.ts
702
+ //#region src/cli/commands/pre-commit/createStepRunner.ts
701
703
  const runCommandAndLogToConsole = execa({
702
704
  stdio: "inherit",
703
705
  reject: false
@@ -733,7 +735,7 @@ function createStepRunner(program) {
733
735
  }
734
736
 
735
737
  //#endregion
736
- //#region src/commands/pre-commit/getCommandArguments.ts
738
+ //#region src/cli/commands/pre-commit/getCommandArguments.ts
737
739
  function getCommandArguments(program, script, scripts, args) {
738
740
  if (!(script in (scripts ?? {}))) program.error(`Could not find script \`${script}\` in package.json.`, {
739
741
  exitCode: 1,
@@ -837,7 +839,7 @@ async function loadAlexCLineConfig(filePath) {
837
839
  }
838
840
 
839
841
  //#endregion
840
- //#region src/commands/pre-commit/pre-commit-2.ts
842
+ //#region src/cli/commands/pre-commit/pre-commit-2.ts
841
843
  function preCommit2(program) {
842
844
  program.command("pre-commit-2").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) => {
843
845
  const configPath = await findAlexCLineConfig(process.cwd());
@@ -877,7 +879,7 @@ function preCommit2(program) {
877
879
  }
878
880
 
879
881
  //#endregion
880
- //#region src/commands/say-hello.ts
882
+ //#region src/cli/commands/say-hello.ts
881
883
  function sayHello(program) {
882
884
  program.command("say-hello").description("Quick test command").action(() => {
883
885
  console.info("Hello!");
@@ -969,7 +971,7 @@ async function getPullRequestTemplatesFromMarkdown(config) {
969
971
  }
970
972
 
971
973
  //#endregion
972
- //#region src/commands/template/pullRequest/create-pull-request-template-2.ts
974
+ //#region src/cli/commands/template/pullRequest/create-pull-request-template-2.ts
973
975
  function createPullRequestTemplate(program) {
974
976
  program.command("create-pull-request-template").alias("create-pull-request-template-2").option("--category <category>", "The category of pull request templates to get (can be either `general` or `infrastructure`)", (rawValue) => {
975
977
  return parseZodSchema(z.enum(PullRequestTemplateCategory), rawValue, () => {
@@ -1081,7 +1083,7 @@ async function validateReleaseDocument(projectName, version, content, allowedRel
1081
1083
  }
1082
1084
 
1083
1085
  //#endregion
1084
- //#region src/commands/template/releaseNote/check-release-note.ts
1086
+ //#region src/cli/commands/template/releaseNote/check-release-note.ts
1085
1087
  function checkReleaseNote(program) {
1086
1088
  program.command("check-release-note").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 }) => {
1087
1089
  const fileContents = await readFile(path.join(process.cwd(), documentPath.fullPath), "utf-8");
@@ -1131,7 +1133,7 @@ async function getReleaseNoteTemplateFromMarkdown(projectName, version, metadata
1131
1133
  }
1132
1134
 
1133
1135
  //#endregion
1134
- //#region src/commands/template/releaseNote/create-release-note-2.ts
1136
+ //#region src/cli/commands/template/releaseNote/create-release-note-2.ts
1135
1137
  function createReleaseNote2(program) {
1136
1138
  program.command("create-release-note-2").argument("[createFor]", normaliseIndents`
1137
1139
  Decide what version to create a release note for exactly:
@@ -1173,7 +1175,7 @@ function createReleaseNote2(program) {
1173
1175
  }
1174
1176
 
1175
1177
  //#endregion
1176
- //#region src/commands/template/releaseNote/migrate-release-notes.ts
1178
+ //#region src/cli/commands/template/releaseNote/migrate-release-notes.ts
1177
1179
  function migrateReleaseNotes(program) {
1178
1180
  program.command("migrate-release-notes").description(normaliseIndents`
1179
1181
  Migrate the docs/releases folder generated from \`create-release-note\` to be more compatible with v2.
@@ -1229,7 +1231,7 @@ function migrateReleaseNotes(program) {
1229
1231
  }
1230
1232
 
1231
1233
  //#endregion
1232
- //#region src/commands/template/releaseNote/set-release-status-2.ts
1234
+ //#region src/cli/commands/template/releaseNote/set-release-status-2.ts
1233
1235
  function setReleaseStatus2(program) {
1234
1236
  program.command("set-release-status-2").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) => {
1235
1237
  const packageInfo = JSON.parse(await readFile(path.join(process.cwd(), "package.json"), "utf-8"));
@@ -1277,7 +1279,7 @@ function parseZodSchemaForProgram(programError, schema, data) {
1277
1279
  //#endregion
1278
1280
  //#region package.json
1279
1281
  var name = "alex-c-line";
1280
- var version = "1.30.2";
1282
+ var version = "1.32.0";
1281
1283
  var description = "Command-line tool with commands to streamline the developer workflow.";
1282
1284
 
1283
1285
  //#endregion
@@ -1313,7 +1315,7 @@ async function checkUpdate(options) {
1313
1315
  }
1314
1316
 
1315
1317
  //#endregion
1316
- //#region src/commands/update.ts
1318
+ //#region src/cli/commands/update.ts
1317
1319
  const optionsSchema = z.object({ check: z.boolean().optional() });
1318
1320
  function update(program) {
1319
1321
  program.command("update").description("Handle updates of the currently installed alex-c-line").option("--check", "Check for available updates").option("--apply", "Apply the latest update").action(async (rawOptions) => {
@@ -1412,7 +1414,7 @@ async function removeAllTarballs(packagePath, packageName) {
1412
1414
  }
1413
1415
 
1414
1416
  //#endregion
1415
- //#region src/commands/use-local-package.ts
1417
+ //#region src/cli/commands/use-local-package.ts
1416
1418
  function useLocalPackage(program) {
1417
1419
  program.command("use-local-package").description(normaliseIndents`
1418
1420
  ${experimentalHeader}
@@ -1515,7 +1517,27 @@ function useLocalPackage(program) {
1515
1517
  }
1516
1518
 
1517
1519
  //#endregion
1518
- //#region src/commands/versioning/get-major-version.ts
1520
+ //#region src/cli/commands/uuid/generate.ts
1521
+ function generateUUID(program) {
1522
+ program.command("generate").description("Generate a random UUID").action(() => {
1523
+ console.info(randomUUID());
1524
+ });
1525
+ }
1526
+
1527
+ //#endregion
1528
+ //#region src/utility/miscellaneous/loadCommands.ts
1529
+ function loadCommands(program, commandMap) {
1530
+ for (const loader of Object.values(commandMap)) loader(program);
1531
+ }
1532
+
1533
+ //#endregion
1534
+ //#region src/cli/commands/uuid/index.ts
1535
+ function uuid(program) {
1536
+ loadCommands(program.command("uuid").description("Commands to help manage UUIDs"), { generateUUID });
1537
+ }
1538
+
1539
+ //#endregion
1540
+ //#region src/cli/commands/versioning/get-major-version.ts
1519
1541
  function getMajorVersion(program) {
1520
1542
  program.command("get-major-version").description("Get the major representation of a version number (e.g. v2, v3 etc...)").argument("<version>", "The version to get the major representation of", (rawValue) => {
1521
1543
  return new VersionNumber(rawValue);
@@ -1525,7 +1547,7 @@ function getMajorVersion(program) {
1525
1547
  }
1526
1548
 
1527
1549
  //#endregion
1528
- //#region src/commands/versioning/get-minor-version.ts
1550
+ //#region src/cli/commands/versioning/get-minor-version.ts
1529
1551
  function getMinorVersion(program) {
1530
1552
  program.command("get-minor-version").description("Get the minor representation of a version number (e.g. v2.1, v3.1 etc...)").argument("<version>", "The version to get the minor representation of", (rawValue) => {
1531
1553
  return new VersionNumber(rawValue);
@@ -1535,7 +1557,7 @@ function getMinorVersion(program) {
1535
1557
  }
1536
1558
 
1537
1559
  //#endregion
1538
- //#region src/commands/versioning/get-version-type.ts
1560
+ //#region src/cli/commands/versioning/get-version-type.ts
1539
1561
  function getVersionType(program) {
1540
1562
  program.command("get-version-type").description("Gets the version type of the given version number.").argument("<version>", "The version to get the version type from", (rawVersion) => {
1541
1563
  return new VersionNumber(rawVersion);
@@ -1545,7 +1567,7 @@ function getVersionType(program) {
1545
1567
  }
1546
1568
 
1547
1569
  //#endregion
1548
- //#region src/commands/versioning/increment-version.ts
1570
+ //#region src/cli/commands/versioning/increment-version.ts
1549
1571
  function incrementVersion(program) {
1550
1572
  program.command("increment-version").description("Increments the given input version depending on the given increment type.").argument("<version>", "The version to increment", (rawVersion) => {
1551
1573
  return new VersionNumber(rawVersion);
@@ -1561,13 +1583,51 @@ function incrementVersion(program) {
1561
1583
  }
1562
1584
 
1563
1585
  //#endregion
1564
- //#region src/utility/miscellaneous/loadCommands.ts
1565
- function loadCommands(program, commandMap) {
1566
- for (const loader of Object.values(commandMap)) loader(program);
1586
+ //#region src/utility/constants/successPrefix.ts
1587
+ const successPrefix = chalk.green("✓");
1588
+
1589
+ //#endregion
1590
+ //#region src/cli/commands/package-json/noPreReleaseDependencies.ts
1591
+ function isPreRelease(dependencyVersionRange) {
1592
+ const minimumFromRange = minVersion(dependencyVersionRange);
1593
+ return minimumFromRange !== null && prerelease(minimumFromRange) !== null;
1594
+ }
1595
+ async function noPreReleaseDependencies(program) {
1596
+ const packageJson = await getPackageJsonContents(process.cwd());
1597
+ if (packageJson === null) throw packageJsonNotFoundError(process.cwd());
1598
+ const dependencies = getDependenciesFromGroup(packageJson, "dependencies");
1599
+ const devDependencies = getDependenciesFromGroup(packageJson, "devDependencies");
1600
+ const preReleaseDependencies = {};
1601
+ const preReleaseDevDependencies = {};
1602
+ for (const [dependencyName, dependencyVersionRange] of Object.entries(dependencies)) if (isPreRelease(dependencyVersionRange)) preReleaseDependencies[dependencyName] = dependencyVersionRange;
1603
+ for (const [dependencyName, dependencyVersionRange] of Object.entries(devDependencies)) if (isPreRelease(dependencyVersionRange)) preReleaseDevDependencies[dependencyName] = dependencyVersionRange;
1604
+ if (Object.keys(preReleaseDependencies).length !== 0 || Object.keys(preReleaseDevDependencies).length !== 0) program.error(normaliseIndents`
1605
+ ${errorPrefix}: Pre-release version pinning is not allowed. Found the following violations:
1606
+
1607
+ ${JSON.stringify({
1608
+ dependencies: preReleaseDependencies,
1609
+ devDependencies: preReleaseDevDependencies
1610
+ }, null, 2)}
1611
+ `, {
1612
+ exitCode: 2,
1613
+ code: "UNEXPECTED_PRE_RELEASE_VERSION"
1614
+ });
1615
+ console.info(`${successPrefix} No pre-release versions found!`);
1616
+ }
1617
+
1618
+ //#endregion
1619
+ //#region src/cli/commands/package-json/index.ts
1620
+ const RuleName = { NO_PRE_RELEASE_DEPENDENCIES: "no-pre-release-dependencies" };
1621
+ function packageJson(program) {
1622
+ program.command("package-json").description("Run checks on your package.json file").argument("[ruleName]", "The name of the rule to check", (rawRuleName) => {
1623
+ return parseZodSchema(z.enum(RuleName), rawRuleName);
1624
+ }).action(async (ruleName) => {
1625
+ if (ruleName === "no-pre-release-dependencies") return await noPreReleaseDependencies(program);
1626
+ });
1567
1627
  }
1568
1628
 
1569
1629
  //#endregion
1570
- //#region src/commands/index.ts
1630
+ //#region src/cli/commands/index.ts
1571
1631
  function createCommands(program) {
1572
1632
  loadCommands(program, {
1573
1633
  artwork,
@@ -1595,7 +1655,9 @@ function createCommands(program) {
1595
1655
  setReleaseStatus,
1596
1656
  setReleaseStatus2,
1597
1657
  update,
1598
- useLocalPackage
1658
+ useLocalPackage,
1659
+ uuid,
1660
+ packageJson
1599
1661
  });
1600
1662
  }
1601
1663
 
@@ -1671,7 +1733,7 @@ async function runAutomatedUpdateCheck() {
1671
1733
  }
1672
1734
 
1673
1735
  //#endregion
1674
- //#region src/index.ts
1736
+ //#region src/cli/index.ts
1675
1737
  (async () => {
1676
1738
  try {
1677
1739
  const program = new Command();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alex-c-line",
3
- "version": "1.30.2",
3
+ "version": "1.32.0",
4
4
  "description": "Command-line tool with commands to streamline the developer workflow.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,8 +34,8 @@
34
34
  "templates"
35
35
  ],
36
36
  "dependencies": {
37
- "@alextheman/utility": "^5.3.0",
38
- "@inquirer/prompts": "^8.2.1",
37
+ "@alextheman/utility": "^5.5.0",
38
+ "@inquirer/prompts": "^8.3.0",
39
39
  "boxen": "^8.0.1",
40
40
  "canvas": "^3.2.1",
41
41
  "chalk": "^5.6.2",
@@ -47,24 +47,27 @@
47
47
  "figlet": "^1.10.0",
48
48
  "gray-matter": "^4.0.3",
49
49
  "libsodium-wrappers": "^0.8.2",
50
+ "semver": "^7.7.4",
50
51
  "supports-color": "^10.2.2",
51
52
  "zod": "^4.3.6"
52
53
  },
53
54
  "devDependencies": {
54
- "@alextheman/eslint-plugin": "^5.8.1",
55
+ "@alextheman/eslint-plugin": "^5.9.0",
55
56
  "@commander-js/extra-typings": "^14.0.0",
56
57
  "@types/eslint": "^9.6.1",
57
- "@types/node": "^25.3.0",
58
+ "@types/node": "^25.3.2",
59
+ "@types/semver": "^7.7.1",
58
60
  "@types/update-notifier": "^6.0.8",
61
+ "cross-env": "^10.1.0",
59
62
  "dotenv-cli": "^11.0.0",
60
- "eslint": "^10.0.1",
63
+ "eslint": "^10.0.2",
61
64
  "husky": "^9.1.7",
62
65
  "prettier": "^3.8.1",
63
66
  "tempy": "^3.2.0",
64
67
  "ts-node": "^10.9.2",
65
68
  "tsdown": "^0.20.3",
66
69
  "typescript": "^5.9.3",
67
- "typescript-eslint": "^8.56.0",
70
+ "typescript-eslint": "^8.56.1",
68
71
  "vite-tsconfig-paths": "^6.1.1",
69
72
  "vitest": "^4.0.18"
70
73
  },
@@ -95,7 +98,7 @@
95
98
  "prepare-local-eslint-plugin": "dotenv -e .env -- sh -c 'ESLINT_PLUGIN_PATH=${LOCAL_ESLINT_PLUGIN_PATH:-../eslint-plugin}; pnpm --prefix \"$ESLINT_PLUGIN_PATH\" run build && pnpm uninstall @alextheman/eslint-plugin && pnpm install --save-dev file:\"$ESLINT_PLUGIN_PATH\"'",
96
99
  "prepare-local-utility": "dotenv -e .env -- sh -c 'UTILITY_PATH=${LOCAL_UTILITY_PATH:-../utility}; pnpm --prefix \"$UTILITY_PATH\" run build && pnpm uninstall @alextheman/utility && pnpm install file:\"$UTILITY_PATH\"'",
97
100
  "test": "vitest run",
98
- "test-end-to-end": "RUN_END_TO_END=true vitest run tests/end-to-end --reporter verbose",
101
+ "test-end-to-end": "cross-env RUN_END_TO_END=true vitest run tests/end-to-end --reporter verbose",
99
102
  "test-watch": "vitest",
100
103
  "update-dependencies": "pnpm update --latest && pnpm update",
101
104
  "use-live-eslint-plugin": "pnpm run prepare-live-eslint-plugin && pnpm run lint",