@eloquence98/ctx 0.1.3 ā 0.1.4
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/cli.js +20 -2
- package/dist/config.js +1 -0
- package/dist/detectors/index.d.ts +3 -0
- package/dist/detectors/index.js +73 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,16 +5,21 @@ import fs from "fs/promises";
|
|
|
5
5
|
import { scanDirectory, getRoutes } from "./scanner.js";
|
|
6
6
|
import { parseFile } from "./parser.js";
|
|
7
7
|
import { formatMarkdown } from "./formatters/index.js";
|
|
8
|
+
import { detectProject, getProjectLabel } from "./detectors/index.js";
|
|
8
9
|
program
|
|
9
10
|
.name("ctx")
|
|
10
11
|
.description("Generate AI-ready context from your codebase")
|
|
11
|
-
.version("0.1.
|
|
12
|
+
.version("0.1.4")
|
|
12
13
|
.argument("[path]", "Path to scan", "./src")
|
|
13
14
|
.option("-o, --output <format>", "Output format: md, json", "md")
|
|
14
15
|
.option("--ai", "Output in AI-optimized compact format")
|
|
15
16
|
.action(async (targetPath, options) => {
|
|
16
17
|
const absolutePath = path.resolve(process.cwd(), targetPath);
|
|
18
|
+
// Detect project type
|
|
19
|
+
const projectRoot = await findProjectRoot(absolutePath);
|
|
20
|
+
const projectType = await detectProject(projectRoot);
|
|
17
21
|
console.log(`\nš Scanning ${absolutePath}...\n`);
|
|
22
|
+
console.log(`š¦ Detected: ${getProjectLabel(projectType)}\n`);
|
|
18
23
|
try {
|
|
19
24
|
// Scan all files
|
|
20
25
|
const files = await scanDirectory(absolutePath);
|
|
@@ -55,6 +60,19 @@ program
|
|
|
55
60
|
process.exit(1);
|
|
56
61
|
}
|
|
57
62
|
});
|
|
63
|
+
async function findProjectRoot(startDir) {
|
|
64
|
+
let current = startDir;
|
|
65
|
+
while (current !== path.dirname(current)) {
|
|
66
|
+
try {
|
|
67
|
+
await fs.access(path.join(current, "package.json"));
|
|
68
|
+
return current;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
current = path.dirname(current);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return startDir;
|
|
75
|
+
}
|
|
58
76
|
async function findAppDirectory(basePath) {
|
|
59
77
|
const possiblePaths = [
|
|
60
78
|
path.join(basePath, "app"),
|
|
@@ -69,7 +87,7 @@ async function findAppDirectory(basePath) {
|
|
|
69
87
|
}
|
|
70
88
|
}
|
|
71
89
|
catch {
|
|
72
|
-
//
|
|
90
|
+
// try next
|
|
73
91
|
}
|
|
74
92
|
}
|
|
75
93
|
return null;
|
package/dist/config.js
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
async function readPackageJson(dir) {
|
|
4
|
+
try {
|
|
5
|
+
const content = await fs.readFile(path.join(dir, "package.json"), "utf-8");
|
|
6
|
+
return JSON.parse(content);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async function fileExists(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
await fs.access(filePath);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function detectProject(dir) {
|
|
22
|
+
const pkg = await readPackageJson(dir);
|
|
23
|
+
const deps = {
|
|
24
|
+
...pkg?.dependencies,
|
|
25
|
+
...pkg?.devDependencies,
|
|
26
|
+
};
|
|
27
|
+
// Check config files first (more specific)
|
|
28
|
+
const hasNextConfig = (await fileExists(path.join(dir, "next.config.js"))) ||
|
|
29
|
+
(await fileExists(path.join(dir, "next.config.mjs"))) ||
|
|
30
|
+
(await fileExists(path.join(dir, "next.config.ts")));
|
|
31
|
+
if (hasNextConfig || deps["next"]) {
|
|
32
|
+
return "nextjs";
|
|
33
|
+
}
|
|
34
|
+
// NestJS
|
|
35
|
+
if (deps["@nestjs/core"]) {
|
|
36
|
+
return "nestjs";
|
|
37
|
+
}
|
|
38
|
+
// SvelteKit
|
|
39
|
+
if (deps["@sveltejs/kit"]) {
|
|
40
|
+
return "sveltekit";
|
|
41
|
+
}
|
|
42
|
+
// Vue
|
|
43
|
+
if (deps["vue"] || deps["nuxt"]) {
|
|
44
|
+
return "vue";
|
|
45
|
+
}
|
|
46
|
+
// Express
|
|
47
|
+
if (deps["express"] || deps["fastify"] || deps["koa"] || deps["hono"]) {
|
|
48
|
+
return "express";
|
|
49
|
+
}
|
|
50
|
+
// React (without Next.js)
|
|
51
|
+
if (deps["react"] && !deps["next"]) {
|
|
52
|
+
return "react";
|
|
53
|
+
}
|
|
54
|
+
// Node.js project (has package.json but no framework)
|
|
55
|
+
if (pkg) {
|
|
56
|
+
return "node";
|
|
57
|
+
}
|
|
58
|
+
// No package.json
|
|
59
|
+
return "vanilla";
|
|
60
|
+
}
|
|
61
|
+
export function getProjectLabel(type) {
|
|
62
|
+
const labels = {
|
|
63
|
+
nextjs: "Next.js",
|
|
64
|
+
react: "React",
|
|
65
|
+
express: "Express/Fastify",
|
|
66
|
+
nestjs: "NestJS",
|
|
67
|
+
vue: "Vue/Nuxt",
|
|
68
|
+
sveltekit: "SvelteKit",
|
|
69
|
+
node: "Node.js",
|
|
70
|
+
vanilla: "JavaScript/TypeScript",
|
|
71
|
+
};
|
|
72
|
+
return labels[type];
|
|
73
|
+
}
|