@claudetools/tools 0.9.0 → 0.9.2

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 (85) hide show
  1. package/dist/cli.js +9 -1
  2. package/dist/codedna/__tests__/examples/mongoose-example.d.ts +6 -0
  3. package/dist/codedna/__tests__/examples/mongoose-example.js +163 -0
  4. package/dist/codedna/__tests__/fixtures/typeorm-production-test.d.ts +1 -0
  5. package/dist/codedna/__tests__/fixtures/typeorm-production-test.js +231 -0
  6. package/dist/codedna/__tests__/fixtures/typeorm-test.d.ts +1 -0
  7. package/dist/codedna/__tests__/fixtures/typeorm-test.js +124 -0
  8. package/dist/codedna/__tests__/laravel-output-review.d.ts +1 -0
  9. package/dist/codedna/__tests__/laravel-output-review.js +249 -0
  10. package/dist/codedna/__tests__/mongoose-output-test.d.ts +1 -0
  11. package/dist/codedna/__tests__/mongoose-output-test.js +178 -0
  12. package/dist/codedna/examples/radix-example.d.ts +2 -0
  13. package/dist/codedna/examples/radix-example.js +259 -0
  14. package/dist/codedna/index.d.ts +5 -3
  15. package/dist/codedna/index.js +6 -3
  16. package/dist/codedna/kappa-ast.d.ts +143 -5
  17. package/dist/codedna/kappa-drizzle-generator.js +8 -5
  18. package/dist/codedna/kappa-gofiber-generator.d.ts +65 -0
  19. package/dist/codedna/kappa-gofiber-generator.js +587 -0
  20. package/dist/codedna/kappa-laravel-generator.d.ts +68 -0
  21. package/dist/codedna/kappa-laravel-generator.js +741 -0
  22. package/dist/codedna/kappa-lexer.d.ts +44 -0
  23. package/dist/codedna/kappa-lexer.js +124 -0
  24. package/dist/codedna/kappa-mantine-generator.d.ts +65 -0
  25. package/dist/codedna/kappa-mantine-generator.js +518 -0
  26. package/dist/codedna/kappa-mongoose-generator.d.ts +44 -0
  27. package/dist/codedna/kappa-mongoose-generator.js +442 -0
  28. package/dist/codedna/kappa-parser.d.ts +43 -1
  29. package/dist/codedna/kappa-parser.js +601 -0
  30. package/dist/codedna/kappa-radix-generator.d.ts +61 -0
  31. package/dist/codedna/kappa-radix-generator.js +566 -0
  32. package/dist/codedna/kappa-typeorm-generator.d.ts +59 -0
  33. package/dist/codedna/kappa-typeorm-generator.js +723 -0
  34. package/dist/codedna/kappa-vitest-generator.d.ts +85 -0
  35. package/dist/codedna/kappa-vitest-generator.js +739 -0
  36. package/dist/codedna/parser.js +26 -1
  37. package/dist/codegen/cloud-client.d.ts +160 -0
  38. package/dist/codegen/cloud-client.js +195 -0
  39. package/dist/codegen/codegen-tool.d.ts +35 -0
  40. package/dist/codegen/codegen-tool.js +312 -0
  41. package/dist/codegen/field-inference.d.ts +24 -0
  42. package/dist/codegen/field-inference.js +101 -0
  43. package/dist/codegen/form-parser.d.ts +13 -0
  44. package/dist/codegen/form-parser.js +186 -0
  45. package/dist/codegen/index.d.ts +2 -0
  46. package/dist/codegen/index.js +4 -0
  47. package/dist/codegen/natural-parser.d.ts +50 -0
  48. package/dist/codegen/natural-parser.js +769 -0
  49. package/dist/handlers/codedna-handlers.d.ts +1 -1
  50. package/dist/handlers/codegen-handlers.d.ts +20 -0
  51. package/dist/handlers/codegen-handlers.js +60 -0
  52. package/dist/handlers/kappa-handlers.d.ts +97 -0
  53. package/dist/handlers/kappa-handlers.js +408 -0
  54. package/dist/handlers/tool-handlers.js +124 -221
  55. package/dist/helpers/api-client.js +48 -3
  56. package/dist/helpers/compact-formatter.d.ts +9 -2
  57. package/dist/helpers/compact-formatter.js +26 -2
  58. package/dist/helpers/config.d.ts +7 -2
  59. package/dist/helpers/config.js +25 -10
  60. package/dist/helpers/session-validation.d.ts +1 -1
  61. package/dist/helpers/session-validation.js +2 -4
  62. package/dist/helpers/tasks.d.ts +21 -0
  63. package/dist/helpers/tasks.js +52 -0
  64. package/dist/helpers/workers.d.ts +1 -1
  65. package/dist/helpers/workers.js +19 -19
  66. package/dist/setup.d.ts +1 -0
  67. package/dist/setup.js +228 -3
  68. package/dist/templates/claude-md.d.ts +1 -1
  69. package/dist/templates/claude-md.js +37 -152
  70. package/dist/templates/orchestrator-prompt.d.ts +2 -2
  71. package/dist/templates/orchestrator-prompt.js +31 -38
  72. package/dist/templates/self-critique.d.ts +50 -0
  73. package/dist/templates/self-critique.js +209 -0
  74. package/dist/templates/worker-prompt.d.ts +3 -3
  75. package/dist/templates/worker-prompt.js +18 -18
  76. package/dist/tools.js +77 -413
  77. package/docs/codedna/generator-testing-summary.md +205 -0
  78. package/docs/codedna/radix-ui-generator.md +478 -0
  79. package/docs/kappa-gofiber-generator.md +274 -0
  80. package/docs/kappa-laravel-fixes.md +172 -0
  81. package/docs/kappa-mongoose-generator.md +322 -0
  82. package/docs/kappa-vitest-generator.md +337 -0
  83. package/package.json +1 -1
  84. package/dist/context/deduplication.test.d.ts +0 -6
  85. package/dist/context/deduplication.test.js +0 -84
@@ -0,0 +1,518 @@
1
+ // =============================================================================
2
+ // Kappa v2.5 Mantine Generator
3
+ // =============================================================================
4
+ //
5
+ // Generates Mantine UI components and forms from Kappa ComponentBlock/FormBlock AST.
6
+ // Supports @mantine/core components, @mantine/form, and @mantine/hooks.
7
+ //
8
+ // =============================================================================
9
+ // Generator Class
10
+ // =============================================================================
11
+ export class KappaMantineGenerator {
12
+ provenance;
13
+ typescript;
14
+ zod;
15
+ forwardRef;
16
+ basePath;
17
+ constructor(options = {}) {
18
+ this.provenance = options.provenance ?? true;
19
+ this.typescript = options.typescript ?? true;
20
+ this.zod = options.zod ?? true;
21
+ this.forwardRef = options.forwardRef ?? false;
22
+ this.basePath = options.basePath ?? 'components';
23
+ }
24
+ /**
25
+ * Generate components from ComponentBlock AST nodes
26
+ */
27
+ generateComponents(components) {
28
+ const files = [];
29
+ for (const component of components) {
30
+ files.push(this.generateComponent(component));
31
+ }
32
+ return { files };
33
+ }
34
+ /**
35
+ * Generate forms from FormBlock AST nodes
36
+ */
37
+ generateForms(forms) {
38
+ const files = [];
39
+ for (const form of forms) {
40
+ files.push(this.generateForm(form));
41
+ }
42
+ return { files };
43
+ }
44
+ // ===========================================================================
45
+ // Component Generation
46
+ // ===========================================================================
47
+ generateComponent(component) {
48
+ const lines = [];
49
+ const ext = this.typescript ? 'tsx' : 'jsx';
50
+ // Header
51
+ if (this.provenance) {
52
+ lines.push('// Generated by Kappa v2.5 CodeDNA - Mantine');
53
+ lines.push(`// Component: ${component.name}`);
54
+ lines.push('');
55
+ }
56
+ // Imports
57
+ lines.push("import { Box, Stack, Group } from '@mantine/core';");
58
+ if (this.forwardRef) {
59
+ lines.push("import { forwardRef } from 'react';");
60
+ }
61
+ if (component.compound && component.compound.length > 0) {
62
+ lines.push("import { createContext, useContext } from 'react';");
63
+ }
64
+ lines.push('');
65
+ // Props interface
66
+ if (this.typescript) {
67
+ lines.push(this.generateComponentPropsInterface(component));
68
+ lines.push('');
69
+ }
70
+ // Component
71
+ if (component.compound && component.compound.length > 0) {
72
+ lines.push(this.generateCompoundComponent(component));
73
+ }
74
+ else if (this.forwardRef) {
75
+ lines.push(this.generateForwardRefComponent(component));
76
+ }
77
+ else {
78
+ lines.push(this.generateFunctionComponent(component));
79
+ }
80
+ return {
81
+ path: `${this.basePath}/${this.toKebabCase(component.name)}.${ext}`,
82
+ content: lines.join('\n'),
83
+ };
84
+ }
85
+ generateComponentPropsInterface(component) {
86
+ const lines = [];
87
+ const propsName = `${component.name}Props`;
88
+ lines.push(`export interface ${propsName} {`);
89
+ for (const prop of component.props) {
90
+ const optional = prop.optional ? '?' : '';
91
+ lines.push(` ${prop.name}${optional}: ${this.mapPropType(prop.type)};`);
92
+ }
93
+ // Mantine style props
94
+ lines.push(' className?: string;');
95
+ lines.push(' style?: React.CSSProperties;');
96
+ lines.push(' children?: React.ReactNode;');
97
+ lines.push('}');
98
+ return lines.join('\n');
99
+ }
100
+ generateFunctionComponent(component) {
101
+ const lines = [];
102
+ const propsType = this.typescript ? `: ${component.name}Props` : '';
103
+ const destructuredProps = this.getDestructuredProps(component);
104
+ lines.push(`export function ${component.name}({ ${destructuredProps} }${propsType}) {`);
105
+ lines.push(' return (');
106
+ if (component.structure) {
107
+ lines.push(this.generateStructureJSX(component.structure, 4));
108
+ }
109
+ else {
110
+ lines.push(` <Box className={className} style={style}>`);
111
+ lines.push(' {children}');
112
+ lines.push(' </Box>');
113
+ }
114
+ lines.push(' );');
115
+ lines.push('}');
116
+ return lines.join('\n');
117
+ }
118
+ generateForwardRefComponent(component) {
119
+ const lines = [];
120
+ const propsType = this.typescript ? `${component.name}Props` : '';
121
+ const refType = this.typescript ? 'HTMLDivElement' : '';
122
+ const destructuredProps = this.getDestructuredProps(component);
123
+ lines.push(`export const ${component.name} = forwardRef<${refType}${propsType ? `, ${propsType}` : ''}>(`);
124
+ lines.push(` function ${component.name}({ ${destructuredProps} }, ref) {`);
125
+ lines.push(' return (');
126
+ if (component.structure) {
127
+ lines.push(this.generateStructureJSX(component.structure, 6, 'ref={ref}'));
128
+ }
129
+ else {
130
+ lines.push(` <Box ref={ref} className={className} style={style}>`);
131
+ lines.push(' {children}');
132
+ lines.push(' </Box>');
133
+ }
134
+ lines.push(' );');
135
+ lines.push(' }');
136
+ lines.push(');');
137
+ return lines.join('\n');
138
+ }
139
+ generateCompoundComponent(component) {
140
+ const lines = [];
141
+ // Context
142
+ if (this.typescript) {
143
+ lines.push(`interface ${component.name}ContextValue {`);
144
+ for (const prop of component.props) {
145
+ lines.push(` ${prop.name}${prop.optional ? '?' : ''}: ${this.mapPropType(prop.type)};`);
146
+ }
147
+ lines.push('}');
148
+ lines.push('');
149
+ }
150
+ const contextType = this.typescript ? `${component.name}ContextValue | null` : '';
151
+ lines.push(`const ${component.name}Context = createContext<${contextType}>(null);`);
152
+ lines.push('');
153
+ // Hook
154
+ lines.push(`function use${component.name}() {`);
155
+ lines.push(` const context = useContext(${component.name}Context);`);
156
+ lines.push(' if (!context) {');
157
+ lines.push(` throw new Error('${component.name} compound components must be used within ${component.name}');`);
158
+ lines.push(' }');
159
+ lines.push(' return context;');
160
+ lines.push('}');
161
+ lines.push('');
162
+ // Root component
163
+ const destructuredProps = this.getDestructuredProps(component);
164
+ const propsType = this.typescript ? `: ${component.name}Props` : '';
165
+ lines.push(`function ${component.name}Root({ ${destructuredProps} }${propsType}) {`);
166
+ const contextValue = component.props.map((p) => p.name).join(', ');
167
+ lines.push(` const value = { ${contextValue} };`);
168
+ lines.push('');
169
+ lines.push(' return (');
170
+ lines.push(` <${component.name}Context.Provider value={value}>`);
171
+ lines.push(` <Box className={className} style={style}>`);
172
+ lines.push(' {children}');
173
+ lines.push(' </Box>');
174
+ lines.push(` </${component.name}Context.Provider>`);
175
+ lines.push(' );');
176
+ lines.push('}');
177
+ lines.push('');
178
+ // Compound parts
179
+ for (const part of component.compound) {
180
+ lines.push(this.generateCompoundPart(component.name, part));
181
+ lines.push('');
182
+ }
183
+ // Export compound object
184
+ lines.push(`export const ${component.name} = Object.assign(${component.name}Root, {`);
185
+ for (const part of component.compound) {
186
+ lines.push(` ${part.name}: ${component.name}${part.name},`);
187
+ }
188
+ lines.push('});');
189
+ return lines.join('\n');
190
+ }
191
+ generateCompoundPart(parentName, part) {
192
+ const lines = [];
193
+ const partName = `${parentName}${part.name}`;
194
+ if (this.typescript) {
195
+ lines.push(`interface ${partName}Props {`);
196
+ lines.push(' className?: string;');
197
+ lines.push(' style?: React.CSSProperties;');
198
+ lines.push(' children?: React.ReactNode;');
199
+ if (part.props) {
200
+ for (const prop of part.props) {
201
+ lines.push(` ${prop}?: string;`);
202
+ }
203
+ }
204
+ lines.push('}');
205
+ lines.push('');
206
+ }
207
+ const propsType = this.typescript ? `: ${partName}Props` : '';
208
+ const propsStr = part.props
209
+ ? `{ className, style, children, ${part.props.join(', ')} }`
210
+ : '{ className, style, children }';
211
+ lines.push(`function ${partName}(${propsStr}${propsType}) {`);
212
+ lines.push(` const context = use${parentName}();`);
213
+ lines.push('');
214
+ lines.push(' return (');
215
+ lines.push(` <Box component="${part.element}" className={className} style={style}>`);
216
+ lines.push(' {children}');
217
+ lines.push(' </Box>');
218
+ lines.push(' );');
219
+ lines.push('}');
220
+ return lines.join('\n');
221
+ }
222
+ generateStructureJSX(structure, indent, extraProps = '') {
223
+ const spaces = ' '.repeat(indent);
224
+ const lines = [];
225
+ const mantineComponent = this.mapToMantineComponent(structure.type);
226
+ const props = Object.entries(structure.props || {})
227
+ .map(([k, v]) => `${k}="${v}"`)
228
+ .join(' ');
229
+ const allProps = [extraProps, props, 'className={className}', 'style={style}'].filter(Boolean).join(' ');
230
+ if (structure.children && structure.children.length > 0) {
231
+ lines.push(`${spaces}<${mantineComponent} ${allProps}>`);
232
+ for (const child of structure.children) {
233
+ lines.push(this.generateStructureJSX(child, indent + 2));
234
+ }
235
+ lines.push(`${spaces}</${mantineComponent}>`);
236
+ }
237
+ else {
238
+ lines.push(`${spaces}<${mantineComponent} ${allProps}>{children}</${mantineComponent}>`);
239
+ }
240
+ return lines.join('\n');
241
+ }
242
+ getDestructuredProps(component) {
243
+ const propNames = component.props.map((p) => p.name);
244
+ propNames.push('className', 'style', 'children');
245
+ return propNames.join(', ');
246
+ }
247
+ // ===========================================================================
248
+ // Form Generation
249
+ // ===========================================================================
250
+ generateForm(form) {
251
+ const lines = [];
252
+ const ext = this.typescript ? 'tsx' : 'jsx';
253
+ const formName = form.name;
254
+ const componentName = `${formName}Form`;
255
+ // Header
256
+ if (this.provenance) {
257
+ lines.push('// Generated by Kappa v2.5 CodeDNA - Mantine');
258
+ lines.push(`// Form: ${formName}`);
259
+ lines.push('');
260
+ }
261
+ lines.push("'use client';");
262
+ lines.push('');
263
+ // Imports
264
+ lines.push("import { useForm } from '@mantine/form';");
265
+ if (this.zod) {
266
+ lines.push("import { zodResolver } from 'mantine-form-zod-resolver';");
267
+ lines.push("import { z } from 'zod';");
268
+ }
269
+ lines.push("import { useState } from 'react';");
270
+ lines.push("import { TextInput, Textarea, NumberInput, Select, Checkbox, Button, Stack, Group } from '@mantine/core';");
271
+ lines.push('');
272
+ // Generate Zod schema
273
+ if (this.zod) {
274
+ lines.push(this.generateZodSchema(form));
275
+ lines.push('');
276
+ if (this.typescript) {
277
+ lines.push(`type ${formName}FormData = z.infer<typeof ${this.toCamelCase(formName)}Schema>;`);
278
+ lines.push('');
279
+ }
280
+ }
281
+ // Component props type
282
+ if (this.typescript) {
283
+ lines.push(`interface ${componentName}Props {`);
284
+ lines.push(` onSubmit: (data: ${this.zod ? `${formName}FormData` : 'Record<string, unknown>'}) => void | Promise<void>;`);
285
+ lines.push(` initialValues?: Partial<${this.zod ? `${formName}FormData` : 'Record<string, unknown>'}>;`);
286
+ lines.push(` isLoading?: boolean;`);
287
+ lines.push('}');
288
+ lines.push('');
289
+ }
290
+ // Component
291
+ const propsType = this.typescript ? `: ${componentName}Props` : '';
292
+ lines.push(`export function ${componentName}({ onSubmit, initialValues, isLoading }${propsType}) {`);
293
+ lines.push(` const [submitting, setSubmitting] = useState(false);`);
294
+ lines.push('');
295
+ // Mantine form hook
296
+ lines.push(` const form = useForm${this.typescript && this.zod ? `<${formName}FormData>` : ''}({`);
297
+ if (this.zod) {
298
+ lines.push(` validate: zodResolver(${this.toCamelCase(formName)}Schema),`);
299
+ }
300
+ lines.push(` initialValues: initialValues ?? ${this.getInitialValues(form)},`);
301
+ lines.push(` });`);
302
+ lines.push('');
303
+ // Submit handler
304
+ lines.push(` async function handleSubmit(data${this.typescript && this.zod ? `: ${formName}FormData` : ''}) {`);
305
+ lines.push(` setSubmitting(true);`);
306
+ lines.push(` try {`);
307
+ lines.push(` await onSubmit(data);`);
308
+ if (form.submit.onSuccess) {
309
+ lines.push(` // onSuccess: ${form.submit.onSuccess}`);
310
+ }
311
+ lines.push(` } catch (error) {`);
312
+ if (form.submit.onError) {
313
+ lines.push(` // onError: ${form.submit.onError}`);
314
+ }
315
+ lines.push(` console.error('Form submission error:', error);`);
316
+ lines.push(` } finally {`);
317
+ lines.push(` setSubmitting(false);`);
318
+ lines.push(` }`);
319
+ lines.push(` }`);
320
+ lines.push('');
321
+ // JSX
322
+ lines.push(' return (');
323
+ lines.push(' <form onSubmit={form.onSubmit(handleSubmit)}>');
324
+ lines.push(' <Stack gap="md">');
325
+ // Render fields using layout or sequentially
326
+ if (form.layout.length > 0) {
327
+ for (const row of form.layout) {
328
+ lines.push(this.generateLayoutRow(row, form.fields));
329
+ }
330
+ }
331
+ else {
332
+ for (const field of form.fields) {
333
+ lines.push(this.generateMantineField(field, 8));
334
+ }
335
+ }
336
+ // Submit button
337
+ lines.push(' <Group justify="flex-end" mt="md">');
338
+ lines.push(' <Button type="submit" loading={submitting || isLoading}>');
339
+ lines.push(` {submitting ? '${form.submit.loading || 'Submitting...'}' : '${form.submit.button}'}`);
340
+ lines.push(' </Button>');
341
+ lines.push(' </Group>');
342
+ lines.push(' </Stack>');
343
+ lines.push(' </form>');
344
+ lines.push(' );');
345
+ lines.push('}');
346
+ return {
347
+ path: `${this.basePath}/forms/${this.toKebabCase(formName)}-form.${ext}`,
348
+ content: lines.join('\n'),
349
+ };
350
+ }
351
+ generateZodSchema(form) {
352
+ const schemaName = `${this.toCamelCase(form.name)}Schema`;
353
+ const lines = [];
354
+ lines.push(`const ${schemaName} = z.object({`);
355
+ for (const field of form.fields) {
356
+ const zodType = this.fieldTypeToZod(field);
357
+ lines.push(` ${field.name}: ${zodType},`);
358
+ }
359
+ lines.push('});');
360
+ return lines.join('\n');
361
+ }
362
+ fieldTypeToZod(field) {
363
+ let zodType;
364
+ switch (field.type) {
365
+ case 'email':
366
+ zodType = "z.string().email('Invalid email address')";
367
+ break;
368
+ case 'number':
369
+ zodType = 'z.number()';
370
+ break;
371
+ case 'checkbox':
372
+ zodType = 'z.boolean()';
373
+ break;
374
+ case 'date':
375
+ case 'time':
376
+ case 'datetime':
377
+ zodType = 'z.string()';
378
+ break;
379
+ case 'multiselect':
380
+ zodType = 'z.array(z.string())';
381
+ break;
382
+ case 'file':
383
+ zodType = 'z.any()';
384
+ break;
385
+ default:
386
+ zodType = 'z.string()';
387
+ }
388
+ if (field.required) {
389
+ // Add min(1) for string types that need non-empty validation
390
+ if (field.type === 'text' ||
391
+ field.type === 'textarea' ||
392
+ field.type === 'password' ||
393
+ field.type === 'email' ||
394
+ field.type === 'select') {
395
+ zodType += ".min(1, 'Required')";
396
+ }
397
+ }
398
+ else {
399
+ zodType += '.optional()';
400
+ }
401
+ return zodType;
402
+ }
403
+ getInitialValues(form) {
404
+ const values = {};
405
+ for (const field of form.fields) {
406
+ if (field.defaultValue !== undefined) {
407
+ // Use the default value directly (already properly typed)
408
+ values[field.name] = field.defaultValue;
409
+ }
410
+ else if (field.type === 'checkbox') {
411
+ values[field.name] = false;
412
+ }
413
+ else if (field.type === 'number') {
414
+ values[field.name] = 0;
415
+ }
416
+ else if (field.type === 'multiselect') {
417
+ values[field.name] = [];
418
+ }
419
+ else {
420
+ values[field.name] = '';
421
+ }
422
+ }
423
+ return JSON.stringify(values, null, 2);
424
+ }
425
+ generateLayoutRow(row, fields) {
426
+ const lines = [];
427
+ const columns = row.columns ?? row.fields.length;
428
+ lines.push(` <Group grow align="flex-start">`);
429
+ for (const fieldName of row.fields) {
430
+ const field = fields.find((f) => f.name === fieldName);
431
+ if (field) {
432
+ lines.push(this.generateMantineField(field, 10));
433
+ }
434
+ }
435
+ lines.push(' </Group>');
436
+ return lines.join('\n');
437
+ }
438
+ generateMantineField(field, indent) {
439
+ const spaces = ' '.repeat(indent);
440
+ switch (field.type) {
441
+ case 'textarea':
442
+ return `${spaces}<Textarea label="${field.label}" placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
443
+ case 'select':
444
+ const options = (field.options || []).map((opt) => `{ value: '${opt.value}', label: '${opt.label}' }`).join(', ');
445
+ return `${spaces}<Select label="${field.label}" placeholder="${field.placeholder || 'Select...'}" ${field.required ? 'required' : ''} data={[${options}]} {...form.getInputProps('${field.name}')} />`;
446
+ case 'checkbox':
447
+ return `${spaces}<Checkbox label="${field.label}" {...form.getInputProps('${field.name}', { type: 'checkbox' })} />`;
448
+ case 'number':
449
+ return `${spaces}<NumberInput label="${field.label}" placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
450
+ case 'email':
451
+ return `${spaces}<TextInput type="email" label="${field.label}" placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
452
+ case 'password':
453
+ return `${spaces}<TextInput type="password" label="${field.label}" placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
454
+ case 'date':
455
+ return `${spaces}<TextInput type="date" label="${field.label}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
456
+ case 'time':
457
+ return `${spaces}<TextInput type="time" label="${field.label}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
458
+ case 'datetime':
459
+ return `${spaces}<TextInput type="datetime-local" label="${field.label}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
460
+ case 'file':
461
+ return `${spaces}<TextInput type="file" label="${field.label}" {...form.getInputProps('${field.name}')} />`;
462
+ default:
463
+ return `${spaces}<TextInput label="${field.label}" placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''} {...form.getInputProps('${field.name}')} />`;
464
+ }
465
+ }
466
+ // ===========================================================================
467
+ // Helpers
468
+ // ===========================================================================
469
+ mapPropType(type) {
470
+ const typeMap = {
471
+ string: 'string',
472
+ number: 'number',
473
+ boolean: 'boolean',
474
+ node: 'React.ReactNode',
475
+ element: 'React.ReactElement',
476
+ func: '() => void',
477
+ array: 'unknown[]',
478
+ object: 'Record<string, unknown>',
479
+ };
480
+ return typeMap[type] || type;
481
+ }
482
+ mapToMantineComponent(type) {
483
+ const componentMap = {
484
+ div: 'Box',
485
+ section: 'Box',
486
+ header: 'Box',
487
+ footer: 'Box',
488
+ article: 'Box',
489
+ aside: 'Box',
490
+ main: 'Box',
491
+ nav: 'Box',
492
+ };
493
+ return componentMap[type] || 'Box';
494
+ }
495
+ toCamelCase(str) {
496
+ return str.charAt(0).toLowerCase() + str.slice(1);
497
+ }
498
+ toKebabCase(str) {
499
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
500
+ }
501
+ }
502
+ // =============================================================================
503
+ // Convenience Functions
504
+ // =============================================================================
505
+ /**
506
+ * Generate Mantine components from Kappa ComponentBlock nodes
507
+ */
508
+ export function generateMantineComponents(components, options = {}) {
509
+ const generator = new KappaMantineGenerator(options);
510
+ return generator.generateComponents(components);
511
+ }
512
+ /**
513
+ * Generate Mantine forms from Kappa FormBlock nodes
514
+ */
515
+ export function generateMantineForms(forms, options = {}) {
516
+ const generator = new KappaMantineGenerator(options);
517
+ return generator.generateForms(forms);
518
+ }
@@ -0,0 +1,44 @@
1
+ import type { EntityBlock } from './kappa-ast.js';
2
+ export interface MongooseGeneratorOptions {
3
+ /** Generate TypeScript interfaces (default: true) */
4
+ typescript?: boolean;
5
+ /** Add provenance comments (default: true) */
6
+ provenance?: boolean;
7
+ /** Generate separate types file (default: true) */
8
+ separateTypes?: boolean;
9
+ }
10
+ export interface GeneratedMongooseSchema {
11
+ /** Main schema file content */
12
+ schema: string;
13
+ /** TypeScript types file content (if separateTypes is true) */
14
+ types?: string;
15
+ }
16
+ export declare class KappaMongooseGenerator {
17
+ private typescript;
18
+ private provenance;
19
+ private separateTypes;
20
+ constructor(options?: MongooseGeneratorOptions);
21
+ /**
22
+ * Generate Mongoose schema from entity blocks
23
+ */
24
+ generate(entities: EntityBlock[]): GeneratedMongooseSchema;
25
+ private generateSchemaFile;
26
+ private generateSchemaImports;
27
+ private fieldUsesSchemaTypes;
28
+ private generateSchema;
29
+ private generateField;
30
+ private generateRelationshipField;
31
+ private generateValidators;
32
+ private getMongooseType;
33
+ private generateIndexes;
34
+ private generateVirtualRelationships;
35
+ private generateInterface;
36
+ private getTypeScriptType;
37
+ private generateTypesFile;
38
+ private toSnakeCase;
39
+ private toCamelCase;
40
+ }
41
+ /**
42
+ * Generate Mongoose schema from Kappa entities
43
+ */
44
+ export declare function generateMongooseSchema(entities: EntityBlock[], options?: MongooseGeneratorOptions): GeneratedMongooseSchema;