@react-spa-scaffold/mcp 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/constants.d.ts +35 -0
  2. package/dist/constants.d.ts.map +1 -0
  3. package/dist/constants.js +35 -0
  4. package/dist/constants.js.map +1 -0
  5. package/dist/features/definitions/theming.d.ts.map +1 -1
  6. package/dist/features/definitions/theming.js +2 -1
  7. package/dist/features/definitions/theming.js.map +1 -1
  8. package/dist/features/types.d.ts +14 -19
  9. package/dist/features/types.d.ts.map +1 -1
  10. package/dist/features/types.js +4 -21
  11. package/dist/features/types.js.map +1 -1
  12. package/dist/features/types.test.d.ts +5 -0
  13. package/dist/features/types.test.d.ts.map +1 -0
  14. package/dist/features/types.test.js +32 -0
  15. package/dist/features/types.test.js.map +1 -0
  16. package/dist/resources/docs.d.ts +2 -8
  17. package/dist/resources/docs.d.ts.map +1 -1
  18. package/dist/resources/docs.js +27 -49
  19. package/dist/resources/docs.js.map +1 -1
  20. package/dist/server.d.ts.map +1 -1
  21. package/dist/server.js +3 -2
  22. package/dist/server.js.map +1 -1
  23. package/dist/tools/get-example.d.ts +4 -15
  24. package/dist/tools/get-example.d.ts.map +1 -1
  25. package/dist/tools/get-example.js +3 -11
  26. package/dist/tools/get-example.js.map +1 -1
  27. package/dist/tools/get-features.d.ts +15 -9
  28. package/dist/tools/get-features.d.ts.map +1 -1
  29. package/dist/tools/get-features.js +12 -0
  30. package/dist/tools/get-features.js.map +1 -1
  31. package/dist/tools/get-file.d.ts +23 -0
  32. package/dist/tools/get-file.d.ts.map +1 -0
  33. package/dist/tools/get-file.js +53 -0
  34. package/dist/tools/get-file.js.map +1 -0
  35. package/dist/tools/get-file.test.d.ts +5 -0
  36. package/dist/tools/get-file.test.d.ts.map +1 -0
  37. package/dist/tools/get-file.test.js +63 -0
  38. package/dist/tools/get-file.test.js.map +1 -0
  39. package/dist/tools/get-scaffold.d.ts +8 -29
  40. package/dist/tools/get-scaffold.d.ts.map +1 -1
  41. package/dist/tools/get-scaffold.js +18 -24
  42. package/dist/tools/get-scaffold.js.map +1 -1
  43. package/dist/tools/get-scaffold.test.js +19 -16
  44. package/dist/tools/get-scaffold.test.js.map +1 -1
  45. package/dist/tools/index.d.ts +1 -1
  46. package/dist/tools/index.d.ts.map +1 -1
  47. package/dist/tools/registry.d.ts +4 -0
  48. package/dist/tools/registry.d.ts.map +1 -1
  49. package/dist/tools/registry.js +33 -15
  50. package/dist/tools/registry.js.map +1 -1
  51. package/dist/tools/types.d.ts +24 -6
  52. package/dist/tools/types.d.ts.map +1 -1
  53. package/dist/tools/types.js +3 -0
  54. package/dist/tools/types.js.map +1 -1
  55. package/dist/utils/cache.d.ts +9 -5
  56. package/dist/utils/cache.d.ts.map +1 -1
  57. package/dist/utils/cache.js +21 -5
  58. package/dist/utils/cache.js.map +1 -1
  59. package/dist/utils/docs.d.ts +1 -3
  60. package/dist/utils/docs.d.ts.map +1 -1
  61. package/dist/utils/docs.js +3 -8
  62. package/dist/utils/docs.js.map +1 -1
  63. package/dist/utils/examples/index.d.ts +1 -1
  64. package/dist/utils/examples/index.d.ts.map +1 -1
  65. package/dist/utils/examples/index.js +6 -10
  66. package/dist/utils/examples/index.js.map +1 -1
  67. package/dist/utils/examples/patterns.test.d.ts +6 -0
  68. package/dist/utils/examples/patterns.test.d.ts.map +1 -0
  69. package/dist/utils/examples/patterns.test.js +75 -0
  70. package/dist/utils/examples/patterns.test.js.map +1 -0
  71. package/dist/utils/paths.d.ts +9 -0
  72. package/dist/utils/paths.d.ts.map +1 -1
  73. package/dist/utils/paths.js +19 -1
  74. package/dist/utils/paths.js.map +1 -1
  75. package/dist/utils/paths.test.js +22 -1
  76. package/dist/utils/paths.test.js.map +1 -1
  77. package/dist/utils/scaffold/claude-md/index.d.ts +7 -0
  78. package/dist/utils/scaffold/claude-md/index.d.ts.map +1 -0
  79. package/dist/utils/scaffold/claude-md/index.js +23 -0
  80. package/dist/utils/scaffold/claude-md/index.js.map +1 -0
  81. package/dist/utils/scaffold/claude-md/sections.d.ts +16 -0
  82. package/dist/utils/scaffold/claude-md/sections.d.ts.map +1 -0
  83. package/dist/utils/scaffold/claude-md/sections.js +269 -0
  84. package/dist/utils/scaffold/claude-md/sections.js.map +1 -0
  85. package/dist/utils/scaffold/commands.d.ts +2 -6
  86. package/dist/utils/scaffold/commands.d.ts.map +1 -1
  87. package/dist/utils/scaffold/commands.js +9 -12
  88. package/dist/utils/scaffold/commands.js.map +1 -1
  89. package/dist/utils/scaffold/compute.d.ts +5 -8
  90. package/dist/utils/scaffold/compute.d.ts.map +1 -1
  91. package/dist/utils/scaffold/compute.js +26 -41
  92. package/dist/utils/scaffold/compute.js.map +1 -1
  93. package/dist/utils/scaffold/dependencies.d.ts +10 -17
  94. package/dist/utils/scaffold/dependencies.d.ts.map +1 -1
  95. package/dist/utils/scaffold/dependencies.js +28 -34
  96. package/dist/utils/scaffold/dependencies.js.map +1 -1
  97. package/dist/utils/scaffold/generators.d.ts +3 -11
  98. package/dist/utils/scaffold/generators.d.ts.map +1 -1
  99. package/dist/utils/scaffold/generators.js +20 -288
  100. package/dist/utils/scaffold/generators.js.map +1 -1
  101. package/dist/utils/scaffold/index.d.ts +2 -3
  102. package/dist/utils/scaffold/index.d.ts.map +1 -1
  103. package/dist/utils/scaffold/index.js +1 -3
  104. package/dist/utils/scaffold/index.js.map +1 -1
  105. package/package.json +2 -2
@@ -0,0 +1,269 @@
1
+ /**
2
+ * CLAUDE.md section generators - each function generates one section.
3
+ */
4
+ import { FEATURE } from '../../../constants.js';
5
+ /** Script descriptions for commands section. */
6
+ const SCRIPT_DESCRIPTIONS = {
7
+ dev: 'Dev server at localhost:5173',
8
+ build: 'Production build (typecheck + bundle)',
9
+ preview: 'Preview production build',
10
+ typecheck: 'TypeScript only',
11
+ lint: 'ESLint check',
12
+ 'lint:fix': 'ESLint auto-fix',
13
+ format: 'Prettier format',
14
+ 'format:check': 'Prettier check',
15
+ test: 'Vitest once',
16
+ 'test:watch': 'Vitest watch mode',
17
+ 'test:coverage': 'Coverage (80% threshold)',
18
+ e2e: 'Playwright E2E',
19
+ 'e2e:ui': 'Playwright UI mode',
20
+ 'i18n:extract': 'Extract translations to .po',
21
+ prepare: 'Initialize Husky hooks',
22
+ };
23
+ export function generateHeader(projectName) {
24
+ return `# CLAUDE.md
25
+
26
+ AI assistant guidance for **${projectName}** - a React 19 + TypeScript + Vite 7 codebase.`;
27
+ }
28
+ export function generateCommandsSection(scripts) {
29
+ const commandLines = Object.keys(scripts)
30
+ .sort()
31
+ .map((script) => {
32
+ const desc = SCRIPT_DESCRIPTIONS[script] || '';
33
+ const padding = ' '.repeat(Math.max(1, 20 - script.length));
34
+ return `npm run ${script}${padding}# ${desc}`;
35
+ });
36
+ return `
37
+ ## Commands
38
+
39
+ \`\`\`bash
40
+ ${commandLines.join('\n')}
41
+ \`\`\``;
42
+ }
43
+ export function generateStructureSection(featureIds) {
44
+ const parts = ['src/', '├── components/ # ui/ (primitives), layout/, shared/ (features)'];
45
+ if (featureIds.includes(FEATURE.API) || featureIds.includes(FEATURE.I18N) || featureIds.includes(FEATURE.MOBILE)) {
46
+ parts.push('├── contexts/ # React Context providers');
47
+ }
48
+ parts.push('├── hooks/ # Custom hooks');
49
+ const libParts = ['config', 'utils', 'format'];
50
+ if (featureIds.includes(FEATURE.API))
51
+ libParts.push('api');
52
+ if (featureIds.includes(FEATURE.ROUTING))
53
+ libParts.push('routes');
54
+ if (featureIds.includes(FEATURE.STATE))
55
+ libParts.push('storage');
56
+ parts.push(`├── lib/ # ${libParts.join(', ')}`);
57
+ if (featureIds.includes(FEATURE.ROUTING))
58
+ parts.push('├── pages/ # Lazy-loaded route components');
59
+ if (featureIds.includes(FEATURE.STATE))
60
+ parts.push('├── stores/ # Zustand stores');
61
+ if (featureIds.includes(FEATURE.I18N)) {
62
+ parts.push('├── i18n/ # LinguiJS config and catalogs');
63
+ parts.push('├── locales/ # Translation files (.po)');
64
+ }
65
+ parts.push('└── types/ # TypeScript definitions');
66
+ if (featureIds.includes(FEATURE.TESTING)) {
67
+ parts.push('', '# Unit tests co-located: *.test.ts/tsx next to source');
68
+ parts.push('e2e/tests/ # Playwright functional E2E tests');
69
+ if (featureIds.includes(FEATURE.PERFORMANCE)) {
70
+ parts.push('e2e/performance/ # Performance regression tests');
71
+ }
72
+ }
73
+ return `
74
+ ## Project Structure
75
+
76
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for full structure and data flow.
77
+
78
+ \`\`\`
79
+ ${parts.join('\n')}
80
+ \`\`\``;
81
+ }
82
+ export function generateCodePatternsSection(featureIds) {
83
+ const stateHierarchy = [];
84
+ if (featureIds.includes(FEATURE.STATE))
85
+ stateHierarchy.push('Zustand (persisted)');
86
+ if (featureIds.includes(FEATURE.API))
87
+ stateHierarchy.push('TanStack Query (server)');
88
+ stateHierarchy.push('Context (UI)', 'useState (local)');
89
+ return `
90
+ ## Code Patterns
91
+
92
+ **Imports**: Always use \`@/\` path alias
93
+
94
+ **Components**: Named exports + \`Props\` interface. Pages use default exports for lazy loading.
95
+
96
+ **TypeScript**: \`type\` for unions, \`interface\` for objects
97
+
98
+ **State hierarchy**: ${stateHierarchy.join(' → ')}
99
+
100
+ See [docs/CODING_STANDARDS.md](docs/CODING_STANDARDS.md) and [docs/COMPONENT_GUIDELINES.md](docs/COMPONENT_GUIDELINES.md).`;
101
+ }
102
+ export function generateUiSection() {
103
+ return `
104
+ ## UI Components (Shadcn/UI)
105
+
106
+ This project uses **Shadcn/UI** with radix-nova style. Components live in \`src/components/ui/\`.
107
+
108
+ ### Adding New Components
109
+
110
+ \`\`\`bash
111
+ npx shadcn@latest add button # Single component
112
+ npx shadcn@latest add dialog card input # Multiple components
113
+ \`\`\`
114
+
115
+ **Pattern**: Import directly (no barrel exports for UI):
116
+
117
+ \`\`\`tsx
118
+ import { Button } from '@/components/ui/button';
119
+ import { cn } from '@/lib/utils';
120
+ \`\`\``;
121
+ }
122
+ export function generateMobileSection() {
123
+ return `
124
+ ## Mobile & Responsive Design
125
+
126
+ This project includes mobile-first responsive utilities.
127
+
128
+ ### Viewport Detection
129
+
130
+ \`\`\`tsx
131
+ import { MobileProvider, useMobileContext } from '@/contexts/mobileContext';
132
+
133
+ // Wrap app with MobileProvider
134
+ <MobileProvider>{children}</MobileProvider>
135
+
136
+ // Use in components
137
+ const { isMobile, isTablet, isDesktop, width } = useMobileContext();
138
+ \`\`\`
139
+
140
+ ### Breakpoints
141
+
142
+ \`\`\`tsx
143
+ import { BREAKPOINTS, useIsMobile, useIsDesktop } from '@/hooks/useMediaQuery';
144
+
145
+ // BREAKPOINTS: sm (640), md (768), lg (1024), xl (1280)
146
+ const isMobile = useIsMobile(); // width < 768px
147
+ const isDesktop = useIsDesktop(); // width >= 1024px
148
+ \`\`\`
149
+
150
+ ### Touch-Aware Sizing
151
+
152
+ \`\`\`tsx
153
+ import { useTouchSizes } from '@/hooks/useTouchSizes';
154
+
155
+ const sizes = useTouchSizes();
156
+ <Button size={sizes.button}>Click</Button> // 'touch' on mobile, 'default' on desktop
157
+ \`\`\``;
158
+ }
159
+ export function generateThemingSection() {
160
+ return `
161
+ ## Theming
162
+
163
+ Light/dark/system theme support with Zustand persistence.
164
+
165
+ ### Usage
166
+
167
+ \`\`\`tsx
168
+ import { usePreferencesStore } from '@/stores/preferencesStore';
169
+
170
+ // Get current theme
171
+ const theme = usePreferencesStore((s) => s.theme);
172
+
173
+ // Toggle theme
174
+ const toggleTheme = usePreferencesStore((s) => s.toggleTheme);
175
+
176
+ // Get resolved theme (actual light/dark value when 'system')
177
+ const getResolvedTheme = usePreferencesStore((s) => s.getResolvedTheme);
178
+ \`\`\`
179
+
180
+ The \`useThemeEffect\` hook automatically applies the \`.dark\` class to the document.
181
+ The ThemeToggle component provides a UI for switching between light, dark, and system themes.`;
182
+ }
183
+ export function generateMcpSection(featureIds) {
184
+ let section = `
185
+ ## MCP Servers (PREFER OVER WebSearch)
186
+
187
+ Use MCP servers for documentation lookup. They provide **structured, version-accurate data** directly from source.`;
188
+ if (featureIds.includes(FEATURE.UI)) {
189
+ section += `
190
+
191
+ ### Shadcn MCP (UI Components)
192
+
193
+ | Need | Tool |
194
+ | ------------------- | ------------------------------------------------ |
195
+ | Find component | \`mcp__shadcn__search_items_in_registries\` |
196
+ | View component code | \`mcp__shadcn__view_items_in_registries\` |
197
+ | Usage examples | \`mcp__shadcn__get_item_examples_from_registries\` |
198
+ | CLI add command | \`mcp__shadcn__get_add_command_for_items\` |`;
199
+ }
200
+ section += `
201
+
202
+ ### Context7 MCP (All Libraries)
203
+
204
+ Use for **any npm package** documentation:
205
+
206
+ \`\`\`
207
+ resolve-library-id → get-library-docs
208
+ \`\`\`
209
+
210
+ **Examples**: react-hook-form, @tanstack/react-query, zustand, zod, date-fns
211
+
212
+ ### Decision Flow
213
+
214
+ \`\`\`
215
+ Need UI component? → Shadcn MCP
216
+ Need library docs? → Context7 MCP (any npm package)
217
+ Need general info? → WebSearch (fallback only)
218
+ \`\`\``;
219
+ return section;
220
+ }
221
+ export function generateI18nSection() {
222
+ return `
223
+ ## Translations (CRITICAL)
224
+
225
+ All user-facing text MUST have translator comments. ESLint enforces this.
226
+
227
+ \`\`\`tsx
228
+ <Trans comment="Dashboard heading">Welcome back</Trans>
229
+ t({ message: 'Close', comment: 'Close button' })
230
+ \`\`\`
231
+
232
+ See [docs/INTERNATIONALIZATION.md](docs/INTERNATIONALIZATION.md).`;
233
+ }
234
+ export function generateTestingSection() {
235
+ return `
236
+ ## Testing
237
+
238
+ See [docs/TESTING.md](docs/TESTING.md) and [docs/E2E_TESTING.md](docs/E2E_TESTING.md).
239
+
240
+ Unit tests are **co-located** with source files (\`*.test.ts/tsx\`). 80% coverage required.
241
+
242
+ \`\`\`typescript
243
+ import { describe, it, expect, vi } from 'vitest';
244
+ import { screen, renderHook } from '@testing-library/react';
245
+ import { render, mockMatchMedia, server } from '@/test';
246
+ \`\`\`
247
+
248
+ MSW handlers auto-reset after each test.`;
249
+ }
250
+ export function generateGotchasSection(featureIds) {
251
+ const gotchas = [];
252
+ if (featureIds.includes(FEATURE.DEVTOOLS)) {
253
+ gotchas.push('**Node.js >= 22.0.0** required (check `.nvmrc`)');
254
+ gotchas.push('**Conventional commits** enforced by commitlint');
255
+ }
256
+ if (featureIds.includes(FEATURE.MOBILE)) {
257
+ gotchas.push('**Context hooks throw** outside provider (e.g., `useMobileContext()`)');
258
+ }
259
+ gotchas.push('**Barrel exports** in each directory via `index.ts`');
260
+ if (featureIds.includes(FEATURE.UI)) {
261
+ gotchas.push('**UI components** import directly: `@/components/ui/button` (no barrel)');
262
+ }
263
+ return `
264
+ ## Common Gotchas
265
+
266
+ ${gotchas.map((g, i) => `${i + 1}. ${g}`).join('\n')}
267
+ `;
268
+ }
269
+ //# sourceMappingURL=sections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sections.js","sourceRoot":"","sources":["../../../../src/utils/scaffold/claude-md/sections.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,7 @@
1
1
  /**
2
- * Setup commands utility
3
- *
4
- * Generates the npm commands needed to set up a scaffolded project.
2
+ * Setup commands utility - generates npm commands for scaffolded projects.
5
3
  */
6
4
  import type { FeatureId } from '../../features/types.js';
7
- /**
8
- * Generate setup commands based on selected features
9
- */
5
+ /** Generate setup commands based on selected features. */
10
6
  export declare function getSetupCommands(featureIds: FeatureId[]): string[];
11
7
  //# sourceMappingURL=commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAgBlE"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAgBlE"}
@@ -1,21 +1,18 @@
1
1
  /**
2
- * Setup commands utility
3
- *
4
- * Generates the npm commands needed to set up a scaffolded project.
5
- */
6
- /**
7
- * Generate setup commands based on selected features
2
+ * Setup commands utility - generates npm commands for scaffolded projects.
8
3
  */
4
+ import { FEATURE, SCRIPT } from '../../constants.js';
5
+ /** Generate setup commands based on selected features. */
9
6
  export function getSetupCommands(featureIds) {
10
7
  const commands = ['npm install'];
11
- if (featureIds.includes('devtools')) {
12
- commands.push('npm run prepare'); // Initialize husky
8
+ if (featureIds.includes(FEATURE.DEVTOOLS)) {
9
+ commands.push(`npm run ${SCRIPT.PREPARE}`);
13
10
  }
14
- if (featureIds.includes('testing')) {
15
- commands.push('npx playwright install chromium'); // Install Playwright browser
11
+ if (featureIds.includes(FEATURE.TESTING)) {
12
+ commands.push('npx playwright install chromium');
16
13
  }
17
- if (featureIds.includes('i18n')) {
18
- commands.push('npm run i18n:extract'); // Extract initial translations
14
+ if (featureIds.includes(FEATURE.I18N)) {
15
+ commands.push(`npm run ${SCRIPT.I18N_EXTRACT}`);
19
16
  }
20
17
  return commands;
21
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../src/utils/scaffold/commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAuB;IACtD,MAAM,QAAQ,GAAa,CAAC,aAAa,CAAC,CAAC;IAE3C,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB;IACvD,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC,6BAA6B;IACjF,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,+BAA+B;IACxE,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../src/utils/scaffold/commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGrD,0DAA0D;AAC1D,MAAM,UAAU,gBAAgB,CAAC,UAAuB;IACtD,MAAM,QAAQ,GAAa,CAAC,aAAa,CAAC,CAAC;IAE3C,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -1,18 +1,15 @@
1
1
  /**
2
- * Scaffold computation orchestrator
2
+ * Scaffold computation orchestrator - coordinates all components.
3
3
  *
4
- * Coordinates all scaffold components to produce the final scaffold result.
4
+ * Returns paths only for configFiles and docs (lazy loading).
5
+ * Use get_file tool to fetch actual content.
5
6
  */
6
7
  import type { ScaffoldResult } from '../../features/types.js';
7
8
  /**
8
9
  * Computes complete scaffold for selected features.
9
10
  *
10
- * Orchestrates dependency resolution, file structure computation,
11
- * and dynamic content generation to produce a complete project scaffold.
12
- *
13
- * @example
14
- * const scaffold = await computeScaffold(['routing', 'ui'], 'my-app');
15
- * // Returns: { packageJson, structure, configFiles, claudeMd, ... }
11
+ * Returns paths only for configFiles and docs (lazy loading).
12
+ * Use get_file tool to fetch actual content when needed.
16
13
  */
17
14
  export declare function computeScaffold(selectedFeatures: string[], projectName?: string): Promise<ScaffoldResult>;
18
15
  //# sourceMappingURL=compute.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/compute.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAe9D;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,WAAW,GAAE,MAAiB,GAC7B,OAAO,CAAC,cAAc,CAAC,CA6DzB"}
1
+ {"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/compute.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAe9D;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,WAAW,GAAE,MAAiB,GAC7B,OAAO,CAAC,cAAc,CAAC,CA2CzB"}
@@ -1,13 +1,15 @@
1
1
  /**
2
- * Scaffold computation orchestrator
2
+ * Scaffold computation orchestrator - coordinates all components.
3
3
  *
4
- * Coordinates all scaffold components to produce the final scaffold result.
4
+ * Returns paths only for configFiles and docs (lazy loading).
5
+ * Use get_file tool to fetch actual content.
5
6
  */
6
7
  import { readFile } from 'fs/promises';
7
- import { computeDocsContent, computeDocsForFeatures } from '../docs.js';
8
+ import { FEATURE } from '../../constants.js';
9
+ import { computeDocsForFeatures } from '../docs.js';
8
10
  import { resolveTemplatePath } from '../paths.js';
9
11
  import { resolveFeatureDependencies, mergeDependencies, mergeScripts } from './dependencies.js';
10
- import { computeFileStructure, getConfigFiles, readConfigFileContent } from './file-structure.js';
12
+ import { computeFileStructure, getConfigFiles } from './file-structure.js';
11
13
  import { getSetupCommands } from './commands.js';
12
14
  import { generateClaudeMd, generateViteEnvDts, generateEnvTs, generateRoutesTs } from './generators.js';
13
15
  async function readSourcePackageJson() {
@@ -18,53 +20,36 @@ async function readSourcePackageJson() {
18
20
  /**
19
21
  * Computes complete scaffold for selected features.
20
22
  *
21
- * Orchestrates dependency resolution, file structure computation,
22
- * and dynamic content generation to produce a complete project scaffold.
23
- *
24
- * @example
25
- * const scaffold = await computeScaffold(['routing', 'ui'], 'my-app');
26
- * // Returns: { packageJson, structure, configFiles, claudeMd, ... }
23
+ * Returns paths only for configFiles and docs (lazy loading).
24
+ * Use get_file tool to fetch actual content when needed.
27
25
  */
28
26
  export async function computeScaffold(selectedFeatures, projectName = 'my-app') {
29
- // Resolve all dependencies
27
+ // Resolve all dependencies (sync)
30
28
  const resolvedFeatures = resolveFeatureDependencies(selectedFeatures);
31
- // Read engines from source package.json
32
- const sourcePackageJson = await readSourcePackageJson();
29
+ // Parallel async operations: package.json and dependencies
30
+ const [sourcePackageJson, depsResult] = await Promise.all([
31
+ readSourcePackageJson(),
32
+ mergeDependencies(resolvedFeatures),
33
+ ]);
33
34
  const engines = sourcePackageJson.engines || {};
34
- // Merge all dependencies (async to read versions from source package.json)
35
- const { dependencies, devDependencies } = await mergeDependencies(resolvedFeatures);
36
- // Merge all scripts
37
- const scripts = mergeScripts(resolvedFeatures);
38
- // Get file structure (add CLAUDE.md which is generated, not from patterns)
39
- // Also add docs based on selected features
40
- const docPaths = computeDocsForFeatures(resolvedFeatures);
41
- const structure = [...computeFileStructure(resolvedFeatures), 'CLAUDE.md', ...docPaths];
42
- // Get config files with actual content read from templates
43
- const configFiles = {};
44
- const configPaths = getConfigFiles(resolvedFeatures);
45
- for (const config of configPaths) {
46
- configFiles[config] = await readConfigFileContent(config);
35
+ const { dependencies, devDependencies, warnings } = depsResult;
36
+ if (warnings.length > 0) {
37
+ console.error('[MCP] Dependency warnings:', warnings.join('; '));
47
38
  }
48
- // Get setup commands
39
+ // Sync operations
40
+ const scripts = mergeScripts(resolvedFeatures);
41
+ const docs = computeDocsForFeatures(resolvedFeatures);
42
+ const structure = [...computeFileStructure(resolvedFeatures), 'CLAUDE.md', ...docs];
49
43
  const setupCommands = getSetupCommands(resolvedFeatures);
50
- // Generate CLAUDE.md content
44
+ // Config files: paths only (lazy loading)
45
+ const configFiles = getConfigFiles(resolvedFeatures);
46
+ // Generate content (sync)
51
47
  const claudeMd = generateClaudeMd(resolvedFeatures, projectName, scripts);
52
- // Generate vite-env.d.ts content
53
48
  const viteEnvDts = generateViteEnvDts(resolvedFeatures);
54
- // Generate env.ts content
55
49
  const envTs = generateEnvTs(resolvedFeatures);
56
- // Generate routes.ts content (only if routing feature is selected)
57
- const routesTs = resolvedFeatures.includes('routing') ? generateRoutesTs() : undefined;
58
- // Get docs with content filtered by features
59
- const docs = await computeDocsContent(resolvedFeatures);
50
+ const routesTs = resolvedFeatures.includes(FEATURE.ROUTING) ? generateRoutesTs() : undefined;
60
51
  return {
61
- packageJson: {
62
- name: projectName,
63
- dependencies,
64
- devDependencies,
65
- scripts,
66
- engines,
67
- },
52
+ packageJson: { name: projectName, dependencies, devDependencies, scripts, engines },
68
53
  structure,
69
54
  configFiles,
70
55
  setupCommands,
@@ -1 +1 @@
1
- {"version":3,"file":"compute.js","sourceRoot":"","sources":["../../../src/utils/scaffold/compute.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compute.js","sourceRoot":"","sources":["../../../src/utils/scaffold/compute.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExG,KAAK,UAAU,qBAAqB;IAClC,MAAM,IAAI,GAAG,mBAAmB,CAAC,cAAc,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,gBAA0B,EAC1B,cAAsB,QAAQ;IAE9B,kCAAkC;IAClC,MAAM,gBAAgB,GAAG,0BAA0B,CAAC,gBAAgB,CAAC,CAAC;IAEtE,2DAA2D;IAC3D,MAAM,CAAC,iBAAiB,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxD,qBAAqB,EAAE;QACvB,iBAAiB,CAAC,gBAAgB,CAAC;KACpC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAI,iBAAiB,CAAC,OAAkC,IAAI,EAAE,CAAC;IAC5E,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC;IAE/D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,kBAAkB;IAClB,MAAM,OAAO,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,CAAC,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,CAAC;IACpF,MAAM,aAAa,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAEzD,0CAA0C;IAC1C,MAAM,WAAW,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAErD,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,gBAAgB,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1E,MAAM,UAAU,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7F,OAAO;QACL,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE;QACnF,SAAS;QACT,WAAW;QACX,aAAa;QACb,QAAQ;QACR,UAAU;QACV,KAAK;QACL,QAAQ;QACR,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -1,30 +1,23 @@
1
1
  /**
2
- * Dependency resolution utilities
3
- *
4
- * Handles merging dependencies from features and resolving versions
5
- * from the source package.json at runtime.
2
+ * Dependency resolution - merges features and resolves versions from package.json.
6
3
  */
7
4
  import type { FeatureId } from '../../features/types.js';
8
5
  /**
9
6
  * Resolves feature dependencies and auto-includes required features.
10
- *
11
- * - Core is always included
12
- * - Theming auto-includes state (for Zustand persistence)
13
- *
14
- * @param selectedFeatures - Array of feature IDs selected by user
15
- * @returns Array of resolved FeatureIds including auto-included dependencies
7
+ * Core is always included. Dependencies declared via `requires` field are resolved recursively.
16
8
  */
17
9
  export declare function resolveFeatureDependencies(selectedFeatures: string[]): FeatureId[];
10
+ /** Result of merging dependencies with any warnings. */
11
+ export interface MergeDependenciesResult {
12
+ dependencies: Record<string, string>;
13
+ devDependencies: Record<string, string>;
14
+ warnings: string[];
15
+ }
18
16
  /**
19
17
  * Merges dependencies from multiple features.
20
- *
21
- * Resolves package versions from the source package.json at runtime.
22
- * This ensures scaffolded projects always use up-to-date dependency versions.
18
+ * Returns structured warnings instead of logging to console.
23
19
  */
24
- export declare function mergeDependencies(featureIds: FeatureId[]): Promise<{
25
- dependencies: Record<string, string>;
26
- devDependencies: Record<string, string>;
27
- }>;
20
+ export declare function mergeDependencies(featureIds: FeatureId[]): Promise<MergeDependenciesResult>;
28
21
  /**
29
22
  * Merge scripts from multiple features
30
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/dependencies.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AA4BzD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAmBlF;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IACxE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC,CAAC,CAwCD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW5E"}
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/dependencies.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAwBzD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CA2BlF;AAED,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAuCjG;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW5E"}
@@ -1,75 +1,69 @@
1
1
  /**
2
- * Dependency resolution utilities
3
- *
4
- * Handles merging dependencies from features and resolving versions
5
- * from the source package.json at runtime.
2
+ * Dependency resolution - merges features and resolves versions from package.json.
6
3
  */
7
4
  import { readFile } from 'fs/promises';
8
5
  import { FEATURES, isFeatureId } from '../../features/index.js';
6
+ import { createSingletonCache } from '../cache.js';
9
7
  import { resolveTemplatePath } from '../paths.js';
10
- // Cache for source package.json to avoid repeated file reads
11
- let cachedSourcePackageJson = null;
12
- /**
13
- * Read and cache the source package.json dependencies
14
- */
8
+ const sourceDepsCache = createSingletonCache();
9
+ /** Read and cache the source package.json dependencies. */
15
10
  async function getSourceDependencies() {
16
- if (!cachedSourcePackageJson) {
11
+ return sourceDepsCache.getOrSet(async () => {
17
12
  const path = resolveTemplatePath('package.json');
18
13
  const content = await readFile(path, 'utf-8');
19
14
  const pkg = JSON.parse(content);
20
- cachedSourcePackageJson = {
15
+ return {
21
16
  dependencies: (pkg.dependencies || {}),
22
17
  devDependencies: (pkg.devDependencies || {}),
23
18
  };
24
- }
25
- return cachedSourcePackageJson;
19
+ });
26
20
  }
27
21
  /**
28
22
  * Resolves feature dependencies and auto-includes required features.
29
- *
30
- * - Core is always included
31
- * - Theming auto-includes state (for Zustand persistence)
32
- *
33
- * @param selectedFeatures - Array of feature IDs selected by user
34
- * @returns Array of resolved FeatureIds including auto-included dependencies
23
+ * Core is always included. Dependencies declared via `requires` field are resolved recursively.
35
24
  */
36
25
  export function resolveFeatureDependencies(selectedFeatures) {
37
26
  const resolved = new Set();
38
- // Always include core
27
+ function addWithDeps(featureId) {
28
+ if (resolved.has(featureId))
29
+ return;
30
+ resolved.add(featureId);
31
+ // Recursively add dependencies declared in `requires`
32
+ const feature = FEATURES[featureId];
33
+ if (feature.requires) {
34
+ for (const dep of feature.requires) {
35
+ addWithDeps(dep);
36
+ }
37
+ }
38
+ }
39
+ // Always include core first
39
40
  resolved.add('core');
40
- // Add all selected features (no recursive dependency resolution)
41
+ // Add selected features with their dependencies
41
42
  for (const featureId of selectedFeatures) {
42
43
  if (isFeatureId(featureId)) {
43
- resolved.add(featureId);
44
+ addWithDeps(featureId);
44
45
  }
45
46
  }
46
- // Theming requires state feature for Zustand persistence
47
- if (resolved.has('theming') && !resolved.has('state')) {
48
- resolved.add('state');
49
- }
50
47
  return Array.from(resolved);
51
48
  }
52
49
  /**
53
50
  * Merges dependencies from multiple features.
54
- *
55
- * Resolves package versions from the source package.json at runtime.
56
- * This ensures scaffolded projects always use up-to-date dependency versions.
51
+ * Returns structured warnings instead of logging to console.
57
52
  */
58
53
  export async function mergeDependencies(featureIds) {
59
54
  const dependencies = {};
60
55
  const devDependencies = {};
61
- // Get source package.json for version lookup
56
+ const warnings = [];
62
57
  const sourcePkg = await getSourceDependencies();
63
58
  for (const featureId of featureIds) {
64
59
  const feature = FEATURES[featureId];
65
- // Look up dependency versions from source package.json
66
60
  if (feature.dependencyNames) {
67
61
  for (const name of feature.dependencyNames) {
68
62
  if (sourcePkg.dependencies[name]) {
69
63
  dependencies[name] = sourcePkg.dependencies[name];
70
64
  }
71
65
  else {
72
- console.warn(`Dependency "${name}" not found in source package.json`);
66
+ warnings.push(`Dependency "${name}" not found in source package.json (feature: ${featureId})`);
73
67
  }
74
68
  }
75
69
  }
@@ -79,16 +73,16 @@ export async function mergeDependencies(featureIds) {
79
73
  devDependencies[name] = sourcePkg.devDependencies[name];
80
74
  }
81
75
  else {
82
- console.warn(`DevDependency "${name}" not found in source package.json`);
76
+ warnings.push(`DevDependency "${name}" not found in source package.json (feature: ${featureId})`);
83
77
  }
84
78
  }
85
79
  }
86
80
  }
87
- // Sort alphabetically
88
81
  const sortObject = (obj) => Object.fromEntries(Object.entries(obj).sort(([a], [b]) => a.localeCompare(b)));
89
82
  return {
90
83
  dependencies: sortObject(dependencies),
91
84
  devDependencies: sortObject(devDependencies),
85
+ warnings,
92
86
  };
93
87
  }
94
88
  /**