@doki-land/nifty 0.0.1 → 0.0.3

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 (45) hide show
  1. package/README.md +29 -0
  2. package/cli/nifty.mjs +11 -11
  3. package/locales/en-US/cli.json +68 -41
  4. package/locales/locales.json +4 -4
  5. package/package.json +4 -4
  6. package/src/cli/authArgs.ts +52 -52
  7. package/src/cli/bump-cmd.ts +55 -55
  8. package/src/cli/bump.ts +237 -237
  9. package/src/cli/change-logs-cmd.ts +97 -0
  10. package/src/cli/cli.ts +47 -39
  11. package/src/cli/context.ts +36 -36
  12. package/src/cli/format-cmd.ts +23 -0
  13. package/src/cli/format.ts +28 -0
  14. package/src/cli/index.ts +9 -9
  15. package/src/cli/install-native-cmd.ts +22 -22
  16. package/src/cli/install-native.ts +80 -80
  17. package/src/cli/lint-cmd.ts +35 -33
  18. package/src/cli/lint.ts +102 -113
  19. package/src/cli/main.ts +1 -1
  20. package/src/cli/options.ts +40 -40
  21. package/src/cli/publish-cmd.ts +38 -34
  22. package/src/cli/publish.ts +95 -95
  23. package/src/cli/resolveNpm.ts +16 -16
  24. package/src/cli/retime-cmd.ts +62 -0
  25. package/src/cli/reword-cmd.ts +87 -0
  26. package/src/cli/trust-cmd.ts +38 -35
  27. package/src/cli/trust.ts +83 -83
  28. package/src/cli/update-cmd.ts +20 -20
  29. package/src/cli/update.ts +32 -185
  30. package/src/cli/upload-cmd.ts +44 -44
  31. package/src/cli/upload.ts +313 -313
  32. package/src/cli/workspace.ts +124 -124
  33. package/src/config/defineConfig.ts +12 -12
  34. package/src/config/detectProject.ts +189 -189
  35. package/src/config/index.ts +25 -25
  36. package/src/config/loadConfig.ts +129 -129
  37. package/src/config/types.ts +57 -43
  38. package/src/git.ts +61 -61
  39. package/src/github.ts +184 -184
  40. package/src/gitmoji.ts +77 -77
  41. package/src/index.ts +36 -36
  42. package/src/native.ts +665 -284
  43. package/src/nifty.ts +95 -95
  44. package/src/types.ts +40 -40
  45. package/Readme.md +0 -30
package/src/native.ts CHANGED
@@ -1,284 +1,665 @@
1
- import { createRequire } from "node:module";
2
- import type {
3
- CommitRecord,
4
- GithubAuthor,
5
- ParsedSubject,
6
- RangeInfo,
7
- ReleaseSection,
8
- TagInfo,
9
- } from "./types.js";
10
-
11
- export type GitmojiExports = {
12
- "known-gitmojis": () => string[];
13
- "validate-subject": (subject: string) => boolean;
14
- "parse-subject": (subject: string) => ParsedSubject;
15
- "format-subject": (gitmoji: string, body: string) => string;
16
- "strip-gitmoji": (subject: string) => string;
17
- "leading-gitmoji": (subject: string) => string | undefined;
18
- "section-for-gitmoji": (gitmoji: string | undefined) => ReleaseSection;
19
- "parse-noreply-email": (email: string) => GithubAuthor | undefined;
20
- "resolve-github-author": (email: string, authorMapJson: string) => GithubAuthor | undefined;
21
- "display-login": (author: GithubAuthor) => string;
22
- "profile-url": (author: GithubAuthor) => string;
23
- "avatar-url": (author: GithubAuthor) => string;
24
- "author-mention": (email: string, authorName: string, authorMapJson: string) => string;
25
- "commit-bullet": (body: string, email: string, authorName: string, authorMapJson: string) => string;
26
- };
27
-
28
- export type GitExports = {
29
- "discover-root": (startPath: string) => string;
30
- "list-version-tags": (repoRoot: string) => string[];
31
- "list-tag-infos": (repoRoot: string) => Array<{ name: string; "short-hash": string }>;
32
- "format-tag-list": (repoRoot: string) => string;
33
- "resolve-range": (
34
- repoRoot: string,
35
- version: string | undefined,
36
- fromRef: string | undefined,
37
- toRef: string | undefined,
38
- ) => { version: string; "from-ref"?: string; "to-ref": string };
39
- "collect-commits": (
40
- repoRoot: string,
41
- fromRef: string | undefined,
42
- toRef: string,
43
- ) => Array<{
44
- hash: string;
45
- email: string;
46
- author: string;
47
- subject: string;
48
- body: string;
49
- gitmoji?: string;
50
- section: string;
51
- }>;
52
- "detect-github-repo": (repoRoot: string) => string | undefined;
53
- "parse-github-remote": (url: string) => string | undefined;
54
- };
55
-
56
- export type PublishReport = {
57
- root: string;
58
- order: string[];
59
- published: string[];
60
- skipped: string[];
61
- skippedVersions: string[];
62
- };
63
-
64
- export type TrustReport = {
65
- root: string;
66
- configured: string[];
67
- skipped: string[];
68
- failed: string[];
69
- };
70
-
71
- export type PublisherExports = {
72
- "publish-workspace": (options: {
73
- cwd?: string;
74
- dryRun?: boolean;
75
- refresh?: boolean;
76
- tag?: string;
77
- access?: string;
78
- npm?: string;
79
- otp?: string;
80
- totpSecret?: string;
81
- token?: string;
82
- }) => PublishReport;
83
- "trust-workspace": (options: {
84
- cwd?: string;
85
- dryRun?: boolean;
86
- refresh?: boolean;
87
- only?: string;
88
- npm?: string;
89
- otp?: string;
90
- totpSecret?: string;
91
- token?: string;
92
- }) => TrustReport;
93
- };
94
-
95
- export type NiftyNative = {
96
- gitmoji: GitmojiExports;
97
- git: GitExports;
98
- publisher: PublisherExports;
99
- };
100
-
101
- type NativeBinding = {
102
- gitmojiKnownGitmojis: () => string[];
103
- gitmojiValidateSubject: (subject: string) => boolean;
104
- gitmojiParseSubject: (subject: string) => ParsedSubject;
105
- gitmojiFormatSubject: (gitmoji: string, body: string) => string;
106
- gitmojiStripGitmoji: (subject: string) => string;
107
- gitmojiLeadingGitmoji: (subject: string) => string | null;
108
- gitmojiSectionForGitmoji: (gitmoji?: string | null) => string;
109
- gitmojiParseNoreplyEmail: (email: string) => GithubAuthor | null;
110
- gitmojiResolveGithubAuthor: (email: string, authorMapJson: string) => GithubAuthor | null;
111
- gitmojiDisplayLogin: (author: GithubAuthor) => string;
112
- gitmojiProfileUrl: (author: GithubAuthor) => string;
113
- gitmojiAvatarUrl: (author: GithubAuthor) => string;
114
- gitmojiAuthorMention: (email: string, authorName: string, authorMapJson: string) => string;
115
- gitmojiCommitBullet: (body: string, email: string, authorName: string, authorMapJson: string) => string;
116
- gitDiscoverRoot: (startPath: string) => string;
117
- gitListVersionTags: (repoRoot: string) => string[];
118
- gitListTagInfos: (repoRoot: string) => Array<{ name: string; shortHash: string }>;
119
- gitFormatTagList: (repoRoot: string) => string;
120
- gitResolveRange: (
121
- repoRoot: string,
122
- version?: string | null,
123
- fromRef?: string | null,
124
- toRef?: string | null,
125
- ) => { version: string; fromRef?: string; toRef: string };
126
- gitCollectCommits: (
127
- repoRoot: string,
128
- fromRef: string | null | undefined,
129
- toRef: string,
130
- ) => CommitRecord[];
131
- gitDetectGithubRepo: (repoRoot: string) => string | null;
132
- gitParseGithubRemote: (url: string) => string | null;
133
- publisherPublishWorkspace: (options: {
134
- cwd?: string | null;
135
- dryRun?: boolean | null;
136
- refresh?: boolean | null;
137
- tag?: string | null;
138
- access?: string | null;
139
- npm?: string | null;
140
- otp?: string | null;
141
- totpSecret?: string | null;
142
- token?: string | null;
143
- }) => PublishReport;
144
- publisherTrustWorkspace: (options: {
145
- cwd?: string | null;
146
- dryRun?: boolean | null;
147
- refresh?: boolean | null;
148
- only?: string | null;
149
- npm?: string | null;
150
- otp?: string | null;
151
- totpSecret?: string | null;
152
- token?: string | null;
153
- }) => TrustReport;
154
- };
155
-
156
- const PLATFORM_PACKAGES: Record<string, string> = {
157
- "win32-x64": "@doki-land/nifty-win32-x64",
158
- "linux-x64": "@doki-land/nifty-linux-x64",
159
- "linux-arm64": "@doki-land/nifty-linux-arm64",
160
- "darwin-x64": "@doki-land/nifty-darwin-x64",
161
- "darwin-arm64": "@doki-land/nifty-darwin-arm64",
162
- };
163
-
164
- function mapAuthor(raw: GithubAuthor | null | undefined): GithubAuthor | undefined {
165
- if (!raw) {
166
- return undefined;
167
- }
168
- return {
169
- id: raw.id !== undefined && raw.id !== null ? BigInt(raw.id) : undefined,
170
- login: raw.login ?? undefined,
171
- };
172
- }
173
-
174
- function wrapBinding(binding: NativeBinding): NiftyNative {
175
- return {
176
- gitmoji: {
177
- "known-gitmojis": () => binding.gitmojiKnownGitmojis(),
178
- "validate-subject": (subject) => binding.gitmojiValidateSubject(subject),
179
- "parse-subject": (subject) => binding.gitmojiParseSubject(subject),
180
- "format-subject": (gitmoji, body) => binding.gitmojiFormatSubject(gitmoji, body),
181
- "strip-gitmoji": (subject) => binding.gitmojiStripGitmoji(subject),
182
- "leading-gitmoji": (subject) => binding.gitmojiLeadingGitmoji(subject) ?? undefined,
183
- "section-for-gitmoji": (gitmoji) => binding.gitmojiSectionForGitmoji(gitmoji) as ReleaseSection,
184
- "parse-noreply-email": (email) => mapAuthor(binding.gitmojiParseNoreplyEmail(email)),
185
- "resolve-github-author": (email, authorMapJson) =>
186
- mapAuthor(binding.gitmojiResolveGithubAuthor(email, authorMapJson)),
187
- "display-login": (author) => binding.gitmojiDisplayLogin(author),
188
- "profile-url": (author) => binding.gitmojiProfileUrl(author),
189
- "avatar-url": (author) => binding.gitmojiAvatarUrl(author),
190
- "author-mention": (email, authorName, authorMapJson) =>
191
- binding.gitmojiAuthorMention(email, authorName, authorMapJson),
192
- "commit-bullet": (body, email, authorName, authorMapJson) =>
193
- binding.gitmojiCommitBullet(body, email, authorName, authorMapJson),
194
- },
195
- git: {
196
- "discover-root": (startPath) => binding.gitDiscoverRoot(startPath),
197
- "list-version-tags": (repoRoot) => binding.gitListVersionTags(repoRoot),
198
- "list-tag-infos": (repoRoot) =>
199
- binding.gitListTagInfos(repoRoot).map((tag) => ({
200
- name: tag.name,
201
- "short-hash": tag.shortHash,
202
- })),
203
- "format-tag-list": (repoRoot) => binding.gitFormatTagList(repoRoot),
204
- "resolve-range": (repoRoot, version, fromRef, toRef) => {
205
- const range = binding.gitResolveRange(repoRoot, version, fromRef, toRef);
206
- return {
207
- version: range.version,
208
- "from-ref": range.fromRef,
209
- "to-ref": range.toRef,
210
- };
211
- },
212
- "collect-commits": (repoRoot, fromRef, toRef) => binding.gitCollectCommits(repoRoot, fromRef, toRef),
213
- "detect-github-repo": (repoRoot) => binding.gitDetectGithubRepo(repoRoot) ?? undefined,
214
- "parse-github-remote": (url) => binding.gitParseGithubRemote(url) ?? undefined,
215
- },
216
- publisher: {
217
- "publish-workspace": (options) =>
218
- binding.publisherPublishWorkspace({
219
- ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
220
- ...(options.dryRun !== undefined ? { dryRun: options.dryRun } : {}),
221
- ...(options.refresh !== undefined ? { refresh: options.refresh } : {}),
222
- ...(options.tag !== undefined ? { tag: options.tag } : {}),
223
- ...(options.access !== undefined ? { access: options.access } : {}),
224
- ...(options.npm !== undefined ? { npm: options.npm } : {}),
225
- ...(options.otp !== undefined ? { otp: options.otp } : {}),
226
- ...(options.totpSecret !== undefined ? { totpSecret: options.totpSecret } : {}),
227
- ...(options.token !== undefined ? { token: options.token } : {}),
228
- }),
229
- "trust-workspace": (options) =>
230
- binding.publisherTrustWorkspace({
231
- ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
232
- ...(options.dryRun !== undefined ? { dryRun: options.dryRun } : {}),
233
- ...(options.refresh !== undefined ? { refresh: options.refresh } : {}),
234
- ...(options.only !== undefined ? { only: options.only } : {}),
235
- ...(options.npm !== undefined ? { npm: options.npm } : {}),
236
- ...(options.otp !== undefined ? { otp: options.otp } : {}),
237
- ...(options.totpSecret !== undefined ? { totpSecret: options.totpSecret } : {}),
238
- ...(options.token !== undefined ? { token: options.token } : {}),
239
- }),
240
- },
241
- };
242
- }
243
-
244
- let cached: NiftyNative | undefined;
245
-
246
- /** Load the platform-specific Node-API binary from `@doki-land/nifty-<platform>`. */
247
- export function loadNiftyNative(): NiftyNative {
248
- if (cached) {
249
- return cached;
250
- }
251
- const key = `${process.platform}-${process.arch}`;
252
- const pkg = PLATFORM_PACKAGES[key];
253
- if (!pkg) {
254
- throw new Error(`Unsupported platform for Nifty native bindings: ${key}`);
255
- }
256
- const require = createRequire(import.meta.url);
257
- const binding = require(pkg).default as NativeBinding;
258
- cached = wrapBinding(binding);
259
- return cached;
260
- }
261
-
262
- export function mapTagInfo(raw: { name: string; "short-hash": string }): TagInfo {
263
- return { name: raw.name, shortHash: raw["short-hash"] };
264
- }
265
-
266
- export function mapRangeInfo(raw: { version: string; "from-ref"?: string; "to-ref": string }): RangeInfo {
267
- return {
268
- version: raw.version,
269
- fromRef: raw["from-ref"],
270
- toRef: raw["to-ref"],
271
- };
272
- }
273
-
274
- export function mapCommitRecord(raw: CommitRecord): CommitRecord {
275
- return {
276
- hash: raw.hash,
277
- email: raw.email,
278
- author: raw.author,
279
- subject: raw.subject,
280
- body: raw.body,
281
- gitmoji: raw.gitmoji,
282
- section: raw.section as ReleaseSection,
283
- };
284
- }
1
+ import { createRequire } from "node:module";
2
+ import type {
3
+ CommitRecord,
4
+ GithubAuthor,
5
+ ParsedSubject,
6
+ RangeInfo,
7
+ ReleaseSection,
8
+ TagInfo,
9
+ } from "./types.js";
10
+
11
+ export type GitmojiExports = {
12
+ "known-gitmojis": () => string[];
13
+ "validate-subject": (subject: string) => boolean;
14
+ "parse-subject": (subject: string) => ParsedSubject;
15
+ "format-subject": (gitmoji: string, body: string) => string;
16
+ "strip-gitmoji": (subject: string) => string;
17
+ "leading-gitmoji": (subject: string) => string | undefined;
18
+ "section-for-gitmoji": (gitmoji: string | undefined) => ReleaseSection;
19
+ "parse-noreply-email": (email: string) => GithubAuthor | undefined;
20
+ "resolve-github-author": (email: string, authorMapJson: string) => GithubAuthor | undefined;
21
+ "display-login": (author: GithubAuthor) => string;
22
+ "profile-url": (author: GithubAuthor) => string;
23
+ "avatar-url": (author: GithubAuthor) => string;
24
+ "author-mention": (email: string, authorName: string, authorMapJson: string) => string;
25
+ "commit-bullet": (body: string, email: string, authorName: string, authorMapJson: string) => string;
26
+ };
27
+
28
+ export type GitExports = {
29
+ "discover-root": (startPath: string) => string;
30
+ "list-version-tags": (repoRoot: string) => string[];
31
+ "list-tag-infos": (repoRoot: string) => Array<{ name: string; "short-hash": string }>;
32
+ "format-tag-list": (repoRoot: string) => string;
33
+ "resolve-range": (
34
+ repoRoot: string,
35
+ version: string | undefined,
36
+ fromRef: string | undefined,
37
+ toRef: string | undefined,
38
+ ) => { version: string; "from-ref"?: string; "to-ref": string };
39
+ "collect-commits": (
40
+ repoRoot: string,
41
+ fromRef: string | undefined,
42
+ toRef: string,
43
+ ) => Array<{
44
+ hash: string;
45
+ email: string;
46
+ author: string;
47
+ subject: string;
48
+ body: string;
49
+ gitmoji?: string;
50
+ section: string;
51
+ }>;
52
+ "detect-github-repo": (repoRoot: string) => string | undefined;
53
+ "parse-github-remote": (url: string) => string | undefined;
54
+ };
55
+
56
+ export type PublishReport = {
57
+ root: string;
58
+ order: string[];
59
+ published: string[];
60
+ skipped: string[];
61
+ skippedVersions: string[];
62
+ };
63
+
64
+ export type TrustReport = {
65
+ root: string;
66
+ configured: string[];
67
+ skipped: string[];
68
+ failed: string[];
69
+ };
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
+
146
+ export type LintDiagnosticRecord = {
147
+ rule: string;
148
+ severity: "error" | "warning" | "info";
149
+ message: string;
150
+ subject?: string;
151
+ hash?: string;
152
+ path?: string;
153
+ line?: number;
154
+ };
155
+
156
+ export type LintRunOptions = {
157
+ cwd?: string;
158
+ fromRef?: string;
159
+ toRef?: string;
160
+ subjects?: string[];
161
+ rules?: Array<{ id: string; enabled?: boolean; severity?: "error" | "warning" | "info" }>;
162
+ scanCargo?: boolean;
163
+ };
164
+
165
+ export type LintReportRecord = {
166
+ diagnostics: LintDiagnosticRecord[];
167
+ errorCount: number;
168
+ warningCount: number;
169
+ };
170
+
171
+ export type LintExports = {
172
+ run: (options: LintRunOptions) => LintReportRecord;
173
+ check: (options: LintRunOptions) => LintReportRecord;
174
+ };
175
+
176
+ export type UpdaterExports = {
177
+ run: (options: { cwd?: string; interactive?: boolean }) => void;
178
+ };
179
+
180
+ export type FormatReportRecord = {
181
+ formatted: number;
182
+ unchanged: number;
183
+ errors: string[];
184
+ };
185
+
186
+ export type FormatterExports = {
187
+ run: (options: { cwd?: string; check?: boolean }) => FormatReportRecord;
188
+ };
189
+
190
+ export type PublisherExports = {
191
+ "publish-workspace": (options: {
192
+ cwd?: string;
193
+ dryRun?: boolean;
194
+ refresh?: boolean;
195
+ only?: string;
196
+ packages?: string[];
197
+ tag?: string;
198
+ access?: string;
199
+ npm?: string;
200
+ otp?: string;
201
+ totpSecret?: string;
202
+ token?: string;
203
+ }) => PublishReport;
204
+ "trust-workspace": (options: {
205
+ cwd?: string;
206
+ dryRun?: boolean;
207
+ refresh?: boolean;
208
+ only?: string;
209
+ packages?: string[];
210
+ npm?: string;
211
+ otp?: string;
212
+ totpSecret?: string;
213
+ token?: string;
214
+ }) => TrustReport;
215
+ };
216
+
217
+ export type NiftyNative = {
218
+ gitmoji: GitmojiExports;
219
+ git: GitExports;
220
+ history: HistoryExports;
221
+ lint: LintExports;
222
+ updater: UpdaterExports;
223
+ formatter: FormatterExports;
224
+ publisher: PublisherExports;
225
+ };
226
+
227
+ type NativeBinding = {
228
+ gitmojiKnownGitmojis: () => string[];
229
+ gitmojiValidateSubject: (subject: string) => boolean;
230
+ gitmojiParseSubject: (subject: string) => ParsedSubject;
231
+ gitmojiFormatSubject: (gitmoji: string, body: string) => string;
232
+ gitmojiStripGitmoji: (subject: string) => string;
233
+ gitmojiLeadingGitmoji: (subject: string) => string | null;
234
+ gitmojiSectionForGitmoji: (gitmoji?: string | null) => string;
235
+ gitmojiParseNoreplyEmail: (email: string) => GithubAuthor | null;
236
+ gitmojiResolveGithubAuthor: (email: string, authorMapJson: string) => GithubAuthor | null;
237
+ gitmojiDisplayLogin: (author: GithubAuthor) => string;
238
+ gitmojiProfileUrl: (author: GithubAuthor) => string;
239
+ gitmojiAvatarUrl: (author: GithubAuthor) => string;
240
+ gitmojiAuthorMention: (email: string, authorName: string, authorMapJson: string) => string;
241
+ gitmojiCommitBullet: (body: string, email: string, authorName: string, authorMapJson: string) => string;
242
+ gitDiscoverRoot: (startPath: string) => string;
243
+ gitListVersionTags: (repoRoot: string) => string[];
244
+ gitListTagInfos: (repoRoot: string) => Array<{ name: string; shortHash: string }>;
245
+ gitFormatTagList: (repoRoot: string) => string;
246
+ gitResolveRange: (
247
+ repoRoot: string,
248
+ version?: string | null,
249
+ fromRef?: string | null,
250
+ toRef?: string | null,
251
+ ) => { version: string; fromRef?: string; toRef: string };
252
+ gitCollectCommits: (
253
+ repoRoot: string,
254
+ fromRef: string | null | undefined,
255
+ toRef: string,
256
+ ) => CommitRecord[];
257
+ gitDetectGithubRepo: (repoRoot: string) => string | null;
258
+ gitParseGithubRemote: (url: string) => string | null;
259
+ publisherPublishWorkspace: (options: {
260
+ cwd?: string | null;
261
+ dryRun?: boolean | null;
262
+ refresh?: boolean | null;
263
+ tag?: string | null;
264
+ access?: string | null;
265
+ npm?: string | null;
266
+ otp?: string | null;
267
+ totpSecret?: string | null;
268
+ token?: string | null;
269
+ only?: string | null;
270
+ packages?: string[] | null;
271
+ }) => PublishReport;
272
+ publisherTrustWorkspace: (options: {
273
+ cwd?: string | null;
274
+ dryRun?: boolean | null;
275
+ refresh?: boolean | null;
276
+ only?: string | null;
277
+ packages?: string[] | null;
278
+ npm?: string | null;
279
+ otp?: string | null;
280
+ totpSecret?: string | null;
281
+ token?: string | null;
282
+ }) => TrustReport;
283
+ gitToolsRewordExport: (options: {
284
+ cwd?: string | null;
285
+ base: string;
286
+ ref?: string | null;
287
+ path: string;
288
+ }) => { count: number; path: string };
289
+ gitToolsRewordRewrite: (options: {
290
+ cwd?: string | null;
291
+ base: string;
292
+ ref?: string | null;
293
+ path: string;
294
+ dryRun?: boolean | null;
295
+ }) => {
296
+ changes: Array<{
297
+ oldOid: string;
298
+ oldSubject: string;
299
+ newSubject: string;
300
+ parentsRelinked: boolean;
301
+ messageChanged: boolean;
302
+ }>;
303
+ oldTip: string;
304
+ newTip?: string | null;
305
+ refName: string;
306
+ dryRun: boolean;
307
+ };
308
+ gitToolsRetimeRange: (options: {
309
+ cwd?: string | null;
310
+ commit: string;
311
+ startDate?: string | null;
312
+ endDate?: string | null;
313
+ branch?: string | null;
314
+ tip?: string | null;
315
+ }) => { branch: string; newTip: string; rewritten: number };
316
+ gitToolsRetimeRoot: (options: {
317
+ cwd?: string | null;
318
+ startDate?: string | null;
319
+ endDate?: string | null;
320
+ branch?: string | null;
321
+ tip?: string | null;
322
+ message?: string | null;
323
+ }) => { branch: string; newTip: string; rewritten: number };
324
+ gitToolsChangelogRender: (options: {
325
+ cwd?: string | null;
326
+ version?: string | null;
327
+ fromRef?: string | null;
328
+ toRef?: string | null;
329
+ write?: boolean | null;
330
+ tags?: boolean | null;
331
+ repo?: string | null;
332
+ authorMap?: string | null;
333
+ releasesDir?: string | null;
334
+ }) => {
335
+ notes: string;
336
+ version: string;
337
+ fromRef?: string | null;
338
+ toRef: string;
339
+ commitCount: number;
340
+ writtenPath?: string | null;
341
+ rangeLabel: string;
342
+ };
343
+ gitToolsChangelogLookup: (options: {
344
+ cwd?: string | null;
345
+ email?: string | null;
346
+ login?: string | null;
347
+ map?: string | null;
348
+ githubToken?: string | null;
349
+ fetch?: boolean | null;
350
+ }) => GithubAuthor;
351
+ lintRun: (options: {
352
+ cwd?: string | null;
353
+ fromRef?: string | null;
354
+ toRef?: string | null;
355
+ subjects?: string[] | null;
356
+ rules?: Array<{ id: string; enabled?: boolean | null; severity?: string | null }> | null;
357
+ scanCargo?: boolean | null;
358
+ check?: boolean | null;
359
+ }) => {
360
+ diagnostics: Array<{
361
+ rule: string;
362
+ severity: string;
363
+ message: string;
364
+ subject?: string | null;
365
+ hash?: string | null;
366
+ path?: string | null;
367
+ line?: number | null;
368
+ }>;
369
+ errorCount: number;
370
+ warningCount: number;
371
+ };
372
+ lintCheck: (options: {
373
+ cwd?: string | null;
374
+ fromRef?: string | null;
375
+ toRef?: string | null;
376
+ subjects?: string[] | null;
377
+ rules?: Array<{ id: string; enabled?: boolean | null; severity?: string | null }> | null;
378
+ scanCargo?: boolean | null;
379
+ check?: boolean | null;
380
+ }) => {
381
+ diagnostics: Array<{
382
+ rule: string;
383
+ severity: string;
384
+ message: string;
385
+ subject?: string | null;
386
+ hash?: string | null;
387
+ path?: string | null;
388
+ line?: number | null;
389
+ }>;
390
+ errorCount: number;
391
+ warningCount: number;
392
+ };
393
+ updaterRun: (options: { cwd?: string | null; interactive?: boolean | null }) => void;
394
+ formatterRun: (options: { cwd?: string | null; check?: boolean | null }) => {
395
+ formatted: number;
396
+ unchanged: number;
397
+ errors: string[];
398
+ };
399
+ };
400
+
401
+ const PLATFORM_PACKAGES: Record<string, string> = {
402
+ "win32-x64": "@doki-land/nifty-win32-x64",
403
+ "linux-x64": "@doki-land/nifty-linux-x64",
404
+ "linux-arm64": "@doki-land/nifty-linux-arm64",
405
+ "darwin-x64": "@doki-land/nifty-darwin-x64",
406
+ "darwin-arm64": "@doki-land/nifty-darwin-arm64",
407
+ };
408
+
409
+ function mapAuthor(raw: GithubAuthor | null | undefined): GithubAuthor | undefined {
410
+ if (!raw) {
411
+ return undefined;
412
+ }
413
+ return {
414
+ id: raw.id !== undefined && raw.id !== null ? BigInt(raw.id) : undefined,
415
+ login: raw.login ?? undefined,
416
+ };
417
+ }
418
+
419
+ function mapLintOptions(options: LintRunOptions) {
420
+ return {
421
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
422
+ ...(options.fromRef !== undefined ? { fromRef: options.fromRef } : {}),
423
+ ...(options.toRef !== undefined ? { toRef: options.toRef } : {}),
424
+ ...(options.subjects !== undefined ? { subjects: options.subjects } : {}),
425
+ ...(options.rules !== undefined ? { rules: options.rules } : {}),
426
+ ...(options.scanCargo !== undefined ? { scanCargo: options.scanCargo } : {}),
427
+ };
428
+ }
429
+
430
+ function mapLintReport(raw: {
431
+ diagnostics: Array<{
432
+ rule: string;
433
+ severity: string;
434
+ message: string;
435
+ subject?: string | null;
436
+ hash?: string | null;
437
+ path?: string | null;
438
+ line?: number | null;
439
+ }>;
440
+ errorCount: number;
441
+ warningCount: number;
442
+ }): LintReportRecord {
443
+ return {
444
+ errorCount: raw.errorCount,
445
+ warningCount: raw.warningCount,
446
+ diagnostics: raw.diagnostics.map((item) => ({
447
+ rule: item.rule,
448
+ severity: item.severity as LintDiagnosticRecord["severity"],
449
+ message: item.message,
450
+ subject: item.subject ?? undefined,
451
+ hash: item.hash ?? undefined,
452
+ path: item.path ?? undefined,
453
+ line: item.line ?? undefined,
454
+ })),
455
+ };
456
+ }
457
+
458
+ function wrapBinding(binding: NativeBinding): NiftyNative {
459
+ return {
460
+ gitmoji: {
461
+ "known-gitmojis": () => binding.gitmojiKnownGitmojis(),
462
+ "validate-subject": (subject) => binding.gitmojiValidateSubject(subject),
463
+ "parse-subject": (subject) => binding.gitmojiParseSubject(subject),
464
+ "format-subject": (gitmoji, body) => binding.gitmojiFormatSubject(gitmoji, body),
465
+ "strip-gitmoji": (subject) => binding.gitmojiStripGitmoji(subject),
466
+ "leading-gitmoji": (subject) => binding.gitmojiLeadingGitmoji(subject) ?? undefined,
467
+ "section-for-gitmoji": (gitmoji) => binding.gitmojiSectionForGitmoji(gitmoji) as ReleaseSection,
468
+ "parse-noreply-email": (email) => mapAuthor(binding.gitmojiParseNoreplyEmail(email)),
469
+ "resolve-github-author": (email, authorMapJson) =>
470
+ mapAuthor(binding.gitmojiResolveGithubAuthor(email, authorMapJson)),
471
+ "display-login": (author) => binding.gitmojiDisplayLogin(author),
472
+ "profile-url": (author) => binding.gitmojiProfileUrl(author),
473
+ "avatar-url": (author) => binding.gitmojiAvatarUrl(author),
474
+ "author-mention": (email, authorName, authorMapJson) =>
475
+ binding.gitmojiAuthorMention(email, authorName, authorMapJson),
476
+ "commit-bullet": (body, email, authorName, authorMapJson) =>
477
+ binding.gitmojiCommitBullet(body, email, authorName, authorMapJson),
478
+ },
479
+ git: {
480
+ "discover-root": (startPath) => binding.gitDiscoverRoot(startPath),
481
+ "list-version-tags": (repoRoot) => binding.gitListVersionTags(repoRoot),
482
+ "list-tag-infos": (repoRoot) =>
483
+ binding.gitListTagInfos(repoRoot).map((tag) => ({
484
+ name: tag.name,
485
+ "short-hash": tag.shortHash,
486
+ })),
487
+ "format-tag-list": (repoRoot) => binding.gitFormatTagList(repoRoot),
488
+ "resolve-range": (repoRoot, version, fromRef, toRef) => {
489
+ const range = binding.gitResolveRange(repoRoot, version, fromRef, toRef);
490
+ return {
491
+ version: range.version,
492
+ "from-ref": range.fromRef,
493
+ "to-ref": range.toRef,
494
+ };
495
+ },
496
+ "collect-commits": (repoRoot, fromRef, toRef) => binding.gitCollectCommits(repoRoot, fromRef, toRef),
497
+ "detect-github-repo": (repoRoot) => binding.gitDetectGithubRepo(repoRoot) ?? undefined,
498
+ "parse-github-remote": (url) => binding.gitParseGithubRemote(url) ?? undefined,
499
+ },
500
+ history: {
501
+ "reword-export": (options) =>
502
+ binding.gitToolsRewordExport({
503
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
504
+ base: options.base,
505
+ ...(options.ref !== undefined ? { ref: options.ref } : {}),
506
+ path: options.path,
507
+ }),
508
+ "reword-rewrite": (options) => {
509
+ const report = binding.gitToolsRewordRewrite({
510
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
511
+ base: options.base,
512
+ ...(options.ref !== undefined ? { ref: options.ref } : {}),
513
+ path: options.path,
514
+ ...(options.dryRun !== undefined ? { dryRun: options.dryRun } : {}),
515
+ });
516
+ return {
517
+ changes: report.changes,
518
+ oldTip: report.oldTip,
519
+ newTip: report.newTip ?? undefined,
520
+ refName: report.refName,
521
+ dryRun: report.dryRun,
522
+ };
523
+ },
524
+ "retime-range": (options) =>
525
+ binding.gitToolsRetimeRange({
526
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
527
+ commit: options.commit,
528
+ ...(options.startDate !== undefined ? { startDate: options.startDate } : {}),
529
+ ...(options.endDate !== undefined ? { endDate: options.endDate } : {}),
530
+ ...(options.branch !== undefined ? { branch: options.branch } : {}),
531
+ ...(options.tip !== undefined ? { tip: options.tip } : {}),
532
+ }),
533
+ "retime-root": (options) =>
534
+ binding.gitToolsRetimeRoot({
535
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
536
+ ...(options.startDate !== undefined ? { startDate: options.startDate } : {}),
537
+ ...(options.endDate !== undefined ? { endDate: options.endDate } : {}),
538
+ ...(options.branch !== undefined ? { branch: options.branch } : {}),
539
+ ...(options.tip !== undefined ? { tip: options.tip } : {}),
540
+ ...(options.message !== undefined ? { message: options.message } : {}),
541
+ }),
542
+ "changelog-render": (options) => {
543
+ const report = binding.gitToolsChangelogRender({
544
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
545
+ ...(options.version !== undefined ? { version: options.version } : {}),
546
+ ...(options.fromRef !== undefined ? { fromRef: options.fromRef } : {}),
547
+ ...(options.toRef !== undefined ? { toRef: options.toRef } : {}),
548
+ ...(options.write !== undefined ? { write: options.write } : {}),
549
+ ...(options.tags !== undefined ? { tags: options.tags } : {}),
550
+ ...(options.repo !== undefined ? { repo: options.repo } : {}),
551
+ ...(options.authorMap !== undefined ? { authorMap: options.authorMap } : {}),
552
+ ...(options.releasesDir !== undefined ? { releasesDir: options.releasesDir } : {}),
553
+ });
554
+ return {
555
+ notes: report.notes,
556
+ version: report.version,
557
+ fromRef: report.fromRef ?? undefined,
558
+ toRef: report.toRef,
559
+ commitCount: report.commitCount,
560
+ writtenPath: report.writtenPath ?? undefined,
561
+ rangeLabel: report.rangeLabel,
562
+ };
563
+ },
564
+ "changelog-lookup": (options) => {
565
+ const author = binding.gitToolsChangelogLookup({
566
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
567
+ ...(options.email !== undefined ? { email: options.email } : {}),
568
+ ...(options.login !== undefined ? { login: options.login } : {}),
569
+ ...(options.map !== undefined ? { map: options.map } : {}),
570
+ ...(options.githubToken !== undefined ? { githubToken: options.githubToken } : {}),
571
+ ...(options.fetch !== undefined ? { fetch: options.fetch } : {}),
572
+ });
573
+ return mapAuthor(author) ?? {};
574
+ },
575
+ },
576
+ lint: {
577
+ run: (options) => mapLintReport(binding.lintRun(mapLintOptions(options))),
578
+ check: (options) => mapLintReport(binding.lintCheck(mapLintOptions(options))),
579
+ },
580
+ updater: {
581
+ run: (options) => {
582
+ binding.updaterRun({
583
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
584
+ ...(options.interactive !== undefined ? { interactive: options.interactive } : {}),
585
+ });
586
+ },
587
+ },
588
+ formatter: {
589
+ run: (options) => binding.formatterRun({
590
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
591
+ ...(options.check !== undefined ? { check: options.check } : {}),
592
+ }),
593
+ },
594
+ publisher: {
595
+ "publish-workspace": (options) =>
596
+ binding.publisherPublishWorkspace({
597
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
598
+ ...(options.dryRun !== undefined ? { dryRun: options.dryRun } : {}),
599
+ ...(options.refresh !== undefined ? { refresh: options.refresh } : {}),
600
+ ...(options.only !== undefined ? { only: options.only } : {}),
601
+ ...(options.packages !== undefined ? { packages: options.packages } : {}),
602
+ ...(options.tag !== undefined ? { tag: options.tag } : {}),
603
+ ...(options.access !== undefined ? { access: options.access } : {}),
604
+ ...(options.npm !== undefined ? { npm: options.npm } : {}),
605
+ ...(options.otp !== undefined ? { otp: options.otp } : {}),
606
+ ...(options.totpSecret !== undefined ? { totpSecret: options.totpSecret } : {}),
607
+ ...(options.token !== undefined ? { token: options.token } : {}),
608
+ }),
609
+ "trust-workspace": (options) =>
610
+ binding.publisherTrustWorkspace({
611
+ ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
612
+ ...(options.dryRun !== undefined ? { dryRun: options.dryRun } : {}),
613
+ ...(options.refresh !== undefined ? { refresh: options.refresh } : {}),
614
+ ...(options.only !== undefined ? { only: options.only } : {}),
615
+ ...(options.packages !== undefined ? { packages: options.packages } : {}),
616
+ ...(options.npm !== undefined ? { npm: options.npm } : {}),
617
+ ...(options.otp !== undefined ? { otp: options.otp } : {}),
618
+ ...(options.totpSecret !== undefined ? { totpSecret: options.totpSecret } : {}),
619
+ ...(options.token !== undefined ? { token: options.token } : {}),
620
+ }),
621
+ },
622
+ };
623
+ }
624
+
625
+ let cached: NiftyNative | undefined;
626
+
627
+ /** Load the platform-specific Node-API binary from `@doki-land/nifty-<platform>`. */
628
+ export function loadNiftyNative(): NiftyNative {
629
+ if (cached) {
630
+ return cached;
631
+ }
632
+ const key = `${process.platform}-${process.arch}`;
633
+ const pkg = PLATFORM_PACKAGES[key];
634
+ if (!pkg) {
635
+ throw new Error(`Unsupported platform for Nifty native bindings: ${key}`);
636
+ }
637
+ const require = createRequire(import.meta.url);
638
+ const binding = require(pkg).default as NativeBinding;
639
+ cached = wrapBinding(binding);
640
+ return cached;
641
+ }
642
+
643
+ export function mapTagInfo(raw: { name: string; "short-hash": string }): TagInfo {
644
+ return { name: raw.name, shortHash: raw["short-hash"] };
645
+ }
646
+
647
+ export function mapRangeInfo(raw: { version: string; "from-ref"?: string; "to-ref": string }): RangeInfo {
648
+ return {
649
+ version: raw.version,
650
+ fromRef: raw["from-ref"],
651
+ toRef: raw["to-ref"],
652
+ };
653
+ }
654
+
655
+ export function mapCommitRecord(raw: CommitRecord): CommitRecord {
656
+ return {
657
+ hash: raw.hash,
658
+ email: raw.email,
659
+ author: raw.author,
660
+ subject: raw.subject,
661
+ body: raw.body,
662
+ gitmoji: raw.gitmoji,
663
+ section: raw.section as ReleaseSection,
664
+ };
665
+ }