@vpxa/kb 0.1.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/LICENSE +21 -0
- package/README.md +1140 -0
- package/bin/kb.mjs +10 -0
- package/package.json +67 -0
- package/packages/analyzers/dist/blast-radius-analyzer.d.ts +23 -0
- package/packages/analyzers/dist/blast-radius-analyzer.js +114 -0
- package/packages/analyzers/dist/dependency-analyzer.d.ts +29 -0
- package/packages/analyzers/dist/dependency-analyzer.js +425 -0
- package/packages/analyzers/dist/diagram-generator.d.ts +13 -0
- package/packages/analyzers/dist/diagram-generator.js +86 -0
- package/packages/analyzers/dist/entry-point-analyzer.d.ts +19 -0
- package/packages/analyzers/dist/entry-point-analyzer.js +239 -0
- package/packages/analyzers/dist/index.d.ts +14 -0
- package/packages/analyzers/dist/index.js +23 -0
- package/packages/analyzers/dist/knowledge-producer.d.ts +32 -0
- package/packages/analyzers/dist/knowledge-producer.js +113 -0
- package/packages/analyzers/dist/pattern-analyzer.d.ts +12 -0
- package/packages/analyzers/dist/pattern-analyzer.js +359 -0
- package/packages/analyzers/dist/regex-call-graph.d.ts +17 -0
- package/packages/analyzers/dist/regex-call-graph.js +428 -0
- package/packages/analyzers/dist/structure-analyzer.d.ts +11 -0
- package/packages/analyzers/dist/structure-analyzer.js +258 -0
- package/packages/analyzers/dist/symbol-analyzer.d.ts +10 -0
- package/packages/analyzers/dist/symbol-analyzer.js +442 -0
- package/packages/analyzers/dist/ts-call-graph.d.ts +27 -0
- package/packages/analyzers/dist/ts-call-graph.js +160 -0
- package/packages/analyzers/dist/types.d.ts +98 -0
- package/packages/analyzers/dist/types.js +1 -0
- package/packages/chunker/dist/call-graph-extractor.d.ts +22 -0
- package/packages/chunker/dist/call-graph-extractor.js +90 -0
- package/packages/chunker/dist/chunker-factory.d.ts +7 -0
- package/packages/chunker/dist/chunker-factory.js +36 -0
- package/packages/chunker/dist/chunker.interface.d.ts +10 -0
- package/packages/chunker/dist/chunker.interface.js +1 -0
- package/packages/chunker/dist/code-chunker.d.ts +14 -0
- package/packages/chunker/dist/code-chunker.js +134 -0
- package/packages/chunker/dist/generic-chunker.d.ts +12 -0
- package/packages/chunker/dist/generic-chunker.js +72 -0
- package/packages/chunker/dist/index.d.ts +8 -0
- package/packages/chunker/dist/index.js +21 -0
- package/packages/chunker/dist/markdown-chunker.d.ts +14 -0
- package/packages/chunker/dist/markdown-chunker.js +122 -0
- package/packages/chunker/dist/treesitter-chunker.d.ts +47 -0
- package/packages/chunker/dist/treesitter-chunker.js +234 -0
- package/packages/cli/dist/commands/analyze.d.ts +3 -0
- package/packages/cli/dist/commands/analyze.js +112 -0
- package/packages/cli/dist/commands/context-cmds.d.ts +3 -0
- package/packages/cli/dist/commands/context-cmds.js +155 -0
- package/packages/cli/dist/commands/environment.d.ts +3 -0
- package/packages/cli/dist/commands/environment.js +204 -0
- package/packages/cli/dist/commands/execution.d.ts +3 -0
- package/packages/cli/dist/commands/execution.js +137 -0
- package/packages/cli/dist/commands/graph.d.ts +3 -0
- package/packages/cli/dist/commands/graph.js +81 -0
- package/packages/cli/dist/commands/init.d.ts +8 -0
- package/packages/cli/dist/commands/init.js +87 -0
- package/packages/cli/dist/commands/knowledge.d.ts +3 -0
- package/packages/cli/dist/commands/knowledge.js +139 -0
- package/packages/cli/dist/commands/search.d.ts +3 -0
- package/packages/cli/dist/commands/search.js +267 -0
- package/packages/cli/dist/commands/system.d.ts +3 -0
- package/packages/cli/dist/commands/system.js +241 -0
- package/packages/cli/dist/commands/workspace.d.ts +3 -0
- package/packages/cli/dist/commands/workspace.js +388 -0
- package/packages/cli/dist/context.d.ts +5 -0
- package/packages/cli/dist/context.js +14 -0
- package/packages/cli/dist/helpers.d.ts +52 -0
- package/packages/cli/dist/helpers.js +458 -0
- package/packages/cli/dist/index.d.ts +8 -0
- package/packages/cli/dist/index.js +69 -0
- package/packages/cli/dist/kb-init.d.ts +57 -0
- package/packages/cli/dist/kb-init.js +82 -0
- package/packages/cli/dist/types.d.ts +7 -0
- package/packages/cli/dist/types.js +1 -0
- package/packages/core/dist/constants.d.ts +49 -0
- package/packages/core/dist/constants.js +43 -0
- package/packages/core/dist/content-detector.d.ts +9 -0
- package/packages/core/dist/content-detector.js +79 -0
- package/packages/core/dist/errors.d.ts +18 -0
- package/packages/core/dist/errors.js +40 -0
- package/packages/core/dist/index.d.ts +6 -0
- package/packages/core/dist/index.js +9 -0
- package/packages/core/dist/logger.d.ts +9 -0
- package/packages/core/dist/logger.js +34 -0
- package/packages/core/dist/types.d.ts +108 -0
- package/packages/core/dist/types.js +1 -0
- package/packages/embeddings/dist/embedder.interface.d.ts +24 -0
- package/packages/embeddings/dist/embedder.interface.js +1 -0
- package/packages/embeddings/dist/index.d.ts +3 -0
- package/packages/embeddings/dist/index.js +5 -0
- package/packages/embeddings/dist/onnx-embedder.d.ts +24 -0
- package/packages/embeddings/dist/onnx-embedder.js +82 -0
- package/packages/indexer/dist/file-hasher.d.ts +11 -0
- package/packages/indexer/dist/file-hasher.js +13 -0
- package/packages/indexer/dist/filesystem-crawler.d.ts +27 -0
- package/packages/indexer/dist/filesystem-crawler.js +125 -0
- package/packages/indexer/dist/graph-extractor.d.ts +22 -0
- package/packages/indexer/dist/graph-extractor.js +111 -0
- package/packages/indexer/dist/incremental-indexer.d.ts +47 -0
- package/packages/indexer/dist/incremental-indexer.js +278 -0
- package/packages/indexer/dist/index.d.ts +5 -0
- package/packages/indexer/dist/index.js +14 -0
- package/packages/server/dist/api.d.ts +8 -0
- package/packages/server/dist/api.js +9 -0
- package/packages/server/dist/config.d.ts +3 -0
- package/packages/server/dist/config.js +75 -0
- package/packages/server/dist/curated-manager.d.ts +86 -0
- package/packages/server/dist/curated-manager.js +357 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.js +134 -0
- package/packages/server/dist/replay-interceptor.d.ts +11 -0
- package/packages/server/dist/replay-interceptor.js +38 -0
- package/packages/server/dist/resources/resources.d.ts +4 -0
- package/packages/server/dist/resources/resources.js +40 -0
- package/packages/server/dist/server.d.ts +21 -0
- package/packages/server/dist/server.js +247 -0
- package/packages/server/dist/tools/analyze.tools.d.ts +11 -0
- package/packages/server/dist/tools/analyze.tools.js +288 -0
- package/packages/server/dist/tools/forge.tools.d.ts +12 -0
- package/packages/server/dist/tools/forge.tools.js +501 -0
- package/packages/server/dist/tools/forget.tool.d.ts +4 -0
- package/packages/server/dist/tools/forget.tool.js +43 -0
- package/packages/server/dist/tools/graph.tool.d.ts +4 -0
- package/packages/server/dist/tools/graph.tool.js +110 -0
- package/packages/server/dist/tools/list.tool.d.ts +4 -0
- package/packages/server/dist/tools/list.tool.js +56 -0
- package/packages/server/dist/tools/lookup.tool.d.ts +4 -0
- package/packages/server/dist/tools/lookup.tool.js +53 -0
- package/packages/server/dist/tools/onboard.tool.d.ts +5 -0
- package/packages/server/dist/tools/onboard.tool.js +112 -0
- package/packages/server/dist/tools/produce.tool.d.ts +3 -0
- package/packages/server/dist/tools/produce.tool.js +74 -0
- package/packages/server/dist/tools/read.tool.d.ts +4 -0
- package/packages/server/dist/tools/read.tool.js +49 -0
- package/packages/server/dist/tools/reindex.tool.d.ts +7 -0
- package/packages/server/dist/tools/reindex.tool.js +70 -0
- package/packages/server/dist/tools/remember.tool.d.ts +4 -0
- package/packages/server/dist/tools/remember.tool.js +45 -0
- package/packages/server/dist/tools/replay.tool.d.ts +3 -0
- package/packages/server/dist/tools/replay.tool.js +89 -0
- package/packages/server/dist/tools/search.tool.d.ts +5 -0
- package/packages/server/dist/tools/search.tool.js +331 -0
- package/packages/server/dist/tools/status.tool.d.ts +4 -0
- package/packages/server/dist/tools/status.tool.js +68 -0
- package/packages/server/dist/tools/toolkit.tools.d.ts +35 -0
- package/packages/server/dist/tools/toolkit.tools.js +1674 -0
- package/packages/server/dist/tools/update.tool.d.ts +4 -0
- package/packages/server/dist/tools/update.tool.js +42 -0
- package/packages/server/dist/tools/utility.tools.d.ts +15 -0
- package/packages/server/dist/tools/utility.tools.js +461 -0
- package/packages/store/dist/graph-store.interface.d.ts +104 -0
- package/packages/store/dist/graph-store.interface.js +1 -0
- package/packages/store/dist/index.d.ts +6 -0
- package/packages/store/dist/index.js +9 -0
- package/packages/store/dist/lance-store.d.ts +32 -0
- package/packages/store/dist/lance-store.js +258 -0
- package/packages/store/dist/sqlite-graph-store.d.ts +43 -0
- package/packages/store/dist/sqlite-graph-store.js +374 -0
- package/packages/store/dist/store-factory.d.ts +9 -0
- package/packages/store/dist/store-factory.js +14 -0
- package/packages/store/dist/store.interface.d.ts +48 -0
- package/packages/store/dist/store.interface.js +1 -0
- package/packages/tools/dist/batch.d.ts +21 -0
- package/packages/tools/dist/batch.js +45 -0
- package/packages/tools/dist/changelog.d.ts +34 -0
- package/packages/tools/dist/changelog.js +112 -0
- package/packages/tools/dist/check.d.ts +26 -0
- package/packages/tools/dist/check.js +59 -0
- package/packages/tools/dist/checkpoint.d.ts +17 -0
- package/packages/tools/dist/checkpoint.js +43 -0
- package/packages/tools/dist/codemod.d.ts +37 -0
- package/packages/tools/dist/codemod.js +69 -0
- package/packages/tools/dist/compact.d.ts +41 -0
- package/packages/tools/dist/compact.js +60 -0
- package/packages/tools/dist/data-transform.d.ts +10 -0
- package/packages/tools/dist/data-transform.js +124 -0
- package/packages/tools/dist/dead-symbols.d.ts +21 -0
- package/packages/tools/dist/dead-symbols.js +71 -0
- package/packages/tools/dist/delegate.d.ts +34 -0
- package/packages/tools/dist/delegate.js +130 -0
- package/packages/tools/dist/diff-parse.d.ts +26 -0
- package/packages/tools/dist/diff-parse.js +153 -0
- package/packages/tools/dist/digest.d.ts +53 -0
- package/packages/tools/dist/digest.js +242 -0
- package/packages/tools/dist/encode.d.ts +14 -0
- package/packages/tools/dist/encode.js +46 -0
- package/packages/tools/dist/env-info.d.ts +28 -0
- package/packages/tools/dist/env-info.js +58 -0
- package/packages/tools/dist/eval.d.ts +13 -0
- package/packages/tools/dist/eval.js +79 -0
- package/packages/tools/dist/evidence-map.d.ts +79 -0
- package/packages/tools/dist/evidence-map.js +203 -0
- package/packages/tools/dist/file-summary.d.ts +32 -0
- package/packages/tools/dist/file-summary.js +106 -0
- package/packages/tools/dist/file-walk.d.ts +4 -0
- package/packages/tools/dist/file-walk.js +75 -0
- package/packages/tools/dist/find-examples.d.ts +25 -0
- package/packages/tools/dist/find-examples.js +48 -0
- package/packages/tools/dist/find.d.ts +47 -0
- package/packages/tools/dist/find.js +120 -0
- package/packages/tools/dist/forge-classify.d.ts +44 -0
- package/packages/tools/dist/forge-classify.js +319 -0
- package/packages/tools/dist/forge-ground.d.ts +64 -0
- package/packages/tools/dist/forge-ground.js +184 -0
- package/packages/tools/dist/git-context.d.ts +22 -0
- package/packages/tools/dist/git-context.js +46 -0
- package/packages/tools/dist/graph-query.d.ts +89 -0
- package/packages/tools/dist/graph-query.js +194 -0
- package/packages/tools/dist/health.d.ts +14 -0
- package/packages/tools/dist/health.js +118 -0
- package/packages/tools/dist/http-request.d.ts +23 -0
- package/packages/tools/dist/http-request.js +58 -0
- package/packages/tools/dist/index.d.ts +49 -0
- package/packages/tools/dist/index.js +273 -0
- package/packages/tools/dist/lane.d.ts +39 -0
- package/packages/tools/dist/lane.js +227 -0
- package/packages/tools/dist/measure.d.ts +38 -0
- package/packages/tools/dist/measure.js +119 -0
- package/packages/tools/dist/onboard.d.ts +41 -0
- package/packages/tools/dist/onboard.js +1139 -0
- package/packages/tools/dist/parse-output.d.ts +80 -0
- package/packages/tools/dist/parse-output.js +158 -0
- package/packages/tools/dist/process-manager.d.ts +18 -0
- package/packages/tools/dist/process-manager.js +69 -0
- package/packages/tools/dist/queue.d.ts +38 -0
- package/packages/tools/dist/queue.js +126 -0
- package/packages/tools/dist/regex-test.d.ts +31 -0
- package/packages/tools/dist/regex-test.js +39 -0
- package/packages/tools/dist/rename.d.ts +29 -0
- package/packages/tools/dist/rename.js +70 -0
- package/packages/tools/dist/replay.d.ts +56 -0
- package/packages/tools/dist/replay.js +108 -0
- package/packages/tools/dist/schema-validate.d.ts +23 -0
- package/packages/tools/dist/schema-validate.js +141 -0
- package/packages/tools/dist/scope-map.d.ts +52 -0
- package/packages/tools/dist/scope-map.js +72 -0
- package/packages/tools/dist/snippet.d.ts +34 -0
- package/packages/tools/dist/snippet.js +80 -0
- package/packages/tools/dist/stash.d.ts +12 -0
- package/packages/tools/dist/stash.js +60 -0
- package/packages/tools/dist/stratum-card.d.ts +31 -0
- package/packages/tools/dist/stratum-card.js +239 -0
- package/packages/tools/dist/symbol.d.ts +28 -0
- package/packages/tools/dist/symbol.js +87 -0
- package/packages/tools/dist/test-run.d.ts +23 -0
- package/packages/tools/dist/test-run.js +55 -0
- package/packages/tools/dist/text-utils.d.ts +16 -0
- package/packages/tools/dist/text-utils.js +31 -0
- package/packages/tools/dist/time-utils.d.ts +18 -0
- package/packages/tools/dist/time-utils.js +135 -0
- package/packages/tools/dist/trace.d.ts +24 -0
- package/packages/tools/dist/trace.js +114 -0
- package/packages/tools/dist/truncation.d.ts +22 -0
- package/packages/tools/dist/truncation.js +45 -0
- package/packages/tools/dist/watch.d.ts +30 -0
- package/packages/tools/dist/watch.js +61 -0
- package/packages/tools/dist/web-fetch.d.ts +45 -0
- package/packages/tools/dist/web-fetch.js +249 -0
- package/packages/tools/dist/web-search.d.ts +23 -0
- package/packages/tools/dist/web-search.js +46 -0
- package/packages/tools/dist/workset.d.ts +45 -0
- package/packages/tools/dist/workset.js +77 -0
- package/packages/tui/dist/App.d.ts +8 -0
- package/packages/tui/dist/App.js +52659 -0
- package/packages/tui/dist/index.d.ts +19 -0
- package/packages/tui/dist/index.js +54742 -0
- package/packages/tui/dist/panels/CuratedPanel.d.ts +8 -0
- package/packages/tui/dist/panels/CuratedPanel.js +34452 -0
- package/packages/tui/dist/panels/LogPanel.d.ts +3 -0
- package/packages/tui/dist/panels/LogPanel.js +51894 -0
- package/packages/tui/dist/panels/SearchPanel.d.ts +10 -0
- package/packages/tui/dist/panels/SearchPanel.js +34985 -0
- package/packages/tui/dist/panels/StatusPanel.d.ts +8 -0
- package/packages/tui/dist/panels/StatusPanel.js +34465 -0
- package/skills/knowledge-base/SKILL.md +316 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb_parse_output — Structured parsers for common build tool output.
|
|
3
|
+
*
|
|
4
|
+
* Converts noisy text output from tsc, vitest, biome, and git status
|
|
5
|
+
* into structured JSON that LLM agents can act on directly.
|
|
6
|
+
*/
|
|
7
|
+
export interface ParsedError {
|
|
8
|
+
file: string;
|
|
9
|
+
line?: number;
|
|
10
|
+
column?: number;
|
|
11
|
+
severity: 'error' | 'warning' | 'info';
|
|
12
|
+
code?: string;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ParsedTestResult {
|
|
16
|
+
name: string;
|
|
17
|
+
file?: string;
|
|
18
|
+
status: 'pass' | 'fail' | 'skip';
|
|
19
|
+
duration?: number;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ParsedTestSummary {
|
|
23
|
+
tests: ParsedTestResult[];
|
|
24
|
+
passed: number;
|
|
25
|
+
failed: number;
|
|
26
|
+
skipped: number;
|
|
27
|
+
duration?: number;
|
|
28
|
+
suites?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface ParsedGitStatus {
|
|
31
|
+
staged: Array<{
|
|
32
|
+
status: string;
|
|
33
|
+
file: string;
|
|
34
|
+
}>;
|
|
35
|
+
unstaged: Array<{
|
|
36
|
+
status: string;
|
|
37
|
+
file: string;
|
|
38
|
+
}>;
|
|
39
|
+
untracked: string[];
|
|
40
|
+
branch?: string;
|
|
41
|
+
}
|
|
42
|
+
export type ParsedOutput = {
|
|
43
|
+
tool: 'tsc';
|
|
44
|
+
errors: ParsedError[];
|
|
45
|
+
} | {
|
|
46
|
+
tool: 'vitest';
|
|
47
|
+
summary: ParsedTestSummary;
|
|
48
|
+
} | {
|
|
49
|
+
tool: 'biome';
|
|
50
|
+
errors: ParsedError[];
|
|
51
|
+
} | {
|
|
52
|
+
tool: 'git-status';
|
|
53
|
+
status: ParsedGitStatus;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Parse `tsc` output into structured errors.
|
|
57
|
+
*
|
|
58
|
+
* Example line: `src/foo.ts(10,5): error TS2339: Property 'x' does not exist`
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseTsc(output: string): ParsedError[];
|
|
61
|
+
/**
|
|
62
|
+
* Parse vitest run output into structured test results.
|
|
63
|
+
*/
|
|
64
|
+
export declare function parseVitest(output: string): ParsedTestSummary;
|
|
65
|
+
/**
|
|
66
|
+
* Parse biome check/lint output into structured errors.
|
|
67
|
+
*
|
|
68
|
+
* Example: `src/foo.ts:10:5 lint/suspicious/noDoubleEquals ━━━`
|
|
69
|
+
* ` × Use === instead of ==`
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseBiome(output: string): ParsedError[];
|
|
72
|
+
/**
|
|
73
|
+
* Parse `git status --porcelain=v1 -b` output into structured status.
|
|
74
|
+
*/
|
|
75
|
+
export declare function parseGitStatus(output: string): ParsedGitStatus;
|
|
76
|
+
/**
|
|
77
|
+
* Auto-detect the tool from output content and parse accordingly.
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseOutput(output: string, tool?: string): ParsedOutput;
|
|
80
|
+
//# sourceMappingURL=parse-output.d.ts.map
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
function parseTsc(output) {
|
|
2
|
+
const errors = [];
|
|
3
|
+
const parenRegex = /^(.+?)\((\d+),(\d+)\):\s+(error|warning)\s+(TS\d+):\s+(.+)$/gm;
|
|
4
|
+
for (const match of output.matchAll(parenRegex)) {
|
|
5
|
+
errors.push({
|
|
6
|
+
file: match[1],
|
|
7
|
+
line: Number.parseInt(match[2], 10),
|
|
8
|
+
column: Number.parseInt(match[3], 10),
|
|
9
|
+
severity: match[4],
|
|
10
|
+
code: match[5],
|
|
11
|
+
message: match[6]
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (errors.length === 0) {
|
|
15
|
+
const colonRegex = /^(.+?):(\d+):(\d+)\s+-\s+(error|warning)\s+(TS\d+):\s+(.+)$/gm;
|
|
16
|
+
for (const match of output.matchAll(colonRegex)) {
|
|
17
|
+
errors.push({
|
|
18
|
+
file: match[1],
|
|
19
|
+
line: Number.parseInt(match[2], 10),
|
|
20
|
+
column: Number.parseInt(match[3], 10),
|
|
21
|
+
severity: match[4],
|
|
22
|
+
code: match[5],
|
|
23
|
+
message: match[6]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return errors;
|
|
28
|
+
}
|
|
29
|
+
function parseVitest(output) {
|
|
30
|
+
const tests = [];
|
|
31
|
+
const testRegex = /^\s*([✓✕×-])\s+(.+?)(?:\s+(\d+)ms)?$/gm;
|
|
32
|
+
for (const match of output.matchAll(testRegex)) {
|
|
33
|
+
const symbol = match[1];
|
|
34
|
+
const status = symbol === "\u2713" ? "pass" : symbol === "-" ? "skip" : "fail";
|
|
35
|
+
tests.push({
|
|
36
|
+
name: match[2].trim(),
|
|
37
|
+
status,
|
|
38
|
+
duration: match[3] ? Number.parseInt(match[3], 10) : void 0
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const fileRegex = /^\s*([✓✕×])\s+(\S+\.test\.\w+)\s+\((\d+)\s+tests?\)\s*(\d+ms)?$/gm;
|
|
42
|
+
for (const match of output.matchAll(fileRegex)) {
|
|
43
|
+
const symbol = match[1];
|
|
44
|
+
const status = symbol === "\u2713" ? "pass" : "fail";
|
|
45
|
+
tests.push({
|
|
46
|
+
name: match[2],
|
|
47
|
+
file: match[2],
|
|
48
|
+
status,
|
|
49
|
+
duration: match[4] ? Number.parseInt(match[4], 10) : void 0
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const summaryRegex = /Tests\s+(?:(\d+)\s+passed)?(?:\s*\|\s*)?(?:(\d+)\s+failed)?(?:\s*\|\s*)?(?:(\d+)\s+skipped)?\s*\((\d+)\)/;
|
|
53
|
+
const summaryMatch = summaryRegex.exec(output);
|
|
54
|
+
const passed = summaryMatch ? Number.parseInt(summaryMatch[1] ?? "0", 10) : tests.filter((t) => t.status === "pass").length;
|
|
55
|
+
const failed = summaryMatch ? Number.parseInt(summaryMatch[2] ?? "0", 10) : tests.filter((t) => t.status === "fail").length;
|
|
56
|
+
const skipped = summaryMatch ? Number.parseInt(summaryMatch[3] ?? "0", 10) : tests.filter((t) => t.status === "skip").length;
|
|
57
|
+
const durationRegex = /Duration\s+(\d+(?:\.\d+)?)(?:ms|s)/;
|
|
58
|
+
const durationMatch = durationRegex.exec(output);
|
|
59
|
+
const duration = durationMatch ? durationMatch[0].includes("s") && !durationMatch[0].includes("ms") ? Number.parseFloat(durationMatch[1]) * 1e3 : Number.parseFloat(durationMatch[1]) : void 0;
|
|
60
|
+
const suitesRegex = /Test Files\s+(\d+)\s+passed/;
|
|
61
|
+
const suitesMatch = suitesRegex.exec(output);
|
|
62
|
+
return {
|
|
63
|
+
tests,
|
|
64
|
+
passed,
|
|
65
|
+
failed,
|
|
66
|
+
skipped,
|
|
67
|
+
duration,
|
|
68
|
+
suites: suitesMatch ? Number.parseInt(suitesMatch[1], 10) : void 0
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function parseBiome(output) {
|
|
72
|
+
const errors = [];
|
|
73
|
+
const blockRegex = /^(.+?):(\d+):(\d+)\s+([\w/]+)\s+━+$/gm;
|
|
74
|
+
for (const match of output.matchAll(blockRegex)) {
|
|
75
|
+
const file = match[1];
|
|
76
|
+
const line = Number.parseInt(match[2], 10);
|
|
77
|
+
const column = Number.parseInt(match[3], 10);
|
|
78
|
+
const code = match[4];
|
|
79
|
+
const afterBlock = output.slice(
|
|
80
|
+
(match.index ?? 0) + match[0].length,
|
|
81
|
+
(match.index ?? 0) + match[0].length + 500
|
|
82
|
+
);
|
|
83
|
+
const msgMatch = /^\s*[×!i]\s+(.+)$/m.exec(afterBlock);
|
|
84
|
+
const message = msgMatch ? msgMatch[1].trim() : code;
|
|
85
|
+
const severity = code.includes("lint") ? "warning" : "error";
|
|
86
|
+
errors.push({ file, line, column, severity, code, message });
|
|
87
|
+
}
|
|
88
|
+
return errors;
|
|
89
|
+
}
|
|
90
|
+
function parseGitStatus(output) {
|
|
91
|
+
const staged = [];
|
|
92
|
+
const unstaged = [];
|
|
93
|
+
const untracked = [];
|
|
94
|
+
let branch;
|
|
95
|
+
for (const line of output.split("\n")) {
|
|
96
|
+
if (!line) continue;
|
|
97
|
+
if (line.startsWith("## ")) {
|
|
98
|
+
branch = line.slice(3).split("...")[0];
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const x = line[0];
|
|
102
|
+
const y = line[1];
|
|
103
|
+
const file = line.slice(3).trim();
|
|
104
|
+
if (x === "?" && y === "?") {
|
|
105
|
+
untracked.push(file);
|
|
106
|
+
} else {
|
|
107
|
+
if (x !== " " && x !== "?") {
|
|
108
|
+
staged.push({ status: statusLabel(x), file });
|
|
109
|
+
}
|
|
110
|
+
if (y !== " " && y !== "?") {
|
|
111
|
+
unstaged.push({ status: statusLabel(y), file });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { staged, unstaged, untracked, branch };
|
|
116
|
+
}
|
|
117
|
+
function statusLabel(code) {
|
|
118
|
+
const labels = {
|
|
119
|
+
M: "modified",
|
|
120
|
+
A: "added",
|
|
121
|
+
D: "deleted",
|
|
122
|
+
R: "renamed",
|
|
123
|
+
C: "copied",
|
|
124
|
+
U: "unmerged"
|
|
125
|
+
};
|
|
126
|
+
return labels[code] ?? code;
|
|
127
|
+
}
|
|
128
|
+
function parseOutput(output, tool) {
|
|
129
|
+
const detected = tool ?? detectTool(output);
|
|
130
|
+
switch (detected) {
|
|
131
|
+
case "tsc":
|
|
132
|
+
return { tool: "tsc", errors: parseTsc(output) };
|
|
133
|
+
case "vitest":
|
|
134
|
+
return { tool: "vitest", summary: parseVitest(output) };
|
|
135
|
+
case "biome":
|
|
136
|
+
return { tool: "biome", errors: parseBiome(output) };
|
|
137
|
+
case "git-status":
|
|
138
|
+
return { tool: "git-status", status: parseGitStatus(output) };
|
|
139
|
+
default:
|
|
140
|
+
throw new Error(`Unknown tool: ${detected}. Supported: tsc, vitest, biome, git-status`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function detectTool(output) {
|
|
144
|
+
if (output.includes("error TS") || /\(\d+,\d+\):\s+error/.test(output)) return "tsc";
|
|
145
|
+
if (output.includes("vitest") || output.includes("Test Files") || output.includes("\u2713"))
|
|
146
|
+
return "vitest";
|
|
147
|
+
if (output.includes("biome") || /\w+\/\w+\s+━+/.test(output)) return "biome";
|
|
148
|
+
if (/^##\s/.test(output) || /^[MADRCU?! ]{2}\s/.test(output)) return "git-status";
|
|
149
|
+
return "unknown";
|
|
150
|
+
}
|
|
151
|
+
export {
|
|
152
|
+
parseBiome,
|
|
153
|
+
parseGitStatus,
|
|
154
|
+
parseOutput,
|
|
155
|
+
parseTsc,
|
|
156
|
+
parseVitest
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=parse-output.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ManagedProcess {
|
|
2
|
+
id: string;
|
|
3
|
+
command: string;
|
|
4
|
+
args: string[];
|
|
5
|
+
pid?: number;
|
|
6
|
+
status: 'running' | 'stopped' | 'error';
|
|
7
|
+
startedAt: string;
|
|
8
|
+
exitCode?: number;
|
|
9
|
+
logs: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function processStart(id: string, command: string, args?: string[], options?: {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
}): ManagedProcess;
|
|
14
|
+
export declare function processStop(id: string): ManagedProcess | undefined;
|
|
15
|
+
export declare function processStatus(id: string): ManagedProcess | undefined;
|
|
16
|
+
export declare function processList(): ManagedProcess[];
|
|
17
|
+
export declare function processLogs(id: string, tail?: number): string[];
|
|
18
|
+
//# sourceMappingURL=process-manager.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
const processes = /* @__PURE__ */ new Map();
|
|
3
|
+
const MAX_LOG_LINES = 200;
|
|
4
|
+
function processStart(id, command, args = [], options) {
|
|
5
|
+
if (processes.has(id)) {
|
|
6
|
+
throw new Error(`Process "${id}" is already running. Stop it first.`);
|
|
7
|
+
}
|
|
8
|
+
const proc = spawn(command, args, {
|
|
9
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
10
|
+
shell: true,
|
|
11
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
12
|
+
});
|
|
13
|
+
const info = {
|
|
14
|
+
id,
|
|
15
|
+
command,
|
|
16
|
+
args,
|
|
17
|
+
pid: proc.pid ?? void 0,
|
|
18
|
+
status: "running",
|
|
19
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20
|
+
logs: []
|
|
21
|
+
};
|
|
22
|
+
const appendLog = (data) => {
|
|
23
|
+
const lines = data.toString().split(/\r?\n/).filter(Boolean);
|
|
24
|
+
info.logs.push(...lines);
|
|
25
|
+
if (info.logs.length > MAX_LOG_LINES) {
|
|
26
|
+
info.logs = info.logs.slice(-MAX_LOG_LINES);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
proc.stdout?.on("data", appendLog);
|
|
30
|
+
proc.stderr?.on("data", appendLog);
|
|
31
|
+
proc.on("exit", (code) => {
|
|
32
|
+
info.status = code === 0 ? "stopped" : "error";
|
|
33
|
+
info.exitCode = code ?? void 0;
|
|
34
|
+
});
|
|
35
|
+
proc.on("error", (err) => {
|
|
36
|
+
info.status = "error";
|
|
37
|
+
info.logs.push(`[error] ${err.message}`);
|
|
38
|
+
});
|
|
39
|
+
processes.set(id, { proc, info });
|
|
40
|
+
return info;
|
|
41
|
+
}
|
|
42
|
+
function processStop(id) {
|
|
43
|
+
const entry = processes.get(id);
|
|
44
|
+
if (!entry) return void 0;
|
|
45
|
+
entry.proc.kill("SIGTERM");
|
|
46
|
+
entry.info.status = "stopped";
|
|
47
|
+
processes.delete(id);
|
|
48
|
+
return entry.info;
|
|
49
|
+
}
|
|
50
|
+
function processStatus(id) {
|
|
51
|
+
return processes.get(id)?.info;
|
|
52
|
+
}
|
|
53
|
+
function processList() {
|
|
54
|
+
return [...processes.values()].map((entry) => entry.info);
|
|
55
|
+
}
|
|
56
|
+
function processLogs(id, tail) {
|
|
57
|
+
const entry = processes.get(id);
|
|
58
|
+
if (!entry) return [];
|
|
59
|
+
if (tail) return entry.info.logs.slice(-tail);
|
|
60
|
+
return entry.info.logs;
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
processList,
|
|
64
|
+
processLogs,
|
|
65
|
+
processStart,
|
|
66
|
+
processStatus,
|
|
67
|
+
processStop
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=process-manager.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface QueueItem {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
status: 'pending' | 'in-progress' | 'done' | 'failed';
|
|
5
|
+
data?: unknown;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
updatedAt: string;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface QueueState {
|
|
11
|
+
name: string;
|
|
12
|
+
items: QueueItem[];
|
|
13
|
+
}
|
|
14
|
+
/** Create a new named queue. */
|
|
15
|
+
export declare function queueCreate(name: string, cwd?: string): QueueState;
|
|
16
|
+
/** Push an item onto a queue. Creates the queue if it doesn't exist. */
|
|
17
|
+
export declare function queuePush(name: string, title: string, data?: unknown, cwd?: string): QueueItem;
|
|
18
|
+
/** Take the next pending item from a queue and mark it in-progress. */
|
|
19
|
+
export declare function queueNext(name: string, cwd?: string): QueueItem | null;
|
|
20
|
+
/** Mark a queue item as done. */
|
|
21
|
+
export declare function queueDone(name: string, id: string, cwd?: string): QueueItem;
|
|
22
|
+
/** Mark a queue item as failed with an error message. */
|
|
23
|
+
export declare function queueFail(name: string, id: string, error: string, cwd?: string): QueueItem;
|
|
24
|
+
/** Get the current state of a queue. */
|
|
25
|
+
export declare function queueGet(name: string, cwd?: string): QueueState | null;
|
|
26
|
+
/** List all queues with their item counts. */
|
|
27
|
+
export declare function queueList(cwd?: string): Array<{
|
|
28
|
+
name: string;
|
|
29
|
+
pending: number;
|
|
30
|
+
done: number;
|
|
31
|
+
failed: number;
|
|
32
|
+
total: number;
|
|
33
|
+
}>;
|
|
34
|
+
/** Clear completed items from a queue. */
|
|
35
|
+
export declare function queueClear(name: string, cwd?: string): number;
|
|
36
|
+
/** Delete a queue entirely. */
|
|
37
|
+
export declare function queueDelete(name: string, cwd?: string): boolean;
|
|
38
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
const QUEUE_DIR = ".kb-state";
|
|
4
|
+
const QUEUE_FILE = "queue.json";
|
|
5
|
+
function queuePath(cwd) {
|
|
6
|
+
return resolve(cwd ?? process.cwd(), QUEUE_DIR, QUEUE_FILE);
|
|
7
|
+
}
|
|
8
|
+
function loadQueues(cwd) {
|
|
9
|
+
const path = queuePath(cwd);
|
|
10
|
+
if (!existsSync(path)) return {};
|
|
11
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
12
|
+
}
|
|
13
|
+
function saveQueues(data, cwd) {
|
|
14
|
+
const path = queuePath(cwd);
|
|
15
|
+
const dir = dirname(path);
|
|
16
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
17
|
+
writeFileSync(path, `${JSON.stringify(data, null, 2)}
|
|
18
|
+
`, "utf-8");
|
|
19
|
+
}
|
|
20
|
+
function generateId() {
|
|
21
|
+
return `q_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
|
|
22
|
+
}
|
|
23
|
+
function queueCreate(name, cwd) {
|
|
24
|
+
const queues = loadQueues(cwd);
|
|
25
|
+
if (queues[name]) {
|
|
26
|
+
throw new Error(`Queue "${name}" already exists`);
|
|
27
|
+
}
|
|
28
|
+
const queue = { name, items: [] };
|
|
29
|
+
queues[name] = queue;
|
|
30
|
+
saveQueues(queues, cwd);
|
|
31
|
+
return queue;
|
|
32
|
+
}
|
|
33
|
+
function queuePush(name, title, data, cwd) {
|
|
34
|
+
const queues = loadQueues(cwd);
|
|
35
|
+
if (!queues[name]) {
|
|
36
|
+
queues[name] = { name, items: [] };
|
|
37
|
+
}
|
|
38
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
39
|
+
const item = {
|
|
40
|
+
id: generateId(),
|
|
41
|
+
title,
|
|
42
|
+
status: "pending",
|
|
43
|
+
data,
|
|
44
|
+
createdAt: now,
|
|
45
|
+
updatedAt: now
|
|
46
|
+
};
|
|
47
|
+
queues[name].items.push(item);
|
|
48
|
+
saveQueues(queues, cwd);
|
|
49
|
+
return item;
|
|
50
|
+
}
|
|
51
|
+
function queueNext(name, cwd) {
|
|
52
|
+
const queues = loadQueues(cwd);
|
|
53
|
+
const queue = queues[name];
|
|
54
|
+
if (!queue) throw new Error(`Queue "${name}" does not exist`);
|
|
55
|
+
const item = queue.items.find((i) => i.status === "pending");
|
|
56
|
+
if (!item) return null;
|
|
57
|
+
item.status = "in-progress";
|
|
58
|
+
item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
59
|
+
saveQueues(queues, cwd);
|
|
60
|
+
return item;
|
|
61
|
+
}
|
|
62
|
+
function queueDone(name, id, cwd) {
|
|
63
|
+
const queues = loadQueues(cwd);
|
|
64
|
+
const queue = queues[name];
|
|
65
|
+
if (!queue) throw new Error(`Queue "${name}" does not exist`);
|
|
66
|
+
const item = queue.items.find((i) => i.id === id);
|
|
67
|
+
if (!item) throw new Error(`Item "${id}" not found in queue "${name}"`);
|
|
68
|
+
item.status = "done";
|
|
69
|
+
item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
70
|
+
saveQueues(queues, cwd);
|
|
71
|
+
return item;
|
|
72
|
+
}
|
|
73
|
+
function queueFail(name, id, error, cwd) {
|
|
74
|
+
const queues = loadQueues(cwd);
|
|
75
|
+
const queue = queues[name];
|
|
76
|
+
if (!queue) throw new Error(`Queue "${name}" does not exist`);
|
|
77
|
+
const item = queue.items.find((i) => i.id === id);
|
|
78
|
+
if (!item) throw new Error(`Item "${id}" not found in queue "${name}"`);
|
|
79
|
+
item.status = "failed";
|
|
80
|
+
item.error = error;
|
|
81
|
+
item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
82
|
+
saveQueues(queues, cwd);
|
|
83
|
+
return item;
|
|
84
|
+
}
|
|
85
|
+
function queueGet(name, cwd) {
|
|
86
|
+
return loadQueues(cwd)[name] ?? null;
|
|
87
|
+
}
|
|
88
|
+
function queueList(cwd) {
|
|
89
|
+
const queues = loadQueues(cwd);
|
|
90
|
+
return Object.values(queues).map((q) => ({
|
|
91
|
+
name: q.name,
|
|
92
|
+
pending: q.items.filter((i) => i.status === "pending").length,
|
|
93
|
+
done: q.items.filter((i) => i.status === "done").length,
|
|
94
|
+
failed: q.items.filter((i) => i.status === "failed").length,
|
|
95
|
+
total: q.items.length
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
function queueClear(name, cwd) {
|
|
99
|
+
const queues = loadQueues(cwd);
|
|
100
|
+
const queue = queues[name];
|
|
101
|
+
if (!queue) throw new Error(`Queue "${name}" does not exist`);
|
|
102
|
+
const before = queue.items.length;
|
|
103
|
+
queue.items = queue.items.filter((i) => i.status === "pending" || i.status === "in-progress");
|
|
104
|
+
const removed = before - queue.items.length;
|
|
105
|
+
saveQueues(queues, cwd);
|
|
106
|
+
return removed;
|
|
107
|
+
}
|
|
108
|
+
function queueDelete(name, cwd) {
|
|
109
|
+
const queues = loadQueues(cwd);
|
|
110
|
+
if (!queues[name]) return false;
|
|
111
|
+
delete queues[name];
|
|
112
|
+
saveQueues(queues, cwd);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
export {
|
|
116
|
+
queueClear,
|
|
117
|
+
queueCreate,
|
|
118
|
+
queueDelete,
|
|
119
|
+
queueDone,
|
|
120
|
+
queueFail,
|
|
121
|
+
queueGet,
|
|
122
|
+
queueList,
|
|
123
|
+
queueNext,
|
|
124
|
+
queuePush
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb_regex_test — Test regex patterns against sample strings.
|
|
3
|
+
*/
|
|
4
|
+
export interface RegexTestOptions {
|
|
5
|
+
pattern: string;
|
|
6
|
+
flags?: string;
|
|
7
|
+
testStrings: string[];
|
|
8
|
+
mode?: 'match' | 'replace' | 'split';
|
|
9
|
+
replacement?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RegexMatchInfo {
|
|
12
|
+
full: string;
|
|
13
|
+
groups: (string | undefined)[];
|
|
14
|
+
index: number;
|
|
15
|
+
}
|
|
16
|
+
export interface RegexTestStringResult {
|
|
17
|
+
input: string;
|
|
18
|
+
matched: boolean;
|
|
19
|
+
matches?: RegexMatchInfo[];
|
|
20
|
+
replaced?: string;
|
|
21
|
+
split?: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface RegexTestResult {
|
|
24
|
+
pattern: string;
|
|
25
|
+
flags: string;
|
|
26
|
+
results: RegexTestStringResult[];
|
|
27
|
+
valid: boolean;
|
|
28
|
+
error?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function regexTest(options: RegexTestOptions): RegexTestResult;
|
|
31
|
+
//# sourceMappingURL=regex-test.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function regexTest(options) {
|
|
2
|
+
const { pattern, flags = "", testStrings, mode = "match", replacement = "" } = options;
|
|
3
|
+
try {
|
|
4
|
+
const regex = new RegExp(pattern, flags);
|
|
5
|
+
const results = testStrings.map((input) => {
|
|
6
|
+
const matched = regex.test(input);
|
|
7
|
+
switch (mode) {
|
|
8
|
+
case "match": {
|
|
9
|
+
const globalFlags = flags.includes("g") ? flags : `${flags}g`;
|
|
10
|
+
const allMatches = [...input.matchAll(new RegExp(pattern, globalFlags))];
|
|
11
|
+
return {
|
|
12
|
+
input,
|
|
13
|
+
matched,
|
|
14
|
+
matches: allMatches.map((m) => ({
|
|
15
|
+
full: m[0],
|
|
16
|
+
groups: [...m.slice(1)],
|
|
17
|
+
index: m.index ?? 0
|
|
18
|
+
}))
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
case "replace":
|
|
22
|
+
return {
|
|
23
|
+
input,
|
|
24
|
+
matched,
|
|
25
|
+
replaced: input.replace(new RegExp(pattern, flags), replacement)
|
|
26
|
+
};
|
|
27
|
+
default:
|
|
28
|
+
return { input, matched, split: input.split(new RegExp(pattern, flags)) };
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return { pattern, flags, results, valid: true };
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return { pattern, flags, results: [], valid: false, error: err.message };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
regexTest
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=regex-test.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface RenameOptions {
|
|
2
|
+
/** Symbol to rename */
|
|
3
|
+
oldName: string;
|
|
4
|
+
/** New symbol name */
|
|
5
|
+
newName: string;
|
|
6
|
+
/** Root directory to search in */
|
|
7
|
+
rootPath: string;
|
|
8
|
+
/** File extensions to process (default: .ts, .tsx, .js, .jsx) */
|
|
9
|
+
extensions?: string[];
|
|
10
|
+
/** Glob patterns to exclude */
|
|
11
|
+
exclude?: string[];
|
|
12
|
+
/** Dry run — don't write changes */
|
|
13
|
+
dryRun?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface RenameChange {
|
|
16
|
+
path: string;
|
|
17
|
+
line: number;
|
|
18
|
+
before: string;
|
|
19
|
+
after: string;
|
|
20
|
+
}
|
|
21
|
+
export interface RenameResult {
|
|
22
|
+
oldName: string;
|
|
23
|
+
newName: string;
|
|
24
|
+
changes: RenameChange[];
|
|
25
|
+
filesModified: number;
|
|
26
|
+
dryRun: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function rename(options: RenameOptions): Promise<RenameResult>;
|
|
29
|
+
//# sourceMappingURL=rename.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { relative } from "node:path";
|
|
3
|
+
import { DEFAULT_TOOL_EXTENSIONS, walkFiles } from "./file-walk.js";
|
|
4
|
+
function escapeRegex(value) {
|
|
5
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6
|
+
}
|
|
7
|
+
function normalizePath(path) {
|
|
8
|
+
return path.replace(/\\/g, "/");
|
|
9
|
+
}
|
|
10
|
+
function createWholeWordPattern(name) {
|
|
11
|
+
return new RegExp(`(^|[^A-Za-z0-9_$])(${escapeRegex(name)})(?=[^A-Za-z0-9_$]|$)`, "g");
|
|
12
|
+
}
|
|
13
|
+
async function rename(options) {
|
|
14
|
+
const {
|
|
15
|
+
oldName,
|
|
16
|
+
newName,
|
|
17
|
+
rootPath,
|
|
18
|
+
extensions = DEFAULT_TOOL_EXTENSIONS,
|
|
19
|
+
exclude = [],
|
|
20
|
+
dryRun = false
|
|
21
|
+
} = options;
|
|
22
|
+
if (!oldName.trim()) {
|
|
23
|
+
throw new Error("oldName must not be empty");
|
|
24
|
+
}
|
|
25
|
+
const pattern = createWholeWordPattern(oldName);
|
|
26
|
+
const filePaths = await walkFiles(rootPath, extensions, exclude);
|
|
27
|
+
const changes = [];
|
|
28
|
+
let filesModified = 0;
|
|
29
|
+
for (const filePath of filePaths) {
|
|
30
|
+
const originalContent = await readFile(filePath, "utf-8");
|
|
31
|
+
const lines = originalContent.split(/\r?\n/);
|
|
32
|
+
let fileChanged = false;
|
|
33
|
+
for (let index = 0; index < lines.length; index++) {
|
|
34
|
+
const before = lines[index];
|
|
35
|
+
pattern.lastIndex = 0;
|
|
36
|
+
const after = before.replace(pattern, (_match, prefix) => {
|
|
37
|
+
fileChanged = true;
|
|
38
|
+
return `${prefix}${newName}`;
|
|
39
|
+
});
|
|
40
|
+
if (before === after) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
lines[index] = after;
|
|
44
|
+
changes.push({
|
|
45
|
+
path: normalizePath(relative(rootPath, filePath)),
|
|
46
|
+
line: index + 1,
|
|
47
|
+
before,
|
|
48
|
+
after
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (!fileChanged) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
filesModified += 1;
|
|
55
|
+
if (!dryRun) {
|
|
56
|
+
await writeFile(filePath, lines.join("\n"), "utf-8");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
oldName,
|
|
61
|
+
newName,
|
|
62
|
+
changes,
|
|
63
|
+
filesModified,
|
|
64
|
+
dryRun
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
rename
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=rename.js.map
|