leadcode 0.1.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.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -0
  3. package/bin/leadcode.js +2 -0
  4. package/dist/analyzers/constants.d.ts +3 -0
  5. package/dist/analyzers/constants.d.ts.map +1 -0
  6. package/dist/analyzers/constants.js +14 -0
  7. package/dist/analyzers/constants.js.map +1 -0
  8. package/dist/analyzers/dependencies.d.ts +8 -0
  9. package/dist/analyzers/dependencies.d.ts.map +1 -0
  10. package/dist/analyzers/dependencies.js +13 -0
  11. package/dist/analyzers/dependencies.js.map +1 -0
  12. package/dist/analyzers/detection.d.ts +6 -0
  13. package/dist/analyzers/detection.d.ts.map +1 -0
  14. package/dist/analyzers/detection.js +334 -0
  15. package/dist/analyzers/detection.js.map +1 -0
  16. package/dist/analyzers/patterns.d.ts +12 -0
  17. package/dist/analyzers/patterns.d.ts.map +1 -0
  18. package/dist/analyzers/patterns.js +84 -0
  19. package/dist/analyzers/patterns.js.map +1 -0
  20. package/dist/analyzers/structure.d.ts +3 -0
  21. package/dist/analyzers/structure.d.ts.map +1 -0
  22. package/dist/analyzers/structure.js +217 -0
  23. package/dist/analyzers/structure.js.map +1 -0
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +64 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/rules/auth.d.ts +3 -0
  29. package/dist/rules/auth.d.ts.map +1 -0
  30. package/dist/rules/auth.js +48 -0
  31. package/dist/rules/auth.js.map +1 -0
  32. package/dist/rules/cross-stack.d.ts +3 -0
  33. package/dist/rules/cross-stack.d.ts.map +1 -0
  34. package/dist/rules/cross-stack.js +320 -0
  35. package/dist/rules/cross-stack.js.map +1 -0
  36. package/dist/rules/drizzle.d.ts +3 -0
  37. package/dist/rules/drizzle.d.ts.map +1 -0
  38. package/dist/rules/drizzle.js +43 -0
  39. package/dist/rules/drizzle.js.map +1 -0
  40. package/dist/rules/index.d.ts +7 -0
  41. package/dist/rules/index.d.ts.map +1 -0
  42. package/dist/rules/index.js +104 -0
  43. package/dist/rules/index.js.map +1 -0
  44. package/dist/rules/nextjs.d.ts +4 -0
  45. package/dist/rules/nextjs.d.ts.map +1 -0
  46. package/dist/rules/nextjs.js +86 -0
  47. package/dist/rules/nextjs.js.map +1 -0
  48. package/dist/rules/node.d.ts +3 -0
  49. package/dist/rules/node.d.ts.map +1 -0
  50. package/dist/rules/node.js +61 -0
  51. package/dist/rules/node.js.map +1 -0
  52. package/dist/rules/prisma.d.ts +3 -0
  53. package/dist/rules/prisma.d.ts.map +1 -0
  54. package/dist/rules/prisma.js +44 -0
  55. package/dist/rules/prisma.js.map +1 -0
  56. package/dist/rules/react.d.ts +3 -0
  57. package/dist/rules/react.d.ts.map +1 -0
  58. package/dist/rules/react.js +58 -0
  59. package/dist/rules/react.js.map +1 -0
  60. package/dist/rules/state.d.ts +3 -0
  61. package/dist/rules/state.d.ts.map +1 -0
  62. package/dist/rules/state.js +54 -0
  63. package/dist/rules/state.js.map +1 -0
  64. package/dist/rules/tailwind.d.ts +3 -0
  65. package/dist/rules/tailwind.d.ts.map +1 -0
  66. package/dist/rules/tailwind.js +41 -0
  67. package/dist/rules/tailwind.js.map +1 -0
  68. package/dist/rules/trpc.d.ts +3 -0
  69. package/dist/rules/trpc.d.ts.map +1 -0
  70. package/dist/rules/trpc.js +35 -0
  71. package/dist/rules/trpc.js.map +1 -0
  72. package/dist/rules/typescript.d.ts +3 -0
  73. package/dist/rules/typescript.d.ts.map +1 -0
  74. package/dist/rules/typescript.js +54 -0
  75. package/dist/rules/typescript.js.map +1 -0
  76. package/dist/rules/validation.d.ts +3 -0
  77. package/dist/rules/validation.d.ts.map +1 -0
  78. package/dist/rules/validation.js +38 -0
  79. package/dist/rules/validation.js.map +1 -0
  80. package/dist/templates/claude-md.d.ts +4 -0
  81. package/dist/templates/claude-md.d.ts.map +1 -0
  82. package/dist/templates/claude-md.js +309 -0
  83. package/dist/templates/claude-md.js.map +1 -0
  84. package/dist/tools/analyze-repo.d.ts +3 -0
  85. package/dist/tools/analyze-repo.d.ts.map +1 -0
  86. package/dist/tools/analyze-repo.js +68 -0
  87. package/dist/tools/analyze-repo.js.map +1 -0
  88. package/dist/tools/detect-gaps.d.ts +3 -0
  89. package/dist/tools/detect-gaps.d.ts.map +1 -0
  90. package/dist/tools/detect-gaps.js +34 -0
  91. package/dist/tools/detect-gaps.js.map +1 -0
  92. package/dist/tools/generate-claude-md.d.ts +3 -0
  93. package/dist/tools/generate-claude-md.d.ts.map +1 -0
  94. package/dist/tools/generate-claude-md.js +70 -0
  95. package/dist/tools/generate-claude-md.js.map +1 -0
  96. package/dist/tools/suggest.d.ts +3 -0
  97. package/dist/tools/suggest.d.ts.map +1 -0
  98. package/dist/tools/suggest.js +340 -0
  99. package/dist/tools/suggest.js.map +1 -0
  100. package/dist/tools/update-claude-md.d.ts +3 -0
  101. package/dist/tools/update-claude-md.d.ts.map +1 -0
  102. package/dist/tools/update-claude-md.js +108 -0
  103. package/dist/tools/update-claude-md.js.map +1 -0
  104. package/dist/tools/validate-claude-md.d.ts +3 -0
  105. package/dist/tools/validate-claude-md.d.ts.map +1 -0
  106. package/dist/tools/validate-claude-md.js +137 -0
  107. package/dist/tools/validate-claude-md.js.map +1 -0
  108. package/dist/types.d.ts +116 -0
  109. package/dist/types.d.ts.map +1 -0
  110. package/dist/types.js +2 -0
  111. package/dist/types.js.map +1 -0
  112. package/package.json +55 -0
@@ -0,0 +1,84 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { IGNORE_DIRS as IGNORE, SOURCE_EXTS } from "./constants.js";
4
+ async function scanDir(dir, patterns, maxDepth = 6) {
5
+ if (maxDepth <= 0)
6
+ return;
7
+ let entries;
8
+ try {
9
+ entries = await readdir(dir, { withFileTypes: true });
10
+ }
11
+ catch {
12
+ return;
13
+ }
14
+ for (const entry of entries) {
15
+ if (IGNORE.has(entry.name) || entry.name.startsWith("."))
16
+ continue;
17
+ if (entry.isDirectory()) {
18
+ await scanDir(join(dir, entry.name), patterns, maxDepth - 1);
19
+ continue;
20
+ }
21
+ const ext = entry.name.split(".").pop() ?? "";
22
+ if (!SOURCE_EXTS.has(ext))
23
+ continue;
24
+ const filePath = join(dir, entry.name);
25
+ let content;
26
+ try {
27
+ content = await readFile(filePath, "utf-8");
28
+ }
29
+ catch {
30
+ continue;
31
+ }
32
+ const lines = content.split("\n");
33
+ if (ext === "tsx" || ext === "jsx") {
34
+ patterns.totalComponents++;
35
+ }
36
+ // Check for 'use client' / 'use server'
37
+ const firstLines = content.slice(0, 200);
38
+ if (firstLines.includes("'use client'") || firstLines.includes('"use client"')) {
39
+ patterns.useClientCount++;
40
+ }
41
+ if (firstLines.includes("'use server'") || firstLines.includes('"use server"')) {
42
+ patterns.useServerCount++;
43
+ }
44
+ // Barrel files
45
+ if (entry.name === "index.ts" || entry.name === "index.js") {
46
+ if (content.includes("export {") || content.includes("export *")) {
47
+ patterns.hasBarrelFiles = true;
48
+ }
49
+ }
50
+ // Path alias
51
+ if (content.includes("from '@/") || content.includes("from \"@/") ||
52
+ content.includes("from '~/") || content.includes("from \"~/")) {
53
+ patterns.usesPathAlias = true;
54
+ }
55
+ // Large files
56
+ if (lines.length > 300) {
57
+ patterns.largeFiles.push(filePath);
58
+ }
59
+ // Console.log count
60
+ const matches = content.match(/console\.log\(/g);
61
+ if (matches) {
62
+ patterns.consoleLogCount += matches.length;
63
+ }
64
+ }
65
+ }
66
+ export async function analyzePatterns(projectPath) {
67
+ const patterns = {
68
+ useClientCount: 0,
69
+ useServerCount: 0,
70
+ totalComponents: 0,
71
+ clientRatio: 0,
72
+ hasBarrelFiles: false,
73
+ usesPathAlias: false,
74
+ largeFiles: [],
75
+ consoleLogCount: 0,
76
+ };
77
+ await scanDir(projectPath, patterns);
78
+ patterns.clientRatio =
79
+ patterns.totalComponents > 0
80
+ ? patterns.useClientCount / patterns.totalComponents
81
+ : 0;
82
+ return patterns;
83
+ }
84
+ //# sourceMappingURL=patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/analyzers/patterns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { StructureInfo } from "../types.js";
2
+ export declare function analyzeStructure(projectPath: string): Promise<StructureInfo>;
3
+ //# sourceMappingURL=structure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/analyzers/structure.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAgIjD,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA+HxB"}
@@ -0,0 +1,217 @@
1
+ import { readdir, readFile, stat } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { IGNORE_DIRS as IGNORE } from "./constants.js";
4
+ async function exists(path) {
5
+ try {
6
+ await stat(path);
7
+ return true;
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ async function getTopLevelDirs(projectPath) {
14
+ const entries = await readdir(projectPath, { withFileTypes: true });
15
+ return entries
16
+ .filter((e) => e.isDirectory() && !IGNORE.has(e.name) && !e.name.startsWith("."))
17
+ .map((e) => e.name);
18
+ }
19
+ /**
20
+ * Recursively search for files matching given names within a directory.
21
+ * Returns true as soon as any match is found (early exit).
22
+ */
23
+ async function hasFileRecursive(dir, fileNames, maxDepth = 5) {
24
+ if (maxDepth <= 0)
25
+ return false;
26
+ try {
27
+ const entries = await readdir(dir, { withFileTypes: true });
28
+ for (const entry of entries) {
29
+ if (IGNORE.has(entry.name) || entry.name.startsWith("."))
30
+ continue;
31
+ if (entry.isFile() && fileNames.includes(entry.name))
32
+ return true;
33
+ if (entry.isDirectory()) {
34
+ const found = await hasFileRecursive(join(dir, entry.name), fileNames, maxDepth - 1);
35
+ if (found)
36
+ return true;
37
+ }
38
+ }
39
+ }
40
+ catch {
41
+ // Permission errors, etc.
42
+ }
43
+ return false;
44
+ }
45
+ /**
46
+ * Search for a string pattern in files within a directory.
47
+ * Returns true if any file contains the pattern.
48
+ */
49
+ async function hasContentRecursive(dir, pattern, extensions, maxDepth = 4) {
50
+ if (maxDepth <= 0)
51
+ return false;
52
+ try {
53
+ const entries = await readdir(dir, { withFileTypes: true });
54
+ for (const entry of entries) {
55
+ if (IGNORE.has(entry.name) || entry.name.startsWith("."))
56
+ continue;
57
+ if (entry.isFile()) {
58
+ const ext = entry.name.split(".").pop() ?? "";
59
+ if (extensions.includes(ext)) {
60
+ try {
61
+ const content = await readFile(join(dir, entry.name), "utf-8");
62
+ if (pattern.test(content))
63
+ return true;
64
+ }
65
+ catch {
66
+ // Skip unreadable files
67
+ }
68
+ }
69
+ }
70
+ if (entry.isDirectory()) {
71
+ const found = await hasContentRecursive(join(dir, entry.name), pattern, extensions, maxDepth - 1);
72
+ if (found)
73
+ return true;
74
+ }
75
+ }
76
+ }
77
+ catch {
78
+ // Permission errors
79
+ }
80
+ return false;
81
+ }
82
+ /**
83
+ * Count source files recursively (ts, tsx, js, jsx).
84
+ */
85
+ async function countSourceFiles(dir, maxDepth = 6) {
86
+ if (maxDepth <= 0)
87
+ return 0;
88
+ let count = 0;
89
+ try {
90
+ const entries = await readdir(dir, { withFileTypes: true });
91
+ for (const entry of entries) {
92
+ if (IGNORE.has(entry.name) || entry.name.startsWith("."))
93
+ continue;
94
+ if (entry.isFile()) {
95
+ const ext = entry.name.split(".").pop() ?? "";
96
+ if (["ts", "tsx", "js", "jsx"].includes(ext))
97
+ count++;
98
+ }
99
+ if (entry.isDirectory()) {
100
+ count += await countSourceFiles(join(dir, entry.name), maxDepth - 1);
101
+ }
102
+ }
103
+ }
104
+ catch {
105
+ // Permission errors
106
+ }
107
+ return count;
108
+ }
109
+ function anyDirExists(topLevelDirs, names) {
110
+ return names.some((n) => topLevelDirs.includes(n));
111
+ }
112
+ export async function analyzeStructure(projectPath) {
113
+ const topLevelDirs = await getTopLevelDirs(projectPath);
114
+ const resolve = (segments) => join(projectPath, ...segments);
115
+ const hasSrcDir = await exists(join(projectPath, "src"));
116
+ const prefix = hasSrcDir ? ["src"] : [];
117
+ // Resolve with and without src/
118
+ const checkPath = async (segments) => (await exists(resolve([...prefix, ...segments]))) ||
119
+ (await exists(resolve(segments)));
120
+ // Parallel basic checks
121
+ const [hasAppDir, hasPagesDir, hasMiddleware] = await Promise.all([
122
+ checkPath(["app"]),
123
+ checkPath(["pages"]),
124
+ Promise.all([
125
+ exists(join(projectPath, "middleware.ts")),
126
+ exists(join(projectPath, "middleware.js")),
127
+ exists(join(projectPath, "src", "middleware.ts")),
128
+ exists(join(projectPath, "src", "middleware.js")),
129
+ ]).then((r) => r.some(Boolean)),
130
+ ]);
131
+ const hasApiRoutes = (await checkPath(["app", "api"])) || (await checkPath(["pages", "api"]));
132
+ // App Router specific file detection (parallel)
133
+ const appDir = hasSrcDir
134
+ ? join(projectPath, "src", "app")
135
+ : join(projectPath, "app");
136
+ const [hasErrorBoundary, hasLoadingStates, hasNotFound, hasMetadata] = hasAppDir
137
+ ? await Promise.all([
138
+ hasFileRecursive(appDir, ["error.tsx", "error.ts", "error.js", "error.jsx"]),
139
+ hasFileRecursive(appDir, ["loading.tsx", "loading.ts", "loading.js", "loading.jsx"]),
140
+ hasFileRecursive(appDir, ["not-found.tsx", "not-found.ts", "not-found.js", "not-found.jsx"]),
141
+ hasContentRecursive(appDir, /export\s+(const\s+metadata|async\s+function\s+generateMetadata|function\s+generateMetadata)/, ["ts", "tsx", "js", "jsx"]),
142
+ ])
143
+ : [false, false, false, false];
144
+ // Parallel infra + directory checks
145
+ const [hasPublicDir, hasLibDir, hasUtilsDir, hasServicesDir, hasComponentsDir, hasHooksDir, hasPrismaSchema, hasTsConfig, hasEnvExample, hasEnvValidation, hasDockerfile, hasRuntime, approximateFileCount,] = await Promise.all([
146
+ exists(join(projectPath, "public")),
147
+ checkPath(["lib"]),
148
+ checkPath(["utils"]),
149
+ checkPath(["services"]),
150
+ checkPath(["components"]),
151
+ checkPath(["hooks"]),
152
+ exists(join(projectPath, "prisma", "schema.prisma")),
153
+ exists(join(projectPath, "tsconfig.json")),
154
+ Promise.all([
155
+ exists(join(projectPath, ".env.example")),
156
+ exists(join(projectPath, ".env.local.example")),
157
+ ]).then((r) => r.some(Boolean)),
158
+ Promise.all([
159
+ exists(join(projectPath, "env.ts")),
160
+ exists(join(projectPath, "env.mjs")),
161
+ exists(join(projectPath, "src", "env.ts")),
162
+ exists(join(projectPath, "src", "env.mjs")),
163
+ exists(join(projectPath, "lib", "env.ts")),
164
+ exists(join(projectPath, "src", "lib", "env.ts")),
165
+ ]).then((r) => r.some(Boolean)),
166
+ Promise.all([
167
+ exists(join(projectPath, "Dockerfile")),
168
+ exists(join(projectPath, "docker-compose.yml")),
169
+ exists(join(projectPath, "docker-compose.yaml")),
170
+ ]).then((r) => r.some(Boolean)),
171
+ Promise.all([
172
+ exists(join(projectPath, "bun.lockb")),
173
+ exists(join(projectPath, "bun.lock")),
174
+ exists(join(projectPath, "deno.json")),
175
+ exists(join(projectPath, "deno.jsonc")),
176
+ ]).then(([bunLockb, bunLock, denoJson, denoJsonc]) => (bunLockb || bunLock) ? "bun" : (denoJson || denoJsonc) ? "deno" : "node"),
177
+ countSourceFiles(projectPath),
178
+ ]);
179
+ // All directory checks
180
+ const allDirs = hasSrcDir
181
+ ? [...topLevelDirs, ...(await getTopLevelDirs(join(projectPath, "src")).catch(() => []))]
182
+ : topLevelDirs;
183
+ return {
184
+ hasSrcDir,
185
+ hasAppDir,
186
+ hasPagesDir,
187
+ hasApiRoutes,
188
+ hasMiddleware,
189
+ hasPublicDir,
190
+ hasLibDir,
191
+ hasUtilsDir,
192
+ hasServicesDir,
193
+ hasComponentsDir,
194
+ hasHooksDir,
195
+ topLevelDirs,
196
+ hasErrorBoundary,
197
+ hasLoadingStates,
198
+ hasNotFound,
199
+ hasMetadata,
200
+ hasPrismaSchema,
201
+ hasDockerfile,
202
+ hasEnvExample,
203
+ hasEnvValidation,
204
+ hasTsConfig,
205
+ hasTestsDir: anyDirExists(allDirs, ["__tests__", "tests", "test", "e2e"]),
206
+ hasSchemasDir: anyDirExists(allDirs, ["schemas", "validators", "validations"]),
207
+ hasActionsDir: anyDirExists(allDirs, ["actions"]),
208
+ hasQueriesDir: anyDirExists(allDirs, ["queries", "data"]),
209
+ hasConfigDir: anyDirExists(allDirs, ["config", "constants"]),
210
+ hasProvidersDir: anyDirExists(allDirs, ["providers", "context"]),
211
+ hasStoreDir: anyDirExists(allDirs, ["store", "stores"]),
212
+ hasTypesDir: anyDirExists(allDirs, ["types"]),
213
+ detectedRuntime: hasRuntime,
214
+ approximateFileCount,
215
+ };
216
+ }
217
+ //# sourceMappingURL=structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.js","sourceRoot":"","sources":["../../src/analyzers/structure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,64 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import * as z from "zod";
4
+ import { registerAnalyzeRepo } from "./tools/analyze-repo.js";
5
+ import { registerDetectGaps } from "./tools/detect-gaps.js";
6
+ import { registerSuggest } from "./tools/suggest.js";
7
+ import { registerGenerateClaudeMd } from "./tools/generate-claude-md.js";
8
+ import { registerValidateClaudeMd } from "./tools/validate-claude-md.js";
9
+ import { registerUpdateClaudeMd } from "./tools/update-claude-md.js";
10
+ const server = new McpServer({
11
+ name: "leadcode",
12
+ version: "0.1.0",
13
+ });
14
+ // Register tools
15
+ registerAnalyzeRepo(server);
16
+ registerDetectGaps(server);
17
+ registerSuggest(server);
18
+ registerGenerateClaudeMd(server);
19
+ registerValidateClaudeMd(server);
20
+ registerUpdateClaudeMd(server);
21
+ // Register prompts
22
+ server.prompt("setup-project", "Full LeadCode workflow: analyze repo → detect gaps → suggest conventions → generate CLAUDE.md", { projectPath: z.string().describe("Absolute path to the project root") }, ({ projectPath }) => ({
23
+ messages: [
24
+ {
25
+ role: "user",
26
+ content: {
27
+ type: "text",
28
+ text: [
29
+ `Please set up LeadCode for the project at ${projectPath}. Follow these steps:`,
30
+ "",
31
+ "1. Call analyze-repo to scan the project and get a full technical analysis.",
32
+ "2. Call detect-gaps with the analysis to identify structural gaps.",
33
+ "3. Call suggest-conventions with the analysis and gaps to get improvement options.",
34
+ "4. Present the analysis, gaps, and suggestions to me in a clear summary.",
35
+ "5. Ask me which options I prefer for each gap (simple / clean / scalable).",
36
+ "6. Once I've chosen, call generate-claude-md with my choices to create the CLAUDE.md file.",
37
+ "",
38
+ "Be thorough and explain each gap and suggestion clearly.",
39
+ ].join("\n"),
40
+ },
41
+ },
42
+ ],
43
+ }));
44
+ server.prompt("validate-project", "Check if an existing CLAUDE.md is still in sync with the project", { projectPath: z.string().describe("Absolute path to the project root") }, ({ projectPath }) => ({
45
+ messages: [
46
+ {
47
+ role: "user",
48
+ content: {
49
+ type: "text",
50
+ text: [
51
+ `Please validate the CLAUDE.md for the project at ${projectPath}.`,
52
+ "",
53
+ "1. Call validate-claude-md to check for drifts between the CLAUDE.md and actual project state.",
54
+ "2. Present any drifts found with clear explanations.",
55
+ "3. If drifts are found, suggest whether to regenerate or manually fix the CLAUDE.md.",
56
+ ].join("\n"),
57
+ },
58
+ },
59
+ ],
60
+ }));
61
+ // Start server
62
+ const transport = new StdioServerTransport();
63
+ await server.connect(transport);
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,iBAAiB;AACjB,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAC3B,eAAe,CAAC,MAAM,CAAC,CAAC;AACxB,wBAAwB,CAAC,MAAM,CAAC,CAAC;AACjC,wBAAwB,CAAC,MAAM,CAAC,CAAC;AACjC,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAE/B,mBAAmB;AACnB,MAAM,CAAC,MAAM,CACX,eAAe,EACf,+FAA+F,EAC/F,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC,EAAE,EACzE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACpB,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,MAAe;YACrB,OAAO,EAAE;gBACP,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE;oBACJ,6CAA6C,WAAW,uBAAuB;oBAC/E,EAAE;oBACF,6EAA6E;oBAC7E,oEAAoE;oBACpE,oFAAoF;oBACpF,0EAA0E;oBAC1E,4EAA4E;oBAC5E,4FAA4F;oBAC5F,EAAE;oBACF,0DAA0D;iBAC3D,CAAC,IAAI,CAAC,IAAI,CAAC;aACb;SACF;KACF;CACF,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,CACX,kBAAkB,EAClB,kEAAkE,EAClE,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC,EAAE,EACzE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACpB,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,MAAe;YACrB,OAAO,EAAE;gBACP,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE;oBACJ,oDAAoD,WAAW,GAAG;oBAClE,EAAE;oBACF,gGAAgG;oBAChG,sDAAsD;oBACtD,sFAAsF;iBACvF,CAAC,IAAI,CAAC,IAAI,CAAC;aACb;SACF;KACF;CACF,CAAC,CACH,CAAC;AAEF,eAAe;AACf,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const authRules: Rule;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/rules/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,SAAS,EAAE,IAiDvB,CAAC"}
@@ -0,0 +1,48 @@
1
+ export const authRules = {
2
+ id: "auth",
3
+ name: "Authentication",
4
+ applies: (a) => a.detected.auth !== null,
5
+ gaps: [
6
+ {
7
+ category: "auth-middleware",
8
+ severity: "high",
9
+ check: (a) => a.framework?.name === "next" &&
10
+ a.framework.variant === "app-router" &&
11
+ !a.structure.hasMiddleware,
12
+ message: "No middleware.ts detected for route protection",
13
+ details: "Next.js App Router should use middleware.ts for authentication checks on protected routes.",
14
+ },
15
+ {
16
+ category: "auth-session",
17
+ severity: "medium",
18
+ check: (a) => !a.structure.hasLibDir && !a.structure.hasUtilsDir,
19
+ message: "No centralized auth utility detected (e.g., lib/auth.ts)",
20
+ details: "Every protected Server Component and API route must validate the session server-side. Never rely on client-side auth state alone.",
21
+ },
22
+ ],
23
+ conventions: [
24
+ {
25
+ id: "auth-server-check",
26
+ description: "Server-side auth checks",
27
+ rule: "Always validate authentication on the server (middleware, Server Components, API routes). Client-side checks are for UX only, not security.",
28
+ },
29
+ {
30
+ id: "auth-centralized",
31
+ description: "Centralized auth utilities",
32
+ rule: "Create a single auth utility (e.g., lib/auth.ts) that exports getCurrentUser(), requireAuth(), etc. All auth checks go through this module.",
33
+ },
34
+ {
35
+ id: "auth-protect-api",
36
+ description: "Protect API routes",
37
+ rule: "Every API route that requires auth must call requireAuth() at the top. No exceptions.",
38
+ },
39
+ ],
40
+ interdictions: [
41
+ "NEVER store auth tokens in localStorage — use httpOnly cookies.",
42
+ "NEVER trust client-sent user IDs — always derive user identity from the session.",
43
+ "NEVER expose user passwords, hashes, or internal IDs in API responses.",
44
+ "NEVER skip auth checks on API routes because 'the UI prevents access'.",
45
+ ],
46
+ crossRefs: [],
47
+ };
48
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/rules/auth.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI;IACxC,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,iBAAiB;YAC3B,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CACX,CAAC,CAAC,SAAS,EAAE,IAAI,KAAK,MAAM;gBAC5B,CAAC,CAAC,SAAS,CAAC,OAAO,KAAK,YAAY;gBACpC,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa;YAC5B,OAAO,EAAE,gDAAgD;YACzD,OAAO,EACL,4FAA4F;SAC/F;QACD;YACE,QAAQ,EAAE,cAAc;YACxB,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW;YAChE,OAAO,EAAE,0DAA0D;YACnE,OAAO,EACL,mIAAmI;SACtI;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,mBAAmB;YACvB,WAAW,EAAE,yBAAyB;YACtC,IAAI,EAAE,6IAA6I;SACpJ;QACD;YACE,EAAE,EAAE,kBAAkB;YACtB,WAAW,EAAE,4BAA4B;YACzC,IAAI,EAAE,6IAA6I;SACpJ;QACD;YACE,EAAE,EAAE,kBAAkB;YACtB,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,uFAAuF;SAC9F;KACF;IACD,aAAa,EAAE;QACb,iEAAiE;QACjE,kFAAkF;QAClF,wEAAwE;QACxE,wEAAwE;KACzE;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const crossStackRules: Rule;
3
+ //# sourceMappingURL=cross-stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-stack.d.ts","sourceRoot":"","sources":["../../src/rules/cross-stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,eAAe,EAAE,IA8T7B,CAAC"}