alex-c-line 2.9.2 → 2.10.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.
package/dist/index.cjs CHANGED
@@ -40,8 +40,8 @@ let dotenv = require("dotenv");
40
40
  let execa = require("execa");
41
41
  let zod = require("zod");
42
42
  zod = __toESM(zod, 1);
43
- let _alextheman_utility_internal = require("@alextheman/utility/internal");
44
43
  let node_url = require("node:url");
44
+ let _alextheman_utility_internal = require("@alextheman/utility/internal");
45
45
  let node_module = require("node:module");
46
46
  let toml = require("toml");
47
47
  let gray_matter = require("gray-matter");
@@ -284,12 +284,6 @@ function internalCheckLockfileVersionDiscrepancy(program) {
284
284
  });
285
285
  }
286
286
  //#endregion
287
- //#region src/configs/types/template/pullRequest/PullRequestTemplateCategory.ts
288
- const PullRequestTemplateCategory = {
289
- GENERAL: "general",
290
- INFRASTRUCTURE: "infrastructure"
291
- };
292
- //#endregion
293
287
  //#region src/utility/fileSystem/findPackageRoot.ts
294
288
  async function findPackageRoot(startDirectory, packageName) {
295
289
  let directory = startDirectory;
@@ -309,6 +303,74 @@ async function findPackageRoot(startDirectory, packageName) {
309
303
  const __filename$3 = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
310
304
  const ALEX_C_LINE_PACKAGE_ROOT = findPackageRoot(node_path.default.dirname(__filename$3), "alex-c-line");
311
305
  //#endregion
306
+ //#region src/cli/commands/internal/dependency-audit/helpers/getLicenseCheck.ts
307
+ const ALLOWED_LICENSES = [
308
+ "MIT",
309
+ "ISC",
310
+ "Apache-2.0",
311
+ "BSD-2-Clause",
312
+ "BSD-3-Clause"
313
+ ];
314
+ const pnpmLicensesSchema = zod.default.record(zod.default.string(), zod.default.array(zod.default.object({
315
+ name: zod.default.string(),
316
+ versions: zod.default.array(zod.default.string())
317
+ })));
318
+ function parseLicenseCheck(input) {
319
+ return _alextheman_utility.az.with(pnpmLicensesSchema).parse(input);
320
+ }
321
+ async function getLicenseCheck(program) {
322
+ const { exitCode, stdout, stderr } = await (0, execa.execa)({ reject: false })`pnpm licenses ls --json`;
323
+ if (![0, 1].includes(exitCode)) program.error(stderr ?? stdout, {
324
+ exitCode,
325
+ code: "LICENSE_CHECK_ERROR"
326
+ });
327
+ const licenseCheck = parseLicenseCheck(JSON.parse(stdout.trim()));
328
+ if (Object.keys(licenseCheck).length === 0) return "No licenses found.";
329
+ const licenseCheckSummaryPath = node_path.default.join(await ALEX_C_LINE_PACKAGE_ROOT, "templates", "dependencyAudit", "licenseCheck", "summary");
330
+ const summaryTableTemplate = await (0, node_fs_promises.readFile)(node_path.default.join(licenseCheckSummaryPath, "table.html"), "utf-8");
331
+ const summaryTableRowTemplate = await (0, node_fs_promises.readFile)(node_path.default.join(licenseCheckSummaryPath, "tableRow.html"), "utf-8");
332
+ const summary = summaryTableTemplate.replace("{{tableRows}}", Object.entries(licenseCheck).map(([license, data]) => {
333
+ return summaryTableRowTemplate.replace("{{license}}", license).replace("{{count}}", data.length.toString());
334
+ }).join("\n"));
335
+ const invalidLicenses = Object.keys(licenseCheck).filter((license) => {
336
+ return !ALLOWED_LICENSES.includes(license);
337
+ });
338
+ let invalidSummary;
339
+ if (invalidLicenses.length === 0) invalidSummary = "No licenses requiring review.";
340
+ else {
341
+ const invalidLicensesInvalidPath = node_path.default.join(await ALEX_C_LINE_PACKAGE_ROOT, "templates", "dependencyAudit", "licenseCheck", "invalid");
342
+ const invalidLicensesTableTemplate = await (0, node_fs_promises.readFile)(node_path.default.join(invalidLicensesInvalidPath, "table.html"), "utf-8");
343
+ const invalidLicensesTableRowTemplate = await (0, node_fs_promises.readFile)(node_path.default.join(invalidLicensesInvalidPath, "tableRow.html"), "utf-8");
344
+ const invalidLicensesListTemplate = await (0, node_fs_promises.readFile)(node_path.default.join(invalidLicensesInvalidPath, "list.html"), "utf-8");
345
+ const invalidLicensesListItemTemplate = await (0, node_fs_promises.readFile)(node_path.default.join(invalidLicensesInvalidPath, "listItem.html"), "utf-8");
346
+ invalidSummary = invalidLicensesTableTemplate.replace("{{tableRows}}", Object.entries(licenseCheck).filter(([license]) => {
347
+ return !ALLOWED_LICENSES.includes(license);
348
+ }).map(([license, data]) => {
349
+ return invalidLicensesTableRowTemplate.replaceAll("{{license}}", license).replace("{{count}}", data.length.toString()).replace("{{dependencies}}", invalidLicensesListTemplate.replace("{{listItems}}", data.flatMap((item) => {
350
+ return item.versions.map((version) => {
351
+ return invalidLicensesListItemTemplate.replace("{{name}}", item.name).replace("{{version}}", version);
352
+ });
353
+ }).join("")));
354
+ }).join("\n"));
355
+ }
356
+ return _alextheman_utility.normaliseIndents`
357
+
358
+ ### Summary
359
+
360
+ ${summary}
361
+
362
+ ### Requires Review
363
+
364
+ ${invalidSummary}
365
+ `;
366
+ }
367
+ //#endregion
368
+ //#region src/configs/types/template/pullRequest/PullRequestTemplateCategory.ts
369
+ const PullRequestTemplateCategory = {
370
+ GENERAL: "general",
371
+ INFRASTRUCTURE: "infrastructure"
372
+ };
373
+ //#endregion
312
374
  //#region src/cli/commands/internal/dependency-audit/helpers/getOutdatedDependencies.ts
313
375
  const pnpmOutdatedSchema = zod.default.record(zod.default.string(), zod.default.object({
314
376
  current: _alextheman_utility.az.versionNumber(),
@@ -413,9 +475,9 @@ async function getSecurityAudit(program) {
413
475
  low: 2,
414
476
  info: 1
415
477
  };
416
- const auditTable = tableTemplate.replace("{{tableRows}}", Object.entries(securityAudit.advisories).toSorted(([_, first], [__, second]) => {
417
- return severityOrder[second.severity] - severityOrder[first.severity];
418
- }).map(([id, data]) => {
478
+ const auditTable = tableTemplate.replace("{{tableRows}}", Object.entries(securityAudit.advisories).toSorted((0, _alextheman_utility.sortBy)(([_, advisory]) => {
479
+ return severityOrder[advisory.severity];
480
+ }, "desc")).map(([id, data]) => {
419
481
  return tableRowTemplate.replace("{{advisoryId}}", id).replace("{{severity}}", data.severity).replace("{{packageName}}", data.module_name).replace("{{title}}", data.title).replace("{{affected}}", data.vulnerable_versions).replace("{{patched}}", data.patched_versions).replace("{{url}}", data.url);
420
482
  }).join("\n"));
421
483
  return _alextheman_utility.normaliseIndents`
@@ -446,6 +508,10 @@ function internalDependencyAudit(program) {
446
508
  ## Outdated Dependencies
447
509
 
448
510
  ${await getOutdatedDependencies(program)}
511
+
512
+ ## Licenses
513
+
514
+ ${await getLicenseCheck(program)}
449
515
  `;
450
516
  console.info(content);
451
517
  if (output) {
@@ -1356,7 +1422,7 @@ function template(program) {
1356
1422
  //#endregion
1357
1423
  //#region package.json
1358
1424
  var name = "alex-c-line";
1359
- var version$1 = "2.9.2";
1425
+ var version$1 = "2.10.0";
1360
1426
  var description = "Command-line tool with commands to streamline the developer workflow.";
1361
1427
  //#endregion
1362
1428
  //#region src/utility/updates/checkUpdate.ts
package/dist/index.js CHANGED
@@ -7,14 +7,14 @@ 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
+ import { ONE_DAY_IN_MILLISECONDS, VersionNumber, az, fillArray, getStringsAndInterpolations, interpolate, isTemplateStringsArray, kebabToCamel, normaliseIndents, omitProperties, parseBoolean, parseVersionType, removeDuplicates, removeUndefinedFromObject, sortBy, stringifyDotenv } from "@alextheman/utility";
11
11
  import { confirm, input, password, select } from "@inquirer/prompts";
12
12
  import { access, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
13
13
  import { parse } from "dotenv";
14
14
  import { ExecaError, execa } from "execa";
15
15
  import z from "zod";
16
- import { DependencyGroup, PackageManager, getDependenciesFromGroup, getExpectedTgzName, getPackageJsonContents, packageJsonNotFoundError } from "@alextheman/utility/internal";
17
16
  import { fileURLToPath, pathToFileURL } from "node:url";
17
+ import { DependencyGroup, PackageManager, getDependenciesFromGroup, getExpectedTgzName, getPackageJsonContents, packageJsonNotFoundError } from "@alextheman/utility/internal";
18
18
  import { parse as parse$1 } from "toml";
19
19
  import matter from "gray-matter";
20
20
  import { parseFilePath } from "@alextheman/utility/node";
@@ -253,12 +253,6 @@ function internalCheckLockfileVersionDiscrepancy(program) {
253
253
  });
254
254
  }
255
255
  //#endregion
256
- //#region src/configs/types/template/pullRequest/PullRequestTemplateCategory.ts
257
- const PullRequestTemplateCategory = {
258
- GENERAL: "general",
259
- INFRASTRUCTURE: "infrastructure"
260
- };
261
- //#endregion
262
256
  //#region src/utility/fileSystem/findPackageRoot.ts
263
257
  async function findPackageRoot(startDirectory, packageName) {
264
258
  let directory = startDirectory;
@@ -278,6 +272,74 @@ async function findPackageRoot(startDirectory, packageName) {
278
272
  const __filename$2 = fileURLToPath(import.meta.url);
279
273
  const ALEX_C_LINE_PACKAGE_ROOT = findPackageRoot(path.dirname(__filename$2), "alex-c-line");
280
274
  //#endregion
275
+ //#region src/cli/commands/internal/dependency-audit/helpers/getLicenseCheck.ts
276
+ const ALLOWED_LICENSES = [
277
+ "MIT",
278
+ "ISC",
279
+ "Apache-2.0",
280
+ "BSD-2-Clause",
281
+ "BSD-3-Clause"
282
+ ];
283
+ const pnpmLicensesSchema = z.record(z.string(), z.array(z.object({
284
+ name: z.string(),
285
+ versions: z.array(z.string())
286
+ })));
287
+ function parseLicenseCheck(input) {
288
+ return az.with(pnpmLicensesSchema).parse(input);
289
+ }
290
+ async function getLicenseCheck(program) {
291
+ const { exitCode, stdout, stderr } = await execa({ reject: false })`pnpm licenses ls --json`;
292
+ if (![0, 1].includes(exitCode)) program.error(stderr ?? stdout, {
293
+ exitCode,
294
+ code: "LICENSE_CHECK_ERROR"
295
+ });
296
+ const licenseCheck = parseLicenseCheck(JSON.parse(stdout.trim()));
297
+ if (Object.keys(licenseCheck).length === 0) return "No licenses found.";
298
+ const licenseCheckSummaryPath = path.join(await ALEX_C_LINE_PACKAGE_ROOT, "templates", "dependencyAudit", "licenseCheck", "summary");
299
+ const summaryTableTemplate = await readFile(path.join(licenseCheckSummaryPath, "table.html"), "utf-8");
300
+ const summaryTableRowTemplate = await readFile(path.join(licenseCheckSummaryPath, "tableRow.html"), "utf-8");
301
+ const summary = summaryTableTemplate.replace("{{tableRows}}", Object.entries(licenseCheck).map(([license, data]) => {
302
+ return summaryTableRowTemplate.replace("{{license}}", license).replace("{{count}}", data.length.toString());
303
+ }).join("\n"));
304
+ const invalidLicenses = Object.keys(licenseCheck).filter((license) => {
305
+ return !ALLOWED_LICENSES.includes(license);
306
+ });
307
+ let invalidSummary;
308
+ if (invalidLicenses.length === 0) invalidSummary = "No licenses requiring review.";
309
+ else {
310
+ const invalidLicensesInvalidPath = path.join(await ALEX_C_LINE_PACKAGE_ROOT, "templates", "dependencyAudit", "licenseCheck", "invalid");
311
+ const invalidLicensesTableTemplate = await readFile(path.join(invalidLicensesInvalidPath, "table.html"), "utf-8");
312
+ const invalidLicensesTableRowTemplate = await readFile(path.join(invalidLicensesInvalidPath, "tableRow.html"), "utf-8");
313
+ const invalidLicensesListTemplate = await readFile(path.join(invalidLicensesInvalidPath, "list.html"), "utf-8");
314
+ const invalidLicensesListItemTemplate = await readFile(path.join(invalidLicensesInvalidPath, "listItem.html"), "utf-8");
315
+ invalidSummary = invalidLicensesTableTemplate.replace("{{tableRows}}", Object.entries(licenseCheck).filter(([license]) => {
316
+ return !ALLOWED_LICENSES.includes(license);
317
+ }).map(([license, data]) => {
318
+ return invalidLicensesTableRowTemplate.replaceAll("{{license}}", license).replace("{{count}}", data.length.toString()).replace("{{dependencies}}", invalidLicensesListTemplate.replace("{{listItems}}", data.flatMap((item) => {
319
+ return item.versions.map((version) => {
320
+ return invalidLicensesListItemTemplate.replace("{{name}}", item.name).replace("{{version}}", version);
321
+ });
322
+ }).join("")));
323
+ }).join("\n"));
324
+ }
325
+ return normaliseIndents`
326
+
327
+ ### Summary
328
+
329
+ ${summary}
330
+
331
+ ### Requires Review
332
+
333
+ ${invalidSummary}
334
+ `;
335
+ }
336
+ //#endregion
337
+ //#region src/configs/types/template/pullRequest/PullRequestTemplateCategory.ts
338
+ const PullRequestTemplateCategory = {
339
+ GENERAL: "general",
340
+ INFRASTRUCTURE: "infrastructure"
341
+ };
342
+ //#endregion
281
343
  //#region src/cli/commands/internal/dependency-audit/helpers/getOutdatedDependencies.ts
282
344
  const pnpmOutdatedSchema = z.record(z.string(), z.object({
283
345
  current: az.versionNumber(),
@@ -382,9 +444,9 @@ async function getSecurityAudit(program) {
382
444
  low: 2,
383
445
  info: 1
384
446
  };
385
- const auditTable = tableTemplate.replace("{{tableRows}}", Object.entries(securityAudit.advisories).toSorted(([_, first], [__, second]) => {
386
- return severityOrder[second.severity] - severityOrder[first.severity];
387
- }).map(([id, data]) => {
447
+ const auditTable = tableTemplate.replace("{{tableRows}}", Object.entries(securityAudit.advisories).toSorted(sortBy(([_, advisory]) => {
448
+ return severityOrder[advisory.severity];
449
+ }, "desc")).map(([id, data]) => {
388
450
  return tableRowTemplate.replace("{{advisoryId}}", id).replace("{{severity}}", data.severity).replace("{{packageName}}", data.module_name).replace("{{title}}", data.title).replace("{{affected}}", data.vulnerable_versions).replace("{{patched}}", data.patched_versions).replace("{{url}}", data.url);
389
451
  }).join("\n"));
390
452
  return normaliseIndents`
@@ -415,6 +477,10 @@ function internalDependencyAudit(program) {
415
477
  ## Outdated Dependencies
416
478
 
417
479
  ${await getOutdatedDependencies(program)}
480
+
481
+ ## Licenses
482
+
483
+ ${await getLicenseCheck(program)}
418
484
  `;
419
485
  console.info(content);
420
486
  if (output) {
@@ -1325,7 +1391,7 @@ function template(program) {
1325
1391
  //#endregion
1326
1392
  //#region package.json
1327
1393
  var name = "alex-c-line";
1328
- var version$1 = "2.9.2";
1394
+ var version$1 = "2.10.0";
1329
1395
  var description = "Command-line tool with commands to streamline the developer workflow.";
1330
1396
  //#endregion
1331
1397
  //#region src/utility/updates/checkUpdate.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alex-c-line",
3
- "version": "2.9.2",
3
+ "version": "2.10.0",
4
4
  "description": "Command-line tool with commands to streamline the developer workflow.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  "templates"
35
35
  ],
36
36
  "dependencies": {
37
- "@alextheman/utility": "5.19.2",
37
+ "@alextheman/utility": "5.21.0",
38
38
  "@inquirer/prompts": "8.5.2",
39
39
  "axios": "1.17.0",
40
40
  "boxen": "8.0.1",
@@ -46,7 +46,7 @@
46
46
  "execa": "9.6.1",
47
47
  "figlet": "1.11.0",
48
48
  "gray-matter": "4.0.3",
49
- "semver": "7.8.2",
49
+ "semver": "7.8.4",
50
50
  "supports-color": "10.2.2",
51
51
  "toml": "4.1.1",
52
52
  "zod": "4.4.3"
@@ -55,7 +55,7 @@
55
55
  "@alextheman/eslint-plugin": "5.17.0",
56
56
  "@commander-js/extra-typings": "15.0.0",
57
57
  "@types/eslint": "9.6.1",
58
- "@types/node": "25.9.1",
58
+ "@types/node": "25.9.3",
59
59
  "@types/semver": "7.7.1",
60
60
  "@types/update-notifier": "6.0.8",
61
61
  "cross-env": "10.1.0",
@@ -63,12 +63,12 @@
63
63
  "eslint": "10.4.1",
64
64
  "husky": "9.1.7",
65
65
  "markdownlint-cli2": "0.22.1",
66
- "prettier": "3.8.3",
66
+ "prettier": "3.8.4",
67
67
  "tempy": "3.2.0",
68
68
  "ts-node": "10.9.2",
69
69
  "tsdown": "0.22.2",
70
70
  "typescript": "6.0.3",
71
- "typescript-eslint": "8.60.1",
71
+ "typescript-eslint": "8.61.0",
72
72
  "vite": "8.0.16",
73
73
  "vitest": "4.1.8"
74
74
  },
@@ -0,0 +1,3 @@
1
+ <ul>
2
+ {{listItems}}
3
+ </ul>
@@ -0,0 +1 @@
1
+ <li>{{name}}@{{version}}</li>
@@ -0,0 +1,12 @@
1
+ <table>
2
+ <thead>
3
+ <tr>
4
+ <th scope="col">License</th>
5
+ <th scope="col">Count</th>
6
+ <th scope="col">Dependencies</th>
7
+ </tr>
8
+ </thead>
9
+ <tbody>
10
+ {{tableRows}}
11
+ </tbody>
12
+ </table>
@@ -0,0 +1,10 @@
1
+ <tr>
2
+ <td>{{license}}</td>
3
+ <td>{{count}}</td>
4
+ <td>
5
+ <details>
6
+ <summary>View all dependencies with {{license}} license</summary>
7
+ {{dependencies}}
8
+ </details>
9
+ </td>
10
+ </tr>
@@ -0,0 +1,11 @@
1
+ <table>
2
+ <thead>
3
+ <tr>
4
+ <th scope="col">License</th>
5
+ <th scope="col">Count</th>
6
+ </tr>
7
+ </thead>
8
+ <tbody>
9
+ {{tableRows}}
10
+ </tbody>
11
+ </table>
@@ -0,0 +1,4 @@
1
+ <tr>
2
+ <td>{{license}}</td>
3
+ <td>{{count}}</td>
4
+ </tr>
@@ -0,0 +1,41 @@
1
+ ---
2
+ id: incident
3
+ placeholders:
4
+ - date
5
+ - severity
6
+ - incidentType
7
+ - projectName
8
+ - reason
9
+ ---
10
+ # Incident on {{date}}
11
+
12
+ **Severity**: {{severity}}
13
+ **Incident Type**: {{incidentType}}
14
+
15
+ This document details a serious incident related to `{{projectName}}` which affected regular usage. Please read below for a description of what went wrong and the steps being taken to resolve it.
16
+
17
+ ## Description of Incident
18
+
19
+ ### Incident Summary
20
+
21
+ A high-level overview of what went wrong.
22
+
23
+ ### Cause(s) of Incident
24
+
25
+ What were the primary contributing factor(s) towards why this incident occurred?
26
+
27
+ ### Consequences of Incident
28
+
29
+ What ended up being affected as a result of this incident occurring?
30
+
31
+ ## Timeline
32
+
33
+ A rough timeline on how the incident played out, from the introduction of the issue to the resolution.
34
+
35
+ ##  Action Plan
36
+
37
+ What steps have we been taking/are planning to take to minimise the chances of this happening again?
38
+
39
+ ## Additional Notes
40
+
41
+ Additional notes here.