claude-crap 0.2.0 → 0.3.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/CHANGELOG.md +33 -0
- package/README.md +4 -3
- package/dist/index.js +64 -1
- package/dist/index.js.map +1 -1
- package/dist/scanner/bootstrap.d.ts +89 -0
- package/dist/scanner/bootstrap.d.ts.map +1 -0
- package/dist/scanner/bootstrap.js +278 -0
- package/dist/scanner/bootstrap.js.map +1 -0
- package/dist/scanner/index.d.ts +1 -0
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +1 -0
- package/dist/scanner/index.js.map +1 -1
- package/dist/schemas/tool-schemas.d.ts +12 -0
- package/dist/schemas/tool-schemas.d.ts.map +1 -1
- package/dist/schemas/tool-schemas.js +12 -0
- package/dist/schemas/tool-schemas.js.map +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/bundle/mcp-server.mjs +280 -0
- package/plugin/bundle/mcp-server.mjs.map +4 -4
- package/plugin/package.json +1 -1
- package/src/index.ts +78 -0
- package/src/scanner/bootstrap.ts +383 -0
- package/src/scanner/index.ts +8 -0
- package/src/schemas/tool-schemas.ts +14 -0
- package/src/tests/integration/mcp-server.integration.test.ts +2 -1
- package/src/tests/scanner-bootstrap.test.ts +186 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the scanner bootstrap module.
|
|
3
|
+
*
|
|
4
|
+
* Tests project type detection, ESLint config generation, and the
|
|
5
|
+
* bootstrap orchestrator's short-circuit and error paths.
|
|
6
|
+
*
|
|
7
|
+
* @module tests/scanner-bootstrap.test
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it } from "node:test";
|
|
11
|
+
import assert from "node:assert/strict";
|
|
12
|
+
import { mkdtempSync, writeFileSync, rmSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
|
|
16
|
+
import { detectProjectType, generateEslintConfig } from "../scanner/bootstrap.js";
|
|
17
|
+
|
|
18
|
+
function makeTmpDir(): string {
|
|
19
|
+
return mkdtempSync(join(tmpdir(), "crap-bootstrap-"));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("detectProjectType", () => {
|
|
23
|
+
it("returns typescript when package.json and tsconfig.json exist", () => {
|
|
24
|
+
const dir = makeTmpDir();
|
|
25
|
+
try {
|
|
26
|
+
writeFileSync(join(dir, "package.json"), "{}");
|
|
27
|
+
writeFileSync(join(dir, "tsconfig.json"), "{}");
|
|
28
|
+
assert.equal(detectProjectType(dir), "typescript");
|
|
29
|
+
} finally {
|
|
30
|
+
rmSync(dir, { recursive: true, force: true });
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("returns javascript when only package.json exists", () => {
|
|
35
|
+
const dir = makeTmpDir();
|
|
36
|
+
try {
|
|
37
|
+
writeFileSync(join(dir, "package.json"), "{}");
|
|
38
|
+
assert.equal(detectProjectType(dir), "javascript");
|
|
39
|
+
} finally {
|
|
40
|
+
rmSync(dir, { recursive: true, force: true });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("returns python when pyproject.toml exists", () => {
|
|
45
|
+
const dir = makeTmpDir();
|
|
46
|
+
try {
|
|
47
|
+
writeFileSync(join(dir, "pyproject.toml"), "[project]");
|
|
48
|
+
assert.equal(detectProjectType(dir), "python");
|
|
49
|
+
} finally {
|
|
50
|
+
rmSync(dir, { recursive: true, force: true });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("returns python when setup.py exists", () => {
|
|
55
|
+
const dir = makeTmpDir();
|
|
56
|
+
try {
|
|
57
|
+
writeFileSync(join(dir, "setup.py"), "from setuptools import setup");
|
|
58
|
+
assert.equal(detectProjectType(dir), "python");
|
|
59
|
+
} finally {
|
|
60
|
+
rmSync(dir, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("returns python when requirements.txt exists", () => {
|
|
65
|
+
const dir = makeTmpDir();
|
|
66
|
+
try {
|
|
67
|
+
writeFileSync(join(dir, "requirements.txt"), "flask==2.0");
|
|
68
|
+
assert.equal(detectProjectType(dir), "python");
|
|
69
|
+
} finally {
|
|
70
|
+
rmSync(dir, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("returns java when pom.xml exists", () => {
|
|
75
|
+
const dir = makeTmpDir();
|
|
76
|
+
try {
|
|
77
|
+
writeFileSync(join(dir, "pom.xml"), "<project></project>");
|
|
78
|
+
assert.equal(detectProjectType(dir), "java");
|
|
79
|
+
} finally {
|
|
80
|
+
rmSync(dir, { recursive: true, force: true });
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("returns java when build.gradle exists", () => {
|
|
85
|
+
const dir = makeTmpDir();
|
|
86
|
+
try {
|
|
87
|
+
writeFileSync(join(dir, "build.gradle"), "plugins {}");
|
|
88
|
+
assert.equal(detectProjectType(dir), "java");
|
|
89
|
+
} finally {
|
|
90
|
+
rmSync(dir, { recursive: true, force: true });
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("returns java when build.gradle.kts exists", () => {
|
|
95
|
+
const dir = makeTmpDir();
|
|
96
|
+
try {
|
|
97
|
+
writeFileSync(join(dir, "build.gradle.kts"), "plugins {}");
|
|
98
|
+
assert.equal(detectProjectType(dir), "java");
|
|
99
|
+
} finally {
|
|
100
|
+
rmSync(dir, { recursive: true, force: true });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("returns csharp when .csproj file exists", () => {
|
|
105
|
+
const dir = makeTmpDir();
|
|
106
|
+
try {
|
|
107
|
+
writeFileSync(join(dir, "MyApp.csproj"), "<Project />");
|
|
108
|
+
assert.equal(detectProjectType(dir), "csharp");
|
|
109
|
+
} finally {
|
|
110
|
+
rmSync(dir, { recursive: true, force: true });
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("returns csharp when .sln file exists", () => {
|
|
115
|
+
const dir = makeTmpDir();
|
|
116
|
+
try {
|
|
117
|
+
writeFileSync(join(dir, "MyApp.sln"), "");
|
|
118
|
+
assert.equal(detectProjectType(dir), "csharp");
|
|
119
|
+
} finally {
|
|
120
|
+
rmSync(dir, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("returns csharp when Directory.Build.props exists", () => {
|
|
125
|
+
const dir = makeTmpDir();
|
|
126
|
+
try {
|
|
127
|
+
writeFileSync(join(dir, "Directory.Build.props"), "<Project />");
|
|
128
|
+
assert.equal(detectProjectType(dir), "csharp");
|
|
129
|
+
} finally {
|
|
130
|
+
rmSync(dir, { recursive: true, force: true });
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("returns unknown for an empty directory", () => {
|
|
135
|
+
const dir = makeTmpDir();
|
|
136
|
+
try {
|
|
137
|
+
assert.equal(detectProjectType(dir), "unknown");
|
|
138
|
+
} finally {
|
|
139
|
+
rmSync(dir, { recursive: true, force: true });
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("typescript wins over python when both signals present", () => {
|
|
144
|
+
const dir = makeTmpDir();
|
|
145
|
+
try {
|
|
146
|
+
writeFileSync(join(dir, "package.json"), "{}");
|
|
147
|
+
writeFileSync(join(dir, "tsconfig.json"), "{}");
|
|
148
|
+
writeFileSync(join(dir, "requirements.txt"), "flask");
|
|
149
|
+
assert.equal(detectProjectType(dir), "typescript");
|
|
150
|
+
} finally {
|
|
151
|
+
rmSync(dir, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe("generateEslintConfig", () => {
|
|
157
|
+
it("TypeScript config includes typescript-eslint import", () => {
|
|
158
|
+
const config = generateEslintConfig(true);
|
|
159
|
+
assert.ok(config.includes('import tseslint from "typescript-eslint"'));
|
|
160
|
+
assert.ok(config.includes("tseslint.config"));
|
|
161
|
+
assert.ok(config.includes("tseslint.configs.recommended"));
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("JavaScript config uses plain array export", () => {
|
|
165
|
+
const config = generateEslintConfig(false);
|
|
166
|
+
assert.ok(config.includes("export default ["));
|
|
167
|
+
assert.ok(!config.includes("typescript-eslint"));
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("both configs include standard ignores", () => {
|
|
171
|
+
for (const isTS of [true, false]) {
|
|
172
|
+
const config = generateEslintConfig(isTS);
|
|
173
|
+
assert.ok(config.includes('"dist/"'), `${isTS ? "TS" : "JS"} should ignore dist/`);
|
|
174
|
+
assert.ok(config.includes('"node_modules/"'), `${isTS ? "TS" : "JS"} should ignore node_modules/`);
|
|
175
|
+
assert.ok(config.includes('"coverage/"'), `${isTS ? "TS" : "JS"} should ignore coverage/`);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("both configs import @eslint/js", () => {
|
|
180
|
+
for (const isTS of [true, false]) {
|
|
181
|
+
const config = generateEslintConfig(isTS);
|
|
182
|
+
assert.ok(config.includes('import js from "@eslint/js"'));
|
|
183
|
+
assert.ok(config.includes("js.configs.recommended"));
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
});
|