leadcode 0.2.2 → 1.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 (110) hide show
  1. package/README.md +52 -47
  2. package/dist/analyzers/detection.d.ts.map +1 -1
  3. package/dist/analyzers/detection.js +30 -0
  4. package/dist/analyzers/detection.js.map +1 -1
  5. package/dist/context7/client.d.ts +17 -0
  6. package/dist/context7/client.d.ts.map +1 -0
  7. package/dist/context7/client.js +82 -0
  8. package/dist/context7/client.js.map +1 -0
  9. package/dist/context7/fetch-all.d.ts +13 -0
  10. package/dist/context7/fetch-all.d.ts.map +1 -0
  11. package/dist/context7/fetch-all.js +104 -0
  12. package/dist/context7/fetch-all.js.map +1 -0
  13. package/dist/context7/index.d.ts +7 -0
  14. package/dist/context7/index.d.ts.map +1 -0
  15. package/dist/context7/index.js +4 -0
  16. package/dist/context7/index.js.map +1 -0
  17. package/dist/context7/queries.d.ts +11 -0
  18. package/dist/context7/queries.d.ts.map +1 -0
  19. package/dist/context7/queries.js +229 -0
  20. package/dist/context7/queries.js.map +1 -0
  21. package/dist/i18n/en.d.ts.map +1 -1
  22. package/dist/i18n/en.js +1 -242
  23. package/dist/i18n/en.js.map +1 -1
  24. package/dist/i18n/fr.d.ts.map +1 -1
  25. package/dist/i18n/fr.js +19 -260
  26. package/dist/i18n/fr.js.map +1 -1
  27. package/dist/i18n/types.d.ts +0 -232
  28. package/dist/i18n/types.d.ts.map +1 -1
  29. package/dist/index.js +11 -19
  30. package/dist/index.js.map +1 -1
  31. package/dist/templates/claude-md.d.ts +3 -2
  32. package/dist/templates/claude-md.d.ts.map +1 -1
  33. package/dist/templates/claude-md.js +92 -67
  34. package/dist/templates/claude-md.js.map +1 -1
  35. package/dist/tools/fetch-docs.d.ts +3 -0
  36. package/dist/tools/fetch-docs.d.ts.map +1 -0
  37. package/dist/tools/fetch-docs.js +39 -0
  38. package/dist/tools/fetch-docs.js.map +1 -0
  39. package/dist/tools/generate-claude-md.d.ts.map +1 -1
  40. package/dist/tools/generate-claude-md.js +10 -11
  41. package/dist/tools/generate-claude-md.js.map +1 -1
  42. package/dist/tools/update-claude-md.d.ts.map +1 -1
  43. package/dist/tools/update-claude-md.js +9 -11
  44. package/dist/tools/update-claude-md.js.map +1 -1
  45. package/dist/tools/validate-claude-md.d.ts.map +1 -1
  46. package/dist/tools/validate-claude-md.js +10 -48
  47. package/dist/tools/validate-claude-md.js.map +1 -1
  48. package/dist/types.d.ts +0 -43
  49. package/dist/types.d.ts.map +1 -1
  50. package/package.json +1 -1
  51. package/dist/rules/auth.d.ts +0 -3
  52. package/dist/rules/auth.d.ts.map +0 -1
  53. package/dist/rules/auth.js +0 -48
  54. package/dist/rules/auth.js.map +0 -1
  55. package/dist/rules/cross-stack.d.ts +0 -3
  56. package/dist/rules/cross-stack.d.ts.map +0 -1
  57. package/dist/rules/cross-stack.js +0 -320
  58. package/dist/rules/cross-stack.js.map +0 -1
  59. package/dist/rules/drizzle.d.ts +0 -3
  60. package/dist/rules/drizzle.d.ts.map +0 -1
  61. package/dist/rules/drizzle.js +0 -43
  62. package/dist/rules/drizzle.js.map +0 -1
  63. package/dist/rules/index.d.ts +0 -7
  64. package/dist/rules/index.d.ts.map +0 -1
  65. package/dist/rules/index.js +0 -104
  66. package/dist/rules/index.js.map +0 -1
  67. package/dist/rules/nextjs.d.ts +0 -4
  68. package/dist/rules/nextjs.d.ts.map +0 -1
  69. package/dist/rules/nextjs.js +0 -86
  70. package/dist/rules/nextjs.js.map +0 -1
  71. package/dist/rules/node.d.ts +0 -3
  72. package/dist/rules/node.d.ts.map +0 -1
  73. package/dist/rules/node.js +0 -61
  74. package/dist/rules/node.js.map +0 -1
  75. package/dist/rules/prisma.d.ts +0 -3
  76. package/dist/rules/prisma.d.ts.map +0 -1
  77. package/dist/rules/prisma.js +0 -44
  78. package/dist/rules/prisma.js.map +0 -1
  79. package/dist/rules/react.d.ts +0 -3
  80. package/dist/rules/react.d.ts.map +0 -1
  81. package/dist/rules/react.js +0 -58
  82. package/dist/rules/react.js.map +0 -1
  83. package/dist/rules/state.d.ts +0 -3
  84. package/dist/rules/state.d.ts.map +0 -1
  85. package/dist/rules/state.js +0 -51
  86. package/dist/rules/state.js.map +0 -1
  87. package/dist/rules/tailwind.d.ts +0 -3
  88. package/dist/rules/tailwind.d.ts.map +0 -1
  89. package/dist/rules/tailwind.js +0 -41
  90. package/dist/rules/tailwind.js.map +0 -1
  91. package/dist/rules/trpc.d.ts +0 -3
  92. package/dist/rules/trpc.d.ts.map +0 -1
  93. package/dist/rules/trpc.js +0 -35
  94. package/dist/rules/trpc.js.map +0 -1
  95. package/dist/rules/typescript.d.ts +0 -3
  96. package/dist/rules/typescript.d.ts.map +0 -1
  97. package/dist/rules/typescript.js +0 -54
  98. package/dist/rules/typescript.js.map +0 -1
  99. package/dist/rules/validation.d.ts +0 -3
  100. package/dist/rules/validation.d.ts.map +0 -1
  101. package/dist/rules/validation.js +0 -38
  102. package/dist/rules/validation.js.map +0 -1
  103. package/dist/tools/detect-gaps.d.ts +0 -3
  104. package/dist/tools/detect-gaps.d.ts.map +0 -1
  105. package/dist/tools/detect-gaps.js +0 -34
  106. package/dist/tools/detect-gaps.js.map +0 -1
  107. package/dist/tools/suggest.d.ts +0 -3
  108. package/dist/tools/suggest.d.ts.map +0 -1
  109. package/dist/tools/suggest.js +0 -99
  110. package/dist/tools/suggest.js.map +0 -1
@@ -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", "react"]);
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
@@ -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"}