@leemour/cli-core 0.7.0 → 0.9.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.
Files changed (47) hide show
  1. package/README.md +73 -11
  2. package/dist/codegen/index.d.ts +12 -0
  3. package/dist/codegen/index.d.ts.map +1 -0
  4. package/dist/codegen/index.js +11 -0
  5. package/dist/codegen/index.js.map +1 -0
  6. package/dist/codegen/manifest.d.ts +41 -0
  7. package/dist/codegen/manifest.d.ts.map +1 -0
  8. package/dist/codegen/manifest.js +59 -0
  9. package/dist/codegen/manifest.js.map +1 -0
  10. package/dist/codegen/model.d.ts +139 -0
  11. package/dist/codegen/model.d.ts.map +1 -0
  12. package/dist/codegen/model.js +7 -0
  13. package/dist/codegen/model.js.map +1 -0
  14. package/dist/codegen/names.d.ts +4 -0
  15. package/dist/codegen/names.d.ts.map +1 -0
  16. package/dist/codegen/names.js +46 -0
  17. package/dist/codegen/names.js.map +1 -0
  18. package/dist/codegen/pipeline.d.ts +24 -0
  19. package/dist/codegen/pipeline.d.ts.map +1 -0
  20. package/dist/codegen/pipeline.js +134 -0
  21. package/dist/codegen/pipeline.js.map +1 -0
  22. package/dist/codegen/runtime.d.ts +24 -0
  23. package/dist/codegen/runtime.d.ts.map +1 -0
  24. package/dist/codegen/runtime.js +38 -0
  25. package/dist/codegen/runtime.js.map +1 -0
  26. package/dist/codegen/tree.d.ts +29 -0
  27. package/dist/codegen/tree.d.ts.map +1 -0
  28. package/dist/codegen/tree.js +87 -0
  29. package/dist/codegen/tree.js.map +1 -0
  30. package/dist/codegen/typescript.d.ts +6 -0
  31. package/dist/codegen/typescript.d.ts.map +1 -0
  32. package/dist/codegen/typescript.js +76 -0
  33. package/dist/codegen/typescript.js.map +1 -0
  34. package/dist/codegen/valibot.d.ts +10 -0
  35. package/dist/codegen/valibot.d.ts.map +1 -0
  36. package/dist/codegen/valibot.js +121 -0
  37. package/dist/codegen/valibot.js.map +1 -0
  38. package/dist/logger.d.ts +1 -1
  39. package/dist/release/index.d.ts +37 -0
  40. package/dist/release/index.d.ts.map +1 -0
  41. package/dist/release/index.js +90 -0
  42. package/dist/release/index.js.map +1 -0
  43. package/dist/release/markdown.d.ts +35 -0
  44. package/dist/release/markdown.d.ts.map +1 -0
  45. package/dist/release/markdown.js +150 -0
  46. package/dist/release/markdown.js.map +1 -0
  47. package/package.json +32 -13
@@ -0,0 +1,37 @@
1
+ export { type ChangelogRules, changelogProblems, type DocsRules, docsProblems, idPattern, JOURNAL_IDS, markdownFiles, slug, } from "./markdown.js";
2
+ export type Check = {
3
+ name: string;
4
+ run: () => string[];
5
+ };
6
+ /**
7
+ * Runs every check even after one fails, so one pass shows the whole list, and returns how many
8
+ * failed. The caller exits: a library that calls `process.exit` cannot be tested.
9
+ */
10
+ export declare const releaseCheck: (checks: readonly Check[], { version, log }: {
11
+ version: string;
12
+ log: (line: string) => void;
13
+ }) => number;
14
+ export declare const run: (root: string, command: string, args: readonly string[]) => {
15
+ ok: boolean;
16
+ output: string;
17
+ };
18
+ /** A check that passes when the command exits 0, and otherwise shows the last 15 lines it printed. */
19
+ export declare const command: (root: string, name: string, ...args: string[]) => () => string[];
20
+ export declare const packageVersion: (root: string) => string;
21
+ export declare const notOnNpm: (root: string, packageName: string, version: string) => () => string[];
22
+ /**
23
+ * `allowed` holds exact paths, and directories ending in `/`; `said` is how the problem names them.
24
+ */
25
+ export declare const packProblems: (paths: readonly string[], allowed: readonly string[], said: string) => string[];
26
+ export declare const packContents: (root: string, allowed: readonly string[], said: string) => () => string[];
27
+ /**
28
+ * The whole of a `version:check` / `version:sync` script: what to print, and the exit code — 2 when
29
+ * either file cannot be read, 1 on drift. A CLI keeps its version in `package.json` and in a source
30
+ * file read at run time — `--version` must not load `package.json`, which is not there once the
31
+ * command is bundled — and the day they disagree is a release day.
32
+ */
33
+ export declare const versionScript: (root: string, argv: readonly string[], file?: string) => {
34
+ code: 0 | 1 | 2;
35
+ message: string;
36
+ };
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,cAAc,EACnB,iBAAiB,EACjB,KAAK,SAAS,EACd,YAAY,EACZ,SAAS,EACT,WAAW,EACX,aAAa,EACb,IAAI,GACL,MAAM,eAAe,CAAA;AAEtB,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,MAAM,EAAE,CAAA;CAAE,CAAA;AAEzD;;;GAGG;AACH,eAAO,MAAM,YAAY,WACf,SAAS,KAAK,EAAE,oBACN;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,WAWnE,CAAA;AAED,eAAO,MAAM,GAAG,SAAU,MAAM,WAAW,MAAM,QAAQ,SAAS,MAAM,EAAE;;;CAIzE,CAAA;AAED,sGAAsG;AACtG,eAAO,MAAM,OAAO,SACX,MAAM,QAAQ,MAAM,WAAW,MAAM,EAAE,WAC1C,MAAM,EAGT,CAAA;AAEH,eAAO,MAAM,cAAc,SAAU,MAAM,WACoD,CAAA;AAE/F,eAAO,MAAM,QAAQ,SAAU,MAAM,eAAe,MAAM,WAAW,MAAM,WAAS,MAAM,EAGlF,CAAA;AAER;;GAEG;AACH,eAAO,MAAM,YAAY,UAAW,SAAS,MAAM,EAAE,WAAW,SAAS,MAAM,EAAE,QAAQ,MAAM,aAG1B,CAAA;AAErE,eAAO,MAAM,YAAY,SAAU,MAAM,WAAW,SAAS,MAAM,EAAE,QAAQ,MAAM,WAAS,MAAM,EASjG,CAAA;AAcD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAClB,MAAM,QACN,SAAS,MAAM,EAAE,oBAEtB;IAAE,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAiBpC,CAAA"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Everything about a release that a program can decide. Each check returns the problems it found,
3
+ * one line each, saying what and where; an empty list is a pass. The judgement half — changelog
4
+ * wording, docs against the diff, live checks — is each CLI's release skill.
5
+ */
6
+ import { spawnSync } from "node:child_process";
7
+ import { readFileSync, writeFileSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ export { changelogProblems, docsProblems, idPattern, JOURNAL_IDS, markdownFiles, slug, } from "./markdown.js";
10
+ /**
11
+ * Runs every check even after one fails, so one pass shows the whole list, and returns how many
12
+ * failed. The caller exits: a library that calls `process.exit` cannot be tested.
13
+ */
14
+ export const releaseCheck = (checks, { version, log }) => {
15
+ let failed = 0;
16
+ for (const { name, run } of checks) {
17
+ const problems = run();
18
+ log(`${problems.length === 0 ? "ok " : "FAIL"} ${name}`);
19
+ for (const problem of problems)
20
+ log(problem.replace(/^/gm, " "));
21
+ if (problems.length > 0)
22
+ failed++;
23
+ }
24
+ log(failed === 0 ? `\n${version}: every check passed` : `\n${version}: ${failed} check(s) failed`);
25
+ return failed;
26
+ };
27
+ export const run = (root, command, args) => {
28
+ const done = spawnSync(command, args, { cwd: root, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
29
+ const output = `${done.stdout ?? ""}${done.stderr ?? ""}${done.error ? String(done.error) : ""}`;
30
+ return { ok: done.status === 0, output };
31
+ };
32
+ /** A check that passes when the command exits 0, and otherwise shows the last 15 lines it printed. */
33
+ export const command = (root, name, ...args) => () => {
34
+ const { ok, output } = run(root, name, args);
35
+ return ok ? [] : [output.trim().split("\n").slice(-15).join("\n") || `exit ${name} ${args.join(" ")}`];
36
+ };
37
+ export const packageVersion = (root) => JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version;
38
+ export const notOnNpm = (root, packageName, version) => () => run(root, "npm", ["view", `${packageName}@${version}`, "version", "--prefer-online"]).ok
39
+ ? [`${version} is already on npm — raise the version`]
40
+ : [];
41
+ /**
42
+ * `allowed` holds exact paths, and directories ending in `/`; `said` is how the problem names them.
43
+ */
44
+ export const packProblems = (paths, allowed, said) => paths
45
+ .filter((path) => !allowed.some((entry) => (entry.endsWith("/") ? path.startsWith(entry) : path === entry)))
46
+ .map((path) => `npm pack: ${path} would ship — only ${said} may`);
47
+ export const packContents = (root, allowed, said) => () => {
48
+ const { ok, output } = run(root, "npm", ["pack", "--dry-run", "--json", "--ignore-scripts"]);
49
+ if (!ok)
50
+ return [output.trim()];
51
+ const [packed] = JSON.parse(output.slice(output.indexOf("[")));
52
+ return packProblems((packed?.files ?? []).map(({ path }) => path), allowed, said);
53
+ };
54
+ const VERSION = /export const VERSION = "([^"]*)"/;
55
+ const versionsOf = (root, file) => {
56
+ const declared = packageVersion(root);
57
+ if (typeof declared !== "string" || !/^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/.test(declared))
58
+ return `package.json has no usable "version" (got ${JSON.stringify(declared)})`;
59
+ const source = readFileSync(join(root, file), "utf8");
60
+ const current = VERSION.exec(source)?.[1];
61
+ if (!current)
62
+ return `${file} does not export a VERSION string`;
63
+ return { declared, current, source };
64
+ };
65
+ /**
66
+ * The whole of a `version:check` / `version:sync` script: what to print, and the exit code — 2 when
67
+ * either file cannot be read, 1 on drift. A CLI keeps its version in `package.json` and in a source
68
+ * file read at run time — `--version` must not load `package.json`, which is not there once the
69
+ * command is bundled — and the day they disagree is a release day.
70
+ */
71
+ export const versionScript = (root, argv, file = "src/version.ts") => {
72
+ const found = versionsOf(root, file);
73
+ if (typeof found === "string")
74
+ return { code: 2, message: found };
75
+ const { declared, current, source } = found;
76
+ if (argv.includes("--sync")) {
77
+ if (current === declared)
78
+ return { code: 0, message: `version ${declared} — already in step` };
79
+ writeFileSync(join(root, file), source.replace(`"${current}"`, `"${declared}"`));
80
+ return { code: 0, message: `${file}: ${current} → ${declared}` };
81
+ }
82
+ if (current !== declared)
83
+ return {
84
+ code: 1,
85
+ message: `version drift: package.json says ${declared}, ${file} says ${current}.\n` +
86
+ "Run `pnpm version:sync` — package.json is the one that is edited.",
87
+ };
88
+ return { code: 0, message: `version ${declared} — package.json and ${file} agree` };
89
+ };
90
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /** The prefixes of the owner's journal ids; a project adds its own (`CLI`, `MAX`, …). */
2
+ export declare const JOURNAL_IDS: readonly ["NEED", "FIND", "BUG", "SEC", "PERF", "UX", "IDEA", "RISK", "DEBT", "ASK", "TASK"];
3
+ export declare const idPattern: (prefixes: readonly string[]) => RegExp;
4
+ export type ChangelogRules = {
5
+ /** The only `###` headings a section may have. */
6
+ headings: readonly string[];
7
+ /** The top section's title until it is dated, `Unreleased` or `Не выпущено`. */
8
+ unreleased: string;
9
+ ids: readonly string[];
10
+ };
11
+ /**
12
+ * `release`: the top section must be `version`, and nothing may be left unreleased — a release
13
+ * workflow builds its notes by matching `## <version> `, so a heading slightly off publishes empty
14
+ * notes without an error.
15
+ */
16
+ export declare const changelogProblems: (text: string, { version, release, headings, unreleased, ids }: ChangelogRules & {
17
+ version?: string;
18
+ release: boolean;
19
+ }) => string[];
20
+ /** GitHub's heading anchor: lower case, only letters, digits, `-`, `_` and spaces kept, spaces to `-`. */
21
+ export declare const slug: (heading: string) => string;
22
+ /** Every `.md` under `directory`, not descending into a directory named in `skip`. */
23
+ export declare const markdownFiles: (directory: string, skip?: ReadonlySet<string>) => string[];
24
+ export type DocsRules = {
25
+ /** Absolute paths; a missing one is passed over. */
26
+ files: readonly string[];
27
+ ids: readonly string[];
28
+ /** A page a user reads, by its path relative to `root`: no correction mark, struck-out text or id. */
29
+ userPage?: (name: string) => boolean;
30
+ correction?: RegExp;
31
+ /** A link not to follow — a private or sibling checkout that CI does not have. */
32
+ skipLink?: (target: string, destination: string) => boolean;
33
+ };
34
+ export declare const docsProblems: (root: string, { files, ids, userPage, correction, skipLink }: DocsRules) => string[];
35
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/release/markdown.ts"],"names":[],"mappings":"AAGA,yFAAyF;AACzF,eAAO,MAAM,WAAW,YAAI,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAU,CAAA;AAEvH,eAAO,MAAM,SAAS,aAAc,SAAS,MAAM,EAAE,WAA4D,CAAA;AAIjH,MAAM,MAAM,cAAc,GAAG;IAC3B,kDAAkD;IAClD,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;CACvB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,SACtB,MAAM,mDACqC,cAAc,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,aAyCzG,CAAA;AAED,0GAA0G;AAC1G,eAAO,MAAM,IAAI,YAAa,MAAM,WAMb,CAAA;AA2BvB,sFAAsF;AACtF,eAAO,MAAM,aAAa,cAAe,MAAM,SAAQ,WAAW,CAAC,MAAM,CAAC,KAAe,MAAM,EAQvF,CAAA;AAER,MAAM,MAAM,SAAS,GAAG;IACtB,oDAAoD;IACpD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;IACtB,sGAAsG;IACtG,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;CAC5D,CAAA;AAED,eAAO,MAAM,YAAY,SACjB,MAAM,kDACsF,SAAS,aA8C5G,CAAA"}
@@ -0,0 +1,150 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
2
+ import { dirname, join, relative, resolve } from "node:path";
3
+ /** The prefixes of the owner's journal ids; a project adds its own (`CLI`, `MAX`, …). */
4
+ export const JOURNAL_IDS = ["NEED", "FIND", "BUG", "SEC", "PERF", "UX", "IDEA", "RISK", "DEBT", "ASK", "TASK"];
5
+ export const idPattern = (prefixes) => new RegExp(`\\b(?:${prefixes.join("|")})-\\d+\\b`, "g");
6
+ const VERSION_HEADING = /^## (\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?) — (\d{2})\.(\d{2})\.(\d{4})$/;
7
+ /**
8
+ * `release`: the top section must be `version`, and nothing may be left unreleased — a release
9
+ * workflow builds its notes by matching `## <version> `, so a heading slightly off publishes empty
10
+ * notes without an error.
11
+ */
12
+ export const changelogProblems = (text, { version, release, headings, unreleased, ids }) => {
13
+ const problems = [];
14
+ const id = idPattern(ids);
15
+ let section;
16
+ let subheadings = new Set();
17
+ let first = true;
18
+ text.split("\n").forEach((line, index) => {
19
+ const where = `CHANGELOG.md:${index + 1}`;
20
+ if (line.startsWith("## ")) {
21
+ section = line.slice(3);
22
+ subheadings = new Set();
23
+ if (section === unreleased) {
24
+ if (release)
25
+ problems.push(`${where}: "${unreleased}" is left — date it as ${version} before releasing`);
26
+ else if (!first)
27
+ problems.push(`${where}: "${unreleased}" must be the top section`);
28
+ }
29
+ else {
30
+ const found = VERSION_HEADING.exec(line);
31
+ if (!found)
32
+ problems.push(`${where}: "${line}" is not "## <version> — DD.MM.YYYY"`);
33
+ else {
34
+ const [, heading, day, month] = found;
35
+ if (Number(day) < 1 || Number(day) > 31 || Number(month) < 1 || Number(month) > 12)
36
+ problems.push(`${where}: "${line}" has no such date`);
37
+ if (release && first && heading !== version)
38
+ problems.push(`${where}: the top section is ${heading}, package.json says ${version}`);
39
+ }
40
+ }
41
+ first = false;
42
+ return;
43
+ }
44
+ if (line.startsWith("### ")) {
45
+ const heading = line.slice(4);
46
+ if (!headings.includes(heading))
47
+ problems.push(`${where}: "${heading}" is not one of: ${headings.join(", ")}`);
48
+ if (subheadings.has(heading))
49
+ problems.push(`${where}: "${heading}" twice in "${section}"`);
50
+ subheadings.add(heading);
51
+ }
52
+ for (const found of line.match(id) ?? [])
53
+ problems.push(`${where}: internal id ${found} — say what changed instead`);
54
+ });
55
+ if (release && first)
56
+ problems.push(`CHANGELOG.md: no section for ${version}`);
57
+ return problems;
58
+ };
59
+ /** GitHub's heading anchor: lower case, only letters, digits, `-`, `_` and spaces kept, spaces to `-`. */
60
+ export const slug = (heading) => heading
61
+ .replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1")
62
+ .replace(/<[^>]+>/g, "")
63
+ .toLowerCase()
64
+ .replace(/[^\p{L}\p{M}\p{N}\-_ ]/gu, "")
65
+ .replace(/ /g, "-");
66
+ const withoutCode = (text) => text
67
+ .replace(/^(```|~~~)[^\n]*\n[\s\S]*?^\1[^\n]*$/gm, (block) => block.replace(/[^\n]/g, " "))
68
+ .replace(/`[^`\n]*`/g, (span) => " ".repeat(span.length));
69
+ // Headings are read from the raw text, so code inside a heading still counts toward its anchor.
70
+ const anchorsOf = (text) => {
71
+ const raw = text.split("\n");
72
+ const anchors = new Set();
73
+ const counts = new Map();
74
+ withoutCode(text)
75
+ .split("\n")
76
+ .forEach((masked, index) => {
77
+ if (!/^#{1,6} /.test(masked))
78
+ return;
79
+ const heading = /^#{1,6} (.+?)\s*#*\s*$/.exec(raw[index] ?? "")?.[1];
80
+ if (heading === undefined)
81
+ return;
82
+ const base = slug(heading);
83
+ const seen = counts.get(base) ?? 0;
84
+ counts.set(base, seen + 1);
85
+ anchors.add(seen === 0 ? base : `${base}-${seen}`);
86
+ });
87
+ for (const [, name = ""] of text.matchAll(/<a\s+(?:name|id)="([^"]+)"/g))
88
+ anchors.add(name);
89
+ return anchors;
90
+ };
91
+ /** Every `.md` under `directory`, not descending into a directory named in `skip`. */
92
+ export const markdownFiles = (directory, skip = new Set()) => existsSync(directory)
93
+ ? readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
94
+ if (skip.has(entry.name))
95
+ return [];
96
+ const path = join(directory, entry.name);
97
+ if (entry.isDirectory())
98
+ return markdownFiles(path, skip);
99
+ return entry.name.endsWith(".md") ? [path] : [];
100
+ })
101
+ : [];
102
+ export const docsProblems = (root, { files, ids, userPage = () => false, correction = /correction \d{4}/i, skipLink = () => false }) => {
103
+ const id = idPattern(ids);
104
+ const cache = new Map();
105
+ const anchors = (path) => {
106
+ let found = cache.get(path);
107
+ if (!found) {
108
+ found = anchorsOf(readFileSync(path, "utf8"));
109
+ cache.set(path, found);
110
+ }
111
+ return found;
112
+ };
113
+ const problems = [];
114
+ for (const path of files.filter((file) => existsSync(file))) {
115
+ const name = relative(root, path);
116
+ const user = userPage(name);
117
+ withoutCode(readFileSync(path, "utf8"))
118
+ .split("\n")
119
+ .forEach((line, index) => {
120
+ const where = `${name}:${index + 1}`;
121
+ for (const [, target] of line.matchAll(/!?\[[^\]]*\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g)) {
122
+ if (!target || /^[a-z][a-z0-9+.-]*:/i.test(target))
123
+ continue;
124
+ const [file = "", anchor] = decodeURIComponent(target).split("#");
125
+ const destination = file === "" ? path : resolve(dirname(path), file);
126
+ if (skipLink(file, destination))
127
+ continue;
128
+ if (!existsSync(destination)) {
129
+ problems.push(`${where}: link to ${file} — no such file`);
130
+ continue;
131
+ }
132
+ if (anchor &&
133
+ destination.endsWith(".md") &&
134
+ statSync(destination).isFile() &&
135
+ !anchors(destination).has(anchor))
136
+ problems.push(`${where}: link to ${file}#${anchor} — no such heading`);
137
+ }
138
+ if (!user)
139
+ return;
140
+ if (correction.test(line))
141
+ problems.push(`${where}: a correction mark on a user page`);
142
+ if (line.includes("~~"))
143
+ problems.push(`${where}: struck-out text on a user page`);
144
+ for (const found of line.match(id) ?? [])
145
+ problems.push(`${where}: internal id ${found} on a user page`);
146
+ });
147
+ }
148
+ return problems;
149
+ };
150
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/release/markdown.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leemour/cli-core",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
5
5
  "license": "MIT",
6
6
  "author": "Viacheslav Ptsarev",
@@ -12,6 +12,7 @@
12
12
  "engines": {
13
13
  "node": ">=22"
14
14
  },
15
+ "packageManager": "pnpm@11.20.0",
15
16
  "files": [
16
17
  "dist",
17
18
  "README.md",
@@ -41,8 +42,35 @@
41
42
  "./update": {
42
43
  "types": "./dist/update/index.d.ts",
43
44
  "default": "./dist/update/index.js"
45
+ },
46
+ "./codegen": {
47
+ "types": "./dist/codegen/index.d.ts",
48
+ "default": "./dist/codegen/index.js"
49
+ },
50
+ "./codegen/runtime": {
51
+ "types": "./dist/codegen/runtime.d.ts",
52
+ "default": "./dist/codegen/runtime.js"
53
+ },
54
+ "./release": {
55
+ "types": "./dist/release/index.d.ts",
56
+ "default": "./dist/release/index.js"
44
57
  }
45
58
  },
59
+ "scripts": {
60
+ "build": "tsc --build",
61
+ "typecheck": "tsc --build --force --emitDeclarationOnly && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json",
62
+ "lint": "biome check .",
63
+ "lint:fix": "biome check --write .",
64
+ "docs:check": "pnpm build && node --experimental-strip-types scripts/docs-check.ts",
65
+ "test": "vitest run",
66
+ "test:watch": "vitest",
67
+ "test:coverage": "vitest run --coverage",
68
+ "test:slow": "vitest run --reporter=json --outputFile=coverage/tests.json >/dev/null; node --experimental-strip-types scripts/slow-tests.ts",
69
+ "smoke:bun": "bun run scripts/smoke.ts",
70
+ "prepare": "lefthook install || true",
71
+ "secrets:scan": "gitleaks git --no-banner --redact .",
72
+ "prepublishOnly": "pnpm build"
73
+ },
46
74
  "dependencies": {
47
75
  "cli-table3": "^0.6.5",
48
76
  "env-paths": "^4.0.0",
@@ -56,10 +84,11 @@
56
84
  "devDependencies": {
57
85
  "@biomejs/biome": "^2.3.14",
58
86
  "@types/node": "^22.20.4",
87
+ "@vitest/coverage-v8": "^5.0.2",
59
88
  "commander": "^15.0.0",
60
89
  "lefthook": "^2.1.8",
61
90
  "typescript": "^7.0.2",
62
- "vitest": "^5.0.1"
91
+ "vitest": "^5.0.2"
63
92
  },
64
93
  "publishConfig": {
65
94
  "access": "public"
@@ -71,15 +100,5 @@
71
100
  "commander": {
72
101
  "optional": true
73
102
  }
74
- },
75
- "scripts": {
76
- "build": "tsc --build",
77
- "typecheck": "tsc --build --force --emitDeclarationOnly",
78
- "lint": "biome check .",
79
- "lint:fix": "biome check --write .",
80
- "test": "vitest run",
81
- "test:watch": "vitest",
82
- "smoke:bun": "bun run scripts/smoke.ts",
83
- "secrets:scan": "gitleaks git --no-banner --redact ."
84
103
  }
85
- }
104
+ }