leadcode 0.2.2 → 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 +30 -0
  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 +1 -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 +19 -260
  21. package/dist/i18n/fr.js.map +1 -1
  22. package/dist/i18n/types.d.ts +0 -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 +92 -67
  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 +0 -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 -51
  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
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const nextjsRules: Rule;
3
- export declare const nextjsPagesRules: Rule;
4
- //# sourceMappingURL=nextjs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/rules/nextjs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,WAAW,EAAE,IAgEzB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,IAuB9B,CAAC"}
@@ -1,86 +0,0 @@
1
- export const nextjsRules = {
2
- id: "nextjs",
3
- name: "Next.js",
4
- applies: (a) => a.framework?.name === "next",
5
- gaps: [
6
- {
7
- category: "error-handling",
8
- severity: "high",
9
- check: (a) => a.structure.hasAppDir && !a.structure.hasErrorBoundary,
10
- message: "No error boundary detected (error.tsx)",
11
- details: "App Router requires error.tsx files for proper error handling. Without them, errors crash the entire page.",
12
- },
13
- {
14
- category: "loading-states",
15
- severity: "medium",
16
- check: (a) => a.structure.hasAppDir && !a.structure.hasLoadingStates,
17
- message: "No loading states detected (loading.tsx)",
18
- details: "loading.tsx enables streaming SSR and instant navigation feedback.",
19
- },
20
- {
21
- category: "metadata",
22
- severity: "low",
23
- check: (a) => a.structure.hasAppDir && !a.structure.hasMetadata,
24
- message: "No metadata/SEO strategy detected",
25
- details: "Next.js App Router uses generateMetadata or metadata exports for SEO.",
26
- },
27
- ],
28
- conventions: [
29
- {
30
- id: "next-server-first",
31
- description: "Server Components by default",
32
- rule: "All components are Server Components unless they need interactivity. Add 'use client' only when required (event handlers, hooks, browser APIs).",
33
- },
34
- {
35
- id: "next-data-fetching",
36
- description: "Data fetching in Server Components",
37
- rule: "Fetch data in Server Components or Server Actions. Never fetch in Client Components unless it's user-triggered.",
38
- },
39
- {
40
- id: "next-route-handlers",
41
- description: "API route structure",
42
- rule: "Use route.ts files in app/api/ for API endpoints. Export named HTTP methods (GET, POST, PUT, DELETE).",
43
- },
44
- {
45
- id: "next-server-actions",
46
- description: "Server Actions for mutations",
47
- rule: "Use Server Actions ('use server') for form submissions and data mutations. Keep them in separate files (e.g., actions.ts).",
48
- },
49
- {
50
- id: "next-no-client-fetch",
51
- description: "No useEffect data fetching",
52
- rule: "Do NOT use useEffect + fetch for initial data loading. Use Server Components or React Query for client-side data.",
53
- },
54
- ],
55
- interdictions: [
56
- "NEVER use getServerSideProps or getStaticProps in App Router — these are Pages Router only.",
57
- "NEVER import server-only modules (fs, database clients) in Client Components.",
58
- "NEVER use 'use client' at layout level unless absolutely necessary — it forces all children to be Client Components.",
59
- "NEVER store sensitive data in client-accessible cookies or localStorage.",
60
- ],
61
- crossRefs: [],
62
- };
63
- export const nextjsPagesRules = {
64
- id: "nextjs-pages",
65
- name: "Next.js Pages Router",
66
- applies: (a) => a.framework?.name === "next" && a.framework.variant === "pages-router",
67
- gaps: [],
68
- conventions: [
69
- {
70
- id: "pages-data-fetching",
71
- description: "Use getServerSideProps/getStaticProps",
72
- rule: "Use getServerSideProps for dynamic data, getStaticProps for static data. Never fetch in component body.",
73
- },
74
- {
75
- id: "pages-api-routes",
76
- description: "API routes in pages/api/",
77
- rule: "Keep API routes in pages/api/. Each file exports a default handler function.",
78
- },
79
- ],
80
- interdictions: [
81
- "NEVER use App Router patterns (Server Components, Server Actions) in Pages Router.",
82
- "NEVER use 'use client' directive — Pages Router components are all client by default.",
83
- ],
84
- crossRefs: [],
85
- };
86
- //# sourceMappingURL=nextjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../../src/rules/nextjs.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,KAAK,MAAM;IAC5C,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB;YACpE,OAAO,EAAE,wCAAwC;YACjD,OAAO,EACL,4GAA4G;SAC/G;QACD;YACE,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB;YACpE,OAAO,EAAE,0CAA0C;YACnD,OAAO,EACL,oEAAoE;SACvE;QACD;YACE,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW;YAC/D,OAAO,EAAE,mCAAmC;YAC5C,OAAO,EACL,uEAAuE;SAC1E;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,mBAAmB;YACvB,WAAW,EAAE,8BAA8B;YAC3C,IAAI,EAAE,iJAAiJ;SACxJ;QACD;YACE,EAAE,EAAE,oBAAoB;YACxB,WAAW,EAAE,oCAAoC;YACjD,IAAI,EAAE,iHAAiH;SACxH;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,qBAAqB;YAClC,IAAI,EAAE,uGAAuG;SAC9G;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,8BAA8B;YAC3C,IAAI,EAAE,4HAA4H;SACnI;QACD;YACE,EAAE,EAAE,sBAAsB;YAC1B,WAAW,EAAE,4BAA4B;YACzC,IAAI,EAAE,mHAAmH;SAC1H;KACF;IACD,aAAa,EAAE;QACb,6FAA6F;QAC7F,+EAA+E;QAC/E,sHAAsH;QACtH,0EAA0E;KAC3E;IACD,SAAS,EAAE,EAAE;CACd,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,sBAAsB;IAC5B,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CACb,CAAC,CAAC,SAAS,EAAE,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,SAAS,CAAC,OAAO,KAAK,cAAc;IACxE,IAAI,EAAE,EAAE;IACR,WAAW,EAAE;QACX;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,uCAAuC;YACpD,IAAI,EAAE,yGAAyG;SAChH;QACD;YACE,EAAE,EAAE,kBAAkB;YACtB,WAAW,EAAE,0BAA0B;YACvC,IAAI,EAAE,8EAA8E;SACrF;KACF;IACD,aAAa,EAAE;QACb,oFAAoF;QACpF,uFAAuF;KACxF;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const nodeRules: Rule;
3
- //# sourceMappingURL=node.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/rules/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,SAAS,EAAE,IA8DvB,CAAC"}
@@ -1,61 +0,0 @@
1
- export const nodeRules = {
2
- id: "node",
3
- name: "Node.js Backend",
4
- applies: (a) => {
5
- const name = a.framework?.name;
6
- return name === "express" || name === "fastify" || name === "hono";
7
- },
8
- gaps: [
9
- {
10
- category: "error-handling",
11
- severity: "high",
12
- check: (a) => !a.structure.hasServicesDir && !a.structure.hasUtilsDir,
13
- message: "No structured error handling layer detected",
14
- details: "Every Express/Fastify app needs centralized error handling. Unhandled errors crash the process.",
15
- },
16
- {
17
- category: "input-validation",
18
- severity: "high",
19
- check: (a) => a.detected.validation === null,
20
- message: "No input validation library detected",
21
- details: "All API inputs must be validated. Without a validation library, Claude will skip validation or do it inconsistently.",
22
- },
23
- {
24
- category: "env-validation",
25
- severity: "medium",
26
- check: (a) => !a.structure.hasEnvValidation,
27
- message: "No environment variable validation detected",
28
- details: "Validate all required env vars at boot time. Fail fast, not at runtime.",
29
- },
30
- ],
31
- conventions: [
32
- {
33
- id: "node-structured-errors",
34
- description: "Structured error responses",
35
- rule: "All API errors must return consistent JSON: { error: string, code: string, details?: unknown }. Use appropriate HTTP status codes.",
36
- },
37
- {
38
- id: "node-async-handlers",
39
- description: "Async error handling",
40
- rule: "Wrap all async route handlers to catch errors. Use express-async-errors or equivalent.",
41
- },
42
- {
43
- id: "node-env-config",
44
- description: "Centralized config",
45
- rule: "All environment variables accessed through a single config module. Never use process.env directly in business logic.",
46
- },
47
- {
48
- id: "node-no-business-in-routes",
49
- description: "Separate routing from logic",
50
- rule: "Route handlers should only: parse input, call a service, return response. Business logic goes in /services.",
51
- },
52
- ],
53
- interdictions: [
54
- "NEVER log sensitive data (passwords, tokens, PII) in any log level.",
55
- "NEVER use synchronous fs or crypto operations in request handlers.",
56
- "NEVER trust client input without validation — validate at every API boundary.",
57
- "NEVER catch errors silently (empty catch blocks).",
58
- ],
59
- crossRefs: [],
60
- };
61
- //# sourceMappingURL=node.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/rules/node.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC;QAC/B,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,CAAC;IACrE,CAAC;IACD,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW;YACrE,OAAO,EAAE,6CAA6C;YACtD,OAAO,EACL,iGAAiG;SACpG;QACD;YACE,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,KAAK,IAAI;YAC5C,OAAO,EAAE,sCAAsC;YAC/C,OAAO,EACL,sHAAsH;SACzH;QACD;YACE,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB;YAC3C,OAAO,EAAE,6CAA6C;YACtD,OAAO,EACL,yEAAyE;SAC5E;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,wBAAwB;YAC5B,WAAW,EAAE,4BAA4B;YACzC,IAAI,EAAE,oIAAoI;SAC3I;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,sBAAsB;YACnC,IAAI,EAAE,wFAAwF;SAC/F;QACD;YACE,EAAE,EAAE,iBAAiB;YACrB,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,sHAAsH;SAC7H;QACD;YACE,EAAE,EAAE,4BAA4B;YAChC,WAAW,EAAE,6BAA6B;YAC1C,IAAI,EAAE,6GAA6G;SACpH;KACF;IACD,aAAa,EAAE;QACb,qEAAqE;QACrE,oEAAoE;QACpE,+EAA+E;QAC/E,mDAAmD;KACpD;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const prismaRules: Rule;
3
- //# sourceMappingURL=prisma.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/rules/prisma.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,WAAW,EAAE,IA2CzB,CAAC"}
@@ -1,44 +0,0 @@
1
- export const prismaRules = {
2
- id: "prisma",
3
- name: "Prisma",
4
- applies: (a) => a.detected.orm === "prisma",
5
- gaps: [
6
- {
7
- category: "prisma-client-singleton",
8
- severity: "high",
9
- check: (a) => !a.structure.hasLibDir && !a.structure.hasUtilsDir,
10
- message: "Verify Prisma client is instantiated as a singleton",
11
- details: "In dev, Next.js hot-reload creates multiple Prisma clients. Use a singleton pattern in lib/prisma.ts or db.ts.",
12
- },
13
- ],
14
- conventions: [
15
- {
16
- id: "prisma-singleton",
17
- description: "Prisma client singleton",
18
- rule: "Instantiate PrismaClient once in lib/prisma.ts (or lib/db.ts). Re-export from there. Never create new PrismaClient() elsewhere.",
19
- },
20
- {
21
- id: "prisma-select",
22
- description: "Select only needed fields",
23
- rule: "Use select or include explicitly. Avoid fetching entire records when only a few fields are needed.",
24
- },
25
- {
26
- id: "prisma-transactions",
27
- description: "Use transactions for multi-step writes",
28
- rule: "Use prisma.$transaction() for operations that must succeed or fail together.",
29
- },
30
- {
31
- id: "prisma-migrations",
32
- description: "Migration discipline",
33
- rule: "Always use 'prisma migrate dev' for schema changes. Never modify the database directly.",
34
- },
35
- ],
36
- interdictions: [
37
- "NEVER use raw SQL unless Prisma's query API cannot express the query.",
38
- "NEVER call Prisma in Client Components or client-side code.",
39
- "NEVER use prisma.$connect() manually — Prisma handles connections automatically.",
40
- "NEVER store the Prisma client in global scope without the singleton pattern.",
41
- ],
42
- crossRefs: [],
43
- };
44
- //# sourceMappingURL=prisma.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prisma.js","sourceRoot":"","sources":["../../src/rules/prisma.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,QAAQ;IAC3C,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,yBAAyB;YACnC,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW;YAChE,OAAO,EAAE,qDAAqD;YAC9D,OAAO,EACL,gHAAgH;SACnH;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,kBAAkB;YACtB,WAAW,EAAE,yBAAyB;YACtC,IAAI,EAAE,iIAAiI;SACxI;QACD;YACE,EAAE,EAAE,eAAe;YACnB,WAAW,EAAE,2BAA2B;YACxC,IAAI,EAAE,oGAAoG;SAC3G;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,wCAAwC;YACrD,IAAI,EAAE,8EAA8E;SACrF;QACD;YACE,EAAE,EAAE,mBAAmB;YACvB,WAAW,EAAE,sBAAsB;YACnC,IAAI,EAAE,yFAAyF;SAChG;KACF;IACD,aAAa,EAAE;QACb,uEAAuE;QACvE,6DAA6D;QAC7D,kFAAkF;QAClF,8EAA8E;KAC/E;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const reactRules: Rule;
3
- //# sourceMappingURL=react.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/rules/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,UAAU,EAAE,IA0DxB,CAAC"}
@@ -1,58 +0,0 @@
1
- export const reactRules = {
2
- id: "react",
3
- name: "React",
4
- applies: (a) => {
5
- const deps = { ...a.dependencies, ...a.devDependencies };
6
- return "react" in deps;
7
- },
8
- gaps: [
9
- {
10
- category: "component-structure",
11
- severity: "medium",
12
- check: (a) => !a.structure.hasComponentsDir,
13
- message: "No dedicated components directory found",
14
- details: "Without a clear component organization, Claude will create components in random locations.",
15
- },
16
- {
17
- category: "testing",
18
- severity: "medium",
19
- check: (a) => !a.detected.testing && !a.structure.hasTestsDir,
20
- message: "No test runner or test directory detected",
21
- details: "Without a testing setup, Claude cannot generate or run tests for new code.",
22
- },
23
- ],
24
- conventions: [
25
- {
26
- id: "react-small-components",
27
- description: "Small, focused components",
28
- rule: "Each component file should do ONE thing. If a component exceeds ~100 lines, split it.",
29
- },
30
- {
31
- id: "react-naming",
32
- description: "Component naming",
33
- rule: "PascalCase for components. Filename matches component name. One exported component per file.",
34
- },
35
- {
36
- id: "react-hooks-extract",
37
- description: "Extract custom hooks",
38
- rule: "Extract reusable logic into custom hooks in a /hooks directory. Keep components focused on rendering.",
39
- },
40
- {
41
- id: "react-no-prop-drilling",
42
- description: "Avoid prop drilling",
43
- rule: "If props are passed through more than 2 levels, use context, composition, or state management.",
44
- },
45
- {
46
- id: "react-key-prop",
47
- description: "Stable keys in lists",
48
- rule: "Always use stable, unique keys for list rendering. Never use array index as key for dynamic lists.",
49
- },
50
- ],
51
- interdictions: [
52
- "NEVER mutate state directly. Always use setState or state management updaters.",
53
- "NEVER use useEffect for derived state — compute it during render.",
54
- "NEVER define components inside other components — it causes remounts on every render.",
55
- ],
56
- crossRefs: [],
57
- };
58
- //# sourceMappingURL=react.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/rules/react.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,OAAO;IACb,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,eAAe,EAAE,CAAC;QACzD,OAAO,OAAO,IAAI,IAAI,CAAC;IACzB,CAAC;IACD,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB;YAC3C,OAAO,EAAE,yCAAyC;YAClD,OAAO,EACL,4FAA4F;SAC/F;QACD;YACE,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW;YAC7D,OAAO,EAAE,2CAA2C;YACpD,OAAO,EACL,4EAA4E;SAC/E;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,wBAAwB;YAC5B,WAAW,EAAE,2BAA2B;YACxC,IAAI,EAAE,uFAAuF;SAC9F;QACD;YACE,EAAE,EAAE,cAAc;YAClB,WAAW,EAAE,kBAAkB;YAC/B,IAAI,EAAE,8FAA8F;SACrG;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,sBAAsB;YACnC,IAAI,EAAE,uGAAuG;SAC9G;QACD;YACE,EAAE,EAAE,wBAAwB;YAC5B,WAAW,EAAE,qBAAqB;YAClC,IAAI,EAAE,gGAAgG;SACvG;QACD;YACE,EAAE,EAAE,gBAAgB;YACpB,WAAW,EAAE,sBAAsB;YACnC,IAAI,EAAE,oGAAoG;SAC3G;KACF;IACD,aAAa,EAAE;QACb,gFAAgF;QAChF,mEAAmE;QACnE,uFAAuF;KACxF;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const stateManagementRules: Rule;
3
- //# sourceMappingURL=state.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/rules/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,oBAAoB,EAAE,IAkDlC,CAAC"}
@@ -1,51 +0,0 @@
1
- export const stateManagementRules = {
2
- id: "state-management",
3
- name: "State Management",
4
- applies: (a) => a.detected.stateManagement !== null,
5
- gaps: [
6
- {
7
- category: "store-organization",
8
- severity: "medium",
9
- check: (a) => !a.structure.hasStoreDir,
10
- message: "No store directory detected",
11
- details: "Without a dedicated store/ directory, Claude will create stores in random locations.",
12
- },
13
- ],
14
- conventions: [
15
- // Zustand-specific
16
- {
17
- id: "state-zustand-small-stores",
18
- description: "Small, focused stores (Zustand)",
19
- rule: "Create one store per domain concern (useAuthStore, useCartStore, useUIStore). Never put everything in a single store.",
20
- },
21
- {
22
- id: "state-zustand-selectors",
23
- description: "Use selectors (Zustand)",
24
- rule: "Always use selectors to subscribe to specific state slices: `useStore(state => state.count)`. Never subscribe to the entire store.",
25
- },
26
- // Redux-specific
27
- {
28
- id: "state-redux-slices",
29
- description: "RTK slices (Redux)",
30
- rule: "Use createSlice from @reduxjs/toolkit. One slice per feature. Never use the legacy connect() API.",
31
- },
32
- // General
33
- {
34
- id: "state-server-vs-client",
35
- description: "Separate server state from client state",
36
- rule: "Server data (API responses) belongs in React Query/SWR. Client state (UI state, forms) belongs in Zustand/Redux/Context. Never mix them.",
37
- },
38
- {
39
- id: "state-no-derived",
40
- description: "No derived state in stores",
41
- rule: "Compute derived values outside the store (selectors, useMemo). Never store computed data that can be derived from other state.",
42
- },
43
- ],
44
- interdictions: [
45
- "NEVER store server-fetched data in Zustand/Redux when React Query/SWR is available.",
46
- "NEVER put async logic (API calls) directly inside Zustand stores — use actions that call services.",
47
- "NEVER use global state for data that only one component needs — use local state instead.",
48
- ],
49
- crossRefs: [],
50
- };
51
- //# sourceMappingURL=state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/rules/state.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,oBAAoB,GAAS;IACxC,EAAE,EAAE,kBAAkB;IACtB,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,KAAK,IAAI;IACnD,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,oBAAoB;YAC9B,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW;YACtC,OAAO,EAAE,6BAA6B;YACtC,OAAO,EACL,sFAAsF;SACzF;KACF;IACD,WAAW,EAAE;QACX,mBAAmB;QACnB;YACE,EAAE,EAAE,4BAA4B;YAChC,WAAW,EAAE,iCAAiC;YAC9C,IAAI,EAAE,uHAAuH;SAC9H;QACD;YACE,EAAE,EAAE,yBAAyB;YAC7B,WAAW,EAAE,yBAAyB;YACtC,IAAI,EAAE,oIAAoI;SAC3I;QACD,iBAAiB;QACjB;YACE,EAAE,EAAE,oBAAoB;YACxB,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,mGAAmG;SAC1G;QACD,UAAU;QACV;YACE,EAAE,EAAE,wBAAwB;YAC5B,WAAW,EAAE,yCAAyC;YACtD,IAAI,EAAE,0IAA0I;SACjJ;QACD;YACE,EAAE,EAAE,kBAAkB;YACtB,WAAW,EAAE,4BAA4B;YACzC,IAAI,EAAE,gIAAgI;SACvI;KACF;IACD,aAAa,EAAE;QACb,qFAAqF;QACrF,oGAAoG;QACpG,0FAA0F;KAC3F;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const tailwindRules: Rule;
3
- //# sourceMappingURL=tailwind.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tailwind.d.ts","sourceRoot":"","sources":["../../src/rules/tailwind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,aAAa,EAAE,IAuC3B,CAAC"}
@@ -1,41 +0,0 @@
1
- export const tailwindRules = {
2
- id: "tailwind",
3
- name: "Tailwind CSS",
4
- applies: (a) => a.detected.css === "tailwind",
5
- gaps: [],
6
- conventions: [
7
- {
8
- id: "tw-class-order",
9
- description: "Tailwind class ordering",
10
- rule: "Order classes: layout (flex, grid) → position → box model (w, h, p, m) → typography → visual (bg, border, shadow) → interactive (hover, focus). Use Prettier plugin for auto-sorting if available.",
11
- },
12
- {
13
- id: "tw-conditional-classes",
14
- description: "Conditional class merging",
15
- rule: "Use cn() (clsx + twMerge) for conditional classes. Never concatenate class strings manually. Define cn() in lib/utils.ts.",
16
- },
17
- {
18
- id: "tw-responsive",
19
- description: "Mobile-first responsive",
20
- rule: "Design mobile-first. Use breakpoint prefixes in ascending order: base → sm: → md: → lg: → xl:.",
21
- },
22
- {
23
- id: "tw-no-arbitrary-recurring",
24
- description: "Avoid recurring arbitrary values",
25
- rule: "If an arbitrary value (e.g., `text-[13px]`, `bg-[#1a1a2e]`) is used more than twice, extract it to the Tailwind config as a design token.",
26
- },
27
- {
28
- id: "tw-apply-sparingly",
29
- description: "Minimal @apply usage",
30
- rule: "Use @apply only for truly global, reused patterns (e.g., .btn-primary). Prefer component composition over @apply.",
31
- },
32
- ],
33
- interdictions: [
34
- "NEVER use inline style={{}} when Tailwind can express the same thing.",
35
- "NEVER create custom CSS classes that duplicate existing Tailwind utilities.",
36
- "NEVER hardcode color hex values in className — use Tailwind color tokens.",
37
- "NEVER use !important in Tailwind — restructure your classes instead.",
38
- ],
39
- crossRefs: [],
40
- };
41
- //# sourceMappingURL=tailwind.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tailwind.js","sourceRoot":"","sources":["../../src/rules/tailwind.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAS;IACjC,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,cAAc;IACpB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,UAAU;IAC7C,IAAI,EAAE,EAAE;IACR,WAAW,EAAE;QACX;YACE,EAAE,EAAE,gBAAgB;YACpB,WAAW,EAAE,yBAAyB;YACtC,IAAI,EAAE,oMAAoM;SAC3M;QACD;YACE,EAAE,EAAE,wBAAwB;YAC5B,WAAW,EAAE,2BAA2B;YACxC,IAAI,EAAE,2HAA2H;SAClI;QACD;YACE,EAAE,EAAE,eAAe;YACnB,WAAW,EAAE,yBAAyB;YACtC,IAAI,EAAE,gGAAgG;SACvG;QACD;YACE,EAAE,EAAE,2BAA2B;YAC/B,WAAW,EAAE,kCAAkC;YAC/C,IAAI,EAAE,2IAA2I;SAClJ;QACD;YACE,EAAE,EAAE,oBAAoB;YACxB,WAAW,EAAE,sBAAsB;YACnC,IAAI,EAAE,mHAAmH;SAC1H;KACF;IACD,aAAa,EAAE;QACb,uEAAuE;QACvE,6EAA6E;QAC7E,2EAA2E;QAC3E,sEAAsE;KACvE;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const trpcRules: Rule;
3
- //# sourceMappingURL=trpc.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trpc.d.ts","sourceRoot":"","sources":["../../src/rules/trpc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,SAAS,EAAE,IAiCvB,CAAC"}
@@ -1,35 +0,0 @@
1
- export const trpcRules = {
2
- id: "trpc",
3
- name: "tRPC",
4
- applies: (a) => a.detected.apiStyle === "trpc",
5
- gaps: [],
6
- conventions: [
7
- {
8
- id: "trpc-router-org",
9
- description: "Router organization",
10
- rule: "Create one router file per domain (userRouter, postRouter, etc.). Merge them in a root appRouter. Keep router files in server/routers/ or lib/trpc/routers/.",
11
- },
12
- {
13
- id: "trpc-middleware",
14
- description: "Auth middleware",
15
- rule: "Create a protectedProcedure that validates auth. Use it for all authenticated endpoints. Never check auth inside individual procedures.",
16
- },
17
- {
18
- id: "trpc-input-validation",
19
- description: "Input validation with Zod",
20
- rule: "Always define .input() with a Zod schema for every procedure that accepts arguments. Share schemas between client and server.",
21
- },
22
- {
23
- id: "trpc-error-handling",
24
- description: "Structured errors",
25
- rule: "Use TRPCError with appropriate codes (NOT_FOUND, UNAUTHORIZED, BAD_REQUEST). Never throw generic Error objects.",
26
- },
27
- ],
28
- interdictions: [
29
- "NEVER use fetch() to call your own tRPC API — use the tRPC client.",
30
- "NEVER put business logic in router files — call service functions.",
31
- "NEVER expose internal error details to the client — use TRPCError with safe messages.",
32
- ],
33
- crossRefs: [],
34
- };
35
- //# sourceMappingURL=trpc.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trpc.js","sourceRoot":"","sources":["../../src/rules/trpc.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,KAAK,MAAM;IAC9C,IAAI,EAAE,EAAE;IACR,WAAW,EAAE;QACX;YACE,EAAE,EAAE,iBAAiB;YACrB,WAAW,EAAE,qBAAqB;YAClC,IAAI,EAAE,8JAA8J;SACrK;QACD;YACE,EAAE,EAAE,iBAAiB;YACrB,WAAW,EAAE,iBAAiB;YAC9B,IAAI,EAAE,yIAAyI;SAChJ;QACD;YACE,EAAE,EAAE,uBAAuB;YAC3B,WAAW,EAAE,2BAA2B;YACxC,IAAI,EAAE,+HAA+H;SACtI;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,mBAAmB;YAChC,IAAI,EAAE,iHAAiH;SACxH;KACF;IACD,aAAa,EAAE;QACb,oEAAoE;QACpE,oEAAoE;QACpE,uFAAuF;KACxF;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const typescriptRules: Rule;
3
- //# sourceMappingURL=typescript.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/rules/typescript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,eAAe,EAAE,IAqD7B,CAAC"}
@@ -1,54 +0,0 @@
1
- export const typescriptRules = {
2
- id: "typescript",
3
- name: "TypeScript",
4
- applies: (a) => a.structure.hasTsConfig,
5
- gaps: [
6
- {
7
- category: "types-dir",
8
- severity: "low",
9
- check: (a) => !a.structure.hasTypesDir && a.structure.approximateFileCount > 20,
10
- message: "No shared types directory detected",
11
- details: "For projects with 20+ files, a dedicated types/ directory helps Claude find and reuse type definitions.",
12
- },
13
- ],
14
- conventions: [
15
- {
16
- id: "ts-strict",
17
- description: "Strict TypeScript",
18
- rule: "Enable strict mode in tsconfig.json. Never use `any` unless justified with a comment explaining why.",
19
- },
20
- {
21
- id: "ts-explicit-returns",
22
- description: "Explicit return types on exports",
23
- rule: "All exported functions must have explicit return types. Internal functions can use inference.",
24
- },
25
- {
26
- id: "ts-no-enums",
27
- description: "Prefer unions over enums",
28
- rule: "Use string union types (`type Status = 'active' | 'inactive'`) instead of enums. Use `as const` satisfies for object maps.",
29
- },
30
- {
31
- id: "ts-discriminated-unions",
32
- description: "Discriminated unions for state",
33
- rule: "Model loading/success/error states with discriminated unions: `{ status: 'loading' } | { status: 'success', data: T } | { status: 'error', error: string }`.",
34
- },
35
- {
36
- id: "ts-import-types",
37
- description: "Type-only imports",
38
- rule: "Use `import type { Foo }` for type-only imports. This improves tree-shaking and makes intent clear.",
39
- },
40
- {
41
- id: "ts-no-non-null",
42
- description: "No non-null assertions",
43
- rule: "Avoid the non-null assertion operator (!). Handle null/undefined cases explicitly with narrowing, optional chaining, or nullish coalescing.",
44
- },
45
- ],
46
- interdictions: [
47
- "NEVER use `// @ts-ignore` — use `// @ts-expect-error` with an explanation of why the suppression is needed.",
48
- "NEVER use `any` in exported function signatures without a comment justifying it.",
49
- "NEVER use `as` type casts to silence type errors — fix the underlying type instead.",
50
- "NEVER use `Object`, `Function`, or `{}` as types — use specific types or `unknown`.",
51
- ],
52
- crossRefs: [],
53
- };
54
- //# sourceMappingURL=typescript.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../src/rules/typescript.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,YAAY;IAChB,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW;IACvC,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,IAAI,CAAC,CAAC,SAAS,CAAC,oBAAoB,GAAG,EAAE;YAC/E,OAAO,EAAE,oCAAoC;YAC7C,OAAO,EACL,yGAAyG;SAC5G;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,WAAW;YACf,WAAW,EAAE,mBAAmB;YAChC,IAAI,EAAE,sGAAsG;SAC7G;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,WAAW,EAAE,kCAAkC;YAC/C,IAAI,EAAE,+FAA+F;SACtG;QACD;YACE,EAAE,EAAE,aAAa;YACjB,WAAW,EAAE,0BAA0B;YACvC,IAAI,EAAE,4HAA4H;SACnI;QACD;YACE,EAAE,EAAE,yBAAyB;YAC7B,WAAW,EAAE,gCAAgC;YAC7C,IAAI,EAAE,8JAA8J;SACrK;QACD;YACE,EAAE,EAAE,iBAAiB;YACrB,WAAW,EAAE,mBAAmB;YAChC,IAAI,EAAE,qGAAqG;SAC5G;QACD;YACE,EAAE,EAAE,gBAAgB;YACpB,WAAW,EAAE,wBAAwB;YACrC,IAAI,EAAE,6IAA6I;SACpJ;KACF;IACD,aAAa,EAAE;QACb,6GAA6G;QAC7G,kFAAkF;QAClF,qFAAqF;QACrF,qFAAqF;KACtF;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Rule } from "../types.js";
2
- export declare const validationRules: Rule;
3
- //# sourceMappingURL=validation.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/rules/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,eAAO,MAAM,eAAe,EAAE,IAqC7B,CAAC"}
@@ -1,38 +0,0 @@
1
- export const validationRules = {
2
- id: "validation",
3
- name: "Input Validation",
4
- applies: (a) => a.detected.validation !== null,
5
- gaps: [
6
- {
7
- category: "shared-schemas",
8
- severity: "medium",
9
- check: (a) => !a.structure.hasSchemasDir,
10
- message: "No shared schemas directory found",
11
- details: "Without a dedicated directory for validation schemas, Claude will duplicate them across files. Create a /schemas or /lib/schemas directory.",
12
- },
13
- ],
14
- conventions: [
15
- {
16
- id: "validation-shared",
17
- description: "Shared validation schemas",
18
- rule: "Define validation schemas in a shared location (lib/schemas/ or schemas/). Import them in both API routes and forms.",
19
- },
20
- {
21
- id: "validation-api-boundary",
22
- description: "Validate at API boundaries",
23
- rule: "Every API route must validate its input using the schema library. Parse, don't validate: use schema.parse() to get typed output.",
24
- },
25
- {
26
- id: "validation-error-messages",
27
- description: "User-friendly error messages",
28
- rule: "Customize validation error messages for user-facing forms. Use schema library's message customization.",
29
- },
30
- ],
31
- interdictions: [
32
- "NEVER validate manually with if/else when a schema library is available.",
33
- "NEVER duplicate schema definitions — import from the shared location.",
34
- "NEVER trust TypeScript types alone for runtime safety — types are erased at runtime.",
35
- ],
36
- crossRefs: [],
37
- };
38
- //# sourceMappingURL=validation.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/rules/validation.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,YAAY;IAChB,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,KAAK,IAAI;IAC9C,IAAI,EAAE;QACJ;YACE,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa;YACxC,OAAO,EAAE,mCAAmC;YAC5C,OAAO,EACL,6IAA6I;SAChJ;KACF;IACD,WAAW,EAAE;QACX;YACE,EAAE,EAAE,mBAAmB;YACvB,WAAW,EAAE,2BAA2B;YACxC,IAAI,EAAE,sHAAsH;SAC7H;QACD;YACE,EAAE,EAAE,yBAAyB;YAC7B,WAAW,EAAE,4BAA4B;YACzC,IAAI,EAAE,kIAAkI;SACzI;QACD;YACE,EAAE,EAAE,2BAA2B;YAC/B,WAAW,EAAE,8BAA8B;YAC3C,IAAI,EAAE,wGAAwG;SAC/G;KACF;IACD,aAAa,EAAE;QACb,0EAA0E;QAC1E,uEAAuE;QACvE,sFAAsF;KACvF;IACD,SAAS,EAAE,EAAE;CACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- export declare function registerDetectGaps(server: McpServer): void;
3
- //# sourceMappingURL=detect-gaps.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detect-gaps.d.ts","sourceRoot":"","sources":["../../src/tools/detect-gaps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmC1D"}