@doki-land/nifty 0.0.4 → 0.0.6

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