@codebakers/mcp 5.4.3 → 5.5.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 (37) hide show
  1. package/INSTALL.md +221 -221
  2. package/LICENSE +21 -21
  3. package/README.md +412 -412
  4. package/dist/cli.js +29 -29
  5. package/dist/cli.js.map +1 -1
  6. package/dist/index.js +11 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/tools/analyze-mockups.js +37 -37
  9. package/dist/tools/autonomous-build.d.ts +18 -18
  10. package/dist/tools/autonomous-build.js +286 -286
  11. package/dist/tools/check-gate.js +6 -6
  12. package/dist/tools/check-scope.js +10 -10
  13. package/dist/tools/enforce-feature.js +15 -15
  14. package/dist/tools/fix-commit.js +18 -18
  15. package/dist/tools/fix-mockups.js +191 -191
  16. package/dist/tools/generate-api-route.js +155 -155
  17. package/dist/tools/generate-chatbot.js +306 -306
  18. package/dist/tools/generate-component.js +117 -117
  19. package/dist/tools/generate-docs.js +525 -525
  20. package/dist/tools/generate-e2e-tests.js +19 -19
  21. package/dist/tools/generate-migration.js +22 -22
  22. package/dist/tools/generate-schema.js +37 -37
  23. package/dist/tools/generate-spec.js +38 -38
  24. package/dist/tools/generate-store-contracts.js +42 -42
  25. package/dist/tools/generate-store.js +109 -109
  26. package/dist/tools/generate-unit-tests.js +57 -57
  27. package/dist/tools/map-dependencies.js +45 -45
  28. package/dist/tools/run-interview.js +142 -142
  29. package/dist/tools/setup-github.js +8 -8
  30. package/dist/tools/setup-supabase.js +8 -8
  31. package/dist/tools/setup-vercel.js +8 -8
  32. package/dist/tools/start.d.ts +12 -0
  33. package/dist/tools/start.d.ts.map +1 -0
  34. package/dist/tools/start.js +220 -0
  35. package/dist/tools/start.js.map +1 -0
  36. package/dist/tools/validate-mockups.js +19 -19
  37. package/package.json +50 -50
@@ -9,29 +9,29 @@ export async function generateE2ETests(args) {
9
9
  const cwd = process.cwd();
10
10
  const { flow_name, steps } = args;
11
11
  const fileName = flow_name.toLowerCase().replace(/\s+/g, '-');
12
- const code = `import { test, expect } from '@playwright/test';
13
-
14
- test.describe('${flow_name}', () => {
15
- test.beforeEach(async ({ page }) => {
16
- await page.goto('/');
17
- });
18
-
19
- test('${flow_name} flow', async ({ page }) => {
20
- ${steps.map((step, i) => `// Step ${i + 1}: ${step}`).join('\n ')}
21
-
22
- await expect(page).toHaveURL('/');
23
- });
24
- });
12
+ const code = `import { test, expect } from '@playwright/test';
13
+
14
+ test.describe('${flow_name}', () => {
15
+ test.beforeEach(async ({ page }) => {
16
+ await page.goto('/');
17
+ });
18
+
19
+ test('${flow_name} flow', async ({ page }) => {
20
+ ${steps.map((step, i) => `// Step ${i + 1}: ${step}`).join('\n ')}
21
+
22
+ await expect(page).toHaveURL('/');
23
+ });
24
+ });
25
25
  `;
26
26
  const filePath = path.join(cwd, `e2e/${fileName}.spec.ts`);
27
27
  await fs.mkdir(path.dirname(filePath), { recursive: true });
28
28
  await fs.writeFile(filePath, code, 'utf-8');
29
- return `🍞 CodeBakers: E2E Tests Generated
30
-
31
- **File:** e2e/${fileName}.spec.ts
32
- **Flow:** ${flow_name}
33
- **Steps:** ${steps.length}
34
-
29
+ return `🍞 CodeBakers: E2E Tests Generated
30
+
31
+ **File:** e2e/${fileName}.spec.ts
32
+ **Flow:** ${flow_name}
33
+ **Steps:** ${steps.length}
34
+
35
35
  ✅ Playwright test created`;
36
36
  }
37
37
  //# sourceMappingURL=generate-e2e-tests.js.map
@@ -47,28 +47,28 @@ export async function generateMigration(args) {
47
47
  await fs.mkdir(migrationDir, { recursive: true });
48
48
  const migrationPath = path.join(migrationDir, filename);
49
49
  await fs.writeFile(migrationPath, sql, 'utf-8');
50
- return `🍞 CodeBakers: Migration Generated
51
-
52
- **File:** supabase/migrations/${filename}
53
- **Table:** ${tableName}
54
- **Fields:** ${fields.length}
55
- **RLS:** ${add_rls ? 'Enabled' : 'Disabled'}
56
-
57
- Migration includes:
58
- ✅ Table creation with UUID primary key
59
- ✅ user_id foreign key (security)
60
- ✅ Timestamps (created_at, updated_at)
61
- ✅ Indexes (user_id, created_at)
62
- ${add_rls ? '✅ RLS policies (user isolation)' : ''}
63
-
64
- **Apply migration:**
65
- \`\`\`bash
66
- supabase db push
67
- \`\`\`
68
-
69
- Or manually:
70
- \`\`\`bash
71
- psql -f supabase/migrations/${filename}
50
+ return `🍞 CodeBakers: Migration Generated
51
+
52
+ **File:** supabase/migrations/${filename}
53
+ **Table:** ${tableName}
54
+ **Fields:** ${fields.length}
55
+ **RLS:** ${add_rls ? 'Enabled' : 'Disabled'}
56
+
57
+ Migration includes:
58
+ ✅ Table creation with UUID primary key
59
+ ✅ user_id foreign key (security)
60
+ ✅ Timestamps (created_at, updated_at)
61
+ ✅ Indexes (user_id, created_at)
62
+ ${add_rls ? '✅ RLS policies (user isolation)' : ''}
63
+
64
+ **Apply migration:**
65
+ \`\`\`bash
66
+ supabase db push
67
+ \`\`\`
68
+
69
+ Or manually:
70
+ \`\`\`bash
71
+ psql -f supabase/migrations/${filename}
72
72
  \`\`\``;
73
73
  }
74
74
  catch (error) {
@@ -24,14 +24,14 @@ export async function generateSchema(args) {
24
24
  // 1. CHECK IF ANALYSIS FILE EXISTS
25
25
  const exists = await fs.access(analysisPath).then(() => true).catch(() => false);
26
26
  if (!exists) {
27
- return `🍞 CodeBakers: Phase 2B - Schema Generation
28
-
29
- ❌ BLOCKER: Mock analysis file not found
30
-
31
- Expected location: ${analysisPath}
32
-
33
- Phase 2B cannot proceed without Phase 2A analysis.
34
-
27
+ return `🍞 CodeBakers: Phase 2B - Schema Generation
28
+
29
+ ❌ BLOCKER: Mock analysis file not found
30
+
31
+ Expected location: ${analysisPath}
32
+
33
+ Phase 2B cannot proceed without Phase 2A analysis.
34
+
35
35
  Next step: Run Phase 2A first (use tool: codebakers_analyze_mockups_deep)`;
36
36
  }
37
37
  // 2. READ MOCK-ANALYSIS.md
@@ -39,12 +39,12 @@ Next step: Run Phase 2A first (use tool: codebakers_analyze_mockups_deep)`;
39
39
  // 3. PARSE ANALYSIS FILE TO EXTRACT SCHEMA REQUIREMENTS
40
40
  const { tables, enums } = parseAnalysisForSchema(analysisContent);
41
41
  if (tables.length === 0) {
42
- return `🍞 CodeBakers: Phase 2B - Schema Generation
43
-
44
- ⚠️ WARNING: No entities found in analysis file
45
-
46
- The mock analysis appears incomplete or empty.
47
-
42
+ return `🍞 CodeBakers: Phase 2B - Schema Generation
43
+
44
+ ⚠️ WARNING: No entities found in analysis file
45
+
46
+ The mock analysis appears incomplete or empty.
47
+
48
48
  Please verify Phase 2A analysis contains data fields and entities.`;
49
49
  }
50
50
  console.error(`Extracted ${tables.length} tables and ${enums.length} enum types`);
@@ -56,33 +56,33 @@ Please verify Phase 2A analysis contains data fields and entities.`;
56
56
  console.error(`✓ Schema generated: ${schemaPath}`);
57
57
  // 6. GENERATE SUMMARY
58
58
  const summary = generateSchemaSummary(tables, enums);
59
- return `🍞 CodeBakers: Phase 2B - Schema Generation Complete
60
-
61
- ${summary}
62
-
63
- 📄 Schema written to: .codebakers/SCHEMA.sql
64
-
65
- Next steps:
66
- 1. Review SCHEMA.sql to verify all tables and relationships
67
- 2. Proceed to Phase 2C: Dependency Mapping (use tool: codebakers_map_dependencies)
68
- 3. Run verification gate before Phase 3
69
-
70
- Verification gate requirement:
71
- → Every data field in mockups has corresponding database column
72
- → All entity relationships captured in foreign keys
59
+ return `🍞 CodeBakers: Phase 2B - Schema Generation Complete
60
+
61
+ ${summary}
62
+
63
+ 📄 Schema written to: .codebakers/SCHEMA.sql
64
+
65
+ Next steps:
66
+ 1. Review SCHEMA.sql to verify all tables and relationships
67
+ 2. Proceed to Phase 2C: Dependency Mapping (use tool: codebakers_map_dependencies)
68
+ 3. Run verification gate before Phase 3
69
+
70
+ Verification gate requirement:
71
+ → Every data field in mockups has corresponding database column
72
+ → All entity relationships captured in foreign keys
73
73
  → No unresolved dependencies`;
74
74
  }
75
75
  catch (error) {
76
76
  console.error('Error during schema generation:', error);
77
- return `🍞 CodeBakers: Phase 2B - Schema Generation Failed
78
-
79
- Error: ${error instanceof Error ? error.message : String(error)}
80
-
81
- Please check:
82
- - Mock analysis file exists and is readable
83
- - Analysis file contains entity and field data
84
- - File permissions allow writing
85
-
77
+ return `🍞 CodeBakers: Phase 2B - Schema Generation Failed
78
+
79
+ Error: ${error instanceof Error ? error.message : String(error)}
80
+
81
+ Please check:
82
+ - Mock analysis file exists and is readable
83
+ - Analysis file contains entity and field data
84
+ - File permissions allow writing
85
+
86
86
  If issue persists, log to ERROR-LOG.md and request human assistance.`;
87
87
  }
88
88
  }
@@ -16,16 +16,16 @@ import * as path from 'path';
16
16
  export async function generateSpec(args) {
17
17
  const { description, project_name } = args;
18
18
  if (!description) {
19
- return `🍞 CodeBakers: Phase 0 - Spec Generation
20
-
21
- Please provide a description of what you want to build.
22
-
23
- Example:
24
- {
25
- "description": "Email client for Microsoft 365 with inbox, compose, and search",
26
- "project_name": "EmailFlow"
27
- }
28
-
19
+ return `🍞 CodeBakers: Phase 0 - Spec Generation
20
+
21
+ Please provide a description of what you want to build.
22
+
23
+ Example:
24
+ {
25
+ "description": "Email client for Microsoft 365 with inbox, compose, and search",
26
+ "project_name": "EmailFlow"
27
+ }
28
+
29
29
  Then I'll generate a complete PROJECT-SPEC.md with Gates 0-5.`;
30
30
  }
31
31
  const cwd = process.cwd();
@@ -58,38 +58,38 @@ Then I'll generate a complete PROJECT-SPEC.md with Gates 0-5.`;
58
58
  await fs.writeFile(buildStatePath, buildStateContent, 'utf-8');
59
59
  console.error(`✓ Build state initialized: ${buildStatePath}`);
60
60
  const summary = generateSpecSummary(gate0, gate1, gate2, gate3, gate4, gate5);
61
- return `🍞 CodeBakers: Phase 0 - Spec Generation Complete
62
-
63
- ${summary}
64
-
65
- 📄 Spec written to: .codebakers/PROJECT-SPEC.md
66
- 📄 Build state initialized: .codebakers/BUILD-STATE.md
67
-
68
- Specification includes:
69
- ✓ Gate 0: Identity (product name, mission, target user, value prop)
70
- ✓ Gate 1: ${gate1.length} entities identified
71
- ✓ Gate 2: ${gate2.length} state changes mapped
72
- ✓ Gate 3: ${gate3.length} roles with permissions
73
- ✓ Gate 4: ${gate4.length} external dependencies
74
- ✓ Gate 5: ${gate5.length} integrations
75
-
76
- Next steps:
77
- 1. Review PROJECT-SPEC.md to verify all requirements
78
- 2. Add/modify entities, permissions, or integrations as needed
79
- 3. When ready, proceed to Phase 1: UI Mockup & Design
61
+ return `🍞 CodeBakers: Phase 0 - Spec Generation Complete
62
+
63
+ ${summary}
64
+
65
+ 📄 Spec written to: .codebakers/PROJECT-SPEC.md
66
+ 📄 Build state initialized: .codebakers/BUILD-STATE.md
67
+
68
+ Specification includes:
69
+ ✓ Gate 0: Identity (product name, mission, target user, value prop)
70
+ ✓ Gate 1: ${gate1.length} entities identified
71
+ ✓ Gate 2: ${gate2.length} state changes mapped
72
+ ✓ Gate 3: ${gate3.length} roles with permissions
73
+ ✓ Gate 4: ${gate4.length} external dependencies
74
+ ✓ Gate 5: ${gate5.length} integrations
75
+
76
+ Next steps:
77
+ 1. Review PROJECT-SPEC.md to verify all requirements
78
+ 2. Add/modify entities, permissions, or integrations as needed
79
+ 3. When ready, proceed to Phase 1: UI Mockup & Design
80
80
  4. Use: codebakers_init_session to resume project`;
81
81
  }
82
82
  catch (error) {
83
83
  console.error('Error during spec generation:', error);
84
- return `🍞 CodeBakers: Phase 0 - Spec Generation Failed
85
-
86
- Error: ${error instanceof Error ? error.message : String(error)}
87
-
88
- Please check:
89
- - Description is clear and specific
90
- - Project directory exists and is writable
91
- - File permissions allow writing
92
-
84
+ return `🍞 CodeBakers: Phase 0 - Spec Generation Failed
85
+
86
+ Error: ${error instanceof Error ? error.message : String(error)}
87
+
88
+ Please check:
89
+ - Description is clear and specific
90
+ - Project directory exists and is writable
91
+ - File permissions allow writing
92
+
93
93
  If issue persists, log to ERROR-LOG.md and request human assistance.`;
94
94
  }
95
95
  }
@@ -24,25 +24,25 @@ export async function generateStoreContracts(args) {
24
24
  const schemaExists = await fs.access(schemaPath).then(() => true).catch(() => false);
25
25
  const depMapExists = await fs.access(depMapPath).then(() => true).catch(() => false);
26
26
  if (!schemaExists) {
27
- return `🍞 CodeBakers: Phase 2D - Store Contract Generation
28
-
29
- ❌ BLOCKER: Schema file not found
30
-
31
- Expected location: ${schemaPath}
32
-
33
- Phase 2D requires Phase 2B schema to generate store contracts.
34
-
27
+ return `🍞 CodeBakers: Phase 2D - Store Contract Generation
28
+
29
+ ❌ BLOCKER: Schema file not found
30
+
31
+ Expected location: ${schemaPath}
32
+
33
+ Phase 2D requires Phase 2B schema to generate store contracts.
34
+
35
35
  Next step: Run Phase 2B first (use tool: codebakers_generate_schema)`;
36
36
  }
37
37
  if (!depMapExists) {
38
- return `🍞 CodeBakers: Phase 2D - Store Contract Generation
39
-
40
- ❌ BLOCKER: Dependency map not found
41
-
42
- Expected location: ${depMapPath}
43
-
44
- Phase 2D requires Phase 2C dependency map to generate store contracts.
45
-
38
+ return `🍞 CodeBakers: Phase 2D - Store Contract Generation
39
+
40
+ ❌ BLOCKER: Dependency map not found
41
+
42
+ Expected location: ${depMapPath}
43
+
44
+ Phase 2D requires Phase 2C dependency map to generate store contracts.
45
+
46
46
  Next step: Run Phase 2C first (use tool: codebakers_map_dependencies)`;
47
47
  }
48
48
  // 2. READ SCHEMA AND DEPENDENCY MAP
@@ -64,36 +64,36 @@ Next step: Run Phase 2C first (use tool: codebakers_map_dependencies)`;
64
64
  console.error(`✓ TypeScript interfaces written: ${interfacesPath}`);
65
65
  // 6. GENERATE SUMMARY
66
66
  const summary = generateContractsSummary(contracts);
67
- return `🍞 CodeBakers: Phase 2D - Store Contract Generation Complete
68
-
69
- ${summary}
70
-
71
- 📄 Documentation: .codebakers/STORE-CONTRACTS.md
72
- 📄 TypeScript interfaces: .codebakers/store-contracts.ts
73
-
74
- These contracts define:
75
- ✓ State shape for each store
76
- ✓ Required methods (create, update, delete, query)
77
- ✓ Method signatures with types
78
- ✓ Dependencies (which stores this store depends on)
79
-
80
- Next steps:
81
- 1. Review store contracts to verify completeness
82
- 2. Phase 2 is now COMPLETE
83
- 3. Ready for Phase 3: Foundation Build
67
+ return `🍞 CodeBakers: Phase 2D - Store Contract Generation Complete
68
+
69
+ ${summary}
70
+
71
+ 📄 Documentation: .codebakers/STORE-CONTRACTS.md
72
+ 📄 TypeScript interfaces: .codebakers/store-contracts.ts
73
+
74
+ These contracts define:
75
+ ✓ State shape for each store
76
+ ✓ Required methods (create, update, delete, query)
77
+ ✓ Method signatures with types
78
+ ✓ Dependencies (which stores this store depends on)
79
+
80
+ Next steps:
81
+ 1. Review store contracts to verify completeness
82
+ 2. Phase 2 is now COMPLETE
83
+ 3. Ready for Phase 3: Foundation Build
84
84
  4. When implementing stores, use store-contracts.ts as the interface`;
85
85
  }
86
86
  catch (error) {
87
87
  console.error('Error during store contract generation:', error);
88
- return `🍞 CodeBakers: Phase 2D - Store Contract Generation Failed
89
-
90
- Error: ${error instanceof Error ? error.message : String(error)}
91
-
92
- Please check:
93
- - Schema file and dependency map exist and are readable
94
- - Files contain valid content
95
- - File permissions allow writing
96
-
88
+ return `🍞 CodeBakers: Phase 2D - Store Contract Generation Failed
89
+
90
+ Error: ${error instanceof Error ? error.message : String(error)}
91
+
92
+ Please check:
93
+ - Schema file and dependency map exist and are readable
94
+ - Files contain valid content
95
+ - File permissions allow writing
96
+
97
97
  If issue persists, log to ERROR-LOG.md and request human assistance.`;
98
98
  }
99
99
  }
@@ -12,84 +12,84 @@ export async function generateStore(args) {
12
12
  const cwd = process.cwd();
13
13
  const { entity, operations, dependencies = [] } = args;
14
14
  const storeName = `${entity.toLowerCase()}-store`;
15
- const code = `import { create } from 'zustand';
16
-
17
- export interface ${entity} {
18
- id: string;
19
- user_id: string;
20
- created_at: string;
21
- updated_at: string;
22
- }
23
-
24
- interface ${entity}Store {
25
- ${entity.toLowerCase()}s: ${entity}[];
26
- loading: boolean;
27
- error: string | null;
28
-
29
- ${operations.includes('list') ? `fetch${entity}s: () => Promise<void>;` : ''}
30
- ${operations.includes('create') ? `create${entity}: (data: Partial<${entity}>) => Promise<void>;` : ''}
31
- ${operations.includes('update') ? `update${entity}: (id: string, data: Partial<${entity}>) => Promise<void>;` : ''}
32
- ${operations.includes('delete') ? `delete${entity}: (id: string) => Promise<void>;` : ''}
33
- }
34
-
35
- export const use${entity}Store = create<${entity}Store>((set, get) => ({
36
- ${entity.toLowerCase()}s: [],
37
- loading: false,
38
- error: null,
39
-
40
- ${operations.includes('list') ? generateFetchMethod(entity) : ''}
41
- ${operations.includes('create') ? generateCreateMethod(entity, dependencies) : ''}
42
- ${operations.includes('update') ? generateUpdateMethod(entity, dependencies) : ''}
43
- ${operations.includes('delete') ? generateDeleteMethod(entity, dependencies) : ''}
44
- }));
15
+ const code = `import { create } from 'zustand';
16
+
17
+ export interface ${entity} {
18
+ id: string;
19
+ user_id: string;
20
+ created_at: string;
21
+ updated_at: string;
22
+ }
23
+
24
+ interface ${entity}Store {
25
+ ${entity.toLowerCase()}s: ${entity}[];
26
+ loading: boolean;
27
+ error: string | null;
28
+
29
+ ${operations.includes('list') ? `fetch${entity}s: () => Promise<void>;` : ''}
30
+ ${operations.includes('create') ? `create${entity}: (data: Partial<${entity}>) => Promise<void>;` : ''}
31
+ ${operations.includes('update') ? `update${entity}: (id: string, data: Partial<${entity}>) => Promise<void>;` : ''}
32
+ ${operations.includes('delete') ? `delete${entity}: (id: string) => Promise<void>;` : ''}
33
+ }
34
+
35
+ export const use${entity}Store = create<${entity}Store>((set, get) => ({
36
+ ${entity.toLowerCase()}s: [],
37
+ loading: false,
38
+ error: null,
39
+
40
+ ${operations.includes('list') ? generateFetchMethod(entity) : ''}
41
+ ${operations.includes('create') ? generateCreateMethod(entity, dependencies) : ''}
42
+ ${operations.includes('update') ? generateUpdateMethod(entity, dependencies) : ''}
43
+ ${operations.includes('delete') ? generateDeleteMethod(entity, dependencies) : ''}
44
+ }));
45
45
  `;
46
46
  const filePath = path.join(cwd, `src/stores/${storeName}.ts`);
47
47
  await fs.mkdir(path.dirname(filePath), { recursive: true });
48
48
  await fs.writeFile(filePath, code, 'utf-8');
49
- return `🍞 CodeBakers: Store Generated
50
-
51
- **File:** src/stores/${storeName}.ts
52
- **Entity:** ${entity}
53
- **Operations:** ${operations.join(', ')}
54
- ${dependencies.length > 0 ? `**Dependencies:** ${dependencies.join(', ')}` : ''}
55
-
56
- Includes:
57
- ✅ TypeScript interfaces
58
- ✅ Zustand store
59
- ✅ Loading/error states
60
- ✅ CRUD operations
49
+ return `🍞 CodeBakers: Store Generated
50
+
51
+ **File:** src/stores/${storeName}.ts
52
+ **Entity:** ${entity}
53
+ **Operations:** ${operations.join(', ')}
54
+ ${dependencies.length > 0 ? `**Dependencies:** ${dependencies.join(', ')}` : ''}
55
+
56
+ Includes:
57
+ ✅ TypeScript interfaces
58
+ ✅ Zustand store
59
+ ✅ Loading/error states
60
+ ✅ CRUD operations
61
61
  ${dependencies.length > 0 ? '✅ Dependency updates (from DEPENDENCY-MAP.md)' : ''}`;
62
62
  }
63
63
  function generateFetchMethod(entity) {
64
- return `fetch${entity}s: async () => {
65
- set({ loading: true, error: null });
66
- try {
67
- const res = await fetch('/api/${entity.toLowerCase()}s');
68
- if (!res.ok) throw new Error('Fetch failed');
69
- const { data } = await res.json();
70
- set({ ${entity.toLowerCase()}s: data, loading: false });
71
- } catch (error) {
72
- set({ error: (error as Error).message, loading: false });
73
- }
74
- },
64
+ return `fetch${entity}s: async () => {
65
+ set({ loading: true, error: null });
66
+ try {
67
+ const res = await fetch('/api/${entity.toLowerCase()}s');
68
+ if (!res.ok) throw new Error('Fetch failed');
69
+ const { data } = await res.json();
70
+ set({ ${entity.toLowerCase()}s: data, loading: false });
71
+ } catch (error) {
72
+ set({ error: (error as Error).message, loading: false });
73
+ }
74
+ },
75
75
  `;
76
76
  }
77
77
  function generateCreateMethod(entity, deps) {
78
- let code = `create${entity}: async (data) => {
79
- set({ loading: true, error: null });
80
- try {
81
- const res = await fetch('/api/${entity.toLowerCase()}s', {
82
- method: 'POST',
83
- headers: { 'Content-Type': 'application/json' },
84
- body: JSON.stringify(data),
85
- });
86
- if (!res.ok) throw new Error('Create failed');
87
- const { data: new${entity} } = await res.json();
88
-
89
- set(state => ({
90
- ${entity.toLowerCase()}s: [new${entity}, ...state.${entity.toLowerCase()}s],
91
- loading: false,
92
- }));
78
+ let code = `create${entity}: async (data) => {
79
+ set({ loading: true, error: null });
80
+ try {
81
+ const res = await fetch('/api/${entity.toLowerCase()}s', {
82
+ method: 'POST',
83
+ headers: { 'Content-Type': 'application/json' },
84
+ body: JSON.stringify(data),
85
+ });
86
+ if (!res.ok) throw new Error('Create failed');
87
+ const { data: new${entity} } = await res.json();
88
+
89
+ set(state => ({
90
+ ${entity.toLowerCase()}s: [new${entity}, ...state.${entity.toLowerCase()}s],
91
+ loading: false,
92
+ }));
93
93
  `;
94
94
  if (deps.length > 0) {
95
95
  code += `\n // Update dependent stores (from DEPENDENCY-MAP.md)\n`;
@@ -97,31 +97,31 @@ function generateCreateMethod(entity, deps) {
97
97
  code += ` ${dep}.getState().refresh();\n`;
98
98
  }
99
99
  }
100
- code += ` } catch (error) {
101
- set({ error: (error as Error).message, loading: false });
102
- }
103
- },
100
+ code += ` } catch (error) {
101
+ set({ error: (error as Error).message, loading: false });
102
+ }
103
+ },
104
104
  `;
105
105
  return code;
106
106
  }
107
107
  function generateUpdateMethod(entity, deps) {
108
- let code = `update${entity}: async (id, data) => {
109
- set({ loading: true, error: null });
110
- try {
111
- const res = await fetch(\`/api/${entity.toLowerCase()}s/\${id}\`, {
112
- method: 'PATCH',
113
- headers: { 'Content-Type': 'application/json' },
114
- body: JSON.stringify(data),
115
- });
116
- if (!res.ok) throw new Error('Update failed');
117
- const { data: updated } = await res.json();
118
-
119
- set(state => ({
120
- ${entity.toLowerCase()}s: state.${entity.toLowerCase()}s.map(item =>
121
- item.id === id ? updated : item
122
- ),
123
- loading: false,
124
- }));
108
+ let code = `update${entity}: async (id, data) => {
109
+ set({ loading: true, error: null });
110
+ try {
111
+ const res = await fetch(\`/api/${entity.toLowerCase()}s/\${id}\`, {
112
+ method: 'PATCH',
113
+ headers: { 'Content-Type': 'application/json' },
114
+ body: JSON.stringify(data),
115
+ });
116
+ if (!res.ok) throw new Error('Update failed');
117
+ const { data: updated } = await res.json();
118
+
119
+ set(state => ({
120
+ ${entity.toLowerCase()}s: state.${entity.toLowerCase()}s.map(item =>
121
+ item.id === id ? updated : item
122
+ ),
123
+ loading: false,
124
+ }));
125
125
  `;
126
126
  if (deps.length > 0) {
127
127
  code += `\n // Update dependent stores\n`;
@@ -129,26 +129,26 @@ function generateUpdateMethod(entity, deps) {
129
129
  code += ` ${dep}.getState().refresh();\n`;
130
130
  }
131
131
  }
132
- code += ` } catch (error) {
133
- set({ error: (error as Error).message, loading: false });
134
- }
135
- },
132
+ code += ` } catch (error) {
133
+ set({ error: (error as Error).message, loading: false });
134
+ }
135
+ },
136
136
  `;
137
137
  return code;
138
138
  }
139
139
  function generateDeleteMethod(entity, deps) {
140
- let code = `delete${entity}: async (id) => {
141
- set({ loading: true, error: null });
142
- try {
143
- const res = await fetch(\`/api/${entity.toLowerCase()}s/\${id}\`, {
144
- method: 'DELETE',
145
- });
146
- if (!res.ok) throw new Error('Delete failed');
147
-
148
- set(state => ({
149
- ${entity.toLowerCase()}s: state.${entity.toLowerCase()}s.filter(item => item.id !== id),
150
- loading: false,
151
- }));
140
+ let code = `delete${entity}: async (id) => {
141
+ set({ loading: true, error: null });
142
+ try {
143
+ const res = await fetch(\`/api/${entity.toLowerCase()}s/\${id}\`, {
144
+ method: 'DELETE',
145
+ });
146
+ if (!res.ok) throw new Error('Delete failed');
147
+
148
+ set(state => ({
149
+ ${entity.toLowerCase()}s: state.${entity.toLowerCase()}s.filter(item => item.id !== id),
150
+ loading: false,
151
+ }));
152
152
  `;
153
153
  if (deps.length > 0) {
154
154
  code += `\n // Update ALL dependent stores (CRITICAL - prevents stale UI)\n`;
@@ -156,10 +156,10 @@ function generateDeleteMethod(entity, deps) {
156
156
  code += ` ${dep}.getState().refresh();\n`;
157
157
  }
158
158
  }
159
- code += ` } catch (error) {
160
- set({ error: (error as Error).message, loading: false });
161
- }
162
- },
159
+ code += ` } catch (error) {
160
+ set({ error: (error as Error).message, loading: false });
161
+ }
162
+ },
163
163
  `;
164
164
  return code;
165
165
  }