Skip to content

Commit 1cdb40c

Browse files
Merge pull request #91 from CodeDeficient/claude/project-thread-36cl1x-compiled-js
Ship compiled JavaScript instead of running TypeScript through tsx
2 parents 52a88d4 + 7dcf6cd commit 1cdb40c

9 files changed

Lines changed: 77 additions & 64 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,16 @@ jobs:
2222
- run: npm ci
2323
- run: npm run typecheck
2424
- run: npm test
25+
- name: Build and run the packaged CLI
26+
run: |
27+
npm pack
28+
mkdir -p /tmp/smoke && cd /tmp/smoke && npm init -y >/dev/null
29+
npm install "$GITHUB_WORKSPACE"/karpeslop-*.tgz
30+
echo 'export const v = 1 as any;' > a.ts
31+
# `as any` is high severity, so a working CLI reports it and exits 1.
32+
# A crash also exits 1, so check the finding is in the output too.
33+
status=0
34+
KARPESLOP_OFFLINE=1 npx karpeslop --no-report a.ts > out.txt 2>&1 || status=$?
35+
cat out.txt
36+
test "$status" -eq 1
37+
grep -q 'unsafe_type_assertion' out.txt

‎.gitignore‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ detector_output.txt
1414
CLAUDE.md
1515
.claude/
1616
.qwen/
17-
QWEN.md
17+
QWEN.md
18+
karpeslop-*.tgz

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All notable changes will be documented in this file.
99
- `swallowed_error` (medium): a `catch` block whose only statements are `console` calls. The error is logged and the code carries on as if the operation succeeded. A comment in the block explaining why that is safe, a rethrow, or any other statement (such as `setError(e)`) means it is not reported, and so does a fallback after the `try`, as for `empty_catch`.
1010

1111
### Changed
12+
- The package ships compiled JavaScript (`dist/`) and runs it directly with Node. It used to run the TypeScript sources through `tsx` on every call: `karpeslop --version` took 1.5 s and an install was 43 MB. It now takes 0.6 s and 31 MB, most of it the TypeScript compiler the rules use to parse code. `tsx` is no longer a runtime dependency.
1213
- `fresh_package_version` skips packages the scanned workspace publishes itself (any `name` in a scanned package.json) and lockfile entries that link a workspace folder. TanStack Query got 184 warnings for `@tanstack/*` versions it had just released.
1314
- Folders named `build`, `out` or `temp` are skipped only at the scan root or next to a package.json, where they hold build output. Deeper ones are often source: Next.js keeps its build pipeline in `packages/next/src/build/`, which was never scanned.
1415
- A run whose paths are all missing, ignored or unsupported ends with a one-line error instead of a stack trace.

‎ai-slop-detector.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,8 @@ turn it off, with severityOverrides in .karpesloprc.json.
11111111
`);
11121112
}
11131113

1114-
async function runIfMain() {
1114+
/** The command-line entry point, used by karpeslop-cli.js and by `tsx ai-slop-detector.ts`. */
1115+
export async function main(): Promise<void> {
11151116
const rootDir = process.cwd();
11161117

11171118
const args = process.argv.slice(2);
@@ -1181,7 +1182,7 @@ async function runIfMain() {
11811182

11821183
// Execute only when run as the main module, not when imported by tests.
11831184
if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
1184-
runIfMain().catch(error => {
1185+
main().catch(error => {
11851186
console.error('KarpeSlop failed:', error);
11861187
process.exit(1);
11871188
});

‎imports.ts‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -636,15 +636,14 @@ function missingExportFinding(
636636
};
637637
}
638638

639-
/** This package's version from package.json, or 'unknown'. */
639+
/** This package's version from package.json (next to this file, or one level up from dist/), or 'unknown'. */
640640
export function ownVersion(): string {
641-
try {
642-
const packagePath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'package.json');
643-
const version: unknown = JSON.parse(fs.readFileSync(packagePath, 'utf8')).version;
644-
return typeof version === 'string' ? version : 'unknown';
645-
} catch {
646-
return 'unknown';
641+
const here = path.dirname(fileURLToPath(import.meta.url));
642+
for (const dir of [here, path.dirname(here)]) {
643+
const version = readJsonObject(path.join(dir, 'package.json'))?.version;
644+
if (typeof version === 'string') return version;
647645
}
646+
return 'unknown';
648647
}
649648

650649
/** Sent with every npm registry request, as the registry asks of programmatic clients. */

‎karpeslop-cli.js‎

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,8 @@
11
#!/usr/bin/env node
2-
// This is an ES module wrapper for the KarpeSlop CLI tool
2+
// The published entry point. The prepare script (run by npm install, npm link and npm pack) compiles the TypeScript sources to dist/.
3+
import { main } from './dist/ai-slop-detector.js';
34

4-
import { spawn } from 'child_process';
5-
import { createRequire } from 'module';
6-
import { fileURLToPath } from 'url';
7-
import { dirname, join } from 'path';
8-
9-
const require = createRequire(import.meta.url);
10-
const __filename = fileURLToPath(import.meta.url);
11-
const __dirname = dirname(__filename);
12-
13-
// Resolve the tsx loader from this package's dependencies so published
14-
// installs do not depend on a specific node_modules/.bin layout.
15-
const detectorPath = join(__dirname, 'ai-slop-detector.ts');
16-
const tsxLoaderPath = require.resolve('tsx');
17-
18-
function exitCodeForSignal(signal) {
19-
const signalExitCodes = {
20-
SIGINT: 130,
21-
SIGTERM: 143,
22-
SIGHUP: 129,
23-
SIGQUIT: 131
24-
};
25-
26-
return signalExitCodes[signal] || 1;
27-
}
28-
29-
function handleChildExit(code, signal) {
30-
if (signal) {
31-
process.exit(exitCodeForSignal(signal));
32-
}
33-
process.exit(code ?? 0);
34-
}
35-
36-
// Get command line arguments, excluding the first two (node and script path)
37-
const args = process.argv.slice(2);
38-
39-
// Run the detector through Node with the resolved tsx loader.
40-
const child = spawn(
41-
process.execPath,
42-
['--import', tsxLoaderPath, detectorPath, ...args],
43-
{ stdio: 'inherit', cwd: process.cwd() }
44-
);
45-
46-
child.on('error', (err) => {
47-
console.error('Failed to start karpeslop:', err.message);
5+
main().catch(error => {
6+
console.error('KarpeSlop failed:', error);
487
process.exit(1);
498
});
50-
51-
child.on('exit', handleChildExit);

‎package-lock.json‎

Lines changed: 31 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)