@wrongstack/plugins 0.236.0 → 0.255.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/file-watcher.js +6 -17
- package/dist/git-autocommit.js +2 -1
- package/dist/index.js +203 -119
- package/dist/semver-bump.d.ts +13 -1
- package/dist/semver-bump.js +188 -94
- package/dist/shell-check.js +3 -2
- package/package.json +3 -3
package/dist/file-watcher.js
CHANGED
|
@@ -99,26 +99,15 @@ var plugin = {
|
|
|
99
99
|
if (autoIndex && isIndexableFile(fullPath)) {
|
|
100
100
|
debounceEvent(`index:${fullPath}`, async () => {
|
|
101
101
|
try {
|
|
102
|
-
const {
|
|
102
|
+
const { enqueueReindex } = await import('@wrongstack/tools/codebase-index/index.js');
|
|
103
103
|
const root = indexProjectRoot || dirPath;
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
const fakeClose = async () => {
|
|
107
|
-
};
|
|
108
|
-
const fakeRecordFileChange = () => {
|
|
109
|
-
};
|
|
110
|
-
const ctx = {
|
|
104
|
+
enqueueReindex({
|
|
111
105
|
projectRoot: root,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
readFiles: /* @__PURE__ */ new Set(),
|
|
116
|
-
fileMtimes: /* @__PURE__ */ new Map(),
|
|
117
|
-
session: { id: "fw", append: fakeAppend, close: fakeClose, recordFileChange: fakeRecordFileChange }
|
|
118
|
-
};
|
|
119
|
-
await runIndexer(ctx, { projectRoot: root, files: [fullPath] });
|
|
106
|
+
files: [fullPath],
|
|
107
|
+
onError: (err) => api.log.warn(`file-watcher: auto-index failed for ${fullPath}: ${err}`)
|
|
108
|
+
});
|
|
120
109
|
api.metrics.counter("index_file", 1);
|
|
121
|
-
api.log.debug(`file-watcher: auto-index
|
|
110
|
+
api.log.debug(`file-watcher: auto-index scheduled for ${fullPath}`);
|
|
122
111
|
} catch (err) {
|
|
123
112
|
api.log.warn(`file-watcher: auto-index failed for ${fullPath}: ${err}`);
|
|
124
113
|
}
|
package/dist/git-autocommit.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFileSync, execSync } from 'child_process';
|
|
2
|
-
import { watch, existsSync,
|
|
2
|
+
import { watch, existsSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { isAbsolute, join } from 'path';
|
|
5
5
|
import { expectDefined, deepMerge as deepMerge$1 } from '@wrongstack/core';
|
|
@@ -135,7 +135,7 @@ async function runAutoDoc(input, api) {
|
|
|
135
135
|
const results = [];
|
|
136
136
|
for (const file of input.files) {
|
|
137
137
|
try {
|
|
138
|
-
const { readFileSync: readFileSync2, writeFileSync } = await import('fs');
|
|
138
|
+
const { readFileSync: readFileSync2, writeFileSync: writeFileSync2 } = await import('fs');
|
|
139
139
|
let content;
|
|
140
140
|
try {
|
|
141
141
|
content = readFileSync2(file, "utf-8");
|
|
@@ -152,7 +152,7 @@ async function runAutoDoc(input, api) {
|
|
|
152
152
|
results.push({ file, entity: entity.name });
|
|
153
153
|
}
|
|
154
154
|
if (!input.dryRun && results.length > 0) {
|
|
155
|
-
|
|
155
|
+
writeFileSync2(file, modified, "utf-8");
|
|
156
156
|
api.log.info(`auto-doc: updated ${file}`);
|
|
157
157
|
}
|
|
158
158
|
} catch (err) {
|
|
@@ -251,7 +251,8 @@ function runGit(args, cwd) {
|
|
|
251
251
|
cwd,
|
|
252
252
|
stdio: ["pipe", "pipe", "pipe"],
|
|
253
253
|
timeout: 3e4,
|
|
254
|
-
maxBuffer: 10 * 1024 * 1024
|
|
254
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
255
|
+
windowsHide: true
|
|
255
256
|
}).trim();
|
|
256
257
|
} catch (err) {
|
|
257
258
|
const e = err;
|
|
@@ -669,7 +670,7 @@ var API_VERSION2 = "^0.1.10";
|
|
|
669
670
|
function runShellCheck(files, severity, cwd) {
|
|
670
671
|
if (!existsSync("shellcheck")) {
|
|
671
672
|
try {
|
|
672
|
-
execSync("shellcheck --version", { encoding: "utf-8", stdio: "ignore" });
|
|
673
|
+
execSync("shellcheck --version", { encoding: "utf-8", stdio: "ignore", windowsHide: true });
|
|
673
674
|
} catch {
|
|
674
675
|
throw new Error("shellcheck is not installed. Install via: apt install shellcheck / brew install shellcheck");
|
|
675
676
|
}
|
|
@@ -693,7 +694,8 @@ function runShellCheck(files, severity, cwd) {
|
|
|
693
694
|
encoding: "utf-8",
|
|
694
695
|
cwd,
|
|
695
696
|
stdio: ["pipe", "pipe", "pipe"],
|
|
696
|
-
timeout: 6e4
|
|
697
|
+
timeout: 6e4,
|
|
698
|
+
windowsHide: true
|
|
697
699
|
});
|
|
698
700
|
} catch (err) {
|
|
699
701
|
const e = err;
|
|
@@ -1202,26 +1204,15 @@ var plugin5 = {
|
|
|
1202
1204
|
if (autoIndex && isIndexableFile(fullPath)) {
|
|
1203
1205
|
debounceEvent(`index:${fullPath}`, async () => {
|
|
1204
1206
|
try {
|
|
1205
|
-
const {
|
|
1207
|
+
const { enqueueReindex } = await import('@wrongstack/tools/codebase-index/index.js');
|
|
1206
1208
|
const root = indexProjectRoot || dirPath;
|
|
1207
|
-
|
|
1208
|
-
};
|
|
1209
|
-
const fakeClose = async () => {
|
|
1210
|
-
};
|
|
1211
|
-
const fakeRecordFileChange = () => {
|
|
1212
|
-
};
|
|
1213
|
-
const ctx = {
|
|
1209
|
+
enqueueReindex({
|
|
1214
1210
|
projectRoot: root,
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
readFiles: /* @__PURE__ */ new Set(),
|
|
1219
|
-
fileMtimes: /* @__PURE__ */ new Map(),
|
|
1220
|
-
session: { id: "fw", append: fakeAppend, close: fakeClose, recordFileChange: fakeRecordFileChange }
|
|
1221
|
-
};
|
|
1222
|
-
await runIndexer(ctx, { projectRoot: root, files: [fullPath] });
|
|
1211
|
+
files: [fullPath],
|
|
1212
|
+
onError: (err) => api.log.warn(`file-watcher: auto-index failed for ${fullPath}: ${err}`)
|
|
1213
|
+
});
|
|
1223
1214
|
api.metrics.counter("index_file", 1);
|
|
1224
|
-
api.log.debug(`file-watcher: auto-index
|
|
1215
|
+
api.log.debug(`file-watcher: auto-index scheduled for ${fullPath}`);
|
|
1225
1216
|
} catch (err) {
|
|
1226
1217
|
api.log.warn(`file-watcher: auto-index failed for ${fullPath}: ${err}`);
|
|
1227
1218
|
}
|
|
@@ -2264,8 +2255,8 @@ var plugin9 = {
|
|
|
2264
2255
|
if (isAbsolute(outputPath) || outputPath.includes("..")) {
|
|
2265
2256
|
return { ok: false, error: 'outputPath must be a relative path without ".." components' };
|
|
2266
2257
|
}
|
|
2267
|
-
const { writeFileSync } = await import('fs');
|
|
2268
|
-
|
|
2258
|
+
const { writeFileSync: writeFileSync2 } = await import('fs');
|
|
2259
|
+
writeFileSync2(outputPath, result, "utf-8");
|
|
2269
2260
|
return {
|
|
2270
2261
|
ok: true,
|
|
2271
2262
|
outputPath,
|
|
@@ -2328,8 +2319,8 @@ var plugin9 = {
|
|
|
2328
2319
|
if (isAbsolute(outputPath) || outputPath.includes("..")) {
|
|
2329
2320
|
return { ok: false, error: 'outputPath must be a relative path without ".." components' };
|
|
2330
2321
|
}
|
|
2331
|
-
const { writeFileSync } = await import('fs');
|
|
2332
|
-
|
|
2322
|
+
const { writeFileSync: writeFileSync2 } = await import('fs');
|
|
2323
|
+
writeFileSync2(outputPath, result, "utf-8");
|
|
2333
2324
|
return {
|
|
2334
2325
|
ok: true,
|
|
2335
2326
|
templatePath,
|
|
@@ -2430,7 +2421,8 @@ function runGit2(args, cwd) {
|
|
|
2430
2421
|
encoding: "utf-8",
|
|
2431
2422
|
cwd,
|
|
2432
2423
|
stdio: ["pipe", "pipe", "pipe"],
|
|
2433
|
-
timeout: 3e4
|
|
2424
|
+
timeout: 3e4,
|
|
2425
|
+
windowsHide: true
|
|
2434
2426
|
}).trim();
|
|
2435
2427
|
} catch (err) {
|
|
2436
2428
|
const e = err;
|
|
@@ -2447,10 +2439,25 @@ function getPackageJson(cwd) {
|
|
|
2447
2439
|
return null;
|
|
2448
2440
|
}
|
|
2449
2441
|
}
|
|
2442
|
+
function collectManifests(root) {
|
|
2443
|
+
const paths = [];
|
|
2444
|
+
const rootPkg = join(root, "package.json");
|
|
2445
|
+
if (existsSync(rootPkg)) paths.push(rootPkg);
|
|
2446
|
+
for (const group of ["packages", "apps"]) {
|
|
2447
|
+
const groupDir = join(root, group);
|
|
2448
|
+
if (!existsSync(groupDir)) continue;
|
|
2449
|
+
for (const entry of readdirSync(groupDir, { withFileTypes: true })) {
|
|
2450
|
+
if (!entry.isDirectory()) continue;
|
|
2451
|
+
const candidate = join(groupDir, entry.name, "package.json");
|
|
2452
|
+
if (existsSync(candidate)) paths.push(candidate);
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
return paths;
|
|
2456
|
+
}
|
|
2450
2457
|
function parseVersion(v) {
|
|
2451
2458
|
const m = v.match(/^v?(\d+)\.(\d+)\.(\d+)/);
|
|
2452
2459
|
if (!m) return [0, 0, 0];
|
|
2453
|
-
return [Number.parseInt(expectDefined(m[1])), Number.parseInt(expectDefined(m[2])), Number.parseInt(expectDefined(m[3]))];
|
|
2460
|
+
return [Number.parseInt(expectDefined(m[1]), 10), Number.parseInt(expectDefined(m[2]), 10), Number.parseInt(expectDefined(m[3]), 10)];
|
|
2454
2461
|
}
|
|
2455
2462
|
function bumpVersion(version, part) {
|
|
2456
2463
|
let [major, minor, patch] = parseVersion(version);
|
|
@@ -2468,6 +2475,15 @@ function bumpVersion(version, part) {
|
|
|
2468
2475
|
}
|
|
2469
2476
|
return `${major}.${minor}.${patch}`;
|
|
2470
2477
|
}
|
|
2478
|
+
function parseConventional(subject) {
|
|
2479
|
+
const m = subject.match(/^(\w+)(!)?(?:\(([^)]+)\))?(!)?:\s+(.+)/);
|
|
2480
|
+
return {
|
|
2481
|
+
type: m?.[1] ?? "chore",
|
|
2482
|
+
breaking: !!(m?.[2] ?? m?.[4]),
|
|
2483
|
+
scope: m?.[3],
|
|
2484
|
+
message: m?.[5] ?? subject
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2471
2487
|
function getRecentCommits(sinceTag, cwd) {
|
|
2472
2488
|
const range = sinceTag ? `${sinceTag}..HEAD` : "-30";
|
|
2473
2489
|
const output = runGit2(["log", range, "--format=%H %s"], cwd);
|
|
@@ -2476,25 +2492,12 @@ function getRecentCommits(sinceTag, cwd) {
|
|
|
2476
2492
|
const spaceIdx = line.indexOf(" ");
|
|
2477
2493
|
const hash = line.slice(0, spaceIdx);
|
|
2478
2494
|
const message = line.slice(spaceIdx + 1);
|
|
2479
|
-
|
|
2480
|
-
const type = m?.[1] ?? "chore";
|
|
2481
|
-
const breaking = !!m?.[2];
|
|
2482
|
-
const scope = m?.[2];
|
|
2483
|
-
const msg = m?.[3] ?? message;
|
|
2484
|
-
return { hash, type, scope, message: msg, breaking };
|
|
2495
|
+
return { hash, ...parseConventional(message) };
|
|
2485
2496
|
});
|
|
2486
2497
|
}
|
|
2487
2498
|
function determineBump(commits) {
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
return "major";
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
for (const c of commits) {
|
|
2494
|
-
if (c.type === "feat" || c.type === "refactor" && c.scope) {
|
|
2495
|
-
return "minor";
|
|
2496
|
-
}
|
|
2497
|
-
}
|
|
2499
|
+
if (commits.some((c) => c.breaking)) return "major";
|
|
2500
|
+
if (commits.some((c) => c.type === "feat")) return "minor";
|
|
2498
2501
|
return "patch";
|
|
2499
2502
|
}
|
|
2500
2503
|
function generateChangelog(commits) {
|
|
@@ -2556,12 +2559,13 @@ var plugin10 = {
|
|
|
2556
2559
|
version: "0.1.0",
|
|
2557
2560
|
description: "Conventional-commit-driven semver version bumps with changelog generation",
|
|
2558
2561
|
apiVersion: API_VERSION9,
|
|
2559
|
-
capabilities: { tools: true },
|
|
2562
|
+
capabilities: { tools: true, slashCommands: true },
|
|
2560
2563
|
defaultConfig: {
|
|
2561
2564
|
tagPrefix: "v",
|
|
2562
2565
|
changelogFile: "CHANGELOG.md",
|
|
2563
2566
|
autoTag: true,
|
|
2564
|
-
tagMessage: "Release {{version}}"
|
|
2567
|
+
tagMessage: "Release {{version}}",
|
|
2568
|
+
defaultPart: "patch"
|
|
2565
2569
|
},
|
|
2566
2570
|
configSchema: {
|
|
2567
2571
|
type: "object",
|
|
@@ -2569,12 +2573,114 @@ var plugin10 = {
|
|
|
2569
2573
|
tagPrefix: { type: "string", default: "v" },
|
|
2570
2574
|
changelogFile: { type: "string", default: "CHANGELOG.md" },
|
|
2571
2575
|
autoTag: { type: "boolean", default: true },
|
|
2572
|
-
tagMessage: { type: "string", default: "Release {{version}}" }
|
|
2576
|
+
tagMessage: { type: "string", default: "Release {{version}}" },
|
|
2577
|
+
defaultPart: { type: "string", enum: ["major", "minor", "patch", "auto"], default: "patch" }
|
|
2573
2578
|
}
|
|
2574
2579
|
},
|
|
2575
2580
|
setup(api) {
|
|
2576
2581
|
const tagPrefix = api.config.extensions?.["semver-bump"]?.["tagPrefix"] ?? "v";
|
|
2577
2582
|
const autoTag = api.config.extensions?.["semver-bump"]?.["autoTag"] ?? true;
|
|
2583
|
+
const VALID_PARTS = ["major", "minor", "patch", "auto"];
|
|
2584
|
+
function readDefaultPart(cfg) {
|
|
2585
|
+
const raw = cfg.extensions?.["semver-bump"]?.["defaultPart"];
|
|
2586
|
+
return VALID_PARTS.includes(raw) ? raw : "patch";
|
|
2587
|
+
}
|
|
2588
|
+
let defaultPart = readDefaultPart(api.config);
|
|
2589
|
+
api.onConfigChange?.((next) => {
|
|
2590
|
+
defaultPart = readDefaultPart(next);
|
|
2591
|
+
});
|
|
2592
|
+
async function performBump(part, dryRun, cwd) {
|
|
2593
|
+
const pkg = getPackageJson(cwd);
|
|
2594
|
+
if (!pkg) {
|
|
2595
|
+
return { ok: false, error: "No package.json found" };
|
|
2596
|
+
}
|
|
2597
|
+
const currentVersion = pkg.version;
|
|
2598
|
+
let bumpPart = part;
|
|
2599
|
+
let commits = [];
|
|
2600
|
+
if (part === "auto") {
|
|
2601
|
+
let lastTag;
|
|
2602
|
+
try {
|
|
2603
|
+
const tagsOutput = runGit2(["describe", "--tags", "--abbrev=0"], cwd);
|
|
2604
|
+
lastTag = tagsOutput || void 0;
|
|
2605
|
+
} catch {
|
|
2606
|
+
}
|
|
2607
|
+
try {
|
|
2608
|
+
commits = getRecentCommits(lastTag, cwd);
|
|
2609
|
+
} catch (err) {
|
|
2610
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2611
|
+
return { ok: false, error: `Git error: ${msg}`, bumpPart: "patch" };
|
|
2612
|
+
}
|
|
2613
|
+
bumpPart = determineBump(commits);
|
|
2614
|
+
} else {
|
|
2615
|
+
bumpPart = part;
|
|
2616
|
+
}
|
|
2617
|
+
const newVersion = bumpVersion(currentVersion, bumpPart);
|
|
2618
|
+
if (dryRun) {
|
|
2619
|
+
return {
|
|
2620
|
+
ok: true,
|
|
2621
|
+
dryRun: true,
|
|
2622
|
+
currentVersion,
|
|
2623
|
+
suggestedBump: bumpPart,
|
|
2624
|
+
newVersion,
|
|
2625
|
+
commitCount: part === "auto" ? commits.length : void 0,
|
|
2626
|
+
message: `Would bump ${currentVersion} \u2192 ${newVersion} (${bumpPart})`
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
const root = cwd ?? process.cwd();
|
|
2630
|
+
const bumpScript = join(root, "scripts", "bump-version.mjs");
|
|
2631
|
+
const changed = collectManifests(root);
|
|
2632
|
+
if (existsSync(bumpScript)) {
|
|
2633
|
+
try {
|
|
2634
|
+
execFileSync(process.execPath, [bumpScript, "set", newVersion], {
|
|
2635
|
+
cwd: root,
|
|
2636
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
2637
|
+
timeout: 3e4,
|
|
2638
|
+
windowsHide: true
|
|
2639
|
+
});
|
|
2640
|
+
} catch (err) {
|
|
2641
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2642
|
+
return { ok: false, error: `bump script failed: ${msg}` };
|
|
2643
|
+
}
|
|
2644
|
+
for (const rel of ["package.json", "package-lock.json", "src/lib/utils.ts", "index.html"]) {
|
|
2645
|
+
const p = join(root, "website", rel);
|
|
2646
|
+
if (existsSync(p)) changed.push(p);
|
|
2647
|
+
}
|
|
2648
|
+
} else {
|
|
2649
|
+
for (const manifest of changed) {
|
|
2650
|
+
const pkgData = JSON.parse(readFileSync(manifest, "utf-8"));
|
|
2651
|
+
pkgData.version = newVersion;
|
|
2652
|
+
writeFileSync(manifest, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
try {
|
|
2656
|
+
runGit2(["add", "--", ...changed], cwd);
|
|
2657
|
+
runGit2(["commit", "-m", `chore: bump version to ${newVersion}`], cwd);
|
|
2658
|
+
} catch {
|
|
2659
|
+
}
|
|
2660
|
+
if (autoTag) {
|
|
2661
|
+
try {
|
|
2662
|
+
runGit2(["tag", "-a", `${tagPrefix}${newVersion}`, "-m", `Release ${newVersion}`], cwd);
|
|
2663
|
+
} catch {
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
api.log.info("semver-bump: bumped", { from: currentVersion, to: newVersion, bump: bumpPart });
|
|
2667
|
+
api.metrics.counter("version_bump", 1, { bump: bumpPart });
|
|
2668
|
+
await api.session.append({
|
|
2669
|
+
type: "semver-bump:bumped",
|
|
2670
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2671
|
+
from: currentVersion,
|
|
2672
|
+
to: newVersion,
|
|
2673
|
+
bump: bumpPart
|
|
2674
|
+
});
|
|
2675
|
+
return {
|
|
2676
|
+
ok: true,
|
|
2677
|
+
currentVersion,
|
|
2678
|
+
newVersion,
|
|
2679
|
+
bump: bumpPart,
|
|
2680
|
+
tag: `${tagPrefix}${newVersion}`,
|
|
2681
|
+
message: `Bumped ${currentVersion} \u2192 ${newVersion} (${bumpPart})`
|
|
2682
|
+
};
|
|
2683
|
+
}
|
|
2578
2684
|
api.tools.register({
|
|
2579
2685
|
name: "semver_bump",
|
|
2580
2686
|
description: "Determine the next version bump from conventional commits since the last tag, or force a specific bump. Creates a git tag.",
|
|
@@ -2583,7 +2689,7 @@ var plugin10 = {
|
|
|
2583
2689
|
properties: {
|
|
2584
2690
|
cwd: { type: "string", description: "Working directory (defaults to project root)" },
|
|
2585
2691
|
dryRun: { type: "boolean", default: false },
|
|
2586
|
-
part: { type: "string", enum: ["major", "minor", "patch", "auto"], default:
|
|
2692
|
+
part: { type: "string", enum: ["major", "minor", "patch", "auto"], default: defaultPart, description: "Version part to bump. Omitted \u2192 the configured default (/settings semver-part, factory default: patch). Use auto to infer from commits." }
|
|
2587
2693
|
}
|
|
2588
2694
|
},
|
|
2589
2695
|
permission: "confirm",
|
|
@@ -2591,76 +2697,62 @@ var plugin10 = {
|
|
|
2591
2697
|
async execute(input) {
|
|
2592
2698
|
const cwd = input["cwd"];
|
|
2593
2699
|
const dryRun = input["dryRun"] ?? false;
|
|
2594
|
-
const part = input["part"] ??
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2700
|
+
const part = input["part"] ?? defaultPart;
|
|
2701
|
+
return performBump(part, dryRun, cwd);
|
|
2702
|
+
}
|
|
2703
|
+
});
|
|
2704
|
+
api.slashCommands.register({
|
|
2705
|
+
name: "semver",
|
|
2706
|
+
description: "Show the current version or bump it (patch/minor/major/auto)",
|
|
2707
|
+
category: "Run",
|
|
2708
|
+
argsHint: "[status|patch|minor|major|auto] [--dry]",
|
|
2709
|
+
help: [
|
|
2710
|
+
"/semver Show current version, latest tag and the suggested bump",
|
|
2711
|
+
"/semver status Same as bare /semver",
|
|
2712
|
+
"/semver patch Bump the patch version (commit + tag)",
|
|
2713
|
+
"/semver minor Bump the minor version (commit + tag)",
|
|
2714
|
+
"/semver major Bump the major version (commit + tag)",
|
|
2715
|
+
"/semver auto Infer the bump from conventional commits since the last tag",
|
|
2716
|
+
"/semver <part> --dry Preview without writing anything"
|
|
2717
|
+
].join("\n"),
|
|
2718
|
+
async run(args, ctx) {
|
|
2719
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
2720
|
+
const dry = tokens.includes("--dry") || tokens.includes("--dry-run");
|
|
2721
|
+
const mode = tokens.find((t) => !t.startsWith("--")) ?? "status";
|
|
2722
|
+
const cwd = ctx?.cwd;
|
|
2723
|
+
if (mode === "status") {
|
|
2724
|
+
const pkg = getPackageJson(cwd);
|
|
2725
|
+
if (!pkg) return { message: "No package.json found" };
|
|
2603
2726
|
let lastTag;
|
|
2604
2727
|
try {
|
|
2605
|
-
|
|
2606
|
-
lastTag = tagsOutput || void 0;
|
|
2728
|
+
lastTag = runGit2(["describe", "--tags", "--abbrev=0"], cwd) || void 0;
|
|
2607
2729
|
} catch {
|
|
2608
2730
|
}
|
|
2731
|
+
let suggestion = "patch";
|
|
2732
|
+
let commitCount = 0;
|
|
2609
2733
|
try {
|
|
2610
|
-
commits = getRecentCommits(lastTag, cwd);
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2734
|
+
const commits = getRecentCommits(lastTag, cwd);
|
|
2735
|
+
commitCount = commits.length;
|
|
2736
|
+
suggestion = determineBump(commits);
|
|
2737
|
+
} catch {
|
|
2614
2738
|
}
|
|
2615
|
-
bumpPart = determineBump(commits);
|
|
2616
|
-
} else {
|
|
2617
|
-
bumpPart = part;
|
|
2618
|
-
}
|
|
2619
|
-
const newVersion = bumpVersion(currentVersion, bumpPart);
|
|
2620
|
-
if (dryRun) {
|
|
2621
2739
|
return {
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2740
|
+
message: [
|
|
2741
|
+
`Current version: ${pkg.version}`,
|
|
2742
|
+
`Latest tag: ${lastTag ?? "(none)"}`,
|
|
2743
|
+
`Commits since: ${commitCount}`,
|
|
2744
|
+
`Suggested bump: ${suggestion} \u2192 ${bumpVersion(pkg.version, suggestion)}`,
|
|
2745
|
+
`Default part: ${defaultPart} (change: /settings semver-part)`,
|
|
2746
|
+
"",
|
|
2747
|
+
"Run /semver patch|minor|major|auto to apply (add --dry to preview)."
|
|
2748
|
+
].join("\n")
|
|
2629
2749
|
};
|
|
2630
2750
|
}
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
const pkgData = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
2634
|
-
pkgData.version = newVersion;
|
|
2635
|
-
fs.writeFileSync(pkgPath, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
|
|
2636
|
-
try {
|
|
2637
|
-
runGit2(["add", "package.json"], cwd);
|
|
2638
|
-
runGit2(["commit", "-m", `chore: bump version to ${newVersion}`], cwd);
|
|
2639
|
-
} catch {
|
|
2751
|
+
if (mode !== "patch" && mode !== "minor" && mode !== "major" && mode !== "auto") {
|
|
2752
|
+
return { message: `Unknown mode "${mode}". Use status, patch, minor, major or auto.` };
|
|
2640
2753
|
}
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
runGit2(["tag", "-a", `${tagPrefix}${newVersion}`, "-m", `Release ${newVersion}`], cwd);
|
|
2644
|
-
} catch {
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2647
|
-
api.log.info("semver-bump: bumped", { from: currentVersion, to: newVersion, bump: bumpPart });
|
|
2648
|
-
api.metrics.counter("version_bump", 1, { bump: bumpPart });
|
|
2649
|
-
await api.session.append({
|
|
2650
|
-
type: "semver-bump:bumped",
|
|
2651
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2652
|
-
from: currentVersion,
|
|
2653
|
-
to: newVersion,
|
|
2654
|
-
bump: bumpPart
|
|
2655
|
-
});
|
|
2656
|
-
return {
|
|
2657
|
-
ok: true,
|
|
2658
|
-
currentVersion,
|
|
2659
|
-
newVersion,
|
|
2660
|
-
bump: bumpPart,
|
|
2661
|
-
tag: `${tagPrefix}${newVersion}`,
|
|
2662
|
-
message: `Bumped ${currentVersion} \u2192 ${newVersion} (${bumpPart})`
|
|
2663
|
-
};
|
|
2754
|
+
const result = await performBump(mode, dry, cwd);
|
|
2755
|
+
return { message: String(result["message"] ?? result["error"] ?? JSON.stringify(result)) };
|
|
2664
2756
|
}
|
|
2665
2757
|
});
|
|
2666
2758
|
api.tools.register({
|
|
@@ -2685,7 +2777,7 @@ var plugin10 = {
|
|
|
2685
2777
|
latestTag = tagsOutput || null;
|
|
2686
2778
|
if (latestTag) {
|
|
2687
2779
|
const countOutput = runGit2(["rev-list", "--count", `${latestTag}..HEAD`], cwd);
|
|
2688
|
-
commitsSinceTag = Number.parseInt(countOutput) || 0;
|
|
2780
|
+
commitsSinceTag = Number.parseInt(countOutput, 10) || 0;
|
|
2689
2781
|
}
|
|
2690
2782
|
} catch {
|
|
2691
2783
|
latestTag = null;
|
|
@@ -2726,15 +2818,7 @@ var plugin10 = {
|
|
|
2726
2818
|
const spaceIdx = line.indexOf(" ");
|
|
2727
2819
|
const hash = line.slice(0, spaceIdx);
|
|
2728
2820
|
const message = line.slice(spaceIdx + 1);
|
|
2729
|
-
|
|
2730
|
-
const type = m?.[1] ?? "chore";
|
|
2731
|
-
return {
|
|
2732
|
-
hash,
|
|
2733
|
-
type,
|
|
2734
|
-
scope: m?.[2],
|
|
2735
|
-
message: m?.[3] ?? message,
|
|
2736
|
-
breaking: !!m?.[2]
|
|
2737
|
-
};
|
|
2821
|
+
return { hash, ...parseConventional(message) };
|
|
2738
2822
|
});
|
|
2739
2823
|
} catch (err) {
|
|
2740
2824
|
return { ok: false, error: `Failed to get git log: ${err}` };
|
package/dist/semver-bump.d.ts
CHANGED
|
@@ -9,6 +9,18 @@ import { Plugin } from '@wrongstack/core';
|
|
|
9
9
|
* - semver_changelog: Generate a changelog between two versions
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
type BumpType = 'major' | 'minor' | 'patch' | 'auto';
|
|
13
|
+
interface ConventionalCommit {
|
|
14
|
+
hash: string;
|
|
15
|
+
type: string;
|
|
16
|
+
scope?: string | undefined;
|
|
17
|
+
message: string;
|
|
18
|
+
breaking: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** Parse a conventional-commit subject line. Accepts the breaking `!` both
|
|
21
|
+
* before and after the scope (`feat!: x`, `feat(api)!: x`). */
|
|
22
|
+
declare function parseConventional(subject: string): Omit<ConventionalCommit, 'hash'>;
|
|
23
|
+
declare function determineBump(commits: ConventionalCommit[]): BumpType;
|
|
12
24
|
declare const plugin: Plugin;
|
|
13
25
|
|
|
14
|
-
export { plugin as default };
|
|
26
|
+
export { plugin as default, determineBump, parseConventional };
|
package/dist/semver-bump.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { expectDefined } from '@wrongstack/core';
|
|
2
2
|
import { execFileSync } from 'child_process';
|
|
3
|
-
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
4
5
|
|
|
5
6
|
// src/semver-bump/index.ts
|
|
6
7
|
var API_VERSION = "^0.1.10";
|
|
@@ -10,7 +11,8 @@ function runGit(args, cwd) {
|
|
|
10
11
|
encoding: "utf-8",
|
|
11
12
|
cwd,
|
|
12
13
|
stdio: ["pipe", "pipe", "pipe"],
|
|
13
|
-
timeout: 3e4
|
|
14
|
+
timeout: 3e4,
|
|
15
|
+
windowsHide: true
|
|
14
16
|
}).trim();
|
|
15
17
|
} catch (err) {
|
|
16
18
|
const e = err;
|
|
@@ -27,10 +29,25 @@ function getPackageJson(cwd) {
|
|
|
27
29
|
return null;
|
|
28
30
|
}
|
|
29
31
|
}
|
|
32
|
+
function collectManifests(root) {
|
|
33
|
+
const paths = [];
|
|
34
|
+
const rootPkg = join(root, "package.json");
|
|
35
|
+
if (existsSync(rootPkg)) paths.push(rootPkg);
|
|
36
|
+
for (const group of ["packages", "apps"]) {
|
|
37
|
+
const groupDir = join(root, group);
|
|
38
|
+
if (!existsSync(groupDir)) continue;
|
|
39
|
+
for (const entry of readdirSync(groupDir, { withFileTypes: true })) {
|
|
40
|
+
if (!entry.isDirectory()) continue;
|
|
41
|
+
const candidate = join(groupDir, entry.name, "package.json");
|
|
42
|
+
if (existsSync(candidate)) paths.push(candidate);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return paths;
|
|
46
|
+
}
|
|
30
47
|
function parseVersion(v) {
|
|
31
48
|
const m = v.match(/^v?(\d+)\.(\d+)\.(\d+)/);
|
|
32
49
|
if (!m) return [0, 0, 0];
|
|
33
|
-
return [Number.parseInt(expectDefined(m[1])), Number.parseInt(expectDefined(m[2])), Number.parseInt(expectDefined(m[3]))];
|
|
50
|
+
return [Number.parseInt(expectDefined(m[1]), 10), Number.parseInt(expectDefined(m[2]), 10), Number.parseInt(expectDefined(m[3]), 10)];
|
|
34
51
|
}
|
|
35
52
|
function bumpVersion(version, part) {
|
|
36
53
|
let [major, minor, patch] = parseVersion(version);
|
|
@@ -48,6 +65,15 @@ function bumpVersion(version, part) {
|
|
|
48
65
|
}
|
|
49
66
|
return `${major}.${minor}.${patch}`;
|
|
50
67
|
}
|
|
68
|
+
function parseConventional(subject) {
|
|
69
|
+
const m = subject.match(/^(\w+)(!)?(?:\(([^)]+)\))?(!)?:\s+(.+)/);
|
|
70
|
+
return {
|
|
71
|
+
type: m?.[1] ?? "chore",
|
|
72
|
+
breaking: !!(m?.[2] ?? m?.[4]),
|
|
73
|
+
scope: m?.[3],
|
|
74
|
+
message: m?.[5] ?? subject
|
|
75
|
+
};
|
|
76
|
+
}
|
|
51
77
|
function getRecentCommits(sinceTag, cwd) {
|
|
52
78
|
const range = sinceTag ? `${sinceTag}..HEAD` : "-30";
|
|
53
79
|
const output = runGit(["log", range, "--format=%H %s"], cwd);
|
|
@@ -56,25 +82,12 @@ function getRecentCommits(sinceTag, cwd) {
|
|
|
56
82
|
const spaceIdx = line.indexOf(" ");
|
|
57
83
|
const hash = line.slice(0, spaceIdx);
|
|
58
84
|
const message = line.slice(spaceIdx + 1);
|
|
59
|
-
|
|
60
|
-
const type = m?.[1] ?? "chore";
|
|
61
|
-
const breaking = !!m?.[2];
|
|
62
|
-
const scope = m?.[2];
|
|
63
|
-
const msg = m?.[3] ?? message;
|
|
64
|
-
return { hash, type, scope, message: msg, breaking };
|
|
85
|
+
return { hash, ...parseConventional(message) };
|
|
65
86
|
});
|
|
66
87
|
}
|
|
67
88
|
function determineBump(commits) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return "major";
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
for (const c of commits) {
|
|
74
|
-
if (c.type === "feat" || c.type === "refactor" && c.scope) {
|
|
75
|
-
return "minor";
|
|
76
|
-
}
|
|
77
|
-
}
|
|
89
|
+
if (commits.some((c) => c.breaking)) return "major";
|
|
90
|
+
if (commits.some((c) => c.type === "feat")) return "minor";
|
|
78
91
|
return "patch";
|
|
79
92
|
}
|
|
80
93
|
function generateChangelog(commits) {
|
|
@@ -136,12 +149,13 @@ var plugin = {
|
|
|
136
149
|
version: "0.1.0",
|
|
137
150
|
description: "Conventional-commit-driven semver version bumps with changelog generation",
|
|
138
151
|
apiVersion: API_VERSION,
|
|
139
|
-
capabilities: { tools: true },
|
|
152
|
+
capabilities: { tools: true, slashCommands: true },
|
|
140
153
|
defaultConfig: {
|
|
141
154
|
tagPrefix: "v",
|
|
142
155
|
changelogFile: "CHANGELOG.md",
|
|
143
156
|
autoTag: true,
|
|
144
|
-
tagMessage: "Release {{version}}"
|
|
157
|
+
tagMessage: "Release {{version}}",
|
|
158
|
+
defaultPart: "patch"
|
|
145
159
|
},
|
|
146
160
|
configSchema: {
|
|
147
161
|
type: "object",
|
|
@@ -149,12 +163,114 @@ var plugin = {
|
|
|
149
163
|
tagPrefix: { type: "string", default: "v" },
|
|
150
164
|
changelogFile: { type: "string", default: "CHANGELOG.md" },
|
|
151
165
|
autoTag: { type: "boolean", default: true },
|
|
152
|
-
tagMessage: { type: "string", default: "Release {{version}}" }
|
|
166
|
+
tagMessage: { type: "string", default: "Release {{version}}" },
|
|
167
|
+
defaultPart: { type: "string", enum: ["major", "minor", "patch", "auto"], default: "patch" }
|
|
153
168
|
}
|
|
154
169
|
},
|
|
155
170
|
setup(api) {
|
|
156
171
|
const tagPrefix = api.config.extensions?.["semver-bump"]?.["tagPrefix"] ?? "v";
|
|
157
172
|
const autoTag = api.config.extensions?.["semver-bump"]?.["autoTag"] ?? true;
|
|
173
|
+
const VALID_PARTS = ["major", "minor", "patch", "auto"];
|
|
174
|
+
function readDefaultPart(cfg) {
|
|
175
|
+
const raw = cfg.extensions?.["semver-bump"]?.["defaultPart"];
|
|
176
|
+
return VALID_PARTS.includes(raw) ? raw : "patch";
|
|
177
|
+
}
|
|
178
|
+
let defaultPart = readDefaultPart(api.config);
|
|
179
|
+
api.onConfigChange?.((next) => {
|
|
180
|
+
defaultPart = readDefaultPart(next);
|
|
181
|
+
});
|
|
182
|
+
async function performBump(part, dryRun, cwd) {
|
|
183
|
+
const pkg = getPackageJson(cwd);
|
|
184
|
+
if (!pkg) {
|
|
185
|
+
return { ok: false, error: "No package.json found" };
|
|
186
|
+
}
|
|
187
|
+
const currentVersion = pkg.version;
|
|
188
|
+
let bumpPart = part;
|
|
189
|
+
let commits = [];
|
|
190
|
+
if (part === "auto") {
|
|
191
|
+
let lastTag;
|
|
192
|
+
try {
|
|
193
|
+
const tagsOutput = runGit(["describe", "--tags", "--abbrev=0"], cwd);
|
|
194
|
+
lastTag = tagsOutput || void 0;
|
|
195
|
+
} catch {
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
commits = getRecentCommits(lastTag, cwd);
|
|
199
|
+
} catch (err) {
|
|
200
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
201
|
+
return { ok: false, error: `Git error: ${msg}`, bumpPart: "patch" };
|
|
202
|
+
}
|
|
203
|
+
bumpPart = determineBump(commits);
|
|
204
|
+
} else {
|
|
205
|
+
bumpPart = part;
|
|
206
|
+
}
|
|
207
|
+
const newVersion = bumpVersion(currentVersion, bumpPart);
|
|
208
|
+
if (dryRun) {
|
|
209
|
+
return {
|
|
210
|
+
ok: true,
|
|
211
|
+
dryRun: true,
|
|
212
|
+
currentVersion,
|
|
213
|
+
suggestedBump: bumpPart,
|
|
214
|
+
newVersion,
|
|
215
|
+
commitCount: part === "auto" ? commits.length : void 0,
|
|
216
|
+
message: `Would bump ${currentVersion} \u2192 ${newVersion} (${bumpPart})`
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const root = cwd ?? process.cwd();
|
|
220
|
+
const bumpScript = join(root, "scripts", "bump-version.mjs");
|
|
221
|
+
const changed = collectManifests(root);
|
|
222
|
+
if (existsSync(bumpScript)) {
|
|
223
|
+
try {
|
|
224
|
+
execFileSync(process.execPath, [bumpScript, "set", newVersion], {
|
|
225
|
+
cwd: root,
|
|
226
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
227
|
+
timeout: 3e4,
|
|
228
|
+
windowsHide: true
|
|
229
|
+
});
|
|
230
|
+
} catch (err) {
|
|
231
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
232
|
+
return { ok: false, error: `bump script failed: ${msg}` };
|
|
233
|
+
}
|
|
234
|
+
for (const rel of ["package.json", "package-lock.json", "src/lib/utils.ts", "index.html"]) {
|
|
235
|
+
const p = join(root, "website", rel);
|
|
236
|
+
if (existsSync(p)) changed.push(p);
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
for (const manifest of changed) {
|
|
240
|
+
const pkgData = JSON.parse(readFileSync(manifest, "utf-8"));
|
|
241
|
+
pkgData.version = newVersion;
|
|
242
|
+
writeFileSync(manifest, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
runGit(["add", "--", ...changed], cwd);
|
|
247
|
+
runGit(["commit", "-m", `chore: bump version to ${newVersion}`], cwd);
|
|
248
|
+
} catch {
|
|
249
|
+
}
|
|
250
|
+
if (autoTag) {
|
|
251
|
+
try {
|
|
252
|
+
runGit(["tag", "-a", `${tagPrefix}${newVersion}`, "-m", `Release ${newVersion}`], cwd);
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
api.log.info("semver-bump: bumped", { from: currentVersion, to: newVersion, bump: bumpPart });
|
|
257
|
+
api.metrics.counter("version_bump", 1, { bump: bumpPart });
|
|
258
|
+
await api.session.append({
|
|
259
|
+
type: "semver-bump:bumped",
|
|
260
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
261
|
+
from: currentVersion,
|
|
262
|
+
to: newVersion,
|
|
263
|
+
bump: bumpPart
|
|
264
|
+
});
|
|
265
|
+
return {
|
|
266
|
+
ok: true,
|
|
267
|
+
currentVersion,
|
|
268
|
+
newVersion,
|
|
269
|
+
bump: bumpPart,
|
|
270
|
+
tag: `${tagPrefix}${newVersion}`,
|
|
271
|
+
message: `Bumped ${currentVersion} \u2192 ${newVersion} (${bumpPart})`
|
|
272
|
+
};
|
|
273
|
+
}
|
|
158
274
|
api.tools.register({
|
|
159
275
|
name: "semver_bump",
|
|
160
276
|
description: "Determine the next version bump from conventional commits since the last tag, or force a specific bump. Creates a git tag.",
|
|
@@ -163,7 +279,7 @@ var plugin = {
|
|
|
163
279
|
properties: {
|
|
164
280
|
cwd: { type: "string", description: "Working directory (defaults to project root)" },
|
|
165
281
|
dryRun: { type: "boolean", default: false },
|
|
166
|
-
part: { type: "string", enum: ["major", "minor", "patch", "auto"], default:
|
|
282
|
+
part: { type: "string", enum: ["major", "minor", "patch", "auto"], default: defaultPart, description: "Version part to bump. Omitted \u2192 the configured default (/settings semver-part, factory default: patch). Use auto to infer from commits." }
|
|
167
283
|
}
|
|
168
284
|
},
|
|
169
285
|
permission: "confirm",
|
|
@@ -171,76 +287,62 @@ var plugin = {
|
|
|
171
287
|
async execute(input) {
|
|
172
288
|
const cwd = input["cwd"];
|
|
173
289
|
const dryRun = input["dryRun"] ?? false;
|
|
174
|
-
const part = input["part"] ??
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
290
|
+
const part = input["part"] ?? defaultPart;
|
|
291
|
+
return performBump(part, dryRun, cwd);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
api.slashCommands.register({
|
|
295
|
+
name: "semver",
|
|
296
|
+
description: "Show the current version or bump it (patch/minor/major/auto)",
|
|
297
|
+
category: "Run",
|
|
298
|
+
argsHint: "[status|patch|minor|major|auto] [--dry]",
|
|
299
|
+
help: [
|
|
300
|
+
"/semver Show current version, latest tag and the suggested bump",
|
|
301
|
+
"/semver status Same as bare /semver",
|
|
302
|
+
"/semver patch Bump the patch version (commit + tag)",
|
|
303
|
+
"/semver minor Bump the minor version (commit + tag)",
|
|
304
|
+
"/semver major Bump the major version (commit + tag)",
|
|
305
|
+
"/semver auto Infer the bump from conventional commits since the last tag",
|
|
306
|
+
"/semver <part> --dry Preview without writing anything"
|
|
307
|
+
].join("\n"),
|
|
308
|
+
async run(args, ctx) {
|
|
309
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
310
|
+
const dry = tokens.includes("--dry") || tokens.includes("--dry-run");
|
|
311
|
+
const mode = tokens.find((t) => !t.startsWith("--")) ?? "status";
|
|
312
|
+
const cwd = ctx?.cwd;
|
|
313
|
+
if (mode === "status") {
|
|
314
|
+
const pkg = getPackageJson(cwd);
|
|
315
|
+
if (!pkg) return { message: "No package.json found" };
|
|
183
316
|
let lastTag;
|
|
184
317
|
try {
|
|
185
|
-
|
|
186
|
-
lastTag = tagsOutput || void 0;
|
|
318
|
+
lastTag = runGit(["describe", "--tags", "--abbrev=0"], cwd) || void 0;
|
|
187
319
|
} catch {
|
|
188
320
|
}
|
|
321
|
+
let suggestion = "patch";
|
|
322
|
+
let commitCount = 0;
|
|
189
323
|
try {
|
|
190
|
-
commits = getRecentCommits(lastTag, cwd);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
324
|
+
const commits = getRecentCommits(lastTag, cwd);
|
|
325
|
+
commitCount = commits.length;
|
|
326
|
+
suggestion = determineBump(commits);
|
|
327
|
+
} catch {
|
|
194
328
|
}
|
|
195
|
-
bumpPart = determineBump(commits);
|
|
196
|
-
} else {
|
|
197
|
-
bumpPart = part;
|
|
198
|
-
}
|
|
199
|
-
const newVersion = bumpVersion(currentVersion, bumpPart);
|
|
200
|
-
if (dryRun) {
|
|
201
329
|
return {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
330
|
+
message: [
|
|
331
|
+
`Current version: ${pkg.version}`,
|
|
332
|
+
`Latest tag: ${lastTag ?? "(none)"}`,
|
|
333
|
+
`Commits since: ${commitCount}`,
|
|
334
|
+
`Suggested bump: ${suggestion} \u2192 ${bumpVersion(pkg.version, suggestion)}`,
|
|
335
|
+
`Default part: ${defaultPart} (change: /settings semver-part)`,
|
|
336
|
+
"",
|
|
337
|
+
"Run /semver patch|minor|major|auto to apply (add --dry to preview)."
|
|
338
|
+
].join("\n")
|
|
209
339
|
};
|
|
210
340
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const pkgData = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
214
|
-
pkgData.version = newVersion;
|
|
215
|
-
fs.writeFileSync(pkgPath, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
|
|
216
|
-
try {
|
|
217
|
-
runGit(["add", "package.json"], cwd);
|
|
218
|
-
runGit(["commit", "-m", `chore: bump version to ${newVersion}`], cwd);
|
|
219
|
-
} catch {
|
|
220
|
-
}
|
|
221
|
-
if (autoTag) {
|
|
222
|
-
try {
|
|
223
|
-
runGit(["tag", "-a", `${tagPrefix}${newVersion}`, "-m", `Release ${newVersion}`], cwd);
|
|
224
|
-
} catch {
|
|
225
|
-
}
|
|
341
|
+
if (mode !== "patch" && mode !== "minor" && mode !== "major" && mode !== "auto") {
|
|
342
|
+
return { message: `Unknown mode "${mode}". Use status, patch, minor, major or auto.` };
|
|
226
343
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
await api.session.append({
|
|
230
|
-
type: "semver-bump:bumped",
|
|
231
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
232
|
-
from: currentVersion,
|
|
233
|
-
to: newVersion,
|
|
234
|
-
bump: bumpPart
|
|
235
|
-
});
|
|
236
|
-
return {
|
|
237
|
-
ok: true,
|
|
238
|
-
currentVersion,
|
|
239
|
-
newVersion,
|
|
240
|
-
bump: bumpPart,
|
|
241
|
-
tag: `${tagPrefix}${newVersion}`,
|
|
242
|
-
message: `Bumped ${currentVersion} \u2192 ${newVersion} (${bumpPart})`
|
|
243
|
-
};
|
|
344
|
+
const result = await performBump(mode, dry, cwd);
|
|
345
|
+
return { message: String(result["message"] ?? result["error"] ?? JSON.stringify(result)) };
|
|
244
346
|
}
|
|
245
347
|
});
|
|
246
348
|
api.tools.register({
|
|
@@ -265,7 +367,7 @@ var plugin = {
|
|
|
265
367
|
latestTag = tagsOutput || null;
|
|
266
368
|
if (latestTag) {
|
|
267
369
|
const countOutput = runGit(["rev-list", "--count", `${latestTag}..HEAD`], cwd);
|
|
268
|
-
commitsSinceTag = Number.parseInt(countOutput) || 0;
|
|
370
|
+
commitsSinceTag = Number.parseInt(countOutput, 10) || 0;
|
|
269
371
|
}
|
|
270
372
|
} catch {
|
|
271
373
|
latestTag = null;
|
|
@@ -306,15 +408,7 @@ var plugin = {
|
|
|
306
408
|
const spaceIdx = line.indexOf(" ");
|
|
307
409
|
const hash = line.slice(0, spaceIdx);
|
|
308
410
|
const message = line.slice(spaceIdx + 1);
|
|
309
|
-
|
|
310
|
-
const type = m?.[1] ?? "chore";
|
|
311
|
-
return {
|
|
312
|
-
hash,
|
|
313
|
-
type,
|
|
314
|
-
scope: m?.[2],
|
|
315
|
-
message: m?.[3] ?? message,
|
|
316
|
-
breaking: !!m?.[2]
|
|
317
|
-
};
|
|
411
|
+
return { hash, ...parseConventional(message) };
|
|
318
412
|
});
|
|
319
413
|
} catch (err) {
|
|
320
414
|
return { ok: false, error: `Failed to get git log: ${err}` };
|
|
@@ -344,4 +438,4 @@ var plugin = {
|
|
|
344
438
|
};
|
|
345
439
|
var semver_bump_default = plugin;
|
|
346
440
|
|
|
347
|
-
export { semver_bump_default as default };
|
|
441
|
+
export { semver_bump_default as default, determineBump, parseConventional };
|
package/dist/shell-check.js
CHANGED
|
@@ -7,7 +7,7 @@ var API_VERSION = "^0.1.10";
|
|
|
7
7
|
function runShellCheck(files, severity, cwd) {
|
|
8
8
|
if (!existsSync("shellcheck")) {
|
|
9
9
|
try {
|
|
10
|
-
execSync("shellcheck --version", { encoding: "utf-8", stdio: "ignore" });
|
|
10
|
+
execSync("shellcheck --version", { encoding: "utf-8", stdio: "ignore", windowsHide: true });
|
|
11
11
|
} catch {
|
|
12
12
|
throw new Error("shellcheck is not installed. Install via: apt install shellcheck / brew install shellcheck");
|
|
13
13
|
}
|
|
@@ -31,7 +31,8 @@ function runShellCheck(files, severity, cwd) {
|
|
|
31
31
|
encoding: "utf-8",
|
|
32
32
|
cwd,
|
|
33
33
|
stdio: ["pipe", "pipe", "pipe"],
|
|
34
|
-
timeout: 6e4
|
|
34
|
+
timeout: 6e4,
|
|
35
|
+
windowsHide: true
|
|
35
36
|
});
|
|
36
37
|
} catch (err) {
|
|
37
38
|
const e = err;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.255.0",
|
|
4
4
|
"description": "Official WrongStack plugin collection — auto-doc, git-autocommit, shell-check, cost-tracker, file-watcher, web-search, json-path, cron, template-engine, semver-bump",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ECOSTACK TECHNOLOGY OÜ",
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
"dist"
|
|
58
58
|
],
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@types/node": "^25.9.
|
|
60
|
+
"@types/node": "^25.9.3",
|
|
61
61
|
"tsup": "^8.5.1",
|
|
62
62
|
"typescript": "^6.0.3",
|
|
63
63
|
"vitest": "^4.1.8"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@wrongstack/core": "0.
|
|
66
|
+
"@wrongstack/core": "0.255.0"
|
|
67
67
|
},
|
|
68
68
|
"scripts": {
|
|
69
69
|
"build": "tsup",
|