@corbat-tech/coding-standards-mcp 1.0.3 → 2.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 (99) hide show
  1. package/README.md +233 -337
  2. package/dist/agent.d.ts +5 -6
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +95 -217
  5. package/dist/agent.js.map +1 -1
  6. package/dist/analysis/code-analyzer.d.ts +44 -0
  7. package/dist/analysis/code-analyzer.d.ts.map +1 -0
  8. package/dist/analysis/code-analyzer.js +528 -0
  9. package/dist/analysis/code-analyzer.js.map +1 -0
  10. package/dist/errors.d.ts +58 -0
  11. package/dist/errors.d.ts.map +1 -0
  12. package/dist/errors.js +112 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/guardrails.d.ts +35 -0
  15. package/dist/guardrails.d.ts.map +1 -0
  16. package/dist/guardrails.js +303 -0
  17. package/dist/guardrails.js.map +1 -0
  18. package/dist/index.js +1 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/logger.d.ts +36 -0
  21. package/dist/logger.d.ts.map +1 -0
  22. package/dist/logger.js +63 -0
  23. package/dist/logger.js.map +1 -0
  24. package/dist/metrics.d.ts +40 -0
  25. package/dist/metrics.d.ts.map +1 -0
  26. package/dist/metrics.js +97 -0
  27. package/dist/metrics.js.map +1 -0
  28. package/dist/profiles.d.ts +1 -1
  29. package/dist/profiles.d.ts.map +1 -1
  30. package/dist/profiles.js +239 -108
  31. package/dist/profiles.js.map +1 -1
  32. package/dist/prompts.js +1 -1
  33. package/dist/prompts.js.map +1 -1
  34. package/dist/tools/definitions.d.ts +143 -0
  35. package/dist/tools/definitions.d.ts.map +1 -0
  36. package/dist/tools/definitions.js +229 -0
  37. package/dist/tools/definitions.js.map +1 -0
  38. package/dist/tools/handlers/get-context.d.ts +12 -0
  39. package/dist/tools/handlers/get-context.d.ts.map +1 -0
  40. package/dist/tools/handlers/get-context.js +233 -0
  41. package/dist/tools/handlers/get-context.js.map +1 -0
  42. package/dist/tools/handlers/health.d.ts +11 -0
  43. package/dist/tools/handlers/health.d.ts.map +1 -0
  44. package/dist/tools/handlers/health.js +57 -0
  45. package/dist/tools/handlers/health.js.map +1 -0
  46. package/dist/tools/handlers/index.d.ts +12 -0
  47. package/dist/tools/handlers/index.d.ts.map +1 -0
  48. package/dist/tools/handlers/index.js +12 -0
  49. package/dist/tools/handlers/index.js.map +1 -0
  50. package/dist/tools/handlers/init.d.ts +12 -0
  51. package/dist/tools/handlers/init.d.ts.map +1 -0
  52. package/dist/tools/handlers/init.js +102 -0
  53. package/dist/tools/handlers/init.js.map +1 -0
  54. package/dist/tools/handlers/profiles.d.ts +11 -0
  55. package/dist/tools/handlers/profiles.d.ts.map +1 -0
  56. package/dist/tools/handlers/profiles.js +25 -0
  57. package/dist/tools/handlers/profiles.js.map +1 -0
  58. package/dist/tools/handlers/search.d.ts +12 -0
  59. package/dist/tools/handlers/search.d.ts.map +1 -0
  60. package/dist/tools/handlers/search.js +58 -0
  61. package/dist/tools/handlers/search.js.map +1 -0
  62. package/dist/tools/handlers/validate.d.ts +15 -0
  63. package/dist/tools/handlers/validate.d.ts.map +1 -0
  64. package/dist/tools/handlers/validate.js +71 -0
  65. package/dist/tools/handlers/validate.js.map +1 -0
  66. package/dist/tools/handlers/verify.d.ts +38 -0
  67. package/dist/tools/handlers/verify.d.ts.map +1 -0
  68. package/dist/tools/handlers/verify.js +172 -0
  69. package/dist/tools/handlers/verify.js.map +1 -0
  70. package/dist/tools/index.d.ts +22 -0
  71. package/dist/tools/index.d.ts.map +1 -0
  72. package/dist/tools/index.js +75 -0
  73. package/dist/tools/index.js.map +1 -0
  74. package/dist/tools/schemas.d.ts +29 -0
  75. package/dist/tools/schemas.d.ts.map +1 -0
  76. package/dist/tools/schemas.js +20 -0
  77. package/dist/tools/schemas.js.map +1 -0
  78. package/dist/tools.js +2 -2
  79. package/dist/tools.js.map +1 -1
  80. package/dist/types.d.ts +141 -71
  81. package/dist/types.d.ts.map +1 -1
  82. package/dist/types.js +92 -40
  83. package/dist/types.js.map +1 -1
  84. package/package.json +2 -2
  85. package/profiles/examples/microservice-kafka.yaml +122 -0
  86. package/profiles/examples/startup-fast.yaml +67 -0
  87. package/profiles/examples/strict-enterprise.yaml +62 -0
  88. package/profiles/templates/angular.yaml +614 -0
  89. package/profiles/templates/csharp-dotnet.yaml +529 -0
  90. package/profiles/templates/flutter.yaml +547 -0
  91. package/profiles/templates/go.yaml +1276 -0
  92. package/profiles/templates/java-spring-backend.yaml +326 -0
  93. package/profiles/templates/kotlin-spring.yaml +417 -0
  94. package/profiles/templates/nextjs.yaml +536 -0
  95. package/profiles/templates/nodejs.yaml +594 -0
  96. package/profiles/templates/python.yaml +546 -0
  97. package/profiles/templates/react.yaml +456 -0
  98. package/profiles/templates/rust.yaml +508 -0
  99. package/profiles/templates/vue.yaml +483 -0
@@ -329,3 +329,459 @@ api:
329
329
  # ├── integration/
330
330
  # ├── e2e/
331
331
  # └── setup.ts
332
+
333
+ # ----------------------------------------------------------------------------
334
+ # CODE EXAMPLES
335
+ # ----------------------------------------------------------------------------
336
+ codeExamples:
337
+ functionalComponent:
338
+ description: "Basic functional component with TypeScript"
339
+ code: |
340
+ // components/UserCard.tsx
341
+ interface UserCardProps {
342
+ user: User;
343
+ onSelect?: (userId: string) => void;
344
+ isActive?: boolean;
345
+ }
346
+
347
+ export default function UserCard({ user, onSelect, isActive = false }: UserCardProps) {
348
+ const handleClick = () => onSelect?.(user.id);
349
+
350
+ return (
351
+ <article
352
+ className={cn('user-card', { 'user-card--active': isActive })}
353
+ onClick={handleClick}
354
+ role="button"
355
+ tabIndex={0}
356
+ aria-pressed={isActive}
357
+ >
358
+ <img src={user.avatar} alt={`${user.name}'s avatar`} />
359
+ <h3>{user.name}</h3>
360
+ <p>{user.email}</p>
361
+ </article>
362
+ );
363
+ }
364
+
365
+ customHook:
366
+ description: "Custom hook with proper typing and cleanup"
367
+ code: |
368
+ // hooks/useDebounce.ts
369
+ import { useState, useEffect } from 'react';
370
+
371
+ export function useDebounce<T>(value: T, delay: number): T {
372
+ const [debouncedValue, setDebouncedValue] = useState(value);
373
+
374
+ useEffect(() => {
375
+ const timer = setTimeout(() => setDebouncedValue(value), delay);
376
+ return () => clearTimeout(timer); // Cleanup
377
+ }, [value, delay]);
378
+
379
+ return debouncedValue;
380
+ }
381
+
382
+ dataFetchingHook:
383
+ description: "Data fetching with TanStack Query"
384
+ code: |
385
+ // hooks/useUsers.ts
386
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
387
+ import { usersApi } from '@/core/api/users';
388
+
389
+ export function useUsers() {
390
+ return useQuery({
391
+ queryKey: ['users'],
392
+ queryFn: usersApi.getAll,
393
+ staleTime: 5 * 60 * 1000, // 5 minutes
394
+ });
395
+ }
396
+
397
+ export function useCreateUser() {
398
+ const queryClient = useQueryClient();
399
+
400
+ return useMutation({
401
+ mutationFn: usersApi.create,
402
+ onSuccess: () => {
403
+ queryClient.invalidateQueries({ queryKey: ['users'] });
404
+ },
405
+ });
406
+ }
407
+
408
+ contextProvider:
409
+ description: "Context with TypeScript for theme/auth"
410
+ code: |
411
+ // context/AuthContext.tsx
412
+ interface AuthContextValue {
413
+ user: User | null;
414
+ isAuthenticated: boolean;
415
+ login: (credentials: Credentials) => Promise<void>;
416
+ logout: () => void;
417
+ }
418
+
419
+ const AuthContext = createContext<AuthContextValue | null>(null);
420
+
421
+ export function AuthProvider({ children }: { children: React.ReactNode }) {
422
+ const [user, setUser] = useState<User | null>(null);
423
+
424
+ const login = async (credentials: Credentials) => {
425
+ const user = await authApi.login(credentials);
426
+ setUser(user);
427
+ };
428
+
429
+ const logout = () => setUser(null);
430
+
431
+ const value: AuthContextValue = {
432
+ user,
433
+ isAuthenticated: !!user,
434
+ login,
435
+ logout,
436
+ };
437
+
438
+ return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
439
+ }
440
+
441
+ export function useAuth(): AuthContextValue {
442
+ const context = useContext(AuthContext);
443
+ if (!context) throw new Error('useAuth must be used within AuthProvider');
444
+ return context;
445
+ }
446
+
447
+ zustandStore:
448
+ description: "Zustand store for global state"
449
+ code: |
450
+ // stores/cartStore.ts
451
+ import { create } from 'zustand';
452
+ import { devtools, persist } from 'zustand/middleware';
453
+
454
+ interface CartState {
455
+ items: CartItem[];
456
+ total: number;
457
+ addItem: (item: CartItem) => void;
458
+ removeItem: (itemId: string) => void;
459
+ clearCart: () => void;
460
+ }
461
+
462
+ export const useCartStore = create<CartState>()(
463
+ devtools(
464
+ persist(
465
+ (set, get) => ({
466
+ items: [],
467
+ total: 0,
468
+
469
+ addItem: (item) =>
470
+ set((state) => ({
471
+ items: [...state.items, item],
472
+ total: state.total + item.price,
473
+ })),
474
+
475
+ removeItem: (itemId) =>
476
+ set((state) => {
477
+ const item = state.items.find((i) => i.id === itemId);
478
+ return {
479
+ items: state.items.filter((i) => i.id !== itemId),
480
+ total: state.total - (item?.price ?? 0),
481
+ };
482
+ }),
483
+
484
+ clearCart: () => set({ items: [], total: 0 }),
485
+ }),
486
+ { name: 'cart-storage' }
487
+ )
488
+ )
489
+ );
490
+
491
+ componentTest:
492
+ description: "Component test with React Testing Library"
493
+ code: |
494
+ // components/UserCard.test.tsx
495
+ import { render, screen } from '@testing-library/react';
496
+ import userEvent from '@testing-library/user-event';
497
+ import { UserCard } from './UserCard';
498
+
499
+ describe('UserCard', () => {
500
+ const mockUser = { id: '1', name: 'John Doe', email: 'john@example.com', avatar: '/avatar.png' };
501
+
502
+ it('renders user information', () => {
503
+ render(<UserCard user={mockUser} />);
504
+
505
+ expect(screen.getByRole('heading', { name: 'John Doe' })).toBeInTheDocument();
506
+ expect(screen.getByText('john@example.com')).toBeInTheDocument();
507
+ expect(screen.getByAltText("John Doe's avatar")).toBeInTheDocument();
508
+ });
509
+
510
+ it('calls onSelect when clicked', async () => {
511
+ const user = userEvent.setup();
512
+ const onSelect = vi.fn();
513
+
514
+ render(<UserCard user={mockUser} onSelect={onSelect} />);
515
+ await user.click(screen.getByRole('button'));
516
+
517
+ expect(onSelect).toHaveBeenCalledWith('1');
518
+ });
519
+
520
+ it('is keyboard accessible', async () => {
521
+ const user = userEvent.setup();
522
+ const onSelect = vi.fn();
523
+
524
+ render(<UserCard user={mockUser} onSelect={onSelect} />);
525
+ await user.tab();
526
+ await user.keyboard('{Enter}');
527
+
528
+ expect(onSelect).toHaveBeenCalled();
529
+ });
530
+ });
531
+
532
+ errorBoundary:
533
+ description: "Error boundary for graceful error handling"
534
+ code: |
535
+ // components/ErrorBoundary.tsx
536
+ interface Props {
537
+ children: React.ReactNode;
538
+ fallback?: React.ReactNode;
539
+ }
540
+
541
+ interface State {
542
+ hasError: boolean;
543
+ error?: Error;
544
+ }
545
+
546
+ export class ErrorBoundary extends React.Component<Props, State> {
547
+ state: State = { hasError: false };
548
+
549
+ static getDerivedStateFromError(error: Error): State {
550
+ return { hasError: true, error };
551
+ }
552
+
553
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
554
+ console.error('Error caught:', error, errorInfo);
555
+ // Log to error tracking service
556
+ }
557
+
558
+ render() {
559
+ if (this.state.hasError) {
560
+ return this.props.fallback ?? (
561
+ <div role="alert">
562
+ <h2>Something went wrong</h2>
563
+ <button onClick={() => this.setState({ hasError: false })}>
564
+ Try again
565
+ </button>
566
+ </div>
567
+ );
568
+ }
569
+ return this.props.children;
570
+ }
571
+ }
572
+
573
+ # ----------------------------------------------------------------------------
574
+ # ANTI-PATTERNS
575
+ # ----------------------------------------------------------------------------
576
+ antiPatterns:
577
+ propDrilling:
578
+ name: "Prop Drilling"
579
+ description: "Passing props through many levels of components"
580
+ bad: |
581
+ // ❌ Props passed through 4 levels
582
+ function App() {
583
+ const [user, setUser] = useState<User | null>(null);
584
+ return <Layout user={user} setUser={setUser} />;
585
+ }
586
+ function Layout({ user, setUser }) {
587
+ return <Sidebar user={user} setUser={setUser} />;
588
+ }
589
+ function Sidebar({ user, setUser }) {
590
+ return <UserMenu user={user} setUser={setUser} />;
591
+ }
592
+ good: |
593
+ // ✅ Use Context or Zustand
594
+ function App() {
595
+ return (
596
+ <AuthProvider>
597
+ <Layout />
598
+ </AuthProvider>
599
+ );
600
+ }
601
+ function UserMenu() {
602
+ const { user, logout } = useAuth(); // Direct access
603
+ return <button onClick={logout}>Logout {user?.name}</button>;
604
+ }
605
+
606
+ useEffectAbuse:
607
+ name: "useEffect for Derived State"
608
+ description: "Using useEffect to synchronize state that should be computed"
609
+ bad: |
610
+ // ❌ useEffect for derived state
611
+ function ProductList({ products }) {
612
+ const [total, setTotal] = useState(0);
613
+
614
+ useEffect(() => {
615
+ const sum = products.reduce((acc, p) => acc + p.price, 0);
616
+ setTotal(sum);
617
+ }, [products]);
618
+
619
+ return <div>Total: {total}</div>;
620
+ }
621
+ good: |
622
+ // ✅ Use useMemo for derived values
623
+ function ProductList({ products }) {
624
+ const total = useMemo(
625
+ () => products.reduce((acc, p) => acc + p.price, 0),
626
+ [products]
627
+ );
628
+
629
+ return <div>Total: {total}</div>;
630
+ }
631
+
632
+ inlineHandlers:
633
+ name: "Inline Function Definitions in JSX"
634
+ description: "Creating new functions on every render"
635
+ bad: |
636
+ // ❌ New function created on every render
637
+ function ItemList({ items, onRemove }) {
638
+ return (
639
+ <ul>
640
+ {items.map(item => (
641
+ <li key={item.id}>
642
+ {item.name}
643
+ <button onClick={() => onRemove(item.id)}>Remove</button>
644
+ </li>
645
+ ))}
646
+ </ul>
647
+ );
648
+ }
649
+ good: |
650
+ // ✅ Use useCallback or extract component
651
+ function ItemList({ items, onRemove }) {
652
+ return (
653
+ <ul>
654
+ {items.map(item => (
655
+ <Item key={item.id} item={item} onRemove={onRemove} />
656
+ ))}
657
+ </ul>
658
+ );
659
+ }
660
+
661
+ const Item = memo(function Item({ item, onRemove }) {
662
+ const handleRemove = useCallback(() => onRemove(item.id), [item.id, onRemove]);
663
+ return (
664
+ <li>
665
+ {item.name}
666
+ <button onClick={handleRemove}>Remove</button>
667
+ </li>
668
+ );
669
+ });
670
+
671
+ useStateForServerData:
672
+ name: "useState for Server Data"
673
+ description: "Managing server state with useState instead of a data fetching library"
674
+ bad: |
675
+ // ❌ Manual server state management
676
+ function UserList() {
677
+ const [users, setUsers] = useState<User[]>([]);
678
+ const [loading, setLoading] = useState(true);
679
+ const [error, setError] = useState<Error | null>(null);
680
+
681
+ useEffect(() => {
682
+ setLoading(true);
683
+ fetchUsers()
684
+ .then(setUsers)
685
+ .catch(setError)
686
+ .finally(() => setLoading(false));
687
+ }, []);
688
+
689
+ // No caching, no refetch, no deduplication...
690
+ }
691
+ good: |
692
+ // ✅ Use TanStack Query
693
+ function UserList() {
694
+ const { data: users, isLoading, error, refetch } = useQuery({
695
+ queryKey: ['users'],
696
+ queryFn: fetchUsers,
697
+ });
698
+
699
+ // Automatic caching, refetch, deduplication, etc.
700
+ }
701
+
702
+ anyType:
703
+ name: "Using 'any' Type"
704
+ description: "Disabling TypeScript's type checking with 'any'"
705
+ bad: |
706
+ // ❌ any disables type safety
707
+ function processData(data: any) {
708
+ return data.items.map((item: any) => item.value);
709
+ }
710
+ good: |
711
+ // ✅ Proper typing
712
+ interface DataItem {
713
+ value: number;
714
+ }
715
+ interface Data {
716
+ items: DataItem[];
717
+ }
718
+
719
+ function processData(data: Data): number[] {
720
+ return data.items.map(item => item.value);
721
+ }
722
+
723
+ testingImplementation:
724
+ name: "Testing Implementation Details"
725
+ description: "Testing internal state or methods instead of behavior"
726
+ bad: |
727
+ // ❌ Testing internal state
728
+ it('increments count state', () => {
729
+ const { result } = renderHook(() => useCounter());
730
+ expect(result.current.count).toBe(0);
731
+ act(() => result.current.increment());
732
+ expect(result.current.count).toBe(1);
733
+ });
734
+
735
+ // ❌ Using getByTestId unnecessarily
736
+ expect(screen.getByTestId('user-name')).toHaveTextContent('John');
737
+ good: |
738
+ // ✅ Test visible behavior
739
+ it('displays incremented count', async () => {
740
+ render(<Counter />);
741
+ expect(screen.getByRole('status')).toHaveTextContent('0');
742
+
743
+ await userEvent.click(screen.getByRole('button', { name: /increment/i }));
744
+
745
+ expect(screen.getByRole('status')).toHaveTextContent('1');
746
+ });
747
+
748
+ // ✅ Use accessible queries
749
+ expect(screen.getByRole('heading', { name: 'John' })).toBeInTheDocument();
750
+
751
+ missingKeyOrBadKey:
752
+ name: "Missing or Non-Unique Keys"
753
+ description: "Not providing keys or using index as key in dynamic lists"
754
+ bad: |
755
+ // ❌ Index as key (causes bugs with reordering)
756
+ {items.map((item, index) => (
757
+ <Item key={index} item={item} />
758
+ ))}
759
+
760
+ // ❌ No key at all
761
+ {items.map(item => (
762
+ <Item item={item} />
763
+ ))}
764
+ good: |
765
+ // ✅ Unique identifier as key
766
+ {items.map(item => (
767
+ <Item key={item.id} item={item} />
768
+ ))}
769
+
770
+ inlineStyles:
771
+ name: "Inline Styles"
772
+ description: "Using inline style objects instead of CSS classes"
773
+ bad: |
774
+ // ❌ Inline styles
775
+ <div style={{ padding: '16px', backgroundColor: '#f0f0f0', marginTop: '8px' }}>
776
+ Content
777
+ </div>
778
+ good: |
779
+ // ✅ Use Tailwind or CSS classes
780
+ <div className="p-4 bg-gray-100 mt-2">
781
+ Content
782
+ </div>
783
+
784
+ // ✅ Or CSS Modules
785
+ <div className={styles.container}>
786
+ Content
787
+ </div>