leadcode 0.2.1 → 1.0.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 (105) hide show
  1. package/dist/analyzers/detection.d.ts.map +1 -1
  2. package/dist/analyzers/detection.js +55 -5
  3. package/dist/analyzers/detection.js.map +1 -1
  4. package/dist/context7/client.d.ts +17 -0
  5. package/dist/context7/client.d.ts.map +1 -0
  6. package/dist/context7/client.js +82 -0
  7. package/dist/context7/client.js.map +1 -0
  8. package/dist/context7/index.d.ts +5 -0
  9. package/dist/context7/index.d.ts.map +1 -0
  10. package/dist/context7/index.js +3 -0
  11. package/dist/context7/index.js.map +1 -0
  12. package/dist/context7/queries.d.ts +11 -0
  13. package/dist/context7/queries.d.ts.map +1 -0
  14. package/dist/context7/queries.js +229 -0
  15. package/dist/context7/queries.js.map +1 -0
  16. package/dist/i18n/en.d.ts.map +1 -1
  17. package/dist/i18n/en.js +3 -242
  18. package/dist/i18n/en.js.map +1 -1
  19. package/dist/i18n/fr.d.ts.map +1 -1
  20. package/dist/i18n/fr.js +21 -260
  21. package/dist/i18n/fr.js.map +1 -1
  22. package/dist/i18n/types.d.ts +2 -232
  23. package/dist/i18n/types.d.ts.map +1 -1
  24. package/dist/index.js +13 -19
  25. package/dist/index.js.map +1 -1
  26. package/dist/templates/claude-md.d.ts +3 -2
  27. package/dist/templates/claude-md.d.ts.map +1 -1
  28. package/dist/templates/claude-md.js +97 -65
  29. package/dist/templates/claude-md.js.map +1 -1
  30. package/dist/tools/fetch-docs.d.ts +13 -0
  31. package/dist/tools/fetch-docs.d.ts.map +1 -0
  32. package/dist/tools/fetch-docs.js +141 -0
  33. package/dist/tools/fetch-docs.js.map +1 -0
  34. package/dist/tools/generate-claude-md.d.ts.map +1 -1
  35. package/dist/tools/generate-claude-md.js +12 -12
  36. package/dist/tools/generate-claude-md.js.map +1 -1
  37. package/dist/tools/update-claude-md.d.ts.map +1 -1
  38. package/dist/tools/update-claude-md.js +63 -11
  39. package/dist/tools/update-claude-md.js.map +1 -1
  40. package/dist/tools/validate-claude-md.d.ts.map +1 -1
  41. package/dist/tools/validate-claude-md.js +10 -48
  42. package/dist/tools/validate-claude-md.js.map +1 -1
  43. package/dist/types.d.ts +2 -43
  44. package/dist/types.d.ts.map +1 -1
  45. package/package.json +1 -1
  46. package/dist/rules/auth.d.ts +0 -3
  47. package/dist/rules/auth.d.ts.map +0 -1
  48. package/dist/rules/auth.js +0 -48
  49. package/dist/rules/auth.js.map +0 -1
  50. package/dist/rules/cross-stack.d.ts +0 -3
  51. package/dist/rules/cross-stack.d.ts.map +0 -1
  52. package/dist/rules/cross-stack.js +0 -320
  53. package/dist/rules/cross-stack.js.map +0 -1
  54. package/dist/rules/drizzle.d.ts +0 -3
  55. package/dist/rules/drizzle.d.ts.map +0 -1
  56. package/dist/rules/drizzle.js +0 -43
  57. package/dist/rules/drizzle.js.map +0 -1
  58. package/dist/rules/index.d.ts +0 -7
  59. package/dist/rules/index.d.ts.map +0 -1
  60. package/dist/rules/index.js +0 -104
  61. package/dist/rules/index.js.map +0 -1
  62. package/dist/rules/nextjs.d.ts +0 -4
  63. package/dist/rules/nextjs.d.ts.map +0 -1
  64. package/dist/rules/nextjs.js +0 -86
  65. package/dist/rules/nextjs.js.map +0 -1
  66. package/dist/rules/node.d.ts +0 -3
  67. package/dist/rules/node.d.ts.map +0 -1
  68. package/dist/rules/node.js +0 -61
  69. package/dist/rules/node.js.map +0 -1
  70. package/dist/rules/prisma.d.ts +0 -3
  71. package/dist/rules/prisma.d.ts.map +0 -1
  72. package/dist/rules/prisma.js +0 -44
  73. package/dist/rules/prisma.js.map +0 -1
  74. package/dist/rules/react.d.ts +0 -3
  75. package/dist/rules/react.d.ts.map +0 -1
  76. package/dist/rules/react.js +0 -58
  77. package/dist/rules/react.js.map +0 -1
  78. package/dist/rules/state.d.ts +0 -3
  79. package/dist/rules/state.d.ts.map +0 -1
  80. package/dist/rules/state.js +0 -54
  81. package/dist/rules/state.js.map +0 -1
  82. package/dist/rules/tailwind.d.ts +0 -3
  83. package/dist/rules/tailwind.d.ts.map +0 -1
  84. package/dist/rules/tailwind.js +0 -41
  85. package/dist/rules/tailwind.js.map +0 -1
  86. package/dist/rules/trpc.d.ts +0 -3
  87. package/dist/rules/trpc.d.ts.map +0 -1
  88. package/dist/rules/trpc.js +0 -35
  89. package/dist/rules/trpc.js.map +0 -1
  90. package/dist/rules/typescript.d.ts +0 -3
  91. package/dist/rules/typescript.d.ts.map +0 -1
  92. package/dist/rules/typescript.js +0 -54
  93. package/dist/rules/typescript.js.map +0 -1
  94. package/dist/rules/validation.d.ts +0 -3
  95. package/dist/rules/validation.d.ts.map +0 -1
  96. package/dist/rules/validation.js +0 -38
  97. package/dist/rules/validation.js.map +0 -1
  98. package/dist/tools/detect-gaps.d.ts +0 -3
  99. package/dist/tools/detect-gaps.d.ts.map +0 -1
  100. package/dist/tools/detect-gaps.js +0 -34
  101. package/dist/tools/detect-gaps.js.map +0 -1
  102. package/dist/tools/suggest.d.ts +0 -3
  103. package/dist/tools/suggest.d.ts.map +0 -1
  104. package/dist/tools/suggest.js +0 -99
  105. package/dist/tools/suggest.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -43,6 +43,8 @@ export interface DetectedStack {
43
43
  css: string | null;
44
44
  testing: string | null;
45
45
  stateManagement: string | null;
46
+ dataFetching: string | null;
47
+ formLibrary: string | null;
46
48
  apiStyle: string | null;
47
49
  bundler: string | null;
48
50
  linter: string | null;
@@ -70,47 +72,4 @@ export interface RepoAnalysis {
70
72
  structure: StructureInfo;
71
73
  detected: DetectedStack;
72
74
  }
73
- export interface Gap {
74
- category: string;
75
- severity: "high" | "medium" | "low";
76
- message: string;
77
- details?: string;
78
- }
79
- export interface SuggestionOption {
80
- level: "simple" | "clean" | "scalable";
81
- description: string;
82
- pros: string[];
83
- cons: string[];
84
- claudeImpact: string;
85
- }
86
- export interface Suggestion {
87
- topic: string;
88
- options: SuggestionOption[];
89
- }
90
- export interface GapCheck {
91
- category: string;
92
- severity: "high" | "medium" | "low";
93
- check: (analysis: RepoAnalysis) => boolean;
94
- message: string;
95
- details?: string;
96
- }
97
- export interface Convention {
98
- id: string;
99
- description: string;
100
- rule: string;
101
- }
102
- export interface CrossRef {
103
- techs: string[];
104
- conventions: Convention[];
105
- interdictions: string[];
106
- }
107
- export interface Rule {
108
- id: string;
109
- name: string;
110
- applies: (analysis: RepoAnalysis) => boolean;
111
- gaps: GapCheck[];
112
- conventions: Convention[];
113
- interdictions: string[];
114
- crossRefs: CrossRef[];
115
- }
116
75
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IAErB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IAErB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IAErB,eAAe,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;IAEzC,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,KAAK,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,OAAO,CAAC;IAC7C,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leadcode",
3
- "version": "0.2.1",
3
+ "version": "1.0.0",
4
4
  "description": "Virtual Lead Tech MCP server for Claude Code – analyzes repos, detects gaps, and generates structured CLAUDE.md files",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const authRules: Rule;
3
- //# sourceMappingURL=auth.d.ts.map
@@ -1 +0,0 @@
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"}
@@ -1,48 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const crossStackRules: Rule;
3
- //# sourceMappingURL=cross-stack.d.ts.map
@@ -1 +0,0 @@
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"}
@@ -1,320 +0,0 @@
1
- export const crossStackRules = {
2
- id: "cross-stack",
3
- name: "Cross-Stack Rules",
4
- applies: () => true, // Always active, individual crossRefs have their own conditions
5
- gaps: [],
6
- conventions: [],
7
- interdictions: [],
8
- crossRefs: [
9
- // Next.js + Prisma
10
- {
11
- techs: ["next", "prisma"],
12
- conventions: [
13
- {
14
- id: "next-prisma-server-only",
15
- description: "Prisma only in server context",
16
- rule: "Import Prisma client ONLY in Server Components, Server Actions, Route Handlers, and middleware. Never in files with 'use client'.",
17
- },
18
- {
19
- id: "next-prisma-singleton",
20
- description: "Prisma singleton for Next.js",
21
- rule: "Use globalThis pattern for Prisma in development to prevent hot-reload connection leaks: `globalThis.prisma ??= new PrismaClient()`.",
22
- },
23
- {
24
- id: "next-prisma-data-layer",
25
- description: "Data access layer",
26
- rule: "Create a data access layer (lib/data/ or lib/queries/) that wraps Prisma calls. Server Components call data functions, not Prisma directly.",
27
- },
28
- ],
29
- interdictions: [
30
- "NEVER import @prisma/client in any file that has 'use client' directive.",
31
- "NEVER pass full Prisma models to Client Components — select only the fields needed and create plain objects.",
32
- "NEVER run Prisma queries inside React render functions without proper caching (use React cache() or unstable_cache).",
33
- ],
34
- },
35
- // Next.js + NextAuth
36
- {
37
- techs: ["next", "next-auth"],
38
- conventions: [
39
- {
40
- id: "next-auth-middleware",
41
- description: "Auth via middleware",
42
- rule: "Use middleware.ts with NextAuth's auth() wrapper to protect routes. Define public routes explicitly, protect everything else by default.",
43
- },
44
- {
45
- id: "next-auth-session-server",
46
- description: "Session in Server Components",
47
- rule: "Use auth() from next-auth in Server Components to get the session. Use useSession() only in Client Components that need reactive session state.",
48
- },
49
- ],
50
- interdictions: [
51
- "NEVER check auth client-side only — always validate server-side.",
52
- "NEVER expose NextAuth secret or provider credentials in client code.",
53
- ],
54
- },
55
- // Next.js + Zod
56
- {
57
- techs: ["next", "zod"],
58
- conventions: [
59
- {
60
- id: "next-zod-server-actions",
61
- description: "Zod in Server Actions",
62
- rule: "Validate all Server Action inputs with Zod schemas. Parse at the top of every action before any business logic.",
63
- },
64
- {
65
- id: "next-zod-route-handlers",
66
- description: "Zod in Route Handlers",
67
- rule: "Validate request body/params with Zod in every Route Handler. Return 400 with formatted errors on validation failure.",
68
- },
69
- ],
70
- interdictions: [],
71
- },
72
- // Prisma + Zod
73
- {
74
- techs: ["prisma", "zod"],
75
- conventions: [
76
- {
77
- id: "prisma-zod-sync",
78
- description: "Keep Prisma and Zod in sync",
79
- rule: "Zod schemas must mirror Prisma models for input validation. Consider using zod-prisma-types or manually maintaining parity.",
80
- },
81
- ],
82
- interdictions: [
83
- "NEVER let Zod schemas drift from Prisma models — this causes runtime type mismatches.",
84
- ],
85
- },
86
- // tRPC + Zod
87
- {
88
- techs: ["trpc", "zod"],
89
- conventions: [
90
- {
91
- id: "trpc-zod-input",
92
- description: "Zod as tRPC input validator",
93
- rule: "Use Zod schemas as tRPC .input() validators. Share schemas between client and server for end-to-end type safety.",
94
- },
95
- ],
96
- interdictions: [],
97
- },
98
- // React Query + Next.js
99
- {
100
- techs: ["next", "react-query"],
101
- conventions: [
102
- {
103
- id: "next-rq-server-prefetch",
104
- description: "Prefetch in Server Components",
105
- rule: "Use React Query's HydrationBoundary to prefetch data in Server Components and hydrate on the client.",
106
- },
107
- {
108
- id: "next-rq-client-only",
109
- description: "React Query for client interactions",
110
- rule: "Use React Query for user-triggered data fetching (pagination, search, mutations). Use Server Components for initial page data.",
111
- },
112
- ],
113
- interdictions: [
114
- "NEVER use React Query to fetch initial page data that could be fetched in a Server Component.",
115
- ],
116
- },
117
- // Tailwind + React
118
- {
119
- techs: ["tailwind", "react"],
120
- conventions: [
121
- {
122
- id: "tailwind-no-style-prop",
123
- description: "Tailwind over inline styles",
124
- rule: "Use Tailwind classes instead of style prop. Use cn() or clsx() for conditional classes.",
125
- },
126
- {
127
- id: "tailwind-component-variants",
128
- description: "Variant management",
129
- rule: "For components with many style variants, use cva (class-variance-authority) or a similar pattern.",
130
- },
131
- ],
132
- interdictions: [
133
- "NEVER mix Tailwind with inline styles unless for truly dynamic values (e.g., calculated positions).",
134
- ],
135
- },
136
- // Next.js + Drizzle
137
- {
138
- techs: ["next", "drizzle"],
139
- conventions: [
140
- {
141
- id: "next-drizzle-server-only",
142
- description: "Drizzle server-only",
143
- rule: "Import the Drizzle client ONLY in Server Components, Server Actions, and Route Handlers. Never in 'use client' files.",
144
- },
145
- {
146
- id: "next-drizzle-connection",
147
- description: "Connection pooling",
148
- rule: "Use a connection pool (e.g., @neondatabase/serverless with pool mode, or pg Pool) for serverless environments. Singleton pattern for the db client.",
149
- },
150
- ],
151
- interdictions: [
152
- "NEVER import drizzle-orm in client-side code.",
153
- "NEVER run migrations in production at runtime — run them in CI/CD.",
154
- ],
155
- },
156
- // Next.js + Clerk
157
- {
158
- techs: ["next", "clerk"],
159
- conventions: [
160
- {
161
- id: "next-clerk-middleware",
162
- description: "Clerk middleware",
163
- rule: "Use clerkMiddleware() in middleware.ts. Define public routes with createRouteMatcher(). All other routes are protected by default.",
164
- },
165
- {
166
- id: "next-clerk-server",
167
- description: "Server-side auth with Clerk",
168
- rule: "Use currentUser() or auth() from @clerk/nextjs/server in Server Components and Route Handlers. Use useUser() only in Client Components.",
169
- },
170
- ],
171
- interdictions: [
172
- "NEVER check auth client-side only with Clerk — always validate on the server.",
173
- "NEVER expose Clerk secret key in client code.",
174
- ],
175
- },
176
- // Next.js + Supabase Auth
177
- {
178
- techs: ["next", "supabase-auth"],
179
- conventions: [
180
- {
181
- id: "next-supabase-server-client",
182
- description: "Supabase server client",
183
- rule: "Create separate Supabase clients for server (createServerClient with cookies) and browser (createBrowserClient). Never share instances.",
184
- },
185
- {
186
- id: "next-supabase-middleware",
187
- description: "Supabase auth middleware",
188
- rule: "Use middleware.ts to refresh the Supabase session on every request. This prevents stale auth tokens.",
189
- },
190
- ],
191
- interdictions: [
192
- "NEVER use the browser Supabase client in Server Components.",
193
- "NEVER skip the middleware session refresh — it causes auth token expiration issues.",
194
- ],
195
- },
196
- // Next.js + Stripe
197
- {
198
- techs: ["next", "stripe"],
199
- conventions: [
200
- {
201
- id: "next-stripe-server-only",
202
- description: "Stripe SDK server-only",
203
- rule: "Import the Stripe Node SDK only in Server Actions and Route Handlers. Use @stripe/stripe-js for client-side (Stripe Elements, checkout redirect).",
204
- },
205
- {
206
- id: "next-stripe-webhooks",
207
- description: "Stripe webhooks",
208
- rule: "Handle Stripe webhooks in a Route Handler (app/api/webhooks/stripe/route.ts). Always verify the webhook signature. Use raw body parsing.",
209
- },
210
- ],
211
- interdictions: [
212
- "NEVER expose your Stripe secret key in client code.",
213
- "NEVER trust client-sent prices or product IDs — always verify on the server.",
214
- "NEVER skip webhook signature verification.",
215
- ],
216
- },
217
- // Next.js + next-intl
218
- {
219
- techs: ["next", "next-intl"],
220
- conventions: [
221
- {
222
- id: "next-intl-middleware",
223
- description: "i18n middleware",
224
- rule: "Configure next-intl middleware in middleware.ts for locale detection and routing. Define supported locales and default locale.",
225
- },
226
- {
227
- id: "next-intl-messages",
228
- description: "Message organization",
229
- rule: "Keep translations in messages/{locale}.json. Organize by namespace matching your app structure. Use useTranslations('namespace') in components.",
230
- },
231
- {
232
- id: "next-intl-server",
233
- description: "Server Components i18n",
234
- rule: "Use getTranslations() in Server Components, useTranslations() in Client Components. Never hardcode user-facing strings.",
235
- },
236
- ],
237
- interdictions: [
238
- "NEVER hardcode user-facing strings — always use translation functions.",
239
- "NEVER forget to add new strings to ALL locale files.",
240
- ],
241
- },
242
- // Prisma + NextAuth
243
- {
244
- techs: ["prisma", "next-auth"],
245
- conventions: [
246
- {
247
- id: "prisma-nextauth-adapter",
248
- description: "Prisma adapter for NextAuth",
249
- rule: "Use @auth/prisma-adapter. Ensure your Prisma schema includes the required models (User, Account, Session, VerificationToken).",
250
- },
251
- {
252
- id: "prisma-nextauth-session",
253
- description: "Session strategy",
254
- rule: "Use JWT strategy for serverless deployments (no DB lookup per request). Use database strategy only if you need server-side session revocation.",
255
- },
256
- ],
257
- interdictions: [
258
- "NEVER modify the NextAuth-required Prisma models (User, Account, Session) without checking adapter compatibility.",
259
- ],
260
- },
261
- // Express/Fastify + Prisma
262
- {
263
- techs: ["express", "prisma"],
264
- conventions: [
265
- {
266
- id: "express-prisma-singleton",
267
- description: "Prisma singleton in Express",
268
- rule: "Create a single PrismaClient instance in a dedicated module (e.g., lib/prisma.ts). Import it in route handlers. Disconnect in graceful shutdown.",
269
- },
270
- {
271
- id: "express-prisma-n-plus-1",
272
- description: "Prevent N+1 queries",
273
- rule: "Always use include/select to fetch related data in one query. Never loop over results and query for each item.",
274
- },
275
- ],
276
- interdictions: [
277
- "NEVER create a new PrismaClient per request — this exhausts database connections.",
278
- ],
279
- },
280
- {
281
- techs: ["fastify", "prisma"],
282
- conventions: [
283
- {
284
- id: "fastify-prisma-plugin",
285
- description: "Prisma as Fastify plugin",
286
- rule: "Register Prisma as a Fastify plugin with proper lifecycle hooks. Disconnect on server close.",
287
- },
288
- ],
289
- interdictions: [
290
- "NEVER create a new PrismaClient per request.",
291
- ],
292
- },
293
- // Tailwind + shadcn
294
- {
295
- techs: ["tailwind", "shadcn"],
296
- conventions: [
297
- {
298
- id: "shadcn-cn-utility",
299
- description: "cn() utility",
300
- rule: "Use the cn() utility (lib/utils.ts) for all className merging. It combines clsx and tailwind-merge.",
301
- },
302
- {
303
- id: "shadcn-customization",
304
- description: "Component customization",
305
- rule: "Customize shadcn components by editing the files in components/ui/. Extend with variants using cva. Never modify the core patterns.",
306
- },
307
- {
308
- id: "shadcn-composition",
309
- description: "Compose, don't modify",
310
- rule: "Build custom components by composing shadcn primitives. If you need a different variant, add it to the cva definition.",
311
- },
312
- ],
313
- interdictions: [
314
- "NEVER override shadcn component styles with inline styles or external CSS — use Tailwind classes and cva variants.",
315
- "NEVER copy-paste shadcn component code instead of using the CLI to add components.",
316
- ],
317
- },
318
- ],
319
- };
320
- //# sourceMappingURL=cross-stack.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cross-stack.js","sourceRoot":"","sources":["../../src/rules/cross-stack.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const drizzleRules: Rule;
3
- //# sourceMappingURL=drizzle.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../src/rules/drizzle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,YAAY,EAAE,IA0C1B,CAAC"}
@@ -1,43 +0,0 @@
1
- export const drizzleRules = {
2
- id: "drizzle",
3
- name: "Drizzle ORM",
4
- applies: (a) => a.detected.orm === "drizzle",
5
- gaps: [
6
- {
7
- category: "drizzle-schema-org",
8
- severity: "medium",
9
- check: (a) => !a.structure.hasSchemasDir && !a.structure.hasLibDir,
10
- message: "No clear schema organization detected for Drizzle",
11
- details: "Drizzle schemas should live in a dedicated directory (e.g., db/schema/ or lib/db/). Without this, Claude will place schema files inconsistently.",
12
- },
13
- ],
14
- conventions: [
15
- {
16
- id: "drizzle-schema-files",
17
- description: "Schema file organization",
18
- rule: "Keep Drizzle schema definitions in db/schema/ with one file per domain entity. Export all from db/schema/index.ts.",
19
- },
20
- {
21
- id: "drizzle-prepared",
22
- description: "Prepared statements for hot paths",
23
- rule: "Use db.query.*.findFirst/findMany with prepared statements (`.prepare()`) for frequently-called queries.",
24
- },
25
- {
26
- id: "drizzle-migrations",
27
- description: "Migration workflow",
28
- rule: "Generate migrations with `drizzle-kit generate`. Apply with `drizzle-kit migrate`. Never modify generated migration files.",
29
- },
30
- {
31
- id: "drizzle-relations",
32
- description: "Define relations explicitly",
33
- rule: "Define relations using the `relations()` helper alongside table definitions. This enables the relational query API.",
34
- },
35
- ],
36
- interdictions: [
37
- "NEVER modify generated migration files — always generate a new migration instead.",
38
- "NEVER use raw SQL when the Drizzle query builder can express the query.",
39
- "NEVER import the database client in client-side code.",
40
- ],
41
- crossRefs: [],
42
- };
43
- //# sourceMappingURL=drizzle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drizzle.js","sourceRoot":"","sources":["../../src/rules/drizzle.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,aAAa;IACnB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,SAAS;IAC5C,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,oBAAoB;YAC9B,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS;YAClE,OAAO,EAAE,mDAAmD;YAC5D,OAAO,EACL,kJAAkJ;SACrJ;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,sBAAsB;YAC1B,WAAW,EAAE,0BAA0B;YACvC,IAAI,EAAE,oHAAoH;SAC3H;QACD;YACE,EAAE,EAAE,kBAAkB;YACtB,WAAW,EAAE,mCAAmC;YAChD,IAAI,EAAE,0GAA0G;SACjH;QACD;YACE,EAAE,EAAE,oBAAoB;YACxB,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,4HAA4H;SACnI;QACD;YACE,EAAE,EAAE,mBAAmB;YACvB,WAAW,EAAE,6BAA6B;YAC1C,IAAI,EAAE,qHAAqH;SAC5H;KACF;IACD,aAAa,EAAE;QACb,mFAAmF;QACnF,yEAAyE;QACzE,uDAAuD;KACxD;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,7 +0,0 @@
1
- import type { Rule, RepoAnalysis, Gap, Convention, CrossRef } from "../types.js";
2
- export declare function getApplicableRules(analysis: RepoAnalysis): Rule[];
3
- export declare function detectGaps(analysis: RepoAnalysis): Gap[];
4
- export declare function getConventions(analysis: RepoAnalysis): Convention[];
5
- export declare function getInterdictions(analysis: RepoAnalysis): string[];
6
- export declare function getActiveCrossRefs(analysis: RepoAnalysis): CrossRef[];
7
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA8BjF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,EAAE,CAEjE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,YAAY,GAAG,GAAG,EAAE,CAkBxD;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,UAAU,EAAE,CAenE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,EAAE,CAejE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,QAAQ,EAAE,CA4BrE"}
@@ -1,104 +0,0 @@
1
- import { nextjsRules, nextjsPagesRules } from "./nextjs.js";
2
- import { reactRules } from "./react.js";
3
- import { nodeRules } from "./node.js";
4
- import { prismaRules } from "./prisma.js";
5
- import { drizzleRules } from "./drizzle.js";
6
- import { authRules } from "./auth.js";
7
- import { validationRules } from "./validation.js";
8
- import { typescriptRules } from "./typescript.js";
9
- import { tailwindRules } from "./tailwind.js";
10
- import { stateManagementRules } from "./state.js";
11
- import { trpcRules } from "./trpc.js";
12
- import { crossStackRules } from "./cross-stack.js";
13
- const allRules = [
14
- nextjsRules,
15
- nextjsPagesRules,
16
- reactRules,
17
- nodeRules,
18
- prismaRules,
19
- drizzleRules,
20
- authRules,
21
- validationRules,
22
- typescriptRules,
23
- tailwindRules,
24
- stateManagementRules,
25
- trpcRules,
26
- crossStackRules,
27
- ];
28
- export function getApplicableRules(analysis) {
29
- return allRules.filter((r) => r.applies(analysis));
30
- }
31
- export function detectGaps(analysis) {
32
- const rules = getApplicableRules(analysis);
33
- const gaps = [];
34
- for (const rule of rules) {
35
- for (const gapCheck of rule.gaps) {
36
- if (gapCheck.check(analysis)) {
37
- gaps.push({
38
- category: gapCheck.category,
39
- severity: gapCheck.severity,
40
- message: gapCheck.message,
41
- details: gapCheck.details,
42
- });
43
- }
44
- }
45
- }
46
- return gaps;
47
- }
48
- export function getConventions(analysis) {
49
- const rules = getApplicableRules(analysis);
50
- const seen = new Set();
51
- const conventions = [];
52
- for (const rule of rules) {
53
- for (const conv of rule.conventions) {
54
- if (!seen.has(conv.id)) {
55
- seen.add(conv.id);
56
- conventions.push(conv);
57
- }
58
- }
59
- }
60
- return conventions;
61
- }
62
- export function getInterdictions(analysis) {
63
- const rules = getApplicableRules(analysis);
64
- const seen = new Set();
65
- const interdictions = [];
66
- for (const rule of rules) {
67
- for (const inter of rule.interdictions) {
68
- if (!seen.has(inter)) {
69
- seen.add(inter);
70
- interdictions.push(inter);
71
- }
72
- }
73
- }
74
- return interdictions;
75
- }
76
- export function getActiveCrossRefs(analysis) {
77
- const rules = getApplicableRules(analysis);
78
- const active = [];
79
- // Build a set of detected tech identifiers
80
- const techs = new Set();
81
- if (analysis.framework) {
82
- techs.add(analysis.framework.name);
83
- // Add "react" for React-based frameworks so cross-refs like ["tailwind", "react"] activate
84
- const reactFrameworks = new Set(["next", "vite-react", "remix"]);
85
- if (reactFrameworks.has(analysis.framework.name))
86
- techs.add("react");
87
- }
88
- const detected = analysis.detected;
89
- // Add all non-null detected techs
90
- for (const value of Object.values(detected)) {
91
- if (typeof value === "string")
92
- techs.add(value);
93
- }
94
- for (const rule of rules) {
95
- for (const crossRef of rule.crossRefs) {
96
- // A crossRef is active if ALL its required techs are present
97
- if (crossRef.techs.every((t) => techs.has(t))) {
98
- active.push(crossRef);
99
- }
100
- }
101
- }
102
- return active;
103
- }
104
- //# sourceMappingURL=index.js.map