@doki-land/nifty 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/locales/en-US/cli.json +24 -1
- package/package.json +16 -20
- package/src/cli/change-logs-cmd.ts +97 -0
- package/src/cli/cli.ts +6 -0
- package/src/cli/retime-cmd.ts +62 -0
- package/src/cli/reword-cmd.ts +87 -0
- package/src/cli/trust-cmd.ts +3 -0
- package/src/config/types.ts +14 -0
- package/src/native.ts +223 -0
- package/Readme.md +0 -30
package/locales/en-US/cli.json
CHANGED
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
"cli.cmd.bump": "Align workspace crate and package versions",
|
|
9
9
|
"cli.cmd.publish": "Publish workspace npm packages (OIDC or token + TOTP)",
|
|
10
10
|
"cli.cmd.trust": "Configure npm Trusted Publisher for workspace packages",
|
|
11
|
+
"cli.cmd.reword": "Rewrite commit messages at the git object layer",
|
|
12
|
+
"cli.cmd.reword.export": "Export a JSON reword map template",
|
|
13
|
+
"cli.cmd.reword.rewrite": "Rewrite commits from a JSON map and update the branch ref",
|
|
14
|
+
"cli.cmd.retime": "Spread commit timestamps across a date range on a new branch",
|
|
15
|
+
"cli.cmd.retime.root": "Retime all commits from repository root through tip",
|
|
16
|
+
"cli.cmd.change-logs": "Draft release reference changelogs from git tags",
|
|
17
|
+
"cli.cmd.change-logs.lookup": "Look up GitHub user id/login from email or login",
|
|
11
18
|
"cli.opt.cwd": "Working directory",
|
|
12
19
|
"cli.opt.interactive": "Prompt before applying dependency updates",
|
|
13
20
|
"cli.opt.from": "Start git ref for commit range",
|
|
@@ -37,5 +44,21 @@
|
|
|
37
44
|
"cli.opt.only": "Limit trust to one package name",
|
|
38
45
|
"cli.opt.otp": "One-time npm password (6 digits)",
|
|
39
46
|
"cli.opt.totp-secret": "Base32 TOTP secret (overrides env)",
|
|
40
|
-
"cli.opt.npm-token": "npm auth token (overrides NPM_TOKEN)"
|
|
47
|
+
"cli.opt.npm-token": "npm auth token (overrides NPM_TOKEN)",
|
|
48
|
+
"cli.opt.base": "Exclusive range start commit (e.g. 34e1e665^)",
|
|
49
|
+
"cli.opt.ref": "Branch ref to rewrite (default: HEAD)",
|
|
50
|
+
"cli.opt.path": "Path to reword JSON map (default: reword.pending.json)",
|
|
51
|
+
"cli.opt.start-date": "Random window start (YYYY-MM-DD or ISO datetime)",
|
|
52
|
+
"cli.opt.end-date": "Random window end",
|
|
53
|
+
"cli.opt.branch": "Output branch name (default: time-travel)",
|
|
54
|
+
"cli.opt.tip": "Range end revision (default: HEAD)",
|
|
55
|
+
"cli.opt.message": "Optional new message for the root commit (retime root)",
|
|
56
|
+
"cli.opt.write": "Write documentation/maintenance/releases/vX.Y.Z.reference.md",
|
|
57
|
+
"cli.opt.tags": "List version tags with short hashes",
|
|
58
|
+
"cli.opt.author-map": "Path to author-github.json",
|
|
59
|
+
"cli.opt.releases-dir": "Releases directory for --write",
|
|
60
|
+
"cli.opt.email": "Author email to resolve",
|
|
61
|
+
"cli.opt.login": "GitHub login to resolve",
|
|
62
|
+
"cli.opt.github-token": "GitHub token for search-by-email",
|
|
63
|
+
"cli.opt.fetch": "Fetch missing numeric id from GitHub API"
|
|
41
64
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
+
"name": "@doki-land/nifty",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Gitmoji-first commit conventions and release helpers (Node-API + TypeScript)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MPL-2.0",
|
|
2
7
|
"bin": {
|
|
3
8
|
"nifty": "cli/nifty.mjs"
|
|
4
9
|
},
|
|
5
|
-
"dependencies": {
|
|
6
|
-
"@vmz/commander": "^0.2.0",
|
|
7
|
-
"jiti": "^2.4.2"
|
|
8
|
-
},
|
|
9
|
-
"description": "Gitmoji-first commit conventions and release helpers (Node-API + TypeScript)",
|
|
10
|
-
"devDependencies": {
|
|
11
|
-
"@types/node": "^22.13.10",
|
|
12
|
-
"typescript": "^5.8.3"
|
|
13
|
-
},
|
|
14
10
|
"exports": {
|
|
15
11
|
".": "./src/index.ts",
|
|
16
12
|
"./cli": "./src/cli/index.ts"
|
|
@@ -20,12 +16,17 @@
|
|
|
20
16
|
"locales",
|
|
21
17
|
"src"
|
|
22
18
|
],
|
|
23
|
-
"
|
|
24
|
-
|
|
19
|
+
"scripts": {
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@vmz/commander": "^0.2.0",
|
|
24
|
+
"jiti": "^2.4.2"
|
|
25
|
+
},
|
|
25
26
|
"optionalDependencies": {
|
|
26
|
-
"@doki-land/nifty-
|
|
27
|
-
"@doki-land/nifty-linux-x64": "0.0.
|
|
28
|
-
"@doki-land/nifty-
|
|
27
|
+
"@doki-land/nifty-win32-x64": "0.0.2",
|
|
28
|
+
"@doki-land/nifty-linux-x64": "0.0.2",
|
|
29
|
+
"@doki-land/nifty-darwin-arm64": "0.0.2"
|
|
29
30
|
},
|
|
30
31
|
"publishConfig": {
|
|
31
32
|
"access": "public"
|
|
@@ -33,10 +34,5 @@
|
|
|
33
34
|
"repository": {
|
|
34
35
|
"type": "git",
|
|
35
36
|
"url": "git+https://github.com/oovm/npm-tools.git"
|
|
36
|
-
}
|
|
37
|
-
"scripts": {
|
|
38
|
-
"typecheck": "tsc --noEmit"
|
|
39
|
-
},
|
|
40
|
-
"type": "module",
|
|
41
|
-
"version": "0.0.1"
|
|
37
|
+
}
|
|
42
38
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
|
|
3
|
+
import type { Cli, ParsedOptions } from "@vmz/commander";
|
|
4
|
+
|
|
5
|
+
import { loadConfig } from "../config/loadConfig.js";
|
|
6
|
+
import { loadNiftyNative } from "../native.js";
|
|
7
|
+
import { bootstrapFromOptions } from "./context.js";
|
|
8
|
+
import { cwdFrom, flag, str } from "./options.js";
|
|
9
|
+
|
|
10
|
+
export function registerChangeLogsCommand(cli: Cli): void {
|
|
11
|
+
const changeLogs = cli.command("change-logs", "cli.cmd.change-logs")
|
|
12
|
+
.option("--version <version>", "cli.opt.version")
|
|
13
|
+
.option("--from <ref>", "cli.opt.from")
|
|
14
|
+
.option("--to <ref>", "cli.opt.to")
|
|
15
|
+
.option("--write", "cli.opt.write")
|
|
16
|
+
.option("--tags", "cli.opt.tags")
|
|
17
|
+
.option("--repo <owner/name>", "cli.opt.repo")
|
|
18
|
+
.option("--author-map <path>", "cli.opt.author-map")
|
|
19
|
+
.option("--releases-dir <path>", "cli.opt.releases-dir");
|
|
20
|
+
|
|
21
|
+
changeLogs
|
|
22
|
+
.command("lookup", "cli.cmd.change-logs.lookup")
|
|
23
|
+
.option("--email <email>", "cli.opt.email")
|
|
24
|
+
.option("--login <login>", "cli.opt.login")
|
|
25
|
+
.option("--map <path>", "cli.opt.author-map")
|
|
26
|
+
.option("--github-token <token>", "cli.opt.github-token")
|
|
27
|
+
.option("--fetch", "cli.opt.fetch")
|
|
28
|
+
.action(async (options) => cmdChangeLogsLookup(options));
|
|
29
|
+
|
|
30
|
+
changeLogs.action(async (options) => cmdChangeLogsRender(options));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function cmdChangeLogsRender(options: ParsedOptions): Promise<number> {
|
|
34
|
+
await bootstrapFromOptions(options);
|
|
35
|
+
const cwd = cwdFrom(options) ?? process.cwd();
|
|
36
|
+
const { config } = await loadConfig({ cwd, createIfMissing: false });
|
|
37
|
+
const native = loadNiftyNative();
|
|
38
|
+
const report = native.history["changelog-render"]({
|
|
39
|
+
cwd,
|
|
40
|
+
version: str(options, "version"),
|
|
41
|
+
fromRef: str(options, "from"),
|
|
42
|
+
toRef: str(options, "to"),
|
|
43
|
+
write: flag(options, "write"),
|
|
44
|
+
tags: flag(options, "tags"),
|
|
45
|
+
repo: str(options, "repo") ?? config.changelog?.repo,
|
|
46
|
+
authorMap: str(options, "author-map") ?? config.changelog?.authorMap,
|
|
47
|
+
releasesDir: str(options, "releases-dir") ?? config.changelog?.releasesDir,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (flag(options, "tags")) {
|
|
51
|
+
console.log(report.notes);
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (report.rangeLabel) {
|
|
56
|
+
console.error(`change-logs: ${report.rangeLabel} — ${report.commitCount} commit(s)`);
|
|
57
|
+
}
|
|
58
|
+
if (report.writtenPath) {
|
|
59
|
+
console.error(`change-logs: wrote ${report.writtenPath}`);
|
|
60
|
+
}
|
|
61
|
+
process.stdout.write(report.notes);
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function cmdChangeLogsLookup(options: ParsedOptions): Promise<number> {
|
|
66
|
+
await bootstrapFromOptions(options);
|
|
67
|
+
const cwd = cwdFrom(options) ?? process.cwd();
|
|
68
|
+
const { config } = await loadConfig({ cwd, createIfMissing: false });
|
|
69
|
+
const email = str(options, "email");
|
|
70
|
+
const login = str(options, "login");
|
|
71
|
+
if (!email && !login) {
|
|
72
|
+
throw new Error("lookup requires --email or --login");
|
|
73
|
+
}
|
|
74
|
+
const native = loadNiftyNative();
|
|
75
|
+
const author = native.history["changelog-lookup"]({
|
|
76
|
+
cwd,
|
|
77
|
+
email,
|
|
78
|
+
login,
|
|
79
|
+
map: str(options, "map") ?? config.changelog?.authorMap,
|
|
80
|
+
githubToken: str(options, "github-token") ?? config.githubToken ?? process.env.GITHUB_TOKEN,
|
|
81
|
+
fetch: flag(options, "fetch"),
|
|
82
|
+
});
|
|
83
|
+
const json: Record<string, unknown> = {};
|
|
84
|
+
if (author.id !== undefined) {
|
|
85
|
+
json.id = author.id;
|
|
86
|
+
}
|
|
87
|
+
if (author.login) {
|
|
88
|
+
json.login = author.login;
|
|
89
|
+
}
|
|
90
|
+
console.log(JSON.stringify(json, null, 2));
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Default author map path relative to repo root (matches git-change-logs). */
|
|
95
|
+
export function defaultAuthorMapPath(repoRoot: string): string {
|
|
96
|
+
return join(repoRoot, "documentation/maintenance/author-github.json");
|
|
97
|
+
}
|
package/src/cli/cli.ts
CHANGED
|
@@ -4,9 +4,12 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
import { createCli } from "@vmz/commander";
|
|
5
5
|
|
|
6
6
|
import { registerBumpCommand } from "./bump-cmd.js";
|
|
7
|
+
import { registerChangeLogsCommand } from "./change-logs-cmd.js";
|
|
7
8
|
import { registerInstallNativeCommand } from "./install-native-cmd.js";
|
|
8
9
|
import { registerLintCommands } from "./lint-cmd.js";
|
|
9
10
|
import { registerPublishCommand } from "./publish-cmd.js";
|
|
11
|
+
import { registerRetimeCommand } from "./retime-cmd.js";
|
|
12
|
+
import { registerRewordCommand } from "./reword-cmd.js";
|
|
10
13
|
import { registerTrustCommand } from "./trust-cmd.js";
|
|
11
14
|
import { registerUpdateCommand } from "./update-cmd.js";
|
|
12
15
|
import { registerUploadCommand } from "./upload-cmd.js";
|
|
@@ -25,6 +28,9 @@ function buildNiftyCli() {
|
|
|
25
28
|
registerBumpCommand(cli);
|
|
26
29
|
registerPublishCommand(cli);
|
|
27
30
|
registerTrustCommand(cli);
|
|
31
|
+
registerRewordCommand(cli);
|
|
32
|
+
registerRetimeCommand(cli);
|
|
33
|
+
registerChangeLogsCommand(cli);
|
|
28
34
|
|
|
29
35
|
return cli;
|
|
30
36
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Cli, ParsedOptions } from "@vmz/commander";
|
|
2
|
+
|
|
3
|
+
import { loadNiftyNative } from "../native.js";
|
|
4
|
+
import { bootstrapFromOptions } from "./context.js";
|
|
5
|
+
import { cwdFrom, str } from "./options.js";
|
|
6
|
+
|
|
7
|
+
export function registerRetimeCommand(cli: Cli): void {
|
|
8
|
+
const retime = cli.command("retime", "cli.cmd.retime")
|
|
9
|
+
.option("-s, --start-date <start>", "cli.opt.start-date")
|
|
10
|
+
.option("--end-date <end>", "cli.opt.end-date")
|
|
11
|
+
.option("-b, --branch <branch>", "cli.opt.branch")
|
|
12
|
+
.option("--tip <ref>", "cli.opt.tip");
|
|
13
|
+
|
|
14
|
+
retime
|
|
15
|
+
.command("root", "cli.cmd.retime.root")
|
|
16
|
+
.option("-s, --start-date <start>", "cli.opt.start-date")
|
|
17
|
+
.option("--end-date <end>", "cli.opt.end-date")
|
|
18
|
+
.option("-b, --branch <branch>", "cli.opt.branch")
|
|
19
|
+
.option("--tip <ref>", "cli.opt.tip")
|
|
20
|
+
.option("-m, --message <text>", "cli.opt.message")
|
|
21
|
+
.action(async (options) => cmdRetimeRoot(options));
|
|
22
|
+
|
|
23
|
+
retime.action(async (options) => cmdRetimeRange(options));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function cmdRetimeRange(options: ParsedOptions): Promise<number> {
|
|
27
|
+
await bootstrapFromOptions(options);
|
|
28
|
+
const commit = options._[0];
|
|
29
|
+
if (!commit) {
|
|
30
|
+
throw new Error("missing commit hash for range retime");
|
|
31
|
+
}
|
|
32
|
+
const native = loadNiftyNative();
|
|
33
|
+
const report = native.history["retime-range"]({
|
|
34
|
+
cwd: cwdFrom(options),
|
|
35
|
+
commit,
|
|
36
|
+
startDate: str(options, "start-date"),
|
|
37
|
+
endDate: str(options, "end-date"),
|
|
38
|
+
branch: str(options, "branch"),
|
|
39
|
+
tip: str(options, "tip"),
|
|
40
|
+
});
|
|
41
|
+
printRetimeSummary(report);
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function cmdRetimeRoot(options: ParsedOptions): Promise<number> {
|
|
46
|
+
await bootstrapFromOptions(options);
|
|
47
|
+
const native = loadNiftyNative();
|
|
48
|
+
const report = native.history["retime-root"]({
|
|
49
|
+
cwd: cwdFrom(options),
|
|
50
|
+
startDate: str(options, "start-date"),
|
|
51
|
+
endDate: str(options, "end-date"),
|
|
52
|
+
branch: str(options, "branch"),
|
|
53
|
+
tip: str(options, "tip"),
|
|
54
|
+
message: str(options, "message"),
|
|
55
|
+
});
|
|
56
|
+
printRetimeSummary(report);
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function printRetimeSummary(report: { rewritten: number; branch: string; newTip: string }): void {
|
|
61
|
+
console.log(`retimed ${report.rewritten} commit(s) on branch ${report.branch}; tip ${report.newTip}`);
|
|
62
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Cli, ParsedOptions } from "@vmz/commander";
|
|
2
|
+
|
|
3
|
+
import { loadNiftyNative } from "../native.js";
|
|
4
|
+
import { bootstrapFromOptions } from "./context.js";
|
|
5
|
+
import { cwdFrom, flag, str } from "./options.js";
|
|
6
|
+
|
|
7
|
+
export function registerRewordCommand(cli: Cli): void {
|
|
8
|
+
const reword = cli.command("reword", "cli.cmd.reword");
|
|
9
|
+
|
|
10
|
+
reword
|
|
11
|
+
.command("export", "cli.cmd.reword.export")
|
|
12
|
+
.option("--base <ref>", "cli.opt.base")
|
|
13
|
+
.option("--ref <ref>", "cli.opt.ref")
|
|
14
|
+
.option("--path <file>", "cli.opt.path")
|
|
15
|
+
.action(async (options) => cmdRewordExport(options));
|
|
16
|
+
|
|
17
|
+
reword
|
|
18
|
+
.command("rewrite", "cli.cmd.reword.rewrite")
|
|
19
|
+
.option("--base <ref>", "cli.opt.base")
|
|
20
|
+
.option("--ref <ref>", "cli.opt.ref")
|
|
21
|
+
.option("--path <file>", "cli.opt.path")
|
|
22
|
+
.option("--dry-run", "cli.opt.dry-run")
|
|
23
|
+
.action(async (options) => cmdRewordRewrite(options));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function cmdRewordExport(options: ParsedOptions): Promise<number> {
|
|
27
|
+
await bootstrapFromOptions(options);
|
|
28
|
+
const base = requireStr(options, "base");
|
|
29
|
+
const path = str(options, "path") ?? "reword.pending.json";
|
|
30
|
+
const native = loadNiftyNative();
|
|
31
|
+
const report = native.history["reword-export"]({
|
|
32
|
+
cwd: cwdFrom(options),
|
|
33
|
+
base,
|
|
34
|
+
ref: str(options, "ref"),
|
|
35
|
+
path,
|
|
36
|
+
});
|
|
37
|
+
console.log(`export: wrote ${report.count} commit entry(ies) to ${report.path}`);
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function cmdRewordRewrite(options: ParsedOptions): Promise<number> {
|
|
42
|
+
await bootstrapFromOptions(options);
|
|
43
|
+
const base = requireStr(options, "base");
|
|
44
|
+
const path = requireStr(options, "path");
|
|
45
|
+
const dryRun = flag(options, "dry-run");
|
|
46
|
+
const native = loadNiftyNative();
|
|
47
|
+
const report = native.history["reword-rewrite"]({
|
|
48
|
+
cwd: cwdFrom(options),
|
|
49
|
+
base,
|
|
50
|
+
ref: str(options, "ref"),
|
|
51
|
+
path,
|
|
52
|
+
dryRun,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (dryRun) {
|
|
56
|
+
if (report.changes.length === 0) {
|
|
57
|
+
console.log("dry-run: no commit objects need rewriting");
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
console.log(`dry-run: ${report.changes.length} commit object(s) would be rewritten on ${report.refName}\n`);
|
|
61
|
+
for (const change of report.changes) {
|
|
62
|
+
console.log(`${change.oldOid} ${change.oldSubject}`);
|
|
63
|
+
console.log(` -> ${change.newSubject}`);
|
|
64
|
+
if (change.parentsRelinked && !change.messageChanged) {
|
|
65
|
+
console.log(" (parent chain relink only)");
|
|
66
|
+
}
|
|
67
|
+
console.log();
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(
|
|
73
|
+
`rewrote ${report.changes.length} commit object(s); ${report.oldTip} -> ${report.newTip ?? report.oldTip}`,
|
|
74
|
+
);
|
|
75
|
+
for (const change of report.changes) {
|
|
76
|
+
console.log(` ${change.oldOid} ${change.newSubject}`);
|
|
77
|
+
}
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function requireStr(options: ParsedOptions, key: string): string {
|
|
82
|
+
const value = str(options, key);
|
|
83
|
+
if (!value) {
|
|
84
|
+
throw new Error(`missing required --${key}`);
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
package/src/cli/trust-cmd.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Cli, ParsedOptions } from "@vmz/commander";
|
|
|
2
2
|
|
|
3
3
|
import { loadNiftyNative } from "../native.js";
|
|
4
4
|
import { authPayload } from "./authArgs.js";
|
|
5
|
+
import { loadConfig } from "../config/loadConfig.js";
|
|
5
6
|
import { bootstrapFromOptions } from "./context.js";
|
|
6
7
|
import { printTrustReport } from "./trust.js";
|
|
7
8
|
import { authFromOptions, cwdFrom, flag, str } from "./options.js";
|
|
@@ -19,12 +20,14 @@ export function registerTrustCommand(cli: Cli): void {
|
|
|
19
20
|
|
|
20
21
|
export async function cmdTrust(options: ParsedOptions): Promise<number> {
|
|
21
22
|
await bootstrapFromOptions(options);
|
|
23
|
+
const { config } = await loadConfig({ cwd: cwdFrom(options), createIfMissing: false });
|
|
22
24
|
const native = loadNiftyNative();
|
|
23
25
|
const report = native.publisher["trust-workspace"]({
|
|
24
26
|
cwd: cwdFrom(options),
|
|
25
27
|
dryRun: flag(options, "dry-run"),
|
|
26
28
|
refresh: flag(options, "refresh"),
|
|
27
29
|
only: str(options, "only"),
|
|
30
|
+
packages: config.publish?.packages,
|
|
28
31
|
...authPayload(authFromOptions(options)),
|
|
29
32
|
});
|
|
30
33
|
printTrustReport(report);
|
package/src/config/types.ts
CHANGED
|
@@ -16,6 +16,20 @@ export type NiftyConfig = {
|
|
|
16
16
|
cargoRoot?: string;
|
|
17
17
|
/** npm package root override. */
|
|
18
18
|
npmRoot?: string;
|
|
19
|
+
/** npm publish / Trusted Publisher (CI uses publish-npm.yml). */
|
|
20
|
+
publish?: {
|
|
21
|
+
/** Package names to trust (includes registry-only native sidecars). */
|
|
22
|
+
packages?: string[];
|
|
23
|
+
};
|
|
24
|
+
/** Release reference changelog defaults (`nifty change-logs`). */
|
|
25
|
+
changelog?: {
|
|
26
|
+
/** GitHub `owner/repo` for contrib.rocks (default: parse `origin`). */
|
|
27
|
+
repo?: string;
|
|
28
|
+
/** Email → GitHub map path (default: `documentation/maintenance/author-github.json`). */
|
|
29
|
+
authorMap?: string;
|
|
30
|
+
/** `--write` output directory (default: `documentation/maintenance/releases`). */
|
|
31
|
+
releasesDir?: string;
|
|
32
|
+
};
|
|
19
33
|
/** Rule-based lint configuration. */
|
|
20
34
|
lint?: {
|
|
21
35
|
rules?: Array<{
|
package/src/native.ts
CHANGED
|
@@ -68,6 +68,81 @@ export type TrustReport = {
|
|
|
68
68
|
failed: string[];
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
export type RewordPlannedChange = {
|
|
72
|
+
oldOid: string;
|
|
73
|
+
oldSubject: string;
|
|
74
|
+
newSubject: string;
|
|
75
|
+
parentsRelinked: boolean;
|
|
76
|
+
messageChanged: boolean;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type RewordRewriteReport = {
|
|
80
|
+
changes: RewordPlannedChange[];
|
|
81
|
+
oldTip: string;
|
|
82
|
+
newTip?: string;
|
|
83
|
+
refName: string;
|
|
84
|
+
dryRun: boolean;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type HistoryExports = {
|
|
88
|
+
"reword-export": (options: {
|
|
89
|
+
cwd?: string;
|
|
90
|
+
base: string;
|
|
91
|
+
ref?: string;
|
|
92
|
+
path: string;
|
|
93
|
+
}) => { count: number; path: string };
|
|
94
|
+
"reword-rewrite": (options: {
|
|
95
|
+
cwd?: string;
|
|
96
|
+
base: string;
|
|
97
|
+
ref?: string;
|
|
98
|
+
path: string;
|
|
99
|
+
dryRun?: boolean;
|
|
100
|
+
}) => RewordRewriteReport;
|
|
101
|
+
"retime-range": (options: {
|
|
102
|
+
cwd?: string;
|
|
103
|
+
commit: string;
|
|
104
|
+
startDate?: string;
|
|
105
|
+
endDate?: string;
|
|
106
|
+
branch?: string;
|
|
107
|
+
tip?: string;
|
|
108
|
+
}) => { branch: string; newTip: string; rewritten: number };
|
|
109
|
+
"retime-root": (options: {
|
|
110
|
+
cwd?: string;
|
|
111
|
+
startDate?: string;
|
|
112
|
+
endDate?: string;
|
|
113
|
+
branch?: string;
|
|
114
|
+
tip?: string;
|
|
115
|
+
message?: string;
|
|
116
|
+
}) => { branch: string; newTip: string; rewritten: number };
|
|
117
|
+
"changelog-render": (options: {
|
|
118
|
+
cwd?: string;
|
|
119
|
+
version?: string;
|
|
120
|
+
fromRef?: string;
|
|
121
|
+
toRef?: string;
|
|
122
|
+
write?: boolean;
|
|
123
|
+
tags?: boolean;
|
|
124
|
+
repo?: string;
|
|
125
|
+
authorMap?: string;
|
|
126
|
+
releasesDir?: string;
|
|
127
|
+
}) => {
|
|
128
|
+
notes: string;
|
|
129
|
+
version: string;
|
|
130
|
+
fromRef?: string;
|
|
131
|
+
toRef: string;
|
|
132
|
+
commitCount: number;
|
|
133
|
+
writtenPath?: string;
|
|
134
|
+
rangeLabel: string;
|
|
135
|
+
};
|
|
136
|
+
"changelog-lookup": (options: {
|
|
137
|
+
cwd?: string;
|
|
138
|
+
email?: string;
|
|
139
|
+
login?: string;
|
|
140
|
+
map?: string;
|
|
141
|
+
githubToken?: string;
|
|
142
|
+
fetch?: boolean;
|
|
143
|
+
}) => GithubAuthor;
|
|
144
|
+
};
|
|
145
|
+
|
|
71
146
|
export type PublisherExports = {
|
|
72
147
|
"publish-workspace": (options: {
|
|
73
148
|
cwd?: string;
|
|
@@ -85,6 +160,7 @@ export type PublisherExports = {
|
|
|
85
160
|
dryRun?: boolean;
|
|
86
161
|
refresh?: boolean;
|
|
87
162
|
only?: string;
|
|
163
|
+
packages?: string[];
|
|
88
164
|
npm?: string;
|
|
89
165
|
otp?: string;
|
|
90
166
|
totpSecret?: string;
|
|
@@ -95,6 +171,7 @@ export type PublisherExports = {
|
|
|
95
171
|
export type NiftyNative = {
|
|
96
172
|
gitmoji: GitmojiExports;
|
|
97
173
|
git: GitExports;
|
|
174
|
+
history: HistoryExports;
|
|
98
175
|
publisher: PublisherExports;
|
|
99
176
|
};
|
|
100
177
|
|
|
@@ -146,11 +223,80 @@ type NativeBinding = {
|
|
|
146
223
|
dryRun?: boolean | null;
|
|
147
224
|
refresh?: boolean | null;
|
|
148
225
|
only?: string | null;
|
|
226
|
+
packages?: string[] | null;
|
|
149
227
|
npm?: string | null;
|
|
150
228
|
otp?: string | null;
|
|
151
229
|
totpSecret?: string | null;
|
|
152
230
|
token?: string | null;
|
|
153
231
|
}) => TrustReport;
|
|
232
|
+
gitToolsRewordExport: (options: {
|
|
233
|
+
cwd?: string | null;
|
|
234
|
+
base: string;
|
|
235
|
+
ref?: string | null;
|
|
236
|
+
path: string;
|
|
237
|
+
}) => { count: number; path: string };
|
|
238
|
+
gitToolsRewordRewrite: (options: {
|
|
239
|
+
cwd?: string | null;
|
|
240
|
+
base: string;
|
|
241
|
+
ref?: string | null;
|
|
242
|
+
path: string;
|
|
243
|
+
dryRun?: boolean | null;
|
|
244
|
+
}) => {
|
|
245
|
+
changes: Array<{
|
|
246
|
+
oldOid: string;
|
|
247
|
+
oldSubject: string;
|
|
248
|
+
newSubject: string;
|
|
249
|
+
parentsRelinked: boolean;
|
|
250
|
+
messageChanged: boolean;
|
|
251
|
+
}>;
|
|
252
|
+
oldTip: string;
|
|
253
|
+
newTip?: string | null;
|
|
254
|
+
refName: string;
|
|
255
|
+
dryRun: boolean;
|
|
256
|
+
};
|
|
257
|
+
gitToolsRetimeRange: (options: {
|
|
258
|
+
cwd?: string | null;
|
|
259
|
+
commit: string;
|
|
260
|
+
startDate?: string | null;
|
|
261
|
+
endDate?: string | null;
|
|
262
|
+
branch?: string | null;
|
|
263
|
+
tip?: string | null;
|
|
264
|
+
}) => { branch: string; newTip: string; rewritten: number };
|
|
265
|
+
gitToolsRetimeRoot: (options: {
|
|
266
|
+
cwd?: string | null;
|
|
267
|
+
startDate?: string | null;
|
|
268
|
+
endDate?: string | null;
|
|
269
|
+
branch?: string | null;
|
|
270
|
+
tip?: string | null;
|
|
271
|
+
message?: string | null;
|
|
272
|
+
}) => { branch: string; newTip: string; rewritten: number };
|
|
273
|
+
gitToolsChangelogRender: (options: {
|
|
274
|
+
cwd?: string | null;
|
|
275
|
+
version?: string | null;
|
|
276
|
+
fromRef?: string | null;
|
|
277
|
+
toRef?: string | null;
|
|
278
|
+
write?: boolean | null;
|
|
279
|
+
tags?: boolean | null;
|
|
280
|
+
repo?: string | null;
|
|
281
|
+
authorMap?: string | null;
|
|
282
|
+
releasesDir?: string | null;
|
|
283
|
+
}) => {
|
|
284
|
+
notes: string;
|
|
285
|
+
version: string;
|
|
286
|
+
fromRef?: string | null;
|
|
287
|
+
toRef: string;
|
|
288
|
+
commitCount: number;
|
|
289
|
+
writtenPath?: string | null;
|
|
290
|
+
rangeLabel: string;
|
|
291
|
+
};
|
|
292
|
+
gitToolsChangelogLookup: (options: {
|
|
293
|
+
cwd?: string | null;
|
|
294
|
+
email?: string | null;
|
|
295
|
+
login?: string | null;
|
|
296
|
+
map?: string | null;
|
|
297
|
+
githubToken?: string | null;
|
|
298
|
+
fetch?: boolean | null;
|
|
299
|
+
}) => GithubAuthor;
|
|
154
300
|
};
|
|
155
301
|
|
|
156
302
|
const PLATFORM_PACKAGES: Record<string, string> = {
|
|
@@ -213,6 +359,82 @@ function wrapBinding(binding: NativeBinding): NiftyNative {
|
|
|
213
359
|
"detect-github-repo": (repoRoot) => binding.gitDetectGithubRepo(repoRoot) ?? undefined,
|
|
214
360
|
"parse-github-remote": (url) => binding.gitParseGithubRemote(url) ?? undefined,
|
|
215
361
|
},
|
|
362
|
+
history: {
|
|
363
|
+
"reword-export": (options) =>
|
|
364
|
+
binding.gitToolsRewordExport({
|
|
365
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
366
|
+
base: options.base,
|
|
367
|
+
...(options.ref !== undefined ? { ref: options.ref } : {}),
|
|
368
|
+
path: options.path,
|
|
369
|
+
}),
|
|
370
|
+
"reword-rewrite": (options) => {
|
|
371
|
+
const report = binding.gitToolsRewordRewrite({
|
|
372
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
373
|
+
base: options.base,
|
|
374
|
+
...(options.ref !== undefined ? { ref: options.ref } : {}),
|
|
375
|
+
path: options.path,
|
|
376
|
+
...(options.dryRun !== undefined ? { dryRun: options.dryRun } : {}),
|
|
377
|
+
});
|
|
378
|
+
return {
|
|
379
|
+
changes: report.changes,
|
|
380
|
+
oldTip: report.oldTip,
|
|
381
|
+
newTip: report.newTip ?? undefined,
|
|
382
|
+
refName: report.refName,
|
|
383
|
+
dryRun: report.dryRun,
|
|
384
|
+
};
|
|
385
|
+
},
|
|
386
|
+
"retime-range": (options) =>
|
|
387
|
+
binding.gitToolsRetimeRange({
|
|
388
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
389
|
+
commit: options.commit,
|
|
390
|
+
...(options.startDate !== undefined ? { startDate: options.startDate } : {}),
|
|
391
|
+
...(options.endDate !== undefined ? { endDate: options.endDate } : {}),
|
|
392
|
+
...(options.branch !== undefined ? { branch: options.branch } : {}),
|
|
393
|
+
...(options.tip !== undefined ? { tip: options.tip } : {}),
|
|
394
|
+
}),
|
|
395
|
+
"retime-root": (options) =>
|
|
396
|
+
binding.gitToolsRetimeRoot({
|
|
397
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
398
|
+
...(options.startDate !== undefined ? { startDate: options.startDate } : {}),
|
|
399
|
+
...(options.endDate !== undefined ? { endDate: options.endDate } : {}),
|
|
400
|
+
...(options.branch !== undefined ? { branch: options.branch } : {}),
|
|
401
|
+
...(options.tip !== undefined ? { tip: options.tip } : {}),
|
|
402
|
+
...(options.message !== undefined ? { message: options.message } : {}),
|
|
403
|
+
}),
|
|
404
|
+
"changelog-render": (options) => {
|
|
405
|
+
const report = binding.gitToolsChangelogRender({
|
|
406
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
407
|
+
...(options.version !== undefined ? { version: options.version } : {}),
|
|
408
|
+
...(options.fromRef !== undefined ? { fromRef: options.fromRef } : {}),
|
|
409
|
+
...(options.toRef !== undefined ? { toRef: options.toRef } : {}),
|
|
410
|
+
...(options.write !== undefined ? { write: options.write } : {}),
|
|
411
|
+
...(options.tags !== undefined ? { tags: options.tags } : {}),
|
|
412
|
+
...(options.repo !== undefined ? { repo: options.repo } : {}),
|
|
413
|
+
...(options.authorMap !== undefined ? { authorMap: options.authorMap } : {}),
|
|
414
|
+
...(options.releasesDir !== undefined ? { releasesDir: options.releasesDir } : {}),
|
|
415
|
+
});
|
|
416
|
+
return {
|
|
417
|
+
notes: report.notes,
|
|
418
|
+
version: report.version,
|
|
419
|
+
fromRef: report.fromRef ?? undefined,
|
|
420
|
+
toRef: report.toRef,
|
|
421
|
+
commitCount: report.commitCount,
|
|
422
|
+
writtenPath: report.writtenPath ?? undefined,
|
|
423
|
+
rangeLabel: report.rangeLabel,
|
|
424
|
+
};
|
|
425
|
+
},
|
|
426
|
+
"changelog-lookup": (options) => {
|
|
427
|
+
const author = binding.gitToolsChangelogLookup({
|
|
428
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
429
|
+
...(options.email !== undefined ? { email: options.email } : {}),
|
|
430
|
+
...(options.login !== undefined ? { login: options.login } : {}),
|
|
431
|
+
...(options.map !== undefined ? { map: options.map } : {}),
|
|
432
|
+
...(options.githubToken !== undefined ? { githubToken: options.githubToken } : {}),
|
|
433
|
+
...(options.fetch !== undefined ? { fetch: options.fetch } : {}),
|
|
434
|
+
});
|
|
435
|
+
return mapAuthor(author) ?? {};
|
|
436
|
+
},
|
|
437
|
+
},
|
|
216
438
|
publisher: {
|
|
217
439
|
"publish-workspace": (options) =>
|
|
218
440
|
binding.publisherPublishWorkspace({
|
|
@@ -232,6 +454,7 @@ function wrapBinding(binding: NativeBinding): NiftyNative {
|
|
|
232
454
|
...(options.dryRun !== undefined ? { dryRun: options.dryRun } : {}),
|
|
233
455
|
...(options.refresh !== undefined ? { refresh: options.refresh } : {}),
|
|
234
456
|
...(options.only !== undefined ? { only: options.only } : {}),
|
|
457
|
+
...(options.packages !== undefined ? { packages: options.packages } : {}),
|
|
235
458
|
...(options.npm !== undefined ? { npm: options.npm } : {}),
|
|
236
459
|
...(options.otp !== undefined ? { otp: options.otp } : {}),
|
|
237
460
|
...(options.totpSecret !== undefined ? { totpSecret: options.totpSecret } : {}),
|
package/Readme.md
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# @doki-land/nifty
|
|
2
|
-
|
|
3
|
-
**Gitmoji is the default Nifty convention.**
|
|
4
|
-
|
|
5
|
-
| Layer | Role |
|
|
6
|
-
| --- | --- |
|
|
7
|
-
| `@doki-land/nifty-<platform>` | Node-API `.node`(gitmoji + gix) |
|
|
8
|
-
| `nifty-publisher` | Rust:`petgraph` 拓扑排序 + `npm publish` |
|
|
9
|
-
| `src/cli/` | CLI 实现(`update` / `lint` / `check` / `upload` / `bump` / `publish`) |
|
|
10
|
-
| `cli/nifty.mjs` | npm `bin` shim(jiti 加载 `src/cli`) |
|
|
11
|
-
| `src/` | TypeScript API |
|
|
12
|
-
|
|
13
|
-
Rust 侧无 `bin` / `cli`。
|
|
14
|
-
|
|
15
|
-
**本仓开发**(pnpm workspace,`projects/packages/*`):
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
pnpm install # 链接 @doki-land/nifty → node_modules/.bin/nifty
|
|
19
|
-
pnpm run build:napi # 构建 native addon
|
|
20
|
-
pnpm exec nifty bump
|
|
21
|
-
pnpm exec nifty publish --dry-run
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
**发布后消费**:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npm install @doki-land/nifty
|
|
28
|
-
nifty bump
|
|
29
|
-
nifty publish --dry-run
|
|
30
|
-
```
|