@claudetools/tools 0.8.10 → 0.9.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 (76) hide show
  1. package/dist/codedna/generators/astro.d.ts +18 -0
  2. package/dist/codedna/generators/astro.js +91 -0
  3. package/dist/codedna/generators/authjs.d.ts +18 -0
  4. package/dist/codedna/generators/authjs.js +68 -0
  5. package/dist/codedna/generators/better-auth.d.ts +18 -0
  6. package/dist/codedna/generators/better-auth.js +62 -0
  7. package/dist/codedna/generators/drizzle-orm.d.ts +18 -0
  8. package/dist/codedna/generators/drizzle-orm.js +65 -0
  9. package/dist/codedna/generators/elysia-api.d.ts +12 -0
  10. package/dist/codedna/generators/elysia-api.js +64 -0
  11. package/dist/codedna/generators/hono-api.d.ts +12 -0
  12. package/dist/codedna/generators/hono-api.js +64 -0
  13. package/dist/codedna/generators/lucia-auth.d.ts +18 -0
  14. package/dist/codedna/generators/lucia-auth.js +69 -0
  15. package/dist/codedna/generators/prisma.d.ts +18 -0
  16. package/dist/codedna/generators/prisma.js +64 -0
  17. package/dist/codedna/generators/react-router-v7.d.ts +18 -0
  18. package/dist/codedna/generators/react-router-v7.js +77 -0
  19. package/dist/codedna/generators/react19-shadcn.d.ts +21 -0
  20. package/dist/codedna/generators/react19-shadcn.js +367 -0
  21. package/dist/codedna/generators/sveltekit.d.ts +18 -0
  22. package/dist/codedna/generators/sveltekit.js +73 -0
  23. package/dist/codedna/generators/tanstack-start-drizzle.d.ts +92 -0
  24. package/dist/codedna/generators/tanstack-start-drizzle.js +824 -0
  25. package/dist/codedna/generators/trpc-api.d.ts +12 -0
  26. package/dist/codedna/generators/trpc-api.js +64 -0
  27. package/dist/codedna/index.d.ts +31 -0
  28. package/dist/codedna/index.js +39 -0
  29. package/dist/codedna/kappa-api-generator.d.ts +89 -0
  30. package/dist/codedna/kappa-api-generator.js +493 -0
  31. package/dist/codedna/kappa-ast.d.ts +552 -0
  32. package/dist/codedna/kappa-ast.js +141 -0
  33. package/dist/codedna/kappa-cli.d.ts +2 -0
  34. package/dist/codedna/kappa-cli.js +302 -0
  35. package/dist/codedna/kappa-component-generator.d.ts +47 -0
  36. package/dist/codedna/kappa-component-generator.js +295 -0
  37. package/dist/codedna/kappa-design-generator.d.ts +52 -0
  38. package/dist/codedna/kappa-design-generator.js +365 -0
  39. package/dist/codedna/kappa-drizzle-generator.d.ts +45 -0
  40. package/dist/codedna/kappa-drizzle-generator.js +355 -0
  41. package/dist/codedna/kappa-form-generator.d.ts +51 -0
  42. package/dist/codedna/kappa-form-generator.js +319 -0
  43. package/dist/codedna/kappa-lexer.d.ts +268 -0
  44. package/dist/codedna/kappa-lexer.js +757 -0
  45. package/dist/codedna/kappa-page-generator.d.ts +57 -0
  46. package/dist/codedna/kappa-page-generator.js +338 -0
  47. package/dist/codedna/kappa-parser.d.ts +261 -0
  48. package/dist/codedna/kappa-parser.js +2547 -0
  49. package/dist/codedna/kappa-provenance.d.ts +101 -0
  50. package/dist/codedna/kappa-provenance.js +199 -0
  51. package/dist/codedna/kappa-types-generator.d.ts +37 -0
  52. package/dist/codedna/kappa-types-generator.js +159 -0
  53. package/dist/codedna/kappa-validator.d.ts +86 -0
  54. package/dist/codedna/kappa-validator.js +638 -0
  55. package/dist/codedna/kappa-zod-generator.d.ts +32 -0
  56. package/dist/codedna/kappa-zod-generator.js +216 -0
  57. package/dist/handlers/codedna-handlers.d.ts +1 -1
  58. package/dist/handlers/kappa-handlers.d.ts +116 -0
  59. package/dist/handlers/kappa-handlers.js +465 -0
  60. package/dist/handlers/tool-handlers.js +121 -0
  61. package/dist/templates/claude-md.d.ts +1 -1
  62. package/dist/templates/claude-md.js +166 -9
  63. package/dist/tools.js +199 -0
  64. package/docs/research/2026-01-02-codedna-il-specification.md +639 -0
  65. package/docs/research/2026-01-02-codedna-v2-research.md +943 -0
  66. package/docs/research/2026-01-02-computation-foundations.md +564 -0
  67. package/docs/research/2026-01-02-hardware-description.md +814 -0
  68. package/docs/research/2026-01-02-kappa-specification.md +697 -0
  69. package/docs/research/2026-01-02-kappa-tanstack-example.md +527 -0
  70. package/docs/research/2026-01-02-kappa-v2-synthesis.md +406 -0
  71. package/docs/research/2026-01-02-kappa-v2.5-specification.md +1218 -0
  72. package/docs/research/2026-01-02-kappa-v3-specification.md +1864 -0
  73. package/docs/research/2026-01-02-kappa-whitepaper.md +662 -0
  74. package/docs/research/2026-01-02-logic-constraint.md +731 -0
  75. package/docs/research/2026-01-02-quantum-computation.md +635 -0
  76. package/package.json +4 -2
@@ -0,0 +1,64 @@
1
+ // =============================================================================
2
+ // Prisma Generator
3
+ // =============================================================================
4
+ //
5
+ // Generate Prisma schema, client extensions, and typed queries.
6
+ // Industry-standard ORM with excellent DX and type safety.
7
+ //
8
+ import { BaseGenerator } from './base.js';
9
+ export class PrismaGenerator extends BaseGenerator {
10
+ getGeneratorId() {
11
+ return 'prisma';
12
+ }
13
+ getRequiredTemplates(options) {
14
+ const templates = [
15
+ 'model.prisma.j2',
16
+ 'types.ts.j2',
17
+ ];
18
+ if (options.clientExtensions) {
19
+ templates.push('client.ts.j2');
20
+ }
21
+ // Service layer with typed queries
22
+ templates.push('service.ts.j2');
23
+ if (options.seedFile) {
24
+ templates.push('seed.ts.j2');
25
+ }
26
+ if (this.isEnabled(options, 'tests')) {
27
+ templates.push('test.ts.j2');
28
+ }
29
+ return templates;
30
+ }
31
+ getFileMapping(entity, options) {
32
+ const entityLower = entity.name.toLowerCase();
33
+ const mapping = {
34
+ [`prisma/models/${entityLower}.prisma`]: 'model.prisma.j2',
35
+ [`src/types/${entityLower}.ts`]: 'types.ts.j2',
36
+ [`src/services/${entityLower}.service.ts`]: 'service.ts.j2',
37
+ };
38
+ if (options.clientExtensions) {
39
+ mapping['src/lib/prisma.ts'] = 'client.ts.j2';
40
+ }
41
+ if (options.seedFile) {
42
+ mapping['prisma/seed.ts'] = 'seed.ts.j2';
43
+ }
44
+ if (this.isEnabled(options, 'tests')) {
45
+ mapping[`src/services/__tests__/${entityLower}.test.ts`] = 'test.ts.j2';
46
+ }
47
+ return mapping;
48
+ }
49
+ /**
50
+ * Generate Prisma schema from entity specification
51
+ */
52
+ async generate(entity, options = {}) {
53
+ // Set defaults - Prisma specific
54
+ const opts = {
55
+ datasource: 'postgresql',
56
+ clientExtensions: true,
57
+ seedFile: false,
58
+ database: 'postgresql',
59
+ ...options,
60
+ };
61
+ // Generate files
62
+ return super.generate(entity, opts);
63
+ }
64
+ }
@@ -0,0 +1,18 @@
1
+ import { BaseGenerator } from './base.js';
2
+ import { EntitySpec } from '../parser.js';
3
+ import { GenerateFrontendOptions } from '../types.js';
4
+ interface ReactRouterV7Options extends GenerateFrontendOptions {
5
+ loaders?: boolean;
6
+ actions?: boolean;
7
+ streaming?: boolean;
8
+ }
9
+ export declare class ReactRouterV7Generator extends BaseGenerator {
10
+ protected getGeneratorId(): string;
11
+ protected getRequiredTemplates(options: ReactRouterV7Options): string[];
12
+ protected getFileMapping(entity: EntitySpec, options: ReactRouterV7Options): Record<string, string>;
13
+ /**
14
+ * Generate React Router v7 routes from entity specification
15
+ */
16
+ generate(entity: EntitySpec, options?: ReactRouterV7Options): Promise<import('../types.js').GenerationResult>;
17
+ }
18
+ export {};
@@ -0,0 +1,77 @@
1
+ // =============================================================================
2
+ // React Router v7 Generator
3
+ // =============================================================================
4
+ //
5
+ // Generate React Router v7 routes with loaders, actions, and type-safe params.
6
+ // Supports the new framework mode with server-side rendering.
7
+ //
8
+ import { BaseGenerator } from './base.js';
9
+ export class ReactRouterV7Generator extends BaseGenerator {
10
+ getGeneratorId() {
11
+ return 'react-router-v7';
12
+ }
13
+ getRequiredTemplates(options) {
14
+ const templates = [
15
+ 'route.tsx.j2',
16
+ 'types.ts.j2',
17
+ 'schema.ts.j2',
18
+ ];
19
+ if (options.loaders !== false) {
20
+ templates.push('loader.ts.j2');
21
+ }
22
+ if (options.actions !== false) {
23
+ templates.push('action.ts.j2');
24
+ }
25
+ if (this.isEnabled(options, 'forms', true)) {
26
+ templates.push('form.tsx.j2');
27
+ }
28
+ if (this.isEnabled(options, 'tables', true)) {
29
+ templates.push('table.tsx.j2');
30
+ }
31
+ if (this.isEnabled(options, 'tests')) {
32
+ templates.push('test.tsx.j2');
33
+ }
34
+ return templates;
35
+ }
36
+ getFileMapping(entity, options) {
37
+ const entityLower = entity.name.toLowerCase();
38
+ const entityPlural = entityLower + 's';
39
+ const mapping = {
40
+ [`app/routes/${entityPlural}/route.tsx`]: 'route.tsx.j2',
41
+ [`app/types/${entityLower}.ts`]: 'types.ts.j2',
42
+ [`app/schemas/${entityLower}.schema.ts`]: 'schema.ts.j2',
43
+ };
44
+ if (options.loaders !== false) {
45
+ mapping[`app/routes/${entityPlural}/loader.ts`] = 'loader.ts.j2';
46
+ }
47
+ if (options.actions !== false) {
48
+ mapping[`app/routes/${entityPlural}/action.ts`] = 'action.ts.j2';
49
+ }
50
+ if (this.isEnabled(options, 'forms', true)) {
51
+ mapping[`app/components/${entity.name}Form.tsx`] = 'form.tsx.j2';
52
+ }
53
+ if (this.isEnabled(options, 'tables', true)) {
54
+ mapping[`app/components/${entity.name}Table.tsx`] = 'table.tsx.j2';
55
+ }
56
+ if (this.isEnabled(options, 'tests')) {
57
+ mapping[`app/routes/${entityPlural}/__tests__/route.test.tsx`] = 'test.tsx.j2';
58
+ }
59
+ return mapping;
60
+ }
61
+ /**
62
+ * Generate React Router v7 routes from entity specification
63
+ */
64
+ async generate(entity, options = {}) {
65
+ // Set defaults - React Router v7 specific
66
+ const opts = {
67
+ forms: true,
68
+ tables: true,
69
+ loaders: true,
70
+ actions: true,
71
+ streaming: false,
72
+ ...options,
73
+ };
74
+ // Generate files
75
+ return super.generate(entity, opts);
76
+ }
77
+ }
@@ -0,0 +1,21 @@
1
+ import { BaseGenerator, GeneratedFile, GeneratorOptions } from './base.js';
2
+ import { EntitySpec } from '../parser.js';
3
+ export interface React19ShadcnOptions extends GeneratorOptions {
4
+ componentPattern?: 'compound' | 'simple';
5
+ formPattern?: 'controlled' | 'uncontrolled';
6
+ includeTable?: boolean;
7
+ includeModal?: boolean;
8
+ includeDrawer?: boolean;
9
+ }
10
+ export declare class React19ShadcnGenerator extends BaseGenerator {
11
+ private engine;
12
+ private options;
13
+ constructor(options?: React19ShadcnOptions);
14
+ generate(entity: EntitySpec): Promise<GeneratedFile[]>;
15
+ private generateFormComponent;
16
+ private generateTableComponent;
17
+ private generateModalComponent;
18
+ private generateDrawerComponent;
19
+ private generateCardComponent;
20
+ private generateTypes;
21
+ }
@@ -0,0 +1,367 @@
1
+ // =============================================================================
2
+ // React 19 + ShadcnUI Component Generator
3
+ // =============================================================================
4
+ //
5
+ // Generates modern React components using:
6
+ // - React 19 features (useOptimistic, useActionState, useFormStatus)
7
+ // - ShadcnUI components (Button, Input, Select, Table, etc.)
8
+ // - Compound component patterns
9
+ // - TypeScript types
10
+ // - Accessible components (ARIA)
11
+ //
12
+ import { BaseGenerator } from './base.js';
13
+ import { TemplateEngine, buildContext } from '../template-engine.js';
14
+ export class React19ShadcnGenerator extends BaseGenerator {
15
+ engine;
16
+ options;
17
+ constructor(options = {}) {
18
+ super();
19
+ this.engine = new TemplateEngine();
20
+ this.options = {
21
+ componentPattern: options.componentPattern || 'compound',
22
+ formPattern: options.formPattern || 'controlled',
23
+ includeTable: options.includeTable ?? true,
24
+ includeModal: options.includeModal ?? true,
25
+ includeDrawer: options.includeDrawer ?? false,
26
+ ...options,
27
+ };
28
+ }
29
+ async generate(entity) {
30
+ const files = [];
31
+ const context = buildContext(entity, this.options);
32
+ // Form component with React 19 hooks
33
+ files.push(await this.generateFormComponent(entity, context));
34
+ // Data table with sorting/filtering
35
+ if (this.options.includeTable) {
36
+ files.push(await this.generateTableComponent(entity, context));
37
+ }
38
+ // Modal component
39
+ if (this.options.includeModal) {
40
+ files.push(await this.generateModalComponent(entity, context));
41
+ }
42
+ // Drawer component
43
+ if (this.options.includeDrawer) {
44
+ files.push(await this.generateDrawerComponent(entity, context));
45
+ }
46
+ // Card component
47
+ files.push(await this.generateCardComponent(entity, context));
48
+ // Types
49
+ files.push(await this.generateTypes(entity, context));
50
+ return files;
51
+ }
52
+ async generateFormComponent(entity, context) {
53
+ const template = `// ${entity.name} Form Component (React 19 + ShadcnUI)
54
+ // Generated by CodeDNA
55
+
56
+ import { useActionState, useOptimistic } from 'react';
57
+ import { Button } from '@/components/ui/button';
58
+ import { Input } from '@/components/ui/input';
59
+ import { Label } from '@/components/ui/label';
60
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
61
+ import { ${entity.name} } from '@/types/${entity.name.toLowerCase()}';
62
+
63
+ interface ${entity.name}FormProps {
64
+ initialData?: Partial<${entity.name}>;
65
+ onSubmit: (data: FormData) => Promise<void>;
66
+ }
67
+
68
+ export function ${entity.name}Form({ initialData, onSubmit }: ${entity.name}FormProps) {
69
+ const [state, formAction, isPending] = useActionState(
70
+ async (prevState: any, formData: FormData) => {
71
+ try {
72
+ await onSubmit(formData);
73
+ return { success: true, error: null };
74
+ } catch (error) {
75
+ return { success: false, error: error instanceof Error ? error.message : 'Failed to submit' };
76
+ }
77
+ },
78
+ { success: false, error: null }
79
+ );
80
+
81
+ return (
82
+ <form action={formAction} className="space-y-6">
83
+ ${entity.fields.map(field => {
84
+ if (field.type.kind === 'primitive') {
85
+ return ` <div className="space-y-2">
86
+ <Label htmlFor="${field.name}">${field.name.charAt(0).toUpperCase() + field.name.slice(1)}</Label>
87
+ <Input
88
+ id="${field.name}"
89
+ name="${field.name}"
90
+ type="${field.type.value === 'email' ? 'email' : field.type.value === 'integer' || field.type.value === 'decimal' ? 'number' : 'text'}"
91
+ defaultValue={initialData?.${field.name} || ''}
92
+ ${field.constraints.some(c => c.kind === 'required') ? 'required' : ''}
93
+ disabled={isPending}
94
+ />
95
+ </div>`;
96
+ }
97
+ else if (field.type.kind === 'enum') {
98
+ return ` <div className="space-y-2">
99
+ <Label htmlFor="${field.name}">${field.name.charAt(0).toUpperCase() + field.name.slice(1)}</Label>
100
+ <Select name="${field.name}" defaultValue={initialData?.${field.name}} disabled={isPending}>
101
+ <SelectTrigger>
102
+ <SelectValue placeholder="Select ${field.name}" />
103
+ </SelectTrigger>
104
+ <SelectContent>
105
+ ${field.type.values.map(v => ` <SelectItem value="${v}">${v}</SelectItem>`).join('\n')}
106
+ </SelectContent>
107
+ </Select>
108
+ </div>`;
109
+ }
110
+ return '';
111
+ }).filter(Boolean).join('\n\n')}
112
+
113
+ {state.error && (
114
+ <div className="text-sm text-red-600">{state.error}</div>
115
+ )}
116
+
117
+ <div className="flex gap-4">
118
+ <Button type="submit" disabled={isPending}>
119
+ {isPending ? 'Saving...' : 'Save'}
120
+ </Button>
121
+ <Button type="button" variant="outline" disabled={isPending}>
122
+ Cancel
123
+ </Button>
124
+ </div>
125
+ </form>
126
+ );
127
+ }`;
128
+ return {
129
+ path: `src/components/${entity.name}Form.tsx`,
130
+ content: template,
131
+ language: 'typescript',
132
+ };
133
+ }
134
+ async generateTableComponent(entity, context) {
135
+ const template = `// ${entity.name} Table Component (React 19 + ShadcnUI)
136
+ // Generated by CodeDNA
137
+
138
+ import { useState } from 'react';
139
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
140
+ import { Button } from '@/components/ui/button';
141
+ import { ${entity.name} } from '@/types/${entity.name.toLowerCase()}';
142
+
143
+ interface ${entity.name}TableProps {
144
+ data: ${entity.name}[];
145
+ onEdit?: (item: ${entity.name}) => void;
146
+ onDelete?: (id: number) => void;
147
+ }
148
+
149
+ export function ${entity.name}Table({ data, onEdit, onDelete }: ${entity.name}TableProps) {
150
+ const [sortField, setSortField] = useState<keyof ${entity.name} | null>(null);
151
+ const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc');
152
+
153
+ const sortedData = [...data].sort((a, b) => {
154
+ if (!sortField) return 0;
155
+ const aVal = a[sortField];
156
+ const bVal = b[sortField];
157
+ if (aVal < bVal) return sortDirection === 'asc' ? -1 : 1;
158
+ if (aVal > bVal) return sortDirection === 'asc' ? 1 : -1;
159
+ return 0;
160
+ });
161
+
162
+ const handleSort = (field: keyof ${entity.name}) => {
163
+ if (sortField === field) {
164
+ setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc');
165
+ } else {
166
+ setSortField(field);
167
+ setSortDirection('asc');
168
+ }
169
+ };
170
+
171
+ return (
172
+ <Table>
173
+ <TableHeader>
174
+ <TableRow>
175
+ <TableHead onClick={() => handleSort('id')} className="cursor-pointer">
176
+ ID {sortField === 'id' && (sortDirection === 'asc' ? '↑' : '↓')}
177
+ </TableHead>
178
+ ${entity.fields.slice(0, 5).map(field => ` <TableHead onClick={() => handleSort('${field.name}' as keyof ${entity.name})} className="cursor-pointer">
179
+ ${field.name.charAt(0).toUpperCase() + field.name.slice(1)} {sortField === '${field.name}' && (sortDirection === 'asc' ? '↑' : '↓')}
180
+ </TableHead>`).join('\n')}
181
+ <TableHead>Actions</TableHead>
182
+ </TableRow>
183
+ </TableHeader>
184
+ <TableBody>
185
+ {sortedData.map((item) => (
186
+ <TableRow key={item.id}>
187
+ <TableCell>{item.id}</TableCell>
188
+ ${entity.fields.slice(0, 5).map(field => ` <TableCell>{item.${field.name}}</TableCell>`).join('\n')}
189
+ <TableCell>
190
+ <div className="flex gap-2">
191
+ {onEdit && (
192
+ <Button variant="outline" size="sm" onClick={() => onEdit(item)}>
193
+ Edit
194
+ </Button>
195
+ )}
196
+ {onDelete && (
197
+ <Button variant="destructive" size="sm" onClick={() => onDelete(item.id)}>
198
+ Delete
199
+ </Button>
200
+ )}
201
+ </div>
202
+ </TableCell>
203
+ </TableRow>
204
+ ))}
205
+ </TableBody>
206
+ </Table>
207
+ );
208
+ }`;
209
+ return {
210
+ path: `src/components/${entity.name}Table.tsx`,
211
+ content: template,
212
+ language: 'typescript',
213
+ };
214
+ }
215
+ async generateModalComponent(entity, context) {
216
+ const template = `// ${entity.name} Modal Component (React 19 + ShadcnUI)
217
+ // Generated by CodeDNA
218
+
219
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
220
+ import { ${entity.name}Form } from './${entity.name}Form';
221
+ import { ${entity.name} } from '@/types/${entity.name.toLowerCase()}';
222
+
223
+ interface ${entity.name}ModalProps {
224
+ open: boolean;
225
+ onOpenChange: (open: boolean) => void;
226
+ initialData?: Partial<${entity.name}>;
227
+ onSubmit: (data: FormData) => Promise<void>;
228
+ }
229
+
230
+ export function ${entity.name}Modal({ open, onOpenChange, initialData, onSubmit }: ${entity.name}ModalProps) {
231
+ const handleSubmit = async (data: FormData) => {
232
+ await onSubmit(data);
233
+ onOpenChange(false);
234
+ };
235
+
236
+ return (
237
+ <Dialog open={open} onOpenChange={onOpenChange}>
238
+ <DialogContent>
239
+ <DialogHeader>
240
+ <DialogTitle>{initialData ? 'Edit' : 'Create'} ${entity.name}</DialogTitle>
241
+ </DialogHeader>
242
+ <${entity.name}Form initialData={initialData} onSubmit={handleSubmit} />
243
+ </DialogContent>
244
+ </Dialog>
245
+ );
246
+ }`;
247
+ return {
248
+ path: `src/components/${entity.name}Modal.tsx`,
249
+ content: template,
250
+ language: 'typescript',
251
+ };
252
+ }
253
+ async generateDrawerComponent(entity, context) {
254
+ const template = `// ${entity.name} Drawer Component (React 19 + ShadcnUI)
255
+ // Generated by CodeDNA
256
+
257
+ import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
258
+ import { ${entity.name}Form } from './${entity.name}Form';
259
+ import { ${entity.name} } from '@/types/${entity.name.toLowerCase()}';
260
+
261
+ interface ${entity.name}DrawerProps {
262
+ open: boolean;
263
+ onOpenChange: (open: boolean) => void;
264
+ initialData?: Partial<${entity.name}>;
265
+ onSubmit: (data: FormData) => Promise<void>;
266
+ }
267
+
268
+ export function ${entity.name}Drawer({ open, onOpenChange, initialData, onSubmit }: ${entity.name}DrawerProps) {
269
+ const handleSubmit = async (data: FormData) => {
270
+ await onSubmit(data);
271
+ onOpenChange(false);
272
+ };
273
+
274
+ return (
275
+ <Sheet open={open} onOpenChange={onOpenChange}>
276
+ <SheetContent>
277
+ <SheetHeader>
278
+ <SheetTitle>{initialData ? 'Edit' : 'Create'} ${entity.name}</SheetTitle>
279
+ </SheetHeader>
280
+ <div className="mt-6">
281
+ <${entity.name}Form initialData={initialData} onSubmit={handleSubmit} />
282
+ </div>
283
+ </SheetContent>
284
+ </Sheet>
285
+ );
286
+ }`;
287
+ return {
288
+ path: `src/components/${entity.name}Drawer.tsx`,
289
+ content: template,
290
+ language: 'typescript',
291
+ };
292
+ }
293
+ async generateCardComponent(entity, context) {
294
+ const template = `// ${entity.name} Card Component (React 19 + ShadcnUI)
295
+ // Generated by CodeDNA
296
+
297
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
298
+ import { ${entity.name} } from '@/types/${entity.name.toLowerCase()}';
299
+
300
+ interface ${entity.name}CardProps {
301
+ item: ${entity.name};
302
+ onEdit?: () => void;
303
+ onDelete?: () => void;
304
+ }
305
+
306
+ export function ${entity.name}Card({ item, onEdit, onDelete }: ${entity.name}CardProps) {
307
+ return (
308
+ <Card>
309
+ <CardHeader>
310
+ <CardTitle>${entity.name} #{item.id}</CardTitle>
311
+ ${entity.fields.slice(0, 1).map(field => ` <CardDescription>{item.${field.name}}</CardDescription>`).join('\n')}
312
+ </CardHeader>
313
+ <CardContent>
314
+ <dl className="space-y-2">
315
+ ${entity.fields.slice(1, 4).map(field => ` <div>
316
+ <dt className="text-sm font-medium text-gray-500">${field.name.charAt(0).toUpperCase() + field.name.slice(1)}</dt>
317
+ <dd className="text-sm text-gray-900">{item.${field.name}}</dd>
318
+ </div>`).join('\n')}
319
+ </dl>
320
+ </CardContent>
321
+ </Card>
322
+ );
323
+ }`;
324
+ return {
325
+ path: `src/components/${entity.name}Card.tsx`,
326
+ content: template,
327
+ language: 'typescript',
328
+ };
329
+ }
330
+ async generateTypes(entity, context) {
331
+ const template = `// ${entity.name} Types
332
+ // Generated by CodeDNA
333
+
334
+ export interface ${entity.name} {
335
+ id: number;
336
+ ${entity.fields.map(field => {
337
+ let type = 'string';
338
+ if (field.type.kind === 'primitive') {
339
+ if (field.type.value === 'integer' || field.type.value === 'decimal')
340
+ type = 'number';
341
+ else if (field.type.value === 'boolean')
342
+ type = 'boolean';
343
+ else if (field.type.value === 'datetime')
344
+ type = 'Date';
345
+ }
346
+ else if (field.type.kind === 'enum') {
347
+ type = field.type.values.map(v => `'${v}'`).join(' | ');
348
+ }
349
+ else if (field.type.kind === 'array') {
350
+ type = `${field.type.itemType}[]`;
351
+ }
352
+ const nullable = !field.constraints.some(c => c.kind === 'required');
353
+ return ` ${field.name}: ${type}${nullable ? ' | null' : ''};`;
354
+ }).join('\n')}
355
+ createdAt: Date;
356
+ updatedAt: Date;
357
+ }
358
+
359
+ export type Create${entity.name}Input = Omit<${entity.name}, 'id' | 'createdAt' | 'updatedAt'>;
360
+ export type Update${entity.name}Input = Partial<Create${entity.name}Input>;`;
361
+ return {
362
+ path: `src/types/${entity.name.toLowerCase()}.ts`,
363
+ content: template,
364
+ language: 'typescript',
365
+ };
366
+ }
367
+ }
@@ -0,0 +1,18 @@
1
+ import { BaseGenerator } from './base.js';
2
+ import { EntitySpec } from '../parser.js';
3
+ import { GenerateFrontendOptions } from '../types.js';
4
+ interface SvelteKitOptions extends GenerateFrontendOptions {
5
+ ssr?: boolean;
6
+ formActions?: boolean;
7
+ superforms?: boolean;
8
+ }
9
+ export declare class SvelteKitGenerator extends BaseGenerator {
10
+ protected getGeneratorId(): string;
11
+ protected getRequiredTemplates(options: SvelteKitOptions): string[];
12
+ protected getFileMapping(entity: EntitySpec, options: SvelteKitOptions): Record<string, string>;
13
+ /**
14
+ * Generate SvelteKit pages and components from entity specification
15
+ */
16
+ generate(entity: EntitySpec, options?: SvelteKitOptions): Promise<import('../types.js').GenerationResult>;
17
+ }
18
+ export {};
@@ -0,0 +1,73 @@
1
+ // =============================================================================
2
+ // SvelteKit Generator
3
+ // =============================================================================
4
+ //
5
+ // Generate SvelteKit pages, components, server routes, and form actions.
6
+ // Full-stack TypeScript with server-side rendering and form handling.
7
+ //
8
+ import { BaseGenerator } from './base.js';
9
+ export class SvelteKitGenerator extends BaseGenerator {
10
+ getGeneratorId() {
11
+ return 'sveltekit';
12
+ }
13
+ getRequiredTemplates(options) {
14
+ const templates = [
15
+ 'page.svelte.j2',
16
+ 'page.server.ts.j2',
17
+ 'schema.ts.j2',
18
+ 'types.ts.j2',
19
+ ];
20
+ if (this.isEnabled(options, 'forms', true)) {
21
+ templates.push('form.svelte.j2');
22
+ }
23
+ if (this.isEnabled(options, 'tables', true)) {
24
+ templates.push('table.svelte.j2');
25
+ }
26
+ if (options.superforms) {
27
+ templates.push('superform.svelte.j2');
28
+ }
29
+ if (this.isEnabled(options, 'tests')) {
30
+ templates.push('test.ts.j2');
31
+ }
32
+ return templates;
33
+ }
34
+ getFileMapping(entity, options) {
35
+ const entityLower = entity.name.toLowerCase();
36
+ const entityPlural = entityLower + 's';
37
+ const mapping = {
38
+ [`src/routes/${entityPlural}/+page.svelte`]: 'page.svelte.j2',
39
+ [`src/routes/${entityPlural}/+page.server.ts`]: 'page.server.ts.j2',
40
+ [`src/lib/schemas/${entityLower}.schema.ts`]: 'schema.ts.j2',
41
+ [`src/lib/types/${entityLower}.ts`]: 'types.ts.j2',
42
+ };
43
+ if (this.isEnabled(options, 'forms', true)) {
44
+ mapping[`src/lib/components/${entity.name}Form.svelte`] = 'form.svelte.j2';
45
+ }
46
+ if (this.isEnabled(options, 'tables', true)) {
47
+ mapping[`src/lib/components/${entity.name}Table.svelte`] = 'table.svelte.j2';
48
+ }
49
+ if (options.superforms) {
50
+ mapping[`src/lib/components/${entity.name}SuperForm.svelte`] = 'superform.svelte.j2';
51
+ }
52
+ if (this.isEnabled(options, 'tests')) {
53
+ mapping[`src/routes/${entityPlural}/__tests__/page.test.ts`] = 'test.ts.j2';
54
+ }
55
+ return mapping;
56
+ }
57
+ /**
58
+ * Generate SvelteKit pages and components from entity specification
59
+ */
60
+ async generate(entity, options = {}) {
61
+ // Set defaults - SvelteKit specific
62
+ const opts = {
63
+ forms: true,
64
+ tables: true,
65
+ ssr: true,
66
+ formActions: true,
67
+ superforms: false,
68
+ ...options,
69
+ };
70
+ // Generate files
71
+ return super.generate(entity, opts);
72
+ }
73
+ }