@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,566 @@
1
+ // =============================================================================
2
+ // Kappa v2.5 Radix UI Component Generator
3
+ // =============================================================================
4
+ //
5
+ // Generates React components using Radix UI primitives from Kappa ComponentBlock AST.
6
+ // Supports compound components, accessibility props, and Radix composition patterns.
7
+ //
8
+ // Radix UI provides unstyled, accessible components that can be composed with
9
+ // Tailwind CSS for complete design control while maintaining accessibility.
10
+ //
11
+ const RADIX_MAPPINGS = {
12
+ Dialog: {
13
+ primitive: 'Dialog',
14
+ packageName: '@radix-ui/react-dialog',
15
+ requiredParts: ['Root', 'Trigger', 'Portal', 'Overlay', 'Content'],
16
+ optionalParts: ['Close', 'Title', 'Description'],
17
+ },
18
+ Modal: {
19
+ primitive: 'Dialog',
20
+ packageName: '@radix-ui/react-dialog',
21
+ requiredParts: ['Root', 'Trigger', 'Portal', 'Overlay', 'Content'],
22
+ optionalParts: ['Close', 'Title', 'Description'],
23
+ },
24
+ Popover: {
25
+ primitive: 'Popover',
26
+ packageName: '@radix-ui/react-popover',
27
+ requiredParts: ['Root', 'Trigger', 'Portal', 'Content'],
28
+ optionalParts: ['Anchor', 'Close', 'Arrow'],
29
+ },
30
+ Select: {
31
+ primitive: 'Select',
32
+ packageName: '@radix-ui/react-select',
33
+ requiredParts: ['Root', 'Trigger', 'Portal', 'Content', 'Viewport', 'Item'],
34
+ optionalParts: ['Value', 'Icon', 'ScrollUpButton', 'ScrollDownButton', 'Group', 'Label', 'Separator'],
35
+ },
36
+ Dropdown: {
37
+ primitive: 'DropdownMenu',
38
+ packageName: '@radix-ui/react-dropdown-menu',
39
+ requiredParts: ['Root', 'Trigger', 'Portal', 'Content', 'Item'],
40
+ optionalParts: ['Group', 'Label', 'Separator', 'CheckboxItem', 'RadioGroup', 'RadioItem', 'Sub', 'SubTrigger', 'SubContent'],
41
+ },
42
+ Tabs: {
43
+ primitive: 'Tabs',
44
+ packageName: '@radix-ui/react-tabs',
45
+ requiredParts: ['Root', 'List', 'Trigger', 'Content'],
46
+ optionalParts: [],
47
+ },
48
+ Accordion: {
49
+ primitive: 'Accordion',
50
+ packageName: '@radix-ui/react-accordion',
51
+ requiredParts: ['Root', 'Item', 'Trigger', 'Content'],
52
+ optionalParts: ['Header'],
53
+ },
54
+ Tooltip: {
55
+ primitive: 'Tooltip',
56
+ packageName: '@radix-ui/react-tooltip',
57
+ requiredParts: ['Provider', 'Root', 'Trigger', 'Portal', 'Content'],
58
+ optionalParts: ['Arrow'],
59
+ },
60
+ };
61
+ // =============================================================================
62
+ // Generator Class
63
+ // =============================================================================
64
+ export class KappaRadixGenerator {
65
+ provenance;
66
+ typescript;
67
+ basePath;
68
+ a11yDocs;
69
+ usedDependencies = new Set();
70
+ constructor(options = {}) {
71
+ this.provenance = options.provenance ?? true;
72
+ this.typescript = options.typescript ?? true;
73
+ this.basePath = options.basePath ?? 'components/ui';
74
+ this.a11yDocs = options.a11yDocs ?? true;
75
+ }
76
+ /**
77
+ * Generate Radix UI component files from ComponentBlock AST nodes
78
+ */
79
+ generate(components) {
80
+ this.usedDependencies.clear();
81
+ const generatedComponents = [];
82
+ for (const component of components) {
83
+ const primitive = this.detectPrimitive(component);
84
+ if (primitive) {
85
+ generatedComponents.push(this.generateRadixComponent(component, primitive));
86
+ }
87
+ else {
88
+ // Generate simple component for non-Radix UI components (Button, Card, Badge, etc.)
89
+ generatedComponents.push(this.generateSimpleComponent(component));
90
+ }
91
+ }
92
+ return {
93
+ components: generatedComponents,
94
+ dependencies: Array.from(this.usedDependencies).sort(),
95
+ };
96
+ }
97
+ // ===========================================================================
98
+ // Primitive Detection
99
+ // ===========================================================================
100
+ detectPrimitive(component) {
101
+ // Check if component name matches a known Radix primitive
102
+ for (const [key, mapping] of Object.entries(RADIX_MAPPINGS)) {
103
+ if (component.name.toLowerCase().includes(key.toLowerCase())) {
104
+ return mapping.primitive;
105
+ }
106
+ }
107
+ // Check if compound parts suggest a Radix primitive
108
+ if (component.compound && component.compound.length > 0) {
109
+ const partNames = component.compound.map(p => p.name.toLowerCase());
110
+ // Dialog/Modal pattern
111
+ if (partNames.includes('trigger') && partNames.includes('content')) {
112
+ if (partNames.includes('overlay')) {
113
+ return 'Dialog';
114
+ }
115
+ return 'Popover';
116
+ }
117
+ // Tabs pattern
118
+ if (partNames.includes('list') && partNames.includes('trigger') && partNames.includes('content')) {
119
+ return 'Tabs';
120
+ }
121
+ // Accordion pattern
122
+ if (partNames.includes('item') && partNames.includes('trigger')) {
123
+ return 'Accordion';
124
+ }
125
+ }
126
+ return null;
127
+ }
128
+ // ===========================================================================
129
+ // Radix Component Generation
130
+ // ===========================================================================
131
+ generateRadixComponent(component, primitive) {
132
+ const mapping = Object.values(RADIX_MAPPINGS).find(m => m.primitive === primitive);
133
+ this.usedDependencies.add(mapping.packageName);
134
+ const lines = [];
135
+ const ext = this.typescript ? 'tsx' : 'jsx';
136
+ // Header
137
+ if (this.provenance) {
138
+ lines.push('// Generated by Kappa v2.5 CodeDNA - Radix UI Generator');
139
+ lines.push(`// Component: ${component.name}`);
140
+ lines.push(`// Primitive: ${primitive}`);
141
+ lines.push('');
142
+ }
143
+ // Accessibility documentation
144
+ if (this.a11yDocs) {
145
+ lines.push('/**');
146
+ lines.push(` * ${component.name} - Built with Radix UI ${primitive}`);
147
+ lines.push(' *');
148
+ lines.push(' * Accessibility features:');
149
+ lines.push(` * - ARIA attributes automatically applied by Radix UI`);
150
+ lines.push(` * - Keyboard navigation support`);
151
+ lines.push(` * - Focus management`);
152
+ if (primitive === 'Dialog' || primitive === 'AlertDialog') {
153
+ lines.push(` * - Focus trap when open`);
154
+ lines.push(` * - Scroll lock when open`);
155
+ }
156
+ lines.push(' */');
157
+ }
158
+ // Imports
159
+ lines.push(...this.generateRadixImports(primitive, mapping, component));
160
+ lines.push('');
161
+ // Generate based on whether it's compound
162
+ if (component.compound && component.compound.length > 0) {
163
+ lines.push(...this.generateCompoundRadixComponent(component, primitive, mapping));
164
+ }
165
+ else {
166
+ lines.push(...this.generateSimpleRadixComponent(component, primitive, mapping));
167
+ }
168
+ return {
169
+ path: `${this.basePath}/${this.toKebabCase(component.name)}.${ext}`,
170
+ content: lines.join('\n'),
171
+ primitive,
172
+ };
173
+ }
174
+ generateRadixImports(primitive, mapping, component) {
175
+ const lines = [];
176
+ // React imports
177
+ lines.push("import * as React from 'react';");
178
+ // Radix imports - import all used parts
179
+ const usedParts = this.getUsedRadixParts(component, mapping);
180
+ const radixImports = usedParts.map(part => `${primitive}${part}`).join(', ');
181
+ lines.push(`import * as ${primitive} from '${mapping.packageName}';`);
182
+ // Utility imports
183
+ lines.push("import { cn } from '@/lib/utils';");
184
+ return lines;
185
+ }
186
+ getUsedRadixParts(component, mapping) {
187
+ const parts = new Set(mapping.requiredParts);
188
+ // Add optional parts if compound components reference them
189
+ if (component.compound) {
190
+ for (const part of component.compound) {
191
+ const radixPart = this.mapCompoundPartToRadix(part.name);
192
+ if (mapping.optionalParts.includes(radixPart)) {
193
+ parts.add(radixPart);
194
+ }
195
+ }
196
+ }
197
+ return Array.from(parts);
198
+ }
199
+ mapCompoundPartToRadix(partName) {
200
+ // Map Kappa compound part names to Radix part names
201
+ const mappings = {
202
+ trigger: 'Trigger',
203
+ content: 'Content',
204
+ overlay: 'Overlay',
205
+ title: 'Title',
206
+ description: 'Description',
207
+ close: 'Close',
208
+ header: 'Header',
209
+ body: 'Content',
210
+ footer: 'Footer',
211
+ item: 'Item',
212
+ list: 'List',
213
+ value: 'Value',
214
+ icon: 'Icon',
215
+ };
216
+ return mappings[partName.toLowerCase()] || partName;
217
+ }
218
+ // ===========================================================================
219
+ // Simple Component Generation
220
+ // ===========================================================================
221
+ generateSimpleRadixComponent(component, primitive, mapping) {
222
+ const lines = [];
223
+ // Props interface
224
+ if (this.typescript) {
225
+ lines.push(this.generateRadixPropsInterface(component, primitive));
226
+ lines.push('');
227
+ }
228
+ // Component
229
+ const propsType = this.typescript ? `: ${component.name}Props` : '';
230
+ const destructuredProps = this.getDestructuredProps(component);
231
+ lines.push(`export const ${component.name} = React.forwardRef<`);
232
+ lines.push(` React.ElementRef<typeof ${primitive}.Content>,`);
233
+ lines.push(` ${component.name}Props`);
234
+ lines.push(`>(({ ${destructuredProps} }, ref) => {`);
235
+ lines.push(' return (');
236
+ lines.push(` <${primitive}.Root>`);
237
+ if (component.structure) {
238
+ lines.push(this.generateRadixStructureJSX(component.structure, primitive, 6));
239
+ }
240
+ else {
241
+ lines.push(` <${primitive}.Content ref={ref} className={cn(className)} {...props}>`);
242
+ lines.push(' {children}');
243
+ lines.push(` </${primitive}.Content>`);
244
+ }
245
+ lines.push(` </${primitive}.Root>`);
246
+ lines.push(' );');
247
+ lines.push('});');
248
+ lines.push('');
249
+ lines.push(`${component.name}.displayName = '${component.name}';`);
250
+ return lines;
251
+ }
252
+ generateRadixPropsInterface(component, primitive) {
253
+ const lines = [];
254
+ const propsName = `${component.name}Props`;
255
+ lines.push(`export interface ${propsName} extends React.ComponentPropsWithoutRef<typeof ${primitive}.Content> {`);
256
+ for (const prop of component.props) {
257
+ const optional = prop.optional ? '?' : '';
258
+ lines.push(` /** ${prop.name} prop */`);
259
+ lines.push(` ${prop.name}${optional}: ${this.mapPropType(prop.type)};`);
260
+ }
261
+ lines.push('}');
262
+ return lines.join('\n');
263
+ }
264
+ generateRadixStructureJSX(structure, primitive, indent) {
265
+ const spaces = ' '.repeat(indent);
266
+ const lines = [];
267
+ const radixComponent = this.mapStructureToRadixComponent(structure.type, primitive);
268
+ const props = Object.entries(structure.props || {})
269
+ .map(([k, v]) => `${k}="${v}"`)
270
+ .join(' ');
271
+ if (structure.children && structure.children.length > 0) {
272
+ lines.push(`${spaces}<${radixComponent} ${props}>`);
273
+ for (const child of structure.children) {
274
+ lines.push(this.generateRadixStructureJSX(child, primitive, indent + 2));
275
+ }
276
+ lines.push(`${spaces}</${radixComponent}>`);
277
+ }
278
+ else {
279
+ lines.push(`${spaces}<${radixComponent} ${props}>{children}</${radixComponent}>`);
280
+ }
281
+ return lines.join('\n');
282
+ }
283
+ mapStructureToRadixComponent(type, primitive) {
284
+ // Map generic structure types to Radix components
285
+ const mappings = {
286
+ overlay: `${primitive}.Overlay`,
287
+ content: `${primitive}.Content`,
288
+ title: `${primitive}.Title`,
289
+ description: `${primitive}.Description`,
290
+ close: `${primitive}.Close`,
291
+ trigger: `${primitive}.Trigger`,
292
+ };
293
+ return mappings[type.toLowerCase()] || `${primitive}.Content`;
294
+ }
295
+ // ===========================================================================
296
+ // Compound Component Generation
297
+ // ===========================================================================
298
+ generateCompoundRadixComponent(component, primitive, mapping) {
299
+ const lines = [];
300
+ // Root component interface
301
+ if (this.typescript) {
302
+ lines.push(`export interface ${component.name}Props extends React.ComponentPropsWithoutRef<typeof ${primitive}.Root> {`);
303
+ for (const prop of component.props) {
304
+ const optional = prop.optional ? '?' : '';
305
+ lines.push(` ${prop.name}${optional}: ${this.mapPropType(prop.type)};`);
306
+ }
307
+ lines.push('}');
308
+ lines.push('');
309
+ }
310
+ // Root component
311
+ const propsType = this.typescript ? `: ${component.name}Props` : '';
312
+ const destructuredProps = this.getDestructuredProps(component);
313
+ lines.push(`const ${component.name}Root = React.forwardRef<`);
314
+ lines.push(` React.ElementRef<typeof ${primitive}.Root>,`);
315
+ lines.push(` ${component.name}Props`);
316
+ lines.push(`>(({ ${destructuredProps} }, ref) => (`);
317
+ lines.push(` <${primitive}.Root ref={ref} className={cn(className)} {...props}>`);
318
+ lines.push(' {children}');
319
+ lines.push(` </${primitive}.Root>`);
320
+ lines.push('));');
321
+ lines.push('');
322
+ lines.push(`${component.name}Root.displayName = '${component.name}Root';`);
323
+ lines.push('');
324
+ // Compound parts
325
+ for (const part of component.compound) {
326
+ lines.push(...this.generateRadixCompoundPart(component.name, part, primitive));
327
+ lines.push('');
328
+ }
329
+ // Export compound object
330
+ lines.push(`export const ${component.name} = Object.assign(${component.name}Root, {`);
331
+ for (const part of component.compound) {
332
+ lines.push(` ${part.name}: ${component.name}${part.name},`);
333
+ }
334
+ lines.push('});');
335
+ return lines;
336
+ }
337
+ generateRadixCompoundPart(parentName, part, primitive) {
338
+ const lines = [];
339
+ const partName = `${parentName}${part.name}`;
340
+ const radixPart = this.mapCompoundPartToRadix(part.name);
341
+ const radixComponent = `${primitive}.${radixPart}`;
342
+ // Props interface
343
+ if (this.typescript) {
344
+ lines.push(`export interface ${partName}Props extends React.ComponentPropsWithoutRef<typeof ${radixComponent}> {`);
345
+ if (part.props) {
346
+ for (const prop of part.props) {
347
+ lines.push(` ${prop}?: string;`);
348
+ }
349
+ }
350
+ lines.push('}');
351
+ lines.push('');
352
+ }
353
+ const propsType = this.typescript ? `: ${partName}Props` : '';
354
+ const propsStr = part.props
355
+ ? `{ className, children, ${part.props.join(', ')}, ...props }`
356
+ : '{ className, children, ...props }';
357
+ lines.push(`const ${partName} = React.forwardRef<`);
358
+ lines.push(` React.ElementRef<typeof ${radixComponent}>,`);
359
+ lines.push(` ${partName}Props`);
360
+ lines.push(`>((`);
361
+ lines.push(` ${propsStr}${propsType},`);
362
+ lines.push(` ref`);
363
+ lines.push(`) => (`);
364
+ lines.push(` <${radixComponent}`);
365
+ lines.push(` ref={ref}`);
366
+ lines.push(` className={cn('${this.toKebabCase(partName)}', className)}`);
367
+ lines.push(` {...props}`);
368
+ lines.push(` >`);
369
+ lines.push(' {children}');
370
+ lines.push(` </${radixComponent}>`);
371
+ lines.push(`));`);
372
+ lines.push('');
373
+ lines.push(`${partName}.displayName = '${partName}';`);
374
+ return lines;
375
+ }
376
+ // ===========================================================================
377
+ // Simple Component Generation (non-Radix)
378
+ // ===========================================================================
379
+ generateSimpleComponent(component) {
380
+ const lines = [];
381
+ const ext = this.typescript ? 'tsx' : 'jsx';
382
+ // Header
383
+ if (this.provenance) {
384
+ lines.push('// Generated by Kappa v2.5 CodeDNA - Simple Component Generator');
385
+ lines.push(`// Component: ${component.name}`);
386
+ lines.push('');
387
+ }
388
+ // Imports
389
+ lines.push("import * as React from 'react';");
390
+ lines.push("import { cn } from '@/lib/utils';");
391
+ lines.push('');
392
+ // Variant styles (if component has variants)
393
+ if (component.variants && component.variants.length > 0) {
394
+ lines.push('// Variant styles');
395
+ lines.push(`const ${component.name.toLowerCase()}Variants = {`);
396
+ for (const variant of component.variants) {
397
+ const className = this.getVariantClassName(component.name, variant.name);
398
+ lines.push(` ${variant.name}: '${className}',`);
399
+ }
400
+ lines.push('} as const;');
401
+ lines.push('');
402
+ lines.push(`type ${component.name}Variant = keyof typeof ${component.name.toLowerCase()}Variants;`);
403
+ lines.push('');
404
+ }
405
+ // Props interface
406
+ if (this.typescript) {
407
+ lines.push(`export interface ${component.name}Props extends React.HTMLAttributes<HTMLElement> {`);
408
+ for (const prop of component.props) {
409
+ const optional = prop.optional ? '?' : '';
410
+ lines.push(` /** ${prop.name} prop */`);
411
+ lines.push(` ${prop.name}${optional}: ${this.mapPropType(prop.type)};`);
412
+ }
413
+ if (component.variants && component.variants.length > 0) {
414
+ const defaultVariant = component.variants[0].name;
415
+ lines.push(` /** Visual variant */`);
416
+ lines.push(` variant?: ${component.name}Variant;`);
417
+ }
418
+ lines.push('}');
419
+ lines.push('');
420
+ }
421
+ // Component
422
+ const destructuredProps = this.getSimpleDestructuredProps(component);
423
+ const elementType = this.getElementType(component.name);
424
+ lines.push(`export const ${component.name} = React.forwardRef<`);
425
+ lines.push(` HTML${elementType}Element,`);
426
+ lines.push(` ${component.name}Props`);
427
+ lines.push(`>(({ ${destructuredProps} }, ref) => {`);
428
+ // Variant handling
429
+ if (component.variants && component.variants.length > 0) {
430
+ const defaultVariant = component.variants[0].name;
431
+ lines.push(` const variantClass = ${component.name.toLowerCase()}Variants[variant ?? '${defaultVariant}'];`);
432
+ lines.push('');
433
+ }
434
+ // Return statement
435
+ lines.push(' return (');
436
+ lines.push(` <${this.getElementTag(component.name)}`);
437
+ lines.push(' ref={ref}');
438
+ if (component.variants && component.variants.length > 0) {
439
+ lines.push(` className={cn('${this.toKebabCase(component.name)}', variantClass, className)}`);
440
+ }
441
+ else {
442
+ lines.push(` className={cn('${this.toKebabCase(component.name)}', className)}`);
443
+ }
444
+ // Add event handlers from props
445
+ for (const prop of component.props) {
446
+ if (prop.name.startsWith('on')) {
447
+ lines.push(` ${prop.name}={${prop.name}}`);
448
+ }
449
+ }
450
+ lines.push(' {...props}');
451
+ lines.push(' >');
452
+ // Add label/children content
453
+ const labelProp = component.props.find(p => p.name === 'label');
454
+ if (labelProp) {
455
+ lines.push(' {label}');
456
+ }
457
+ else {
458
+ lines.push(' {children}');
459
+ }
460
+ lines.push(` </${this.getElementTag(component.name)}>`);
461
+ lines.push(' );');
462
+ lines.push('});');
463
+ lines.push('');
464
+ lines.push(`${component.name}.displayName = '${component.name}';`);
465
+ return {
466
+ path: `${this.basePath}/${this.toKebabCase(component.name)}.${ext}`,
467
+ content: lines.join('\n'),
468
+ primitive: 'Toggle', // Placeholder since this isn't actually a Radix primitive
469
+ };
470
+ }
471
+ getSimpleDestructuredProps(component) {
472
+ const propNames = component.props.map((p) => p.name);
473
+ if (component.variants && component.variants.length > 0) {
474
+ propNames.push('variant');
475
+ }
476
+ propNames.push('className', 'children', '...props');
477
+ return propNames.join(', ');
478
+ }
479
+ getVariantClassName(componentName, variantName) {
480
+ const base = this.toKebabCase(componentName);
481
+ const styles = {
482
+ button: {
483
+ primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
484
+ secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
485
+ destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
486
+ outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
487
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
488
+ link: 'text-primary underline-offset-4 hover:underline',
489
+ },
490
+ card: {
491
+ default: 'border bg-card text-card-foreground shadow-sm',
492
+ outlined: 'border-2 bg-background',
493
+ elevated: 'bg-card text-card-foreground shadow-lg',
494
+ },
495
+ badge: {
496
+ default: 'border-transparent bg-primary text-primary-foreground',
497
+ secondary: 'border-transparent bg-secondary text-secondary-foreground',
498
+ outline: 'text-foreground',
499
+ destructive: 'border-transparent bg-destructive text-destructive-foreground',
500
+ },
501
+ };
502
+ const componentStyles = styles[componentName.toLowerCase()];
503
+ if (componentStyles && componentStyles[variantName]) {
504
+ return componentStyles[variantName];
505
+ }
506
+ // Generic variant styles
507
+ return `${base}--${variantName}`;
508
+ }
509
+ getElementType(componentName) {
510
+ const mappings = {
511
+ button: 'Button',
512
+ input: 'Input',
513
+ textarea: 'TextArea',
514
+ select: 'Select',
515
+ card: 'Div',
516
+ badge: 'Div',
517
+ avatar: 'Div',
518
+ alert: 'Div',
519
+ };
520
+ return mappings[componentName.toLowerCase()] || 'Div';
521
+ }
522
+ getElementTag(componentName) {
523
+ const mappings = {
524
+ button: 'button',
525
+ input: 'input',
526
+ textarea: 'textarea',
527
+ select: 'select',
528
+ link: 'a',
529
+ };
530
+ return mappings[componentName.toLowerCase()] || 'div';
531
+ }
532
+ // ===========================================================================
533
+ // Helpers
534
+ // ===========================================================================
535
+ getDestructuredProps(component) {
536
+ const propNames = component.props.map((p) => p.name);
537
+ propNames.push('className', 'children', '...props');
538
+ return propNames.join(', ');
539
+ }
540
+ mapPropType(type) {
541
+ const typeMap = {
542
+ string: 'string',
543
+ number: 'number',
544
+ boolean: 'boolean',
545
+ node: 'React.ReactNode',
546
+ element: 'React.ReactElement',
547
+ func: '() => void',
548
+ array: 'unknown[]',
549
+ object: 'Record<string, unknown>',
550
+ };
551
+ return typeMap[type] || type;
552
+ }
553
+ toKebabCase(str) {
554
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
555
+ }
556
+ }
557
+ // =============================================================================
558
+ // Convenience Function
559
+ // =============================================================================
560
+ /**
561
+ * Generate Radix UI component files from Kappa ComponentBlock nodes
562
+ */
563
+ export function generateRadixComponents(components, options = {}) {
564
+ const generator = new KappaRadixGenerator(options);
565
+ return generator.generate(components);
566
+ }
@@ -0,0 +1,59 @@
1
+ import type { EntityBlock } from './kappa-ast.js';
2
+ export type TypeORMDialect = 'postgres' | 'mysql' | 'sqlite';
3
+ export interface TypeORMGeneratorOptions {
4
+ /** Database dialect (default: postgres) */
5
+ dialect?: TypeORMDialect;
6
+ /** Generate repository classes (default: false) */
7
+ repositories?: boolean;
8
+ /** Generate migration files (default: true) */
9
+ migrations?: boolean;
10
+ /** Add provenance comments (default: true) */
11
+ provenance?: boolean;
12
+ }
13
+ export interface GeneratedTypeORM {
14
+ /** Entity class files (map of entity name to content) */
15
+ entities: Record<string, string>;
16
+ /** Repository files (if enabled) */
17
+ repositories?: Record<string, string>;
18
+ /** Migration file content (if enabled) */
19
+ migration?: string;
20
+ /** Data source configuration */
21
+ dataSource: string;
22
+ }
23
+ export declare class KappaTypeORMGenerator {
24
+ private dialect;
25
+ private provenance;
26
+ private generateRepositories;
27
+ private generateMigrations;
28
+ constructor(options?: TypeORMGeneratorOptions);
29
+ /**
30
+ * Generate TypeORM entities from entity blocks
31
+ */
32
+ generate(entities: EntityBlock[]): GeneratedTypeORM;
33
+ private generateEntity;
34
+ private generateEntityImports;
35
+ private generateEntityClass;
36
+ private generatePrimaryKey;
37
+ private generateField;
38
+ private generateRelationship;
39
+ private getColumnType;
40
+ private getTSType;
41
+ /**
42
+ * Determine the foreign key column type based on the related entity's primary key
43
+ */
44
+ private getForeignKeyType;
45
+ private generateDataSource;
46
+ private generateRepositoryFiles;
47
+ private generateRepository;
48
+ private generateMigrationFile;
49
+ private generateCreateTableSQL;
50
+ private generateColumnSQL;
51
+ private generateCreateIndexSQL;
52
+ private toSnakeCase;
53
+ private toCamelCase;
54
+ private toLowerCamelCase;
55
+ }
56
+ /**
57
+ * Generate TypeORM entities from Kappa entity blocks
58
+ */
59
+ export declare function generateTypeORMEntities(entities: EntityBlock[], options?: TypeORMGeneratorOptions): GeneratedTypeORM;