@doki-land/nifty 0.0.0 → 0.0.1
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/Readme.md +30 -30
- package/cli/nifty.mjs +11 -11
- package/locales/en-US/cli.json +41 -0
- package/locales/locales.json +4 -0
- package/package.json +13 -6
- package/src/cli/authArgs.ts +52 -52
- package/src/cli/bump-cmd.ts +55 -0
- package/src/cli/bump.ts +237 -237
- package/src/cli/cli.ts +39 -0
- package/src/cli/context.ts +36 -26
- package/src/cli/index.ts +9 -8
- package/src/cli/install-native-cmd.ts +22 -0
- package/src/cli/install-native.ts +80 -0
- package/src/cli/lint-cmd.ts +33 -0
- package/src/cli/lint.ts +113 -109
- package/src/cli/main.ts +1 -64
- package/src/cli/options.ts +40 -0
- package/src/cli/publish-cmd.ts +34 -0
- package/src/cli/publish.ts +95 -85
- package/src/cli/resolveNpm.ts +16 -16
- package/src/cli/trust-cmd.ts +35 -0
- package/src/cli/trust.ts +83 -77
- package/src/cli/update-cmd.ts +20 -0
- package/src/cli/update.ts +185 -182
- package/src/cli/upload-cmd.ts +44 -0
- package/src/cli/upload.ts +313 -280
- package/src/cli/workspace.ts +124 -124
- package/src/config/defineConfig.ts +12 -12
- package/src/config/detectProject.ts +189 -189
- package/src/config/index.ts +25 -25
- package/src/config/loadConfig.ts +129 -129
- package/src/config/types.ts +43 -43
- package/src/git.ts +61 -61
- package/src/github.ts +184 -184
- package/src/gitmoji.ts +77 -77
- package/src/index.ts +36 -36
- package/src/native.ts +284 -277
- package/src/nifty.ts +95 -95
- package/src/types.ts +40 -40
package/src/cli/bump.ts
CHANGED
|
@@ -1,237 +1,237 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
import { findWorkspaceRoot } from "./workspace.js";
|
|
5
|
-
|
|
6
|
-
export type BumpKind = "patch" | "minor" | "major";
|
|
7
|
-
|
|
8
|
-
export type BumpOptions = {
|
|
9
|
-
/** Explicit target version. When set, overrides `kind`. */
|
|
10
|
-
version?: string;
|
|
11
|
-
kind?: BumpKind;
|
|
12
|
-
cwd?: string;
|
|
13
|
-
dryRun?: boolean;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type BumpReport = {
|
|
17
|
-
root: string;
|
|
18
|
-
from: string;
|
|
19
|
-
to: string;
|
|
20
|
-
kind?: BumpKind;
|
|
21
|
-
cargo: string[];
|
|
22
|
-
npm: string[];
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const DEFAULT_KIND: BumpKind = "patch";
|
|
26
|
-
|
|
27
|
-
export async function runBump(argv: string[]): Promise<void> {
|
|
28
|
-
const options = parseBumpArgs(argv);
|
|
29
|
-
const report = bumpWorkspace(options);
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function parseBumpArgs(argv: string[]): BumpOptions {
|
|
34
|
-
let version: string | undefined;
|
|
35
|
-
let kind: BumpKind = DEFAULT_KIND;
|
|
36
|
-
let cwd: string | undefined;
|
|
37
|
-
let dryRun = false;
|
|
38
|
-
|
|
39
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
40
|
-
const arg = argv[i];
|
|
41
|
-
if (arg === "--dry-run") {
|
|
42
|
-
dryRun = true;
|
|
43
|
-
} else if (arg === "-C" || arg === "--cwd") {
|
|
44
|
-
cwd = argv[++i];
|
|
45
|
-
} else if (arg === "--version" || arg === "-v") {
|
|
46
|
-
version = argv[++i];
|
|
47
|
-
} else if (arg === "--patch") {
|
|
48
|
-
kind = "patch";
|
|
49
|
-
} else if (arg === "--minor") {
|
|
50
|
-
kind = "minor";
|
|
51
|
-
} else if (arg === "--major") {
|
|
52
|
-
kind = "major";
|
|
53
|
-
} else if (arg === "-h" || arg === "--help") {
|
|
54
|
-
printBumpHelp();
|
|
55
|
-
process.exit(0);
|
|
56
|
-
} else if (!arg.startsWith("-")) {
|
|
57
|
-
if (isBumpKind(arg)) {
|
|
58
|
-
kind = arg;
|
|
59
|
-
} else {
|
|
60
|
-
version = arg;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (version) {
|
|
66
|
-
assertVersion(version);
|
|
67
|
-
}
|
|
68
|
-
return { version, kind, cwd, dryRun };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function isBumpKind(value: string): value is BumpKind {
|
|
72
|
-
return value === "patch" || value === "minor" || value === "major";
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function assertVersion(version: string): void {
|
|
76
|
-
if (!/^\d+\.\d+\.\d+(-[\w.-]+)?$/.test(version)) {
|
|
77
|
-
throw new Error(`invalid version ${version}, expected semver like 0.0.0`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function bumpWorkspace(options: BumpOptions): BumpReport {
|
|
82
|
-
const root = findWorkspaceRoot(options.cwd ?? process.cwd());
|
|
83
|
-
const cratesDir = join(root, "projects", "crates");
|
|
84
|
-
const packagesDir = join(root, "projects", "packages");
|
|
85
|
-
|
|
86
|
-
const cargoPaths = collectCargoManifests(cratesDir);
|
|
87
|
-
const npmPaths = collectPackageManifests(packagesDir);
|
|
88
|
-
const from = readWorkspaceVersion(cargoPaths, npmPaths);
|
|
89
|
-
const to = options.version ?? bumpSemver(from, options.kind ?? DEFAULT_KIND);
|
|
90
|
-
assertVersion(to);
|
|
91
|
-
|
|
92
|
-
const cargo = cargoPaths.map((path) => bumpCargoManifest(path, to, options.dryRun));
|
|
93
|
-
const npm = npmPaths.map((path) => bumpPackageManifest(path, to, options.dryRun));
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
root,
|
|
97
|
-
from,
|
|
98
|
-
to,
|
|
99
|
-
kind: options.version ? undefined : options.kind ?? DEFAULT_KIND,
|
|
100
|
-
cargo,
|
|
101
|
-
npm,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function readWorkspaceVersion(cargoPaths: string[], npmPaths: string[]): string {
|
|
106
|
-
const versions = new Set<string>();
|
|
107
|
-
for (const path of cargoPaths) {
|
|
108
|
-
versions.add(readCargoVersion(path));
|
|
109
|
-
}
|
|
110
|
-
for (const path of npmPaths) {
|
|
111
|
-
versions.add(readPackageVersion(path));
|
|
112
|
-
}
|
|
113
|
-
if (versions.size === 0) {
|
|
114
|
-
throw new Error("no crate or package versions found in workspace");
|
|
115
|
-
}
|
|
116
|
-
if (versions.size > 1) {
|
|
117
|
-
throw new Error(`workspace versions are out of sync: ${[...versions].sort().join(", ")}`);
|
|
118
|
-
}
|
|
119
|
-
return [...versions][0];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function readCargoVersion(path: string): string {
|
|
123
|
-
const original = readFileSync(path, "utf8");
|
|
124
|
-
const match = original.match(/^version\s*=\s*"([^"]*)"/m);
|
|
125
|
-
if (!match) {
|
|
126
|
-
throw new Error(`no [package].version found in ${path}`);
|
|
127
|
-
}
|
|
128
|
-
return match[1];
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function readPackageVersion(path: string): string {
|
|
132
|
-
const parsed = JSON.parse(readFileSync(path, "utf8")) as { version?: string };
|
|
133
|
-
if (!parsed.version) {
|
|
134
|
-
throw new Error(`no version field in ${path}`);
|
|
135
|
-
}
|
|
136
|
-
return parsed.version;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export function bumpSemver(version: string, kind: BumpKind): string {
|
|
140
|
-
const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-.*)?$/);
|
|
141
|
-
if (!match) {
|
|
142
|
-
throw new Error(`cannot bump non-semver version ${version}`);
|
|
143
|
-
}
|
|
144
|
-
let major = Number(match[1]);
|
|
145
|
-
let minor = Number(match[2]);
|
|
146
|
-
let patch = Number(match[3]);
|
|
147
|
-
|
|
148
|
-
switch (kind) {
|
|
149
|
-
case "patch":
|
|
150
|
-
patch += 1;
|
|
151
|
-
break;
|
|
152
|
-
case "minor":
|
|
153
|
-
minor += 1;
|
|
154
|
-
patch = 0;
|
|
155
|
-
break;
|
|
156
|
-
case "major":
|
|
157
|
-
major += 1;
|
|
158
|
-
minor = 0;
|
|
159
|
-
patch = 0;
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return `${major}.${minor}.${patch}`;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function collectCargoManifests(cratesDir: string): string[] {
|
|
167
|
-
if (!existsSync(cratesDir)) {
|
|
168
|
-
return [];
|
|
169
|
-
}
|
|
170
|
-
return readdirSync(cratesDir, { withFileTypes: true })
|
|
171
|
-
.filter((entry) => entry.isDirectory())
|
|
172
|
-
.map((entry) => join(cratesDir, entry.name, "Cargo.toml"))
|
|
173
|
-
.filter((path) => existsSync(path));
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function collectPackageManifests(packagesDir: string): string[] {
|
|
177
|
-
if (!existsSync(packagesDir)) {
|
|
178
|
-
return [];
|
|
179
|
-
}
|
|
180
|
-
return readdirSync(packagesDir, { withFileTypes: true })
|
|
181
|
-
.filter((entry) => entry.isDirectory() && entry.name !== "node_modules")
|
|
182
|
-
.map((entry) => join(packagesDir, entry.name, "package.json"))
|
|
183
|
-
.filter((path) => existsSync(path));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function bumpCargoManifest(path: string, version: string, dryRun?: boolean): string {
|
|
187
|
-
const original = readFileSync(path, "utf8");
|
|
188
|
-
const next = original.replace(/^version\s*=\s*"[^"]*"/m, `version = "${version}"`);
|
|
189
|
-
if (next === original) {
|
|
190
|
-
throw new Error(`no [package].version found in ${path}`);
|
|
191
|
-
}
|
|
192
|
-
if (!dryRun) {
|
|
193
|
-
writeFileSync(path, next, "utf8");
|
|
194
|
-
}
|
|
195
|
-
return path;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function bumpPackageManifest(path: string, version: string, dryRun?: boolean): string {
|
|
199
|
-
const original = readFileSync(path, "utf8");
|
|
200
|
-
const parsed = JSON.parse(original) as { version?: string };
|
|
201
|
-
if (!parsed.version) {
|
|
202
|
-
throw new Error(`no version field in ${path}`);
|
|
203
|
-
}
|
|
204
|
-
parsed.version = version;
|
|
205
|
-
const next = `${JSON.stringify(parsed, null, 4)}\n`;
|
|
206
|
-
if (!dryRun) {
|
|
207
|
-
writeFileSync(path, next, "utf8");
|
|
208
|
-
}
|
|
209
|
-
return path;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function
|
|
213
|
-
const prefix = dryRun ? "would bump" : "bumped";
|
|
214
|
-
const kind = report.kind ? ` (${report.kind})` : "";
|
|
215
|
-
console.log(`${prefix} workspace ${report.root} ${report.from} -> ${report.to}${kind}`);
|
|
216
|
-
for (const path of report.cargo) {
|
|
217
|
-
console.log(` cargo: ${path}`);
|
|
218
|
-
}
|
|
219
|
-
for (const path of report.npm) {
|
|
220
|
-
console.log(` npm: ${path}`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function printBumpHelp(): void {
|
|
225
|
-
console.log(`nifty bump — align all crate and package versions in the workspace
|
|
226
|
-
|
|
227
|
-
Usage:
|
|
228
|
-
nifty bump # bump patch (default)
|
|
229
|
-
nifty bump patch
|
|
230
|
-
nifty bump minor
|
|
231
|
-
nifty bump major
|
|
232
|
-
nifty bump 1.2.3 # set explicit version
|
|
233
|
-
nifty bump --version 1.2.3
|
|
234
|
-
nifty bump --dry-run
|
|
235
|
-
nifty bump -C <cwd>
|
|
236
|
-
`);
|
|
237
|
-
}
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { findWorkspaceRoot } from "./workspace.js";
|
|
5
|
+
|
|
6
|
+
export type BumpKind = "patch" | "minor" | "major";
|
|
7
|
+
|
|
8
|
+
export type BumpOptions = {
|
|
9
|
+
/** Explicit target version. When set, overrides `kind`. */
|
|
10
|
+
version?: string;
|
|
11
|
+
kind?: BumpKind;
|
|
12
|
+
cwd?: string;
|
|
13
|
+
dryRun?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type BumpReport = {
|
|
17
|
+
root: string;
|
|
18
|
+
from: string;
|
|
19
|
+
to: string;
|
|
20
|
+
kind?: BumpKind;
|
|
21
|
+
cargo: string[];
|
|
22
|
+
npm: string[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const DEFAULT_KIND: BumpKind = "patch";
|
|
26
|
+
|
|
27
|
+
export async function runBump(argv: string[]): Promise<void> {
|
|
28
|
+
const options = parseBumpArgs(argv);
|
|
29
|
+
const report = bumpWorkspace(options);
|
|
30
|
+
printBumpReport(report, options.dryRun);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function parseBumpArgs(argv: string[]): BumpOptions {
|
|
34
|
+
let version: string | undefined;
|
|
35
|
+
let kind: BumpKind = DEFAULT_KIND;
|
|
36
|
+
let cwd: string | undefined;
|
|
37
|
+
let dryRun = false;
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
40
|
+
const arg = argv[i];
|
|
41
|
+
if (arg === "--dry-run") {
|
|
42
|
+
dryRun = true;
|
|
43
|
+
} else if (arg === "-C" || arg === "--cwd") {
|
|
44
|
+
cwd = argv[++i];
|
|
45
|
+
} else if (arg === "--version" || arg === "-v") {
|
|
46
|
+
version = argv[++i];
|
|
47
|
+
} else if (arg === "--patch") {
|
|
48
|
+
kind = "patch";
|
|
49
|
+
} else if (arg === "--minor") {
|
|
50
|
+
kind = "minor";
|
|
51
|
+
} else if (arg === "--major") {
|
|
52
|
+
kind = "major";
|
|
53
|
+
} else if (arg === "-h" || arg === "--help") {
|
|
54
|
+
printBumpHelp();
|
|
55
|
+
process.exit(0);
|
|
56
|
+
} else if (!arg.startsWith("-")) {
|
|
57
|
+
if (isBumpKind(arg)) {
|
|
58
|
+
kind = arg;
|
|
59
|
+
} else {
|
|
60
|
+
version = arg;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (version) {
|
|
66
|
+
assertVersion(version);
|
|
67
|
+
}
|
|
68
|
+
return { version, kind, cwd, dryRun };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isBumpKind(value: string): value is BumpKind {
|
|
72
|
+
return value === "patch" || value === "minor" || value === "major";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function assertVersion(version: string): void {
|
|
76
|
+
if (!/^\d+\.\d+\.\d+(-[\w.-]+)?$/.test(version)) {
|
|
77
|
+
throw new Error(`invalid version ${version}, expected semver like 0.0.0`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function bumpWorkspace(options: BumpOptions): BumpReport {
|
|
82
|
+
const root = findWorkspaceRoot(options.cwd ?? process.cwd());
|
|
83
|
+
const cratesDir = join(root, "projects", "crates");
|
|
84
|
+
const packagesDir = join(root, "projects", "packages");
|
|
85
|
+
|
|
86
|
+
const cargoPaths = collectCargoManifests(cratesDir);
|
|
87
|
+
const npmPaths = collectPackageManifests(packagesDir);
|
|
88
|
+
const from = readWorkspaceVersion(cargoPaths, npmPaths);
|
|
89
|
+
const to = options.version ?? bumpSemver(from, options.kind ?? DEFAULT_KIND);
|
|
90
|
+
assertVersion(to);
|
|
91
|
+
|
|
92
|
+
const cargo = cargoPaths.map((path) => bumpCargoManifest(path, to, options.dryRun));
|
|
93
|
+
const npm = npmPaths.map((path) => bumpPackageManifest(path, to, options.dryRun));
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
root,
|
|
97
|
+
from,
|
|
98
|
+
to,
|
|
99
|
+
kind: options.version ? undefined : options.kind ?? DEFAULT_KIND,
|
|
100
|
+
cargo,
|
|
101
|
+
npm,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function readWorkspaceVersion(cargoPaths: string[], npmPaths: string[]): string {
|
|
106
|
+
const versions = new Set<string>();
|
|
107
|
+
for (const path of cargoPaths) {
|
|
108
|
+
versions.add(readCargoVersion(path));
|
|
109
|
+
}
|
|
110
|
+
for (const path of npmPaths) {
|
|
111
|
+
versions.add(readPackageVersion(path));
|
|
112
|
+
}
|
|
113
|
+
if (versions.size === 0) {
|
|
114
|
+
throw new Error("no crate or package versions found in workspace");
|
|
115
|
+
}
|
|
116
|
+
if (versions.size > 1) {
|
|
117
|
+
throw new Error(`workspace versions are out of sync: ${[...versions].sort().join(", ")}`);
|
|
118
|
+
}
|
|
119
|
+
return [...versions][0];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function readCargoVersion(path: string): string {
|
|
123
|
+
const original = readFileSync(path, "utf8");
|
|
124
|
+
const match = original.match(/^version\s*=\s*"([^"]*)"/m);
|
|
125
|
+
if (!match) {
|
|
126
|
+
throw new Error(`no [package].version found in ${path}`);
|
|
127
|
+
}
|
|
128
|
+
return match[1];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function readPackageVersion(path: string): string {
|
|
132
|
+
const parsed = JSON.parse(readFileSync(path, "utf8")) as { version?: string };
|
|
133
|
+
if (!parsed.version) {
|
|
134
|
+
throw new Error(`no version field in ${path}`);
|
|
135
|
+
}
|
|
136
|
+
return parsed.version;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function bumpSemver(version: string, kind: BumpKind): string {
|
|
140
|
+
const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-.*)?$/);
|
|
141
|
+
if (!match) {
|
|
142
|
+
throw new Error(`cannot bump non-semver version ${version}`);
|
|
143
|
+
}
|
|
144
|
+
let major = Number(match[1]);
|
|
145
|
+
let minor = Number(match[2]);
|
|
146
|
+
let patch = Number(match[3]);
|
|
147
|
+
|
|
148
|
+
switch (kind) {
|
|
149
|
+
case "patch":
|
|
150
|
+
patch += 1;
|
|
151
|
+
break;
|
|
152
|
+
case "minor":
|
|
153
|
+
minor += 1;
|
|
154
|
+
patch = 0;
|
|
155
|
+
break;
|
|
156
|
+
case "major":
|
|
157
|
+
major += 1;
|
|
158
|
+
minor = 0;
|
|
159
|
+
patch = 0;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return `${major}.${minor}.${patch}`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function collectCargoManifests(cratesDir: string): string[] {
|
|
167
|
+
if (!existsSync(cratesDir)) {
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
170
|
+
return readdirSync(cratesDir, { withFileTypes: true })
|
|
171
|
+
.filter((entry) => entry.isDirectory())
|
|
172
|
+
.map((entry) => join(cratesDir, entry.name, "Cargo.toml"))
|
|
173
|
+
.filter((path) => existsSync(path));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function collectPackageManifests(packagesDir: string): string[] {
|
|
177
|
+
if (!existsSync(packagesDir)) {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
return readdirSync(packagesDir, { withFileTypes: true })
|
|
181
|
+
.filter((entry) => entry.isDirectory() && entry.name !== "node_modules")
|
|
182
|
+
.map((entry) => join(packagesDir, entry.name, "package.json"))
|
|
183
|
+
.filter((path) => existsSync(path));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function bumpCargoManifest(path: string, version: string, dryRun?: boolean): string {
|
|
187
|
+
const original = readFileSync(path, "utf8");
|
|
188
|
+
const next = original.replace(/^version\s*=\s*"[^"]*"/m, `version = "${version}"`);
|
|
189
|
+
if (next === original) {
|
|
190
|
+
throw new Error(`no [package].version found in ${path}`);
|
|
191
|
+
}
|
|
192
|
+
if (!dryRun) {
|
|
193
|
+
writeFileSync(path, next, "utf8");
|
|
194
|
+
}
|
|
195
|
+
return path;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function bumpPackageManifest(path: string, version: string, dryRun?: boolean): string {
|
|
199
|
+
const original = readFileSync(path, "utf8");
|
|
200
|
+
const parsed = JSON.parse(original) as { version?: string };
|
|
201
|
+
if (!parsed.version) {
|
|
202
|
+
throw new Error(`no version field in ${path}`);
|
|
203
|
+
}
|
|
204
|
+
parsed.version = version;
|
|
205
|
+
const next = `${JSON.stringify(parsed, null, 4)}\n`;
|
|
206
|
+
if (!dryRun) {
|
|
207
|
+
writeFileSync(path, next, "utf8");
|
|
208
|
+
}
|
|
209
|
+
return path;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function printBumpReport(report: BumpReport, dryRun?: boolean): void {
|
|
213
|
+
const prefix = dryRun ? "would bump" : "bumped";
|
|
214
|
+
const kind = report.kind ? ` (${report.kind})` : "";
|
|
215
|
+
console.log(`${prefix} workspace ${report.root} ${report.from} -> ${report.to}${kind}`);
|
|
216
|
+
for (const path of report.cargo) {
|
|
217
|
+
console.log(` cargo: ${path}`);
|
|
218
|
+
}
|
|
219
|
+
for (const path of report.npm) {
|
|
220
|
+
console.log(` npm: ${path}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function printBumpHelp(): void {
|
|
225
|
+
console.log(`nifty bump — align all crate and package versions in the workspace
|
|
226
|
+
|
|
227
|
+
Usage:
|
|
228
|
+
nifty bump # bump patch (default)
|
|
229
|
+
nifty bump patch
|
|
230
|
+
nifty bump minor
|
|
231
|
+
nifty bump major
|
|
232
|
+
nifty bump 1.2.3 # set explicit version
|
|
233
|
+
nifty bump --version 1.2.3
|
|
234
|
+
nifty bump --dry-run
|
|
235
|
+
nifty bump -C <cwd>
|
|
236
|
+
`);
|
|
237
|
+
}
|
package/src/cli/cli.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { createCli } from "@vmz/commander";
|
|
5
|
+
|
|
6
|
+
import { registerBumpCommand } from "./bump-cmd.js";
|
|
7
|
+
import { registerInstallNativeCommand } from "./install-native-cmd.js";
|
|
8
|
+
import { registerLintCommands } from "./lint-cmd.js";
|
|
9
|
+
import { registerPublishCommand } from "./publish-cmd.js";
|
|
10
|
+
import { registerTrustCommand } from "./trust-cmd.js";
|
|
11
|
+
import { registerUpdateCommand } from "./update-cmd.js";
|
|
12
|
+
import { registerUploadCommand } from "./upload-cmd.js";
|
|
13
|
+
|
|
14
|
+
function buildNiftyCli() {
|
|
15
|
+
const localesRoot = join(dirname(fileURLToPath(import.meta.url)), "../../locales");
|
|
16
|
+
const cli = createCli("nifty")
|
|
17
|
+
.locales(localesRoot)
|
|
18
|
+
.intro("cli.intro")
|
|
19
|
+
.option("-C, --cwd <dir>", "cli.opt.cwd");
|
|
20
|
+
|
|
21
|
+
registerUpdateCommand(cli);
|
|
22
|
+
registerLintCommands(cli);
|
|
23
|
+
registerUploadCommand(cli);
|
|
24
|
+
registerInstallNativeCommand(cli);
|
|
25
|
+
registerBumpCommand(cli);
|
|
26
|
+
registerPublishCommand(cli);
|
|
27
|
+
registerTrustCommand(cli);
|
|
28
|
+
|
|
29
|
+
return cli;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function runCli(argv: string[]): Promise<number> {
|
|
33
|
+
try {
|
|
34
|
+
return await buildNiftyCli().parse(argv);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/cli/context.ts
CHANGED
|
@@ -1,26 +1,36 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
|
|
3
|
+
import type { ParsedOptions } from "@vmz/commander";
|
|
4
|
+
|
|
5
|
+
import { loadConfig } from "../config/loadConfig.js";
|
|
6
|
+
import { cwdFrom } from "./options.js";
|
|
7
|
+
|
|
8
|
+
/** Parse shared CLI flags used across nifty commands. */
|
|
9
|
+
export function parseCliContext(argv: string[]): { cwd: string; dryRun: boolean } {
|
|
10
|
+
let cwd = process.cwd();
|
|
11
|
+
let dryRun = false;
|
|
12
|
+
|
|
13
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
14
|
+
const arg = argv[i];
|
|
15
|
+
if (arg === "--dry-run") {
|
|
16
|
+
dryRun = true;
|
|
17
|
+
} else if (arg === "-C" || arg === "--cwd") {
|
|
18
|
+
cwd = resolve(argv[++i] ?? cwd);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return { cwd, dryRun };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Ensure `nifty.config.*` exists before running a command (skip create on `--dry-run`). */
|
|
26
|
+
export async function bootstrapNiftyConfig(argv: string[]): Promise<void> {
|
|
27
|
+
const { cwd, dryRun } = parseCliContext(argv);
|
|
28
|
+
await loadConfig({ cwd, createIfMissing: !dryRun });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Commander action hook: load config from parsed global/command flags. */
|
|
32
|
+
export async function bootstrapFromOptions(options: ParsedOptions): Promise<void> {
|
|
33
|
+
const cwd = cwdFrom(options) ?? process.cwd();
|
|
34
|
+
const dryRun = options["dry-run"] === true;
|
|
35
|
+
await loadConfig({ cwd, createIfMissing: !dryRun });
|
|
36
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export { runCli } from "./main.js";
|
|
2
|
-
export { bumpSemver, bumpWorkspace, runBump, type BumpKind, type BumpOptions, type BumpReport } from "./bump.js";
|
|
3
|
-
export { runPublish, type PublishOptions, type PublishReport } from "./publish.js";
|
|
4
|
-
export { runTrust, type TrustReport } from "./trust.js";
|
|
5
|
-
export { runUpdate } from "./update.js";
|
|
6
|
-
export { runLint } from "./lint.js";
|
|
7
|
-
export { runUpload } from "./upload.js";
|
|
8
|
-
export {
|
|
1
|
+
export { runCli } from "./main.js";
|
|
2
|
+
export { bumpSemver, bumpWorkspace, runBump, type BumpKind, type BumpOptions, type BumpReport } from "./bump.js";
|
|
3
|
+
export { runPublish, type PublishOptions, type PublishReport } from "./publish.js";
|
|
4
|
+
export { runTrust, type TrustReport } from "./trust.js";
|
|
5
|
+
export { runUpdate } from "./update.js";
|
|
6
|
+
export { runLint } from "./lint.js";
|
|
7
|
+
export { runUpload } from "./upload.js";
|
|
8
|
+
export { installNativeFromOptions, type InstallNativeOptions } from "./install-native.js";
|
|
9
|
+
export { findWorkspaceRoot, listWorkspacePackages, type WorkspacePackage } from "./workspace.js";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Cli, ParsedOptions } from "@vmz/commander";
|
|
2
|
+
|
|
3
|
+
import { installNativeFromOptions } from "./install-native.js";
|
|
4
|
+
import { cwdFrom, str } from "./options.js";
|
|
5
|
+
|
|
6
|
+
export function registerInstallNativeCommand(cli: Cli): void {
|
|
7
|
+
cli.command("install-native", "cli.cmd.install-native")
|
|
8
|
+
.option("--from <dir>", "cli.opt.from-artifacts")
|
|
9
|
+
.action(async (options) => cmdInstallNative(options));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function cmdInstallNative(options: ParsedOptions): Promise<number> {
|
|
13
|
+
const from =
|
|
14
|
+
str(options, "from") ??
|
|
15
|
+
process.env.NATIVE_ARTIFACT_ROOT ??
|
|
16
|
+
"native-artifacts";
|
|
17
|
+
installNativeFromOptions({
|
|
18
|
+
from,
|
|
19
|
+
cwd: cwdFrom(options),
|
|
20
|
+
});
|
|
21
|
+
return 0;
|
|
22
|
+
}
|