@react-spa-scaffold/mcp 1.2.1 → 2.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.
- package/README.md +39 -127
- package/dist/features/definitions/api.d.ts.map +1 -1
- package/dist/features/definitions/api.js +1 -11
- package/dist/features/definitions/api.js.map +1 -1
- package/dist/features/definitions/ci.d.ts.map +1 -1
- package/dist/features/definitions/ci.js +0 -11
- package/dist/features/definitions/ci.js.map +1 -1
- package/dist/features/definitions/core.d.ts.map +1 -1
- package/dist/features/definitions/core.js +2 -15
- package/dist/features/definitions/core.js.map +1 -1
- package/dist/features/definitions/devtools.d.ts.map +1 -1
- package/dist/features/definitions/devtools.js +1 -15
- package/dist/features/definitions/devtools.js.map +1 -1
- package/dist/features/definitions/forms.d.ts.map +1 -1
- package/dist/features/definitions/forms.js +1 -10
- package/dist/features/definitions/forms.js.map +1 -1
- package/dist/features/definitions/i18n.d.ts.map +1 -1
- package/dist/features/definitions/i18n.js +2 -15
- package/dist/features/definitions/i18n.js.map +1 -1
- package/dist/features/definitions/mobile.d.ts.map +1 -1
- package/dist/features/definitions/mobile.js +0 -10
- package/dist/features/definitions/mobile.js.map +1 -1
- package/dist/features/definitions/observability.d.ts.map +1 -1
- package/dist/features/definitions/observability.js +2 -13
- package/dist/features/definitions/observability.js.map +1 -1
- package/dist/features/definitions/performance.d.ts.map +1 -1
- package/dist/features/definitions/performance.js +2 -14
- package/dist/features/definitions/performance.js.map +1 -1
- package/dist/features/definitions/routing.d.ts.map +1 -1
- package/dist/features/definitions/routing.js +1 -10
- package/dist/features/definitions/routing.js.map +1 -1
- package/dist/features/definitions/state.d.ts.map +1 -1
- package/dist/features/definitions/state.js +1 -12
- package/dist/features/definitions/state.js.map +1 -1
- package/dist/features/definitions/testing.d.ts.map +1 -1
- package/dist/features/definitions/testing.js +1 -17
- package/dist/features/definitions/testing.js.map +1 -1
- package/dist/features/definitions/theming.d.ts.map +1 -1
- package/dist/features/definitions/theming.js +0 -9
- package/dist/features/definitions/theming.js.map +1 -1
- package/dist/features/definitions/ui.d.ts.map +1 -1
- package/dist/features/definitions/ui.js +2 -16
- package/dist/features/definitions/ui.js.map +1 -1
- package/dist/features/types.d.ts +2 -4
- package/dist/features/types.d.ts.map +1 -1
- package/dist/server.js +6 -6
- package/dist/tools/add-features.d.ts +44 -0
- package/dist/tools/add-features.d.ts.map +1 -0
- package/dist/tools/add-features.js +157 -0
- package/dist/tools/add-features.js.map +1 -0
- package/dist/tools/add-features.test.d.ts +5 -0
- package/dist/tools/add-features.test.d.ts.map +1 -0
- package/dist/tools/add-features.test.js +170 -0
- package/dist/tools/add-features.test.js.map +1 -0
- package/dist/tools/get-features.d.ts +1 -2
- package/dist/tools/get-features.d.ts.map +1 -1
- package/dist/tools/get-features.js +1 -2
- package/dist/tools/get-features.js.map +1 -1
- package/dist/tools/get-features.test.js +6 -2
- package/dist/tools/get-features.test.js.map +1 -1
- package/dist/tools/get-file.d.ts +1 -1
- package/dist/tools/get-file.d.ts.map +1 -1
- package/dist/tools/get-file.js +12 -8
- package/dist/tools/get-file.js.map +1 -1
- package/dist/tools/get-scaffold.d.ts +3 -4
- package/dist/tools/get-scaffold.d.ts.map +1 -1
- package/dist/tools/get-scaffold.js +58 -29
- package/dist/tools/get-scaffold.js.map +1 -1
- package/dist/tools/get-scaffold.test.js +25 -10
- package/dist/tools/get-scaffold.test.js.map +1 -1
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/registry.js +8 -8
- package/dist/tools/registry.js.map +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/scaffold/compute.js +1 -1
- package/dist/utils/scaffold/compute.js.map +1 -1
- package/dist/utils/scaffold/dependencies.d.ts +15 -2
- package/dist/utils/scaffold/dependencies.d.ts.map +1 -1
- package/dist/utils/scaffold/dependencies.js +15 -8
- package/dist/utils/scaffold/dependencies.js.map +1 -1
- package/dist/utils/scaffold/file-structure.d.ts +12 -0
- package/dist/utils/scaffold/file-structure.d.ts.map +1 -1
- package/dist/utils/scaffold/file-structure.js +23 -0
- package/dist/utils/scaffold/file-structure.js.map +1 -1
- package/dist/utils/scaffold/generators.d.ts.map +1 -1
- package/dist/utils/scaffold/generators.js +10 -0
- package/dist/utils/scaffold/generators.js.map +1 -1
- package/dist/utils/scaffold/index.d.ts +3 -2
- package/dist/utils/scaffold/index.d.ts.map +1 -1
- package/dist/utils/scaffold/index.js +1 -1
- package/dist/utils/scaffold/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/e2e/tests/language.spec.ts +2 -1
- package/templates/src/contexts/queryContext.tsx +1 -2
- package/templates/src/lib/storage.ts +1 -1
- package/dist/tools/get-example.d.ts +0 -38
- package/dist/tools/get-example.d.ts.map +0 -1
- package/dist/tools/get-example.js +0 -83
- package/dist/tools/get-example.js.map +0 -1
- package/dist/tools/get-example.test.d.ts +0 -5
- package/dist/tools/get-example.test.d.ts.map +0 -1
- package/dist/tools/get-example.test.js +0 -63
- package/dist/tools/get-example.test.js.map +0 -1
- package/dist/utils/examples/api-patterns.d.ts +0 -3
- package/dist/utils/examples/api-patterns.d.ts.map +0 -1
- package/dist/utils/examples/api-patterns.js +0 -19
- package/dist/utils/examples/api-patterns.js.map +0 -1
- package/dist/utils/examples/component-patterns.d.ts +0 -3
- package/dist/utils/examples/component-patterns.d.ts.map +0 -1
- package/dist/utils/examples/component-patterns.js +0 -71
- package/dist/utils/examples/component-patterns.js.map +0 -1
- package/dist/utils/examples/context-patterns.d.ts +0 -3
- package/dist/utils/examples/context-patterns.d.ts.map +0 -1
- package/dist/utils/examples/context-patterns.js +0 -32
- package/dist/utils/examples/context-patterns.js.map +0 -1
- package/dist/utils/examples/hook-patterns.d.ts +0 -3
- package/dist/utils/examples/hook-patterns.d.ts.map +0 -1
- package/dist/utils/examples/hook-patterns.js +0 -55
- package/dist/utils/examples/hook-patterns.js.map +0 -1
- package/dist/utils/examples/i18n-patterns.d.ts +0 -3
- package/dist/utils/examples/i18n-patterns.d.ts.map +0 -1
- package/dist/utils/examples/i18n-patterns.js +0 -43
- package/dist/utils/examples/i18n-patterns.js.map +0 -1
- package/dist/utils/examples/index.d.ts +0 -12
- package/dist/utils/examples/index.d.ts.map +0 -1
- package/dist/utils/examples/index.js +0 -65
- package/dist/utils/examples/index.js.map +0 -1
- package/dist/utils/examples/mobile-patterns.d.ts +0 -3
- package/dist/utils/examples/mobile-patterns.d.ts.map +0 -1
- package/dist/utils/examples/mobile-patterns.js +0 -38
- package/dist/utils/examples/mobile-patterns.js.map +0 -1
- package/dist/utils/examples/page-patterns.d.ts +0 -3
- package/dist/utils/examples/page-patterns.d.ts.map +0 -1
- package/dist/utils/examples/page-patterns.js +0 -34
- package/dist/utils/examples/page-patterns.js.map +0 -1
- package/dist/utils/examples/patterns.test.d.ts +0 -6
- package/dist/utils/examples/patterns.test.d.ts.map +0 -1
- package/dist/utils/examples/patterns.test.js +0 -75
- package/dist/utils/examples/patterns.test.js.map +0 -1
- package/dist/utils/examples/store-patterns.d.ts +0 -3
- package/dist/utils/examples/store-patterns.d.ts.map +0 -1
- package/dist/utils/examples/store-patterns.js +0 -40
- package/dist/utils/examples/store-patterns.js.map +0 -1
- package/dist/utils/examples/test-patterns.d.ts +0 -3
- package/dist/utils/examples/test-patterns.d.ts.map +0 -1
- package/dist/utils/examples/test-patterns.js +0 -58
- package/dist/utils/examples/test-patterns.js.map +0 -1
- package/dist/utils/examples/types.d.ts +0 -17
- package/dist/utils/examples/types.d.ts.map +0 -1
- package/dist/utils/examples/types.js +0 -2
- package/dist/utils/examples/types.js.map +0 -1
- package/dist/utils/examples/utility-patterns.d.ts +0 -3
- package/dist/utils/examples/utility-patterns.d.ts.map +0 -1
- package/dist/utils/examples/utility-patterns.js +0 -77
- package/dist/utils/examples/utility-patterns.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../src/features/definitions/routing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,KAAK;IACf,
|
|
1
|
+
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../src/features/definitions/routing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE;QACL,oBAAoB;QACpB,wBAAwB;QACxB,oBAAoB;QACpB,+BAA+B;QAC/B,uCAAuC;KACxC;IACD,SAAS,EAAE,CAAC,8BAA8B,CAAC;IAC3C,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,KAAK,EAAE,OAcnB,CAAC"}
|
|
@@ -2,17 +2,7 @@ export const state = {
|
|
|
2
2
|
name: 'State Management',
|
|
3
3
|
description: 'Zustand with persistence, devtools, and multi-tab sync',
|
|
4
4
|
required: false,
|
|
5
|
-
|
|
6
|
-
'Zustand store',
|
|
7
|
-
'Persist middleware (localStorage)',
|
|
8
|
-
'Devtools middleware',
|
|
9
|
-
'Multi-tab sync utility (initPreferencesSync)',
|
|
10
|
-
'Storage utilities (get/set/remove/clear)',
|
|
11
|
-
'Prefixed storage keys',
|
|
12
|
-
'Example preferences store (theme)',
|
|
13
|
-
'Type-safe store selectors',
|
|
14
|
-
],
|
|
15
|
-
dependencyNames: ['zustand'],
|
|
5
|
+
dependencies: ['zustand'],
|
|
16
6
|
files: [
|
|
17
7
|
'src/stores/preferencesStore.ts',
|
|
18
8
|
'src/stores/index.ts',
|
|
@@ -21,7 +11,6 @@ export const state = {
|
|
|
21
11
|
'src/types/preferences.ts',
|
|
22
12
|
],
|
|
23
13
|
testFiles: ['src/lib/storage.test.ts', 'src/stores/preferencesStore.test.ts'],
|
|
24
|
-
patterns: ['zustand-store', 'store-persistence', 'multi-tab-sync', 'storage-utility'],
|
|
25
14
|
scripts: {},
|
|
26
15
|
};
|
|
27
16
|
//# sourceMappingURL=state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAY;IAC5B,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,wDAAwD;IACrE,QAAQ,EAAE,KAAK;IACf,
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAY;IAC5B,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,wDAAwD;IACrE,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,SAAS,CAAC;IACzB,KAAK,EAAE;QACL,gCAAgC;QAChC,qBAAqB;QACrB,oBAAoB;QACpB,wBAAwB;QACxB,0BAA0B;KAC3B;IACD,SAAS,EAAE,CAAC,yBAAyB,EAAE,qCAAqC,CAAC;IAC7E,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,OAsCrB,CAAC"}
|
|
@@ -2,20 +2,7 @@ export const testing = {
|
|
|
2
2
|
name: 'Testing',
|
|
3
3
|
description: 'Vitest + Testing Library + Playwright + MSW',
|
|
4
4
|
required: false,
|
|
5
|
-
|
|
6
|
-
'Vitest for unit testing',
|
|
7
|
-
'React Testing Library',
|
|
8
|
-
'@testing-library/user-event for interactions',
|
|
9
|
-
'Playwright for E2E testing (Chromium)',
|
|
10
|
-
'MSW (Mock Service Worker) for API mocking',
|
|
11
|
-
'Test utilities (render, providers, mocks)',
|
|
12
|
-
'80% coverage threshold (lines, functions, statements, branches)',
|
|
13
|
-
'jsdom environment',
|
|
14
|
-
'Example tests for components, hooks, stores, utilities',
|
|
15
|
-
'MSW handlers for API endpoints',
|
|
16
|
-
'Test fixtures for mock data',
|
|
17
|
-
],
|
|
18
|
-
devDependencyNames: [
|
|
5
|
+
devDependencies: [
|
|
19
6
|
'@playwright/test',
|
|
20
7
|
'@testing-library/jest-dom',
|
|
21
8
|
'@testing-library/react',
|
|
@@ -40,10 +27,7 @@ export const testing = {
|
|
|
40
27
|
'e2e/tests/',
|
|
41
28
|
'vitest.config.ts',
|
|
42
29
|
'playwright.config.ts',
|
|
43
|
-
'docs/TESTING.md',
|
|
44
|
-
'docs/E2E_TESTING.md',
|
|
45
30
|
],
|
|
46
|
-
patterns: ['test-component', 'test-hook', 'test-store', 'test-utility', 'msw-handler', 'test-fixture'],
|
|
47
31
|
scripts: {
|
|
48
32
|
test: 'vitest run',
|
|
49
33
|
'test:watch': 'vitest',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,6CAA6C;IAC1D,QAAQ,EAAE,KAAK;IACf,
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,6CAA6C;IAC1D,QAAQ,EAAE,KAAK;IACf,eAAe,EAAE;QACf,kBAAkB;QAClB,2BAA2B;QAC3B,wBAAwB;QACxB,6BAA6B;QAC7B,qBAAqB;QACrB,OAAO;QACP,KAAK;QACL,QAAQ;KACT;IACD,KAAK,EAAE;QACL,mBAAmB;QACnB,mBAAmB;QACnB,wBAAwB;QACxB,mBAAmB;QACnB,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,mBAAmB;QACnB,oBAAoB;QACpB,eAAe;QACf,YAAY;QACZ,kBAAkB;QAClB,sBAAsB;KACvB;IACD,OAAO,EAAE;QACP,IAAI,EAAE,YAAY;QAClB,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,uBAAuB;QACxC,GAAG,EAAE,sCAAsC;QAC3C,QAAQ,EAAE,2CAA2C;KACtD;IACD,WAAW,EAAE,CAAC,kBAAkB,EAAE,sBAAsB,EAAE,mBAAmB,CAAC;CAC/E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theming.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/theming.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"theming.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/theming.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,OAgBrB,CAAC"}
|
|
@@ -3,14 +3,6 @@ export const theming = {
|
|
|
3
3
|
description: 'Light/dark/system theme toggle with CSS variables',
|
|
4
4
|
required: false,
|
|
5
5
|
requires: ['state'], // Needs Zustand for persistence
|
|
6
|
-
includes: [
|
|
7
|
-
'Light/dark/system theme modes',
|
|
8
|
-
'useThemeEffect hook (applies .dark class to document)',
|
|
9
|
-
'ThemeToggle component',
|
|
10
|
-
'System preference detection (prefers-color-scheme)',
|
|
11
|
-
'Zustand persistence via preferencesStore',
|
|
12
|
-
'Multi-tab sync via storage events',
|
|
13
|
-
],
|
|
14
6
|
files: [
|
|
15
7
|
'src/hooks/useThemeEffect.ts',
|
|
16
8
|
'src/components/shared/ThemeToggle/ThemeToggle.tsx',
|
|
@@ -21,7 +13,6 @@ export const theming = {
|
|
|
21
13
|
'src/components/shared/ThemeToggle/ThemeToggle.test.tsx',
|
|
22
14
|
'e2e/tests/theme.spec.ts',
|
|
23
15
|
],
|
|
24
|
-
patterns: ['theme-toggle', 'hook-effect'],
|
|
25
16
|
scripts: {},
|
|
26
17
|
};
|
|
27
18
|
//# sourceMappingURL=theming.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theming.js","sourceRoot":"","sources":["../../../src/features/definitions/theming.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,mDAAmD;IAChE,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,gCAAgC;IACrD,
|
|
1
|
+
{"version":3,"file":"theming.js","sourceRoot":"","sources":["../../../src/features/definitions/theming.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,mDAAmD;IAChE,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,gCAAgC;IACrD,KAAK,EAAE;QACL,6BAA6B;QAC7B,mDAAmD;QACnD,4CAA4C;KAC7C;IACD,SAAS,EAAE;QACT,kCAAkC;QAClC,wDAAwD;QACxD,yBAAyB;KAC1B;IACD,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,EAAE,EAAE,OA4BhB,CAAC"}
|
|
@@ -2,20 +2,7 @@ export const ui = {
|
|
|
2
2
|
name: 'UI Components',
|
|
3
3
|
description: 'Shadcn/UI + icons + animations + toasts',
|
|
4
4
|
required: false,
|
|
5
|
-
|
|
6
|
-
'Shadcn/UI component system (radix-nova style)',
|
|
7
|
-
'Radix UI primitives',
|
|
8
|
-
'CVA (class-variance-authority) for variants',
|
|
9
|
-
'Lucide React icons',
|
|
10
|
-
'tw-animate-css for animations',
|
|
11
|
-
'Sonner toast notifications',
|
|
12
|
-
'Button with variants (default, destructive, outline, etc.)',
|
|
13
|
-
'DropdownMenu component',
|
|
14
|
-
'Loading, Skeleton, Spinner components',
|
|
15
|
-
'VisuallyHidden and SkipLink (accessibility)',
|
|
16
|
-
'components.json for shadcn CLI',
|
|
17
|
-
],
|
|
18
|
-
dependencyNames: [
|
|
5
|
+
dependencies: [
|
|
19
6
|
'@radix-ui/react-slot',
|
|
20
7
|
'class-variance-authority',
|
|
21
8
|
'lucide-react',
|
|
@@ -23,7 +10,7 @@ export const ui = {
|
|
|
23
10
|
'sonner',
|
|
24
11
|
'tw-animate-css',
|
|
25
12
|
],
|
|
26
|
-
|
|
13
|
+
devDependencies: ['shadcn'],
|
|
27
14
|
files: [
|
|
28
15
|
'src/components/ui/button.tsx',
|
|
29
16
|
'src/components/ui/dropdown-menu.tsx',
|
|
@@ -37,7 +24,6 @@ export const ui = {
|
|
|
37
24
|
'components.json',
|
|
38
25
|
],
|
|
39
26
|
testFiles: ['src/components/ui/loading.test.tsx', 'src/components/layout/Header.test.tsx'],
|
|
40
|
-
patterns: ['component-ui', 'button-variants', 'forward-ref-component'],
|
|
41
27
|
scripts: {},
|
|
42
28
|
configFiles: ['components.json'],
|
|
43
29
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/features/definitions/ui.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,EAAE,GAAY;IACzB,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,yCAAyC;IACtD,QAAQ,EAAE,KAAK;IACf,
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/features/definitions/ui.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,EAAE,GAAY;IACzB,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,yCAAyC;IACtD,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE;QACZ,sBAAsB;QACtB,0BAA0B;QAC1B,cAAc;QACd,UAAU;QACV,QAAQ;QACR,gBAAgB;KACjB;IACD,eAAe,EAAE,CAAC,QAAQ,CAAC;IAC3B,KAAK,EAAE;QACL,8BAA8B;QAC9B,qCAAqC;QACrC,+BAA+B;QAC/B,gCAAgC;QAChC,+BAA+B;QAC/B,8BAA8B;QAC9B,uCAAuC;QACvC,kCAAkC;QAClC,gCAAgC;QAChC,iBAAiB;KAClB;IACD,SAAS,EAAE,CAAC,oCAAoC,EAAE,uCAAuC,CAAC;IAC1F,OAAO,EAAE,EAAE;IACX,WAAW,EAAE,CAAC,iBAAiB,CAAC;CACjC,CAAC"}
|
package/dist/features/types.d.ts
CHANGED
|
@@ -12,16 +12,14 @@ export interface Feature {
|
|
|
12
12
|
name: string;
|
|
13
13
|
description: string;
|
|
14
14
|
required: boolean;
|
|
15
|
-
includes: string[];
|
|
16
15
|
/** Other features this feature depends on (auto-included when this feature is selected). */
|
|
17
16
|
requires?: FeatureId[];
|
|
18
17
|
/** Dependency package names - versions resolved from package.json at runtime. */
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
dependencies?: string[];
|
|
19
|
+
devDependencies?: string[];
|
|
21
20
|
files: string[];
|
|
22
21
|
/** Test files - only included when 'testing' feature is also selected. */
|
|
23
22
|
testFiles?: string[];
|
|
24
|
-
patterns: string[];
|
|
25
23
|
scripts?: Record<string, string>;
|
|
26
24
|
configFiles?: string[];
|
|
27
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/features/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,oFAAoF;AACpF,eAAO,MAAM,WAAW,EAA6B,SAAS,SAAS,EAAE,CAAC;AAE1E,oCAAoC;AACpC,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;AAE/D,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE7D;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/features/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,oFAAoF;AACpF,eAAO,MAAM,WAAW,EAA6B,SAAS,SAAS,EAAE,CAAC;AAE1E,oCAAoC;AACpC,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;AAE/D,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE7D;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,8DAA8D;AAC9D,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjC,CAAC;IACF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB"}
|
package/dist/server.js
CHANGED
|
@@ -22,16 +22,16 @@ const SERVER_INSTRUCTIONS = `
|
|
|
22
22
|
react-spa-scaffold MCP Server - Project Scaffolding Assistant
|
|
23
23
|
|
|
24
24
|
Usage:
|
|
25
|
-
1.
|
|
26
|
-
2.
|
|
27
|
-
3.
|
|
28
|
-
|
|
25
|
+
1. get_features - list available feature modules
|
|
26
|
+
2. get_scaffold - get project structure (paths only)
|
|
27
|
+
3. get_file - fetch content for EACH file
|
|
28
|
+
|
|
29
|
+
CRITICAL: Do not generate files. Fetch via get_file, then strip unselected features.
|
|
29
30
|
|
|
30
31
|
Tips:
|
|
31
32
|
- Core feature is always included automatically
|
|
32
|
-
- Features are mostly independent - select only what you need
|
|
33
33
|
- Theming feature automatically includes state (requires Zustand)
|
|
34
|
-
-
|
|
34
|
+
- Read docs:// resources for conventions and best practices
|
|
35
35
|
`.trim();
|
|
36
36
|
/** Creates and configures the MCP server. */
|
|
37
37
|
export function createServer() {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* add_features tool
|
|
3
|
+
*
|
|
4
|
+
* Get files and dependencies for adding features to an existing project.
|
|
5
|
+
* Unlike get_scaffold, this tool does NOT auto-include the `core` feature,
|
|
6
|
+
* as it assumes the project already has core scaffolded.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import type { FeatureId } from '../features/types.js';
|
|
10
|
+
import type { ToolDefinition } from './types.js';
|
|
11
|
+
/** Zod schema for add_features input */
|
|
12
|
+
export declare const addFeaturesSchema: z.ZodObject<{
|
|
13
|
+
features: z.ZodArray<z.ZodString>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type AddFeaturesInput = z.infer<typeof addFeaturesSchema>;
|
|
16
|
+
/** Handler function */
|
|
17
|
+
export declare function addFeatures(input: AddFeaturesInput): Promise<{
|
|
18
|
+
selectedFeatures: string[];
|
|
19
|
+
resolvedFeatures: FeatureId[];
|
|
20
|
+
featureDetails: {
|
|
21
|
+
id: FeatureId;
|
|
22
|
+
name: string;
|
|
23
|
+
description: string;
|
|
24
|
+
wasExplicitlySelected: boolean;
|
|
25
|
+
wasAutoIncluded: boolean;
|
|
26
|
+
}[];
|
|
27
|
+
dependencies: Record<string, string>;
|
|
28
|
+
devDependencies: Record<string, string>;
|
|
29
|
+
scripts: Record<string, string>;
|
|
30
|
+
files: string[];
|
|
31
|
+
testFiles: string[];
|
|
32
|
+
configFiles: string[];
|
|
33
|
+
docs: string[];
|
|
34
|
+
regenerated: {
|
|
35
|
+
routesTs?: string;
|
|
36
|
+
envTs?: string;
|
|
37
|
+
viteEnvDts?: string;
|
|
38
|
+
};
|
|
39
|
+
warnings: string[];
|
|
40
|
+
instructions: string;
|
|
41
|
+
}>;
|
|
42
|
+
/** Tool definition */
|
|
43
|
+
export declare const addFeaturesToolDefinition: ToolDefinition;
|
|
44
|
+
//# sourceMappingURL=add-features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-features.d.ts","sourceRoot":"","sources":["../../src/tools/add-features.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAUtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wCAAwC;AACxC,eAAO,MAAM,iBAAiB;;iBAiB5B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEjE,uBAAuB;AACvB,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB;;;;;;;;;;;;;;;;;;mBAwB1C,MAAM;gBACT,MAAM;qBACD,MAAM;;;;GAyDtB;AA8BD,sBAAsB;AACtB,eAAO,MAAM,yBAAyB,EAAE,cAmCvC,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* add_features tool
|
|
3
|
+
*
|
|
4
|
+
* Get files and dependencies for adding features to an existing project.
|
|
5
|
+
* Unlike get_scaffold, this tool does NOT auto-include the `core` feature,
|
|
6
|
+
* as it assumes the project already has core scaffolded.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { FEATURE_IDS, FEATURES } from '../features/index.js';
|
|
10
|
+
import { computeDocsForFeatures } from '../utils/docs.js';
|
|
11
|
+
import { collectFeatureFiles, getConfigFiles, mergeDependencies, mergeScripts, resolveFeatureDependencies, } from '../utils/scaffold/index.js';
|
|
12
|
+
import { generateEnvTs, generateRoutesTs, generateViteEnvDts } from '../utils/scaffold/generators.js';
|
|
13
|
+
/** Zod schema for add_features input */
|
|
14
|
+
export const addFeaturesSchema = z.object({
|
|
15
|
+
features: z
|
|
16
|
+
.array(z.string())
|
|
17
|
+
.min(1, 'At least one feature required')
|
|
18
|
+
.max(15, 'Maximum 15 features allowed')
|
|
19
|
+
.check((ctx) => {
|
|
20
|
+
const invalidFeatures = ctx.value.filter((f) => !(f in FEATURES));
|
|
21
|
+
if (invalidFeatures.length > 0) {
|
|
22
|
+
ctx.issues.push({
|
|
23
|
+
code: 'custom',
|
|
24
|
+
message: `Invalid features: ${invalidFeatures.join(', ')}. Valid: ${FEATURE_IDS.join(', ')}`,
|
|
25
|
+
input: ctx.value,
|
|
26
|
+
path: [],
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
.describe('List of feature IDs to add (e.g., ["routing", "state", "forms"])'),
|
|
31
|
+
});
|
|
32
|
+
/** Handler function */
|
|
33
|
+
export async function addFeatures(input) {
|
|
34
|
+
const { features } = input;
|
|
35
|
+
// 1. Resolve feature dependencies WITHOUT auto-including core
|
|
36
|
+
// (existing projects already have core scaffolded)
|
|
37
|
+
const resolvedFeatureIds = resolveFeatureDependencies(features, { includeCore: false });
|
|
38
|
+
// 2. Merge dependencies from all features
|
|
39
|
+
const { dependencies, devDependencies, warnings } = await mergeDependencies(resolvedFeatureIds);
|
|
40
|
+
// 3. Merge scripts
|
|
41
|
+
const scripts = mergeScripts(resolvedFeatureIds);
|
|
42
|
+
// 4. Collect file paths from all features
|
|
43
|
+
const { files, testFiles } = collectFeatureFiles(resolvedFeatureIds);
|
|
44
|
+
// 5. Get config files that may need updates
|
|
45
|
+
const configFiles = getConfigFiles(resolvedFeatureIds);
|
|
46
|
+
// 6. Get relevant documentation
|
|
47
|
+
const docs = computeDocsForFeatures(resolvedFeatureIds);
|
|
48
|
+
// 7. Generate code if routing/api/observability included
|
|
49
|
+
const regenerated = {};
|
|
50
|
+
if (resolvedFeatureIds.includes('routing')) {
|
|
51
|
+
regenerated.routesTs = generateRoutesTs();
|
|
52
|
+
}
|
|
53
|
+
// Always generate env files if api or observability is added
|
|
54
|
+
if (resolvedFeatureIds.includes('api') || resolvedFeatureIds.includes('observability')) {
|
|
55
|
+
regenerated.envTs = generateEnvTs(resolvedFeatureIds);
|
|
56
|
+
regenerated.viteEnvDts = generateViteEnvDts(resolvedFeatureIds);
|
|
57
|
+
}
|
|
58
|
+
// 8. Build feature details
|
|
59
|
+
const featureDetails = resolvedFeatureIds.map((id) => {
|
|
60
|
+
const feature = FEATURES[id];
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
name: feature.name,
|
|
64
|
+
description: feature.description,
|
|
65
|
+
wasExplicitlySelected: features.includes(id),
|
|
66
|
+
wasAutoIncluded: !features.includes(id),
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
// Selected and resolved features
|
|
71
|
+
selectedFeatures: features,
|
|
72
|
+
resolvedFeatures: resolvedFeatureIds,
|
|
73
|
+
featureDetails,
|
|
74
|
+
// Dependencies to install
|
|
75
|
+
dependencies,
|
|
76
|
+
devDependencies,
|
|
77
|
+
// Scripts to add to package.json
|
|
78
|
+
scripts,
|
|
79
|
+
// Files to create (fetch via get_file)
|
|
80
|
+
files,
|
|
81
|
+
testFiles,
|
|
82
|
+
// Config files that may need updates
|
|
83
|
+
configFiles,
|
|
84
|
+
// Documentation files (fetch via get_file)
|
|
85
|
+
docs,
|
|
86
|
+
// Generated code (write directly, no need for get_file)
|
|
87
|
+
regenerated,
|
|
88
|
+
// Warnings (e.g., missing deps in source package.json)
|
|
89
|
+
warnings,
|
|
90
|
+
// Usage instructions
|
|
91
|
+
instructions: generateInstructions(resolvedFeatureIds),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function generateInstructions(features) {
|
|
95
|
+
const hasRouting = features.includes('routing');
|
|
96
|
+
const hasEnvChanges = features.includes('api') || features.includes('observability');
|
|
97
|
+
return `## Integration Instructions
|
|
98
|
+
|
|
99
|
+
1. Install dependencies:
|
|
100
|
+
\`npm install <dependencies>\`
|
|
101
|
+
\`npm install -D <devDependencies>\`
|
|
102
|
+
|
|
103
|
+
2. Add scripts to package.json
|
|
104
|
+
|
|
105
|
+
3. Write generated content (if any):${hasRouting ? '\n - `src/lib/routes.ts` ← from `regenerated.routesTs`' : ''}${hasEnvChanges ? '\n - `src/lib/env.ts` ← from `regenerated.envTs`\n - `src/vite-env.d.ts` ← from `regenerated.viteEnvDts`' : ''}
|
|
106
|
+
|
|
107
|
+
4. For EACH file in \`files\` and \`testFiles\`:
|
|
108
|
+
- Fetch content via \`get_file({ path: "..." })\`
|
|
109
|
+
- Create file in project
|
|
110
|
+
- Integrate with existing code as needed
|
|
111
|
+
|
|
112
|
+
5. Review and update config files:
|
|
113
|
+
- Check each file in \`configFiles\`
|
|
114
|
+
- Merge any feature-specific configurations
|
|
115
|
+
|
|
116
|
+
6. Update existing files to use new features:
|
|
117
|
+
- Import and use new stores/hooks/components
|
|
118
|
+
- Add providers to App.tsx if needed`;
|
|
119
|
+
}
|
|
120
|
+
/** Tool definition */
|
|
121
|
+
export const addFeaturesToolDefinition = {
|
|
122
|
+
name: 'add_features',
|
|
123
|
+
description: `Get files and dependencies for adding features to an existing project.
|
|
124
|
+
|
|
125
|
+
Returns metadata for incrementally adding features without scaffolding entire project.
|
|
126
|
+
Does NOT auto-include \`core\` feature (assumes project already has core).
|
|
127
|
+
|
|
128
|
+
**Returns:**
|
|
129
|
+
- \`resolvedFeatures\`: Features including auto-resolved dependencies
|
|
130
|
+
- \`featureDetails\`: Details with wasExplicitlySelected/wasAutoIncluded flags
|
|
131
|
+
- \`dependencies\`: npm packages to install (production)
|
|
132
|
+
- \`devDependencies\`: npm packages to install (dev)
|
|
133
|
+
- \`scripts\`: npm scripts to add
|
|
134
|
+
- \`files\`: Source files to create (fetch via get_file)
|
|
135
|
+
- \`testFiles\`: Test files to create (fetch via get_file)
|
|
136
|
+
- \`configFiles\`: Config files that may need updates
|
|
137
|
+
- \`docs\`: Documentation files (fetch via get_file)
|
|
138
|
+
- \`regenerated\`: Generated code (routesTs, envTs, viteEnvDts)
|
|
139
|
+
- \`warnings\`: Any issues encountered
|
|
140
|
+
- \`instructions\`: Integration guidance
|
|
141
|
+
|
|
142
|
+
**Feature Dependencies:**
|
|
143
|
+
- theming → state (auto-included)
|
|
144
|
+
|
|
145
|
+
**Usage Pattern:**
|
|
146
|
+
1. Call add_features with feature list
|
|
147
|
+
2. Install dependencies
|
|
148
|
+
3. Add scripts to package.json
|
|
149
|
+
4. Write generated content from \`regenerated\`
|
|
150
|
+
5. Fetch each file via \`get_file({ path: "..." })\`
|
|
151
|
+
6. Integrate files into existing project
|
|
152
|
+
7. Update config files as needed
|
|
153
|
+
|
|
154
|
+
**Example:** features: ["theming"] → resolvedFeatures: ["theming", "state"]`,
|
|
155
|
+
inputSchema: z.toJSONSchema(addFeaturesSchema),
|
|
156
|
+
};
|
|
157
|
+
//# sourceMappingURL=add-features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-features.js","sourceRoot":"","sources":["../../src/tools/add-features.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-features.test.d.ts","sourceRoot":"","sources":["../../src/tools/add-features.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for add_features tool
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { addFeatures, addFeaturesSchema } from './add-features.js';
|
|
6
|
+
describe('add_features tool', () => {
|
|
7
|
+
describe('schema validation', () => {
|
|
8
|
+
it('requires at least one feature', () => {
|
|
9
|
+
const result = addFeaturesSchema.safeParse({ features: [] });
|
|
10
|
+
expect(result.success).toBe(false);
|
|
11
|
+
if (!result.success) {
|
|
12
|
+
expect(result.error.message).toContain('At least one feature required');
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
it('rejects invalid features via schema', () => {
|
|
16
|
+
const result = addFeaturesSchema.safeParse({
|
|
17
|
+
features: ['invalid-feature'],
|
|
18
|
+
});
|
|
19
|
+
expect(result.success).toBe(false);
|
|
20
|
+
if (!result.success) {
|
|
21
|
+
expect(result.error.message).toContain('Invalid features');
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
it('accepts valid features', () => {
|
|
25
|
+
const result = addFeaturesSchema.safeParse({
|
|
26
|
+
features: ['state', 'routing'],
|
|
27
|
+
});
|
|
28
|
+
expect(result.success).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
it('rejects more than 15 features', () => {
|
|
31
|
+
const result = addFeaturesSchema.safeParse({
|
|
32
|
+
features: Array(16).fill('state'),
|
|
33
|
+
});
|
|
34
|
+
expect(result.success).toBe(false);
|
|
35
|
+
if (!result.success) {
|
|
36
|
+
expect(result.error.message).toContain('Maximum 15 features');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe('feature resolution', () => {
|
|
41
|
+
it('does NOT auto-include core feature', async () => {
|
|
42
|
+
const result = await addFeatures({ features: ['state'] });
|
|
43
|
+
expect(result.resolvedFeatures).not.toContain('core');
|
|
44
|
+
expect(result.resolvedFeatures).toContain('state');
|
|
45
|
+
});
|
|
46
|
+
it('auto-includes feature dependencies (theming → state)', async () => {
|
|
47
|
+
const result = await addFeatures({ features: ['theming'] });
|
|
48
|
+
expect(result.resolvedFeatures).toContain('theming');
|
|
49
|
+
expect(result.resolvedFeatures).toContain('state');
|
|
50
|
+
expect(result.resolvedFeatures).not.toContain('core');
|
|
51
|
+
});
|
|
52
|
+
it('marks auto-included features correctly', async () => {
|
|
53
|
+
const result = await addFeatures({ features: ['theming'] });
|
|
54
|
+
const themingDetail = result.featureDetails.find((f) => f.id === 'theming');
|
|
55
|
+
const stateDetail = result.featureDetails.find((f) => f.id === 'state');
|
|
56
|
+
// Theming was explicitly selected
|
|
57
|
+
expect(themingDetail?.wasExplicitlySelected).toBe(true);
|
|
58
|
+
expect(themingDetail?.wasAutoIncluded).toBe(false);
|
|
59
|
+
// State was auto-included (dependency of theming)
|
|
60
|
+
expect(stateDetail?.wasExplicitlySelected).toBe(false);
|
|
61
|
+
expect(stateDetail?.wasAutoIncluded).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('returns only selected features when no dependencies', async () => {
|
|
64
|
+
const result = await addFeatures({ features: ['ui'] });
|
|
65
|
+
expect(result.resolvedFeatures).toEqual(['ui']);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('dependencies', () => {
|
|
69
|
+
it('returns dependencies for selected features', async () => {
|
|
70
|
+
const result = await addFeatures({ features: ['state'] });
|
|
71
|
+
expect(result.dependencies).toHaveProperty('zustand');
|
|
72
|
+
});
|
|
73
|
+
it('returns routing dependencies when routing selected', async () => {
|
|
74
|
+
const result = await addFeatures({ features: ['routing'] });
|
|
75
|
+
expect(result.dependencies).toHaveProperty('react-router');
|
|
76
|
+
});
|
|
77
|
+
it('does NOT include core dependencies', async () => {
|
|
78
|
+
const result = await addFeatures({ features: ['state'] });
|
|
79
|
+
// Core deps like react/react-dom should not be included
|
|
80
|
+
expect(result.dependencies).not.toHaveProperty('react');
|
|
81
|
+
expect(result.dependencies).not.toHaveProperty('react-dom');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('files', () => {
|
|
85
|
+
it('returns files for selected features', async () => {
|
|
86
|
+
const result = await addFeatures({ features: ['state'] });
|
|
87
|
+
expect(result.files).toContain('src/stores/preferencesStore.ts');
|
|
88
|
+
expect(result.files).toContain('src/stores/index.ts');
|
|
89
|
+
});
|
|
90
|
+
it('returns testFiles for selected features', async () => {
|
|
91
|
+
const result = await addFeatures({ features: ['state'] });
|
|
92
|
+
expect(result.testFiles).toContain('src/stores/preferencesStore.test.ts');
|
|
93
|
+
});
|
|
94
|
+
it('includes files from auto-included dependencies', async () => {
|
|
95
|
+
const result = await addFeatures({ features: ['theming'] });
|
|
96
|
+
// Theming files
|
|
97
|
+
expect(result.files).toContain('src/hooks/useThemeEffect.ts');
|
|
98
|
+
// State files (auto-included dependency)
|
|
99
|
+
expect(result.files).toContain('src/stores/preferencesStore.ts');
|
|
100
|
+
});
|
|
101
|
+
it('returns configFiles that may need updates', async () => {
|
|
102
|
+
// Use 'ui' feature which has configFiles defined (components.json)
|
|
103
|
+
const result = await addFeatures({ features: ['ui'] });
|
|
104
|
+
expect(Array.isArray(result.configFiles)).toBe(true);
|
|
105
|
+
expect(result.configFiles).toContain('components.json');
|
|
106
|
+
});
|
|
107
|
+
it('returns empty configFiles when feature has none', async () => {
|
|
108
|
+
// 'state' feature has no configFiles
|
|
109
|
+
const result = await addFeatures({ features: ['state'] });
|
|
110
|
+
expect(Array.isArray(result.configFiles)).toBe(true);
|
|
111
|
+
expect(result.configFiles.length).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('docs', () => {
|
|
115
|
+
it('returns relevant documentation files', async () => {
|
|
116
|
+
const result = await addFeatures({ features: ['testing'] });
|
|
117
|
+
expect(result.docs).toContain('docs/TESTING.md');
|
|
118
|
+
});
|
|
119
|
+
it('includes universal docs', async () => {
|
|
120
|
+
const result = await addFeatures({ features: ['state'] });
|
|
121
|
+
expect(result.docs).toContain('docs/ARCHITECTURE.md');
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
describe('regenerated content', () => {
|
|
125
|
+
it('generates routesTs when routing is selected', async () => {
|
|
126
|
+
const result = await addFeatures({ features: ['routing'] });
|
|
127
|
+
expect(result.regenerated.routesTs).toBeDefined();
|
|
128
|
+
expect(result.regenerated.routesTs).toContain('ROUTES');
|
|
129
|
+
});
|
|
130
|
+
it('does NOT generate routesTs when routing is not selected', async () => {
|
|
131
|
+
const result = await addFeatures({ features: ['state'] });
|
|
132
|
+
expect(result.regenerated.routesTs).toBeUndefined();
|
|
133
|
+
});
|
|
134
|
+
it('generates envTs when api is selected', async () => {
|
|
135
|
+
const result = await addFeatures({ features: ['api'] });
|
|
136
|
+
expect(result.regenerated.envTs).toBeDefined();
|
|
137
|
+
expect(result.regenerated.viteEnvDts).toBeDefined();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('instructions', () => {
|
|
141
|
+
it('returns integration instructions', async () => {
|
|
142
|
+
const result = await addFeatures({ features: ['state'] });
|
|
143
|
+
expect(result.instructions).toContain('Integration Instructions');
|
|
144
|
+
expect(result.instructions).toContain('npm install');
|
|
145
|
+
expect(result.instructions).toContain('get_file');
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe('difference from get_scaffold', () => {
|
|
149
|
+
it('does NOT include core feature or its files', async () => {
|
|
150
|
+
const result = await addFeatures({ features: ['ui'] });
|
|
151
|
+
// Core files should NOT be included
|
|
152
|
+
expect(result.files).not.toContain('src/App.tsx');
|
|
153
|
+
expect(result.files).not.toContain('src/main.tsx');
|
|
154
|
+
// Only UI files
|
|
155
|
+
expect(result.resolvedFeatures).toEqual(['ui']);
|
|
156
|
+
});
|
|
157
|
+
it('does NOT include package.json template', async () => {
|
|
158
|
+
const result = await addFeatures({ features: ['state'] });
|
|
159
|
+
// Should NOT have full packageJson, just deps
|
|
160
|
+
expect(result).not.toHaveProperty('packageJson');
|
|
161
|
+
expect(result).toHaveProperty('dependencies');
|
|
162
|
+
expect(result).toHaveProperty('devDependencies');
|
|
163
|
+
});
|
|
164
|
+
it('does NOT include claudeMd', async () => {
|
|
165
|
+
const result = await addFeatures({ features: ['state'] });
|
|
166
|
+
expect(result).not.toHaveProperty('claudeMd');
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=add-features.test.js.map
|