@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
@@ -596,3 +596,486 @@ vueuse:
596
596
  #
597
597
  # e2e/ # E2E tests
598
598
  # └── specs/
599
+
600
+ # ----------------------------------------------------------------------------
601
+ # CODE EXAMPLES
602
+ # ----------------------------------------------------------------------------
603
+ codeExamples:
604
+ compositionAPIComponent:
605
+ description: "Modern Vue 3 component with script setup"
606
+ code: |
607
+ <!-- components/UserCard.vue -->
608
+ <script setup lang="ts">
609
+ import { computed } from 'vue'
610
+ import type { User } from '@/types'
611
+
612
+ const props = defineProps<{
613
+ user: User
614
+ isActive?: boolean
615
+ }>()
616
+
617
+ const emit = defineEmits<{
618
+ (e: 'select', userId: string): void
619
+ }>()
620
+
621
+ const fullName = computed(() => `${props.user.firstName} ${props.user.lastName}`)
622
+
623
+ function handleClick() {
624
+ emit('select', props.user.id)
625
+ }
626
+ </script>
627
+
628
+ <template>
629
+ <article
630
+ class="user-card"
631
+ :class="{ 'user-card--active': isActive }"
632
+ @click="handleClick"
633
+ >
634
+ <img :src="user.avatar" :alt="`${fullName}'s avatar`" />
635
+ <h3>{{ fullName }}</h3>
636
+ <p>{{ user.email }}</p>
637
+ </article>
638
+ </template>
639
+
640
+ <style scoped>
641
+ .user-card {
642
+ @apply p-4 rounded-lg shadow cursor-pointer transition-colors;
643
+ }
644
+ .user-card--active {
645
+ @apply ring-2 ring-primary;
646
+ }
647
+ </style>
648
+
649
+ defineModel:
650
+ description: "Two-way binding with defineModel (Vue 3.4+)"
651
+ code: |
652
+ <!-- components/SearchInput.vue -->
653
+ <script setup lang="ts">
654
+ const modelValue = defineModel<string>({ required: true })
655
+ const isFocused = ref(false)
656
+
657
+ // Automatically handles :model-value and @update:model-value
658
+ </script>
659
+
660
+ <template>
661
+ <input
662
+ v-model="modelValue"
663
+ type="search"
664
+ placeholder="Search..."
665
+ :class="{ 'ring-2': isFocused }"
666
+ @focus="isFocused = true"
667
+ @blur="isFocused = false"
668
+ />
669
+ </template>
670
+
671
+ composable:
672
+ description: "Reusable composable with proper patterns"
673
+ code: |
674
+ // composables/useUser.ts
675
+ import { ref, readonly, watch, type Ref } from 'vue'
676
+ import { useUserApi } from '@/api/users'
677
+ import type { User } from '@/types'
678
+
679
+ export function useUser(userId: Ref<string>) {
680
+ const user = ref<User | null>(null)
681
+ const isLoading = ref(false)
682
+ const error = ref<Error | null>(null)
683
+
684
+ const api = useUserApi()
685
+
686
+ async function fetchUser() {
687
+ if (!userId.value) return
688
+
689
+ isLoading.value = true
690
+ error.value = null
691
+
692
+ try {
693
+ user.value = await api.getById(userId.value)
694
+ } catch (e) {
695
+ error.value = e as Error
696
+ user.value = null
697
+ } finally {
698
+ isLoading.value = false
699
+ }
700
+ }
701
+
702
+ // React to userId changes
703
+ watch(userId, fetchUser, { immediate: true })
704
+
705
+ return {
706
+ user: readonly(user),
707
+ isLoading: readonly(isLoading),
708
+ error: readonly(error),
709
+ refetch: fetchUser
710
+ }
711
+ }
712
+
713
+ piniaStore:
714
+ description: "Pinia store with Setup Store syntax"
715
+ code: |
716
+ // stores/auth.ts
717
+ import { defineStore } from 'pinia'
718
+ import { ref, computed, readonly } from 'vue'
719
+ import { useRouter } from 'vue-router'
720
+ import { authApi } from '@/api/auth'
721
+ import type { User, Credentials } from '@/types'
722
+
723
+ export const useAuthStore = defineStore('auth', () => {
724
+ const router = useRouter()
725
+
726
+ // State
727
+ const user = ref<User | null>(null)
728
+ const token = ref<string | null>(localStorage.getItem('token'))
729
+ const isLoading = ref(false)
730
+
731
+ // Getters
732
+ const isAuthenticated = computed(() => !!token.value && !!user.value)
733
+ const displayName = computed(() =>
734
+ user.value ? `${user.value.firstName} ${user.value.lastName}` : ''
735
+ )
736
+
737
+ // Actions
738
+ async function login(credentials: Credentials) {
739
+ isLoading.value = true
740
+ try {
741
+ const response = await authApi.login(credentials)
742
+ token.value = response.token
743
+ user.value = response.user
744
+ localStorage.setItem('token', response.token)
745
+ router.push('/dashboard')
746
+ } finally {
747
+ isLoading.value = false
748
+ }
749
+ }
750
+
751
+ function logout() {
752
+ token.value = null
753
+ user.value = null
754
+ localStorage.removeItem('token')
755
+ router.push('/login')
756
+ }
757
+
758
+ return {
759
+ // State (readonly for external access)
760
+ user: readonly(user),
761
+ token: readonly(token),
762
+ isLoading: readonly(isLoading),
763
+ // Getters
764
+ isAuthenticated,
765
+ displayName,
766
+ // Actions
767
+ login,
768
+ logout
769
+ }
770
+ })
771
+
772
+ genericComponent:
773
+ description: "Generic component for type-safe reusable lists"
774
+ code: |
775
+ <!-- components/DataList.vue -->
776
+ <script setup lang="ts" generic="T extends { id: string }">
777
+ defineProps<{
778
+ items: T[]
779
+ selected?: T | null
780
+ }>()
781
+
782
+ const emit = defineEmits<{
783
+ (e: 'select', item: T): void
784
+ (e: 'remove', item: T): void
785
+ }>()
786
+ </script>
787
+
788
+ <template>
789
+ <ul class="data-list">
790
+ <li
791
+ v-for="item in items"
792
+ :key="item.id"
793
+ :class="{ selected: selected?.id === item.id }"
794
+ @click="emit('select', item)"
795
+ >
796
+ <slot :item="item" />
797
+ <button @click.stop="emit('remove', item)">Remove</button>
798
+ </li>
799
+ </ul>
800
+ </template>
801
+
802
+ componentTest:
803
+ description: "Component test with Vue Testing Library"
804
+ code: |
805
+ // components/UserCard.spec.ts
806
+ import { render, screen } from '@testing-library/vue'
807
+ import userEvent from '@testing-library/user-event'
808
+ import { describe, it, expect, vi } from 'vitest'
809
+ import UserCard from './UserCard.vue'
810
+
811
+ describe('UserCard', () => {
812
+ const mockUser = {
813
+ id: '1',
814
+ firstName: 'John',
815
+ lastName: 'Doe',
816
+ email: 'john@example.com',
817
+ avatar: '/avatar.png'
818
+ }
819
+
820
+ it('displays user information', () => {
821
+ render(UserCard, {
822
+ props: { user: mockUser }
823
+ })
824
+
825
+ expect(screen.getByText('John Doe')).toBeInTheDocument()
826
+ expect(screen.getByText('john@example.com')).toBeInTheDocument()
827
+ })
828
+
829
+ it('emits select event when clicked', async () => {
830
+ const user = userEvent.setup()
831
+ const { emitted } = render(UserCard, {
832
+ props: { user: mockUser }
833
+ })
834
+
835
+ await user.click(screen.getByRole('article'))
836
+
837
+ expect(emitted()).toHaveProperty('select')
838
+ expect(emitted().select[0]).toEqual(['1'])
839
+ })
840
+
841
+ it('applies active class when isActive is true', () => {
842
+ render(UserCard, {
843
+ props: { user: mockUser, isActive: true }
844
+ })
845
+
846
+ expect(screen.getByRole('article')).toHaveClass('user-card--active')
847
+ })
848
+ })
849
+
850
+ tanstackQuery:
851
+ description: "Data fetching with TanStack Query for Vue"
852
+ code: |
853
+ // composables/useProducts.ts
854
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/vue-query'
855
+ import { productsApi } from '@/api/products'
856
+ import type { Product, CreateProductDto } from '@/types'
857
+
858
+ export function useProducts() {
859
+ return useQuery({
860
+ queryKey: ['products'],
861
+ queryFn: productsApi.getAll,
862
+ staleTime: 5 * 60 * 1000
863
+ })
864
+ }
865
+
866
+ export function useProduct(id: Ref<string>) {
867
+ return useQuery({
868
+ queryKey: ['products', id],
869
+ queryFn: () => productsApi.getById(id.value),
870
+ enabled: computed(() => !!id.value)
871
+ })
872
+ }
873
+
874
+ export function useCreateProduct() {
875
+ const queryClient = useQueryClient()
876
+
877
+ return useMutation({
878
+ mutationFn: (data: CreateProductDto) => productsApi.create(data),
879
+ onSuccess: () => {
880
+ queryClient.invalidateQueries({ queryKey: ['products'] })
881
+ }
882
+ })
883
+ }
884
+
885
+ # ----------------------------------------------------------------------------
886
+ # ANTI-PATTERNS
887
+ # ----------------------------------------------------------------------------
888
+ antiPatterns:
889
+ optionsAPIInNewCode:
890
+ name: "Using Options API in New Code"
891
+ description: "Options API is legacy; use Composition API with script setup"
892
+ bad: |
893
+ // ❌ Options API
894
+ export default {
895
+ data() {
896
+ return { count: 0 }
897
+ },
898
+ methods: {
899
+ increment() {
900
+ this.count++
901
+ }
902
+ },
903
+ computed: {
904
+ doubled() {
905
+ return this.count * 2
906
+ }
907
+ }
908
+ }
909
+ good: |
910
+ // ✅ Composition API with script setup
911
+ <script setup lang="ts">
912
+ const count = ref(0)
913
+ const doubled = computed(() => count.value * 2)
914
+
915
+ function increment() {
916
+ count.value++
917
+ }
918
+ </script>
919
+
920
+ reactiveForEverything:
921
+ name: "Using reactive() for Everything"
922
+ description: "reactive() has limitations; prefer ref() for most cases"
923
+ bad: |
924
+ // ❌ reactive has issues with reassignment and destructuring
925
+ const state = reactive({
926
+ user: null,
927
+ isLoading: false
928
+ })
929
+
930
+ // This breaks reactivity!
931
+ state = { user: newUser, isLoading: false }
932
+
933
+ // This also loses reactivity
934
+ const { user } = state
935
+ good: |
936
+ // ✅ Use ref() for individual values
937
+ const user = ref<User | null>(null)
938
+ const isLoading = ref(false)
939
+
940
+ // Safe reassignment
941
+ user.value = newUser
942
+
943
+ // Or use computed for derived state
944
+ const isLoggedIn = computed(() => !!user.value)
945
+
946
+ mutatingProps:
947
+ name: "Mutating Props Directly"
948
+ description: "Props are read-only; emit events or use defineModel"
949
+ bad: |
950
+ // ❌ Mutating props directly
951
+ const props = defineProps<{ items: string[] }>()
952
+
953
+ function addItem(item: string) {
954
+ props.items.push(item) // DON'T DO THIS
955
+ }
956
+ good: |
957
+ // ✅ Emit event to parent
958
+ const props = defineProps<{ items: string[] }>()
959
+ const emit = defineEmits<{
960
+ (e: 'update:items', items: string[]): void
961
+ }>()
962
+
963
+ function addItem(item: string) {
964
+ emit('update:items', [...props.items, item])
965
+ }
966
+
967
+ // ✅ Or use defineModel for two-way binding
968
+ const items = defineModel<string[]>('items', { required: true })
969
+
970
+ function addItem(item: string) {
971
+ items.value = [...items.value, item]
972
+ }
973
+
974
+ watchEffectOverwatch:
975
+ name: "Using watchEffect When watch Is Better"
976
+ description: "watchEffect runs immediately and tracks all refs; use watch for explicit dependencies"
977
+ bad: |
978
+ // ❌ watchEffect tracks everything used inside
979
+ watchEffect(() => {
980
+ if (userId.value) {
981
+ fetchUser(userId.value) // Also tracks any refs inside fetchUser!
982
+ }
983
+ })
984
+ good: |
985
+ // ✅ Explicit dependencies with watch
986
+ watch(userId, (newId) => {
987
+ if (newId) {
988
+ fetchUser(newId)
989
+ }
990
+ }, { immediate: true })
991
+
992
+ vIfWithVFor:
993
+ name: "Using v-if with v-for on Same Element"
994
+ description: "v-if has higher priority than v-for in Vue 3, causing unexpected behavior"
995
+ bad: |
996
+ // ❌ v-if evaluated before v-for
997
+ <li v-for="item in items" v-if="item.isActive" :key="item.id">
998
+ {{ item.name }}
999
+ </li>
1000
+ good: |
1001
+ // ✅ Filter in computed
1002
+ <script setup lang="ts">
1003
+ const activeItems = computed(() => items.value.filter(item => item.isActive))
1004
+ </script>
1005
+
1006
+ <template>
1007
+ <li v-for="item in activeItems" :key="item.id">
1008
+ {{ item.name }}
1009
+ </li>
1010
+ </template>
1011
+
1012
+ // ✅ Or use template wrapper
1013
+ <template v-for="item in items" :key="item.id">
1014
+ <li v-if="item.isActive">{{ item.name }}</li>
1015
+ </template>
1016
+
1017
+ noKeyInVFor:
1018
+ name: "Missing :key in v-for"
1019
+ description: "Always provide a unique key for v-for items"
1020
+ bad: |
1021
+ // ❌ No key
1022
+ <li v-for="item in items">{{ item.name }}</li>
1023
+
1024
+ // ❌ Index as key
1025
+ <li v-for="(item, index) in items" :key="index">{{ item.name }}</li>
1026
+ good: |
1027
+ // ✅ Unique identifier as key
1028
+ <li v-for="item in items" :key="item.id">{{ item.name }}</li>
1029
+
1030
+ storeToRefsForActions:
1031
+ name: "Using storeToRefs for Actions"
1032
+ description: "storeToRefs only works for state/getters, not actions"
1033
+ bad: |
1034
+ // ❌ login is undefined (actions aren't refs)
1035
+ const { user, login } = storeToRefs(useAuthStore())
1036
+ good: |
1037
+ // ✅ Destructure actions directly
1038
+ const authStore = useAuthStore()
1039
+ const { user, isAuthenticated } = storeToRefs(authStore)
1040
+ const { login, logout } = authStore
1041
+
1042
+ heavyComputedWithoutMemo:
1043
+ name: "Expensive Computed Without Caching Awareness"
1044
+ description: "Computed values are cached, but be aware of dependency tracking"
1045
+ bad: |
1046
+ // ❌ Computed recalculates on ANY items change
1047
+ const expensiveResult = computed(() =>
1048
+ items.value.map(item => heavyCalculation(item))
1049
+ )
1050
+ good: |
1051
+ // ✅ Use v-memo or shallowRef for large lists
1052
+ const items = shallowRef<Item[]>([])
1053
+
1054
+ // Or memoize heavy calculations
1055
+ const memoizedCalculation = useMemoize(heavyCalculation)
1056
+ const result = computed(() =>
1057
+ items.value.map(item => memoizedCalculation(item))
1058
+ )
1059
+
1060
+ directDomManipulation:
1061
+ name: "Direct DOM Manipulation"
1062
+ description: "Let Vue handle the DOM; use refs for necessary DOM access"
1063
+ bad: |
1064
+ // ❌ Direct DOM manipulation
1065
+ document.querySelector('.my-element').classList.add('active')
1066
+ document.getElementById('input').focus()
1067
+ good: |
1068
+ // ✅ Use template refs
1069
+ <script setup lang="ts">
1070
+ const inputRef = ref<HTMLInputElement | null>(null)
1071
+ const isActive = ref(false)
1072
+
1073
+ function focusInput() {
1074
+ inputRef.value?.focus()
1075
+ }
1076
+ </script>
1077
+
1078
+ <template>
1079
+ <input ref="inputRef" />
1080
+ <div :class="{ active: isActive }">Content</div>
1081
+ </template>