@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,302 @@
1
+ #!/usr/bin/env node
2
+ // =============================================================================
3
+ // Kappa v2.5 CLI
4
+ // =============================================================================
5
+ //
6
+ // Command-line interface for the Kappa DSL.
7
+ // Parse, validate, and generate code from Kappa specifications.
8
+ //
9
+ import { parseArgs } from 'node:util';
10
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, watch } from 'node:fs';
11
+ import { join, basename, extname } from 'node:path';
12
+ import { parseToAST } from './kappa-parser.js';
13
+ import { validateKappaSpec, formatValidationResults } from './kappa-validator.js';
14
+ import { generateDrizzleSchema } from './kappa-drizzle-generator.js';
15
+ import { generateZodSchemas } from './kappa-zod-generator.js';
16
+ import { generateTypeScriptTypes } from './kappa-types-generator.js';
17
+ import { generateAPI } from './kappa-api-generator.js';
18
+ // =============================================================================
19
+ // Version
20
+ // =============================================================================
21
+ const VERSION = '2.5.0';
22
+ // =============================================================================
23
+ // Help Text
24
+ // =============================================================================
25
+ const HELP_TEXT = `
26
+ Kappa v${VERSION} - Declarative Application Specification Language
27
+
28
+ Usage:
29
+ kappa [command] [options] <file.kappa>
30
+
31
+ Commands:
32
+ parse Parse and display the AST
33
+ validate Validate the specification
34
+ generate Generate code from the specification (default)
35
+
36
+ Options:
37
+ -h, --help Show this help message
38
+ -v, --version Show version number
39
+ -o, --output Output directory (default: ./generated)
40
+ -w, --watch Watch for changes and regenerate
41
+ -q, --quiet Suppress non-error output
42
+ --validate Validate before generating (default: true)
43
+ --generate What to generate: drizzle,zod,types,api (default: all)
44
+ --framework API framework: hono,express,trpc (default: hono)
45
+ --dialect Database dialect: postgresql,sqlite,mysql (default: postgresql)
46
+
47
+ Examples:
48
+ kappa app.kappa # Generate all code
49
+ kappa validate app.kappa # Validate only
50
+ kappa parse app.kappa # Show AST
51
+ kappa -o src/db app.kappa # Output to src/db
52
+ kappa --generate drizzle,zod app.kappa # Generate specific outputs
53
+ kappa -w app.kappa # Watch mode
54
+
55
+ `;
56
+ // =============================================================================
57
+ // CLI Parsing
58
+ // =============================================================================
59
+ function parseCliArgs() {
60
+ const { values, positionals } = parseArgs({
61
+ options: {
62
+ help: { type: 'boolean', short: 'h', default: false },
63
+ version: { type: 'boolean', short: 'v', default: false },
64
+ output: { type: 'string', short: 'o', default: './generated' },
65
+ watch: { type: 'boolean', short: 'w', default: false },
66
+ validate: { type: 'boolean', default: true },
67
+ generate: { type: 'string', multiple: true, default: [] },
68
+ framework: { type: 'string', default: 'hono' },
69
+ dialect: { type: 'string', default: 'postgresql' },
70
+ quiet: { type: 'boolean', short: 'q', default: false },
71
+ },
72
+ allowPositionals: true,
73
+ strict: false,
74
+ });
75
+ // Determine command and file
76
+ let command = 'generate';
77
+ let file = '';
78
+ if (positionals.length === 1) {
79
+ // Just a file - default to generate
80
+ file = positionals[0];
81
+ }
82
+ else if (positionals.length >= 2) {
83
+ // Command and file
84
+ command = positionals[0];
85
+ file = positionals[1];
86
+ }
87
+ // Parse generate option (can be comma-separated)
88
+ let generateList = [];
89
+ const generateOpt = values.generate;
90
+ if (generateOpt && generateOpt.length > 0) {
91
+ for (const g of generateOpt) {
92
+ generateList.push(...g.split(','));
93
+ }
94
+ }
95
+ if (generateList.length === 0) {
96
+ generateList = ['drizzle', 'zod', 'types', 'api'];
97
+ }
98
+ return {
99
+ options: {
100
+ help: values.help ?? false,
101
+ version: values.version ?? false,
102
+ output: values.output ?? './generated',
103
+ watch: values.watch ?? false,
104
+ validate: values.validate ?? true,
105
+ generate: generateList,
106
+ framework: values.framework ?? 'hono',
107
+ dialect: values.dialect ?? 'postgresql',
108
+ quiet: values.quiet ?? false,
109
+ },
110
+ command,
111
+ file,
112
+ };
113
+ }
114
+ // =============================================================================
115
+ // Commands
116
+ // =============================================================================
117
+ function log(options, message) {
118
+ if (!options.quiet) {
119
+ console.log(message);
120
+ }
121
+ }
122
+ function parseCommand(file, options) {
123
+ const content = readFileSync(file, 'utf-8');
124
+ const ast = parseToAST(content);
125
+ if (!ast) {
126
+ console.error(`Error: Failed to parse ${file}`);
127
+ return null;
128
+ }
129
+ log(options, JSON.stringify(ast, null, 2));
130
+ return ast;
131
+ }
132
+ function validateCommand(file, options) {
133
+ const content = readFileSync(file, 'utf-8');
134
+ const ast = parseToAST(content);
135
+ if (!ast) {
136
+ console.error(`Error: Failed to parse ${file}`);
137
+ return false;
138
+ }
139
+ const result = validateKappaSpec(ast);
140
+ const formatted = formatValidationResults(result);
141
+ if (result.valid) {
142
+ log(options, `✓ ${file} is valid`);
143
+ if (result.warnings.length > 0) {
144
+ console.log(formatted);
145
+ }
146
+ return true;
147
+ }
148
+ else {
149
+ console.error(`✗ ${file} has errors:`);
150
+ console.error(formatted);
151
+ return false;
152
+ }
153
+ }
154
+ function generateCommand(file, options) {
155
+ const content = readFileSync(file, 'utf-8');
156
+ const ast = parseToAST(content);
157
+ if (!ast) {
158
+ console.error(`Error: Failed to parse ${file}`);
159
+ return false;
160
+ }
161
+ // Validate first if requested
162
+ if (options.validate) {
163
+ const result = validateKappaSpec(ast);
164
+ if (!result.valid) {
165
+ console.error(`✗ Validation failed for ${file}:`);
166
+ console.error(formatValidationResults(result));
167
+ return false;
168
+ }
169
+ }
170
+ // Ensure output directory exists
171
+ if (!existsSync(options.output)) {
172
+ mkdirSync(options.output, { recursive: true });
173
+ }
174
+ const specName = basename(file, extname(file));
175
+ let filesWritten = 0;
176
+ // Generate Drizzle schema
177
+ if (options.generate.includes('drizzle') && ast.entities.length > 0) {
178
+ const drizzle = generateDrizzleSchema(ast.entities, {
179
+ dialect: options.dialect,
180
+ provenance: true,
181
+ });
182
+ writeFileSync(join(options.output, `${specName}.schema.ts`), drizzle.schema);
183
+ filesWritten++;
184
+ if (drizzle.types) {
185
+ writeFileSync(join(options.output, `${specName}.schema.types.ts`), drizzle.types);
186
+ filesWritten++;
187
+ }
188
+ if (drizzle.relations) {
189
+ writeFileSync(join(options.output, `${specName}.relations.ts`), drizzle.relations);
190
+ filesWritten++;
191
+ }
192
+ log(options, ` ✓ Drizzle schema`);
193
+ }
194
+ // Generate Zod schemas
195
+ if (options.generate.includes('zod') && ast.entities.length > 0) {
196
+ const zod = generateZodSchemas(ast.entities, { provenance: true });
197
+ writeFileSync(join(options.output, `${specName}.schemas.ts`), zod.schemas);
198
+ filesWritten++;
199
+ log(options, ` ✓ Zod validation schemas`);
200
+ }
201
+ // Generate TypeScript types
202
+ if (options.generate.includes('types') && ast.entities.length > 0) {
203
+ const types = generateTypeScriptTypes(ast.entities, { provenance: true });
204
+ writeFileSync(join(options.output, `${specName}.types.ts`), types.types);
205
+ filesWritten++;
206
+ log(options, ` ✓ TypeScript types`);
207
+ }
208
+ // Generate API routes
209
+ if (options.generate.includes('api') && ast.apis.length > 0) {
210
+ const api = generateAPI(ast.apis, {
211
+ framework: options.framework,
212
+ provenance: true,
213
+ });
214
+ writeFileSync(join(options.output, `${specName}.routes.ts`), api.routes);
215
+ filesWritten++;
216
+ if (api.validation) {
217
+ writeFileSync(join(options.output, `${specName}.validation.ts`), api.validation);
218
+ filesWritten++;
219
+ }
220
+ if (api.errors) {
221
+ writeFileSync(join(options.output, `${specName}.errors.ts`), api.errors);
222
+ filesWritten++;
223
+ }
224
+ log(options, ` ✓ API routes (${options.framework})`);
225
+ }
226
+ log(options, `\n✓ Generated ${filesWritten} files to ${options.output}/`);
227
+ return true;
228
+ }
229
+ function watchMode(file, options) {
230
+ log(options, `Watching ${file} for changes...`);
231
+ log(options, 'Press Ctrl+C to stop.\n');
232
+ // Initial generation
233
+ generateCommand(file, options);
234
+ // Watch for changes
235
+ const watcher = watch(file, (eventType) => {
236
+ if (eventType === 'change') {
237
+ log(options, `\n[${new Date().toLocaleTimeString()}] File changed, regenerating...`);
238
+ generateCommand(file, options);
239
+ }
240
+ });
241
+ // Handle Ctrl+C
242
+ process.on('SIGINT', () => {
243
+ watcher.close();
244
+ log(options, '\nStopped watching.');
245
+ process.exit(0);
246
+ });
247
+ }
248
+ // =============================================================================
249
+ // Main
250
+ // =============================================================================
251
+ async function main() {
252
+ const { options, command, file } = parseCliArgs();
253
+ // Handle help
254
+ if (options.help) {
255
+ console.log(HELP_TEXT);
256
+ process.exit(0);
257
+ }
258
+ // Handle version
259
+ if (options.version) {
260
+ console.log(`Kappa v${VERSION}`);
261
+ process.exit(0);
262
+ }
263
+ // Require a file
264
+ if (!file) {
265
+ console.error('Error: No input file specified.');
266
+ console.error('Usage: kappa [command] [options] <file.kappa>');
267
+ console.error('Run "kappa --help" for more information.');
268
+ process.exit(1);
269
+ }
270
+ // Check file exists
271
+ if (!existsSync(file)) {
272
+ console.error(`Error: File not found: ${file}`);
273
+ process.exit(1);
274
+ }
275
+ // Execute command
276
+ let success = true;
277
+ switch (command) {
278
+ case 'parse':
279
+ const ast = parseCommand(file, options);
280
+ success = ast !== null;
281
+ break;
282
+ case 'validate':
283
+ success = validateCommand(file, options);
284
+ break;
285
+ case 'generate':
286
+ default:
287
+ if (options.watch) {
288
+ watchMode(file, options);
289
+ return; // Watch mode doesn't exit
290
+ }
291
+ else {
292
+ success = generateCommand(file, options);
293
+ }
294
+ break;
295
+ }
296
+ process.exit(success ? 0 : 1);
297
+ }
298
+ // Run if executed directly
299
+ main().catch((error) => {
300
+ console.error('Fatal error:', error);
301
+ process.exit(1);
302
+ });
@@ -0,0 +1,47 @@
1
+ import type { ComponentBlock } from './kappa-ast.js';
2
+ export interface ComponentGeneratorOptions {
3
+ /** Add provenance comments (default: true) */
4
+ provenance?: boolean;
5
+ /** Generate TypeScript (default: true) */
6
+ typescript?: boolean;
7
+ /** Use forwardRef (default: false) */
8
+ forwardRef?: boolean;
9
+ /** Base path for components (default: 'components') */
10
+ basePath?: string;
11
+ }
12
+ export interface GeneratedComponent {
13
+ /** Component file path */
14
+ path: string;
15
+ /** Component content */
16
+ content: string;
17
+ }
18
+ export interface GeneratedComponents {
19
+ /** Generated component files */
20
+ components: GeneratedComponent[];
21
+ }
22
+ export declare class KappaComponentGenerator {
23
+ private provenance;
24
+ private typescript;
25
+ private forwardRef;
26
+ private basePath;
27
+ constructor(options?: ComponentGeneratorOptions);
28
+ /**
29
+ * Generate component files from ComponentBlock AST nodes
30
+ */
31
+ generate(components: ComponentBlock[]): GeneratedComponents;
32
+ private generateSimpleComponent;
33
+ private generatePropsInterface;
34
+ private generateFunctionComponent;
35
+ private generateForwardRefComponent;
36
+ private getDestructuredProps;
37
+ private generateStructureJSX;
38
+ private generateVariants;
39
+ private generateCompoundComponent;
40
+ private generateCompoundPart;
41
+ private mapPropType;
42
+ private toKebabCase;
43
+ }
44
+ /**
45
+ * Generate component files from Kappa ComponentBlock nodes
46
+ */
47
+ export declare function generateComponents(components: ComponentBlock[], options?: ComponentGeneratorOptions): GeneratedComponents;
@@ -0,0 +1,295 @@
1
+ // =============================================================================
2
+ // Kappa v2.5 Component Generator
3
+ // =============================================================================
4
+ //
5
+ // Generates React components from Kappa ComponentBlock AST.
6
+ // Supports compound components, variants, and structured layouts.
7
+ //
8
+ // =============================================================================
9
+ // Generator Class
10
+ // =============================================================================
11
+ export class KappaComponentGenerator {
12
+ provenance;
13
+ typescript;
14
+ forwardRef;
15
+ basePath;
16
+ constructor(options = {}) {
17
+ this.provenance = options.provenance ?? true;
18
+ this.typescript = options.typescript ?? true;
19
+ this.forwardRef = options.forwardRef ?? false;
20
+ this.basePath = options.basePath ?? 'components';
21
+ }
22
+ /**
23
+ * Generate component files from ComponentBlock AST nodes
24
+ */
25
+ generate(components) {
26
+ const generatedComponents = [];
27
+ for (const component of components) {
28
+ if (component.compound && component.compound.length > 0) {
29
+ generatedComponents.push(this.generateCompoundComponent(component));
30
+ }
31
+ else {
32
+ generatedComponents.push(this.generateSimpleComponent(component));
33
+ }
34
+ }
35
+ return { components: generatedComponents };
36
+ }
37
+ // ===========================================================================
38
+ // Simple Component Generation
39
+ // ===========================================================================
40
+ generateSimpleComponent(component) {
41
+ const lines = [];
42
+ const ext = this.typescript ? 'tsx' : 'jsx';
43
+ // Header
44
+ if (this.provenance) {
45
+ lines.push('// Generated by Kappa v2.5 CodeDNA');
46
+ lines.push(`// Component: ${component.name}`);
47
+ lines.push('');
48
+ }
49
+ // Imports
50
+ if (this.forwardRef) {
51
+ lines.push("import { forwardRef } from 'react';");
52
+ }
53
+ lines.push("import { cn } from '@/lib/utils';");
54
+ lines.push('');
55
+ // Props interface
56
+ if (this.typescript) {
57
+ lines.push(this.generatePropsInterface(component));
58
+ lines.push('');
59
+ }
60
+ // Component
61
+ if (this.forwardRef) {
62
+ lines.push(this.generateForwardRefComponent(component));
63
+ }
64
+ else {
65
+ lines.push(this.generateFunctionComponent(component));
66
+ }
67
+ // Variants
68
+ if (component.variants.length > 0) {
69
+ lines.push('');
70
+ lines.push(this.generateVariants(component));
71
+ }
72
+ return {
73
+ path: `${this.basePath}/${this.toKebabCase(component.name)}.${ext}`,
74
+ content: lines.join('\n'),
75
+ };
76
+ }
77
+ generatePropsInterface(component) {
78
+ const lines = [];
79
+ const propsName = `${component.name}Props`;
80
+ lines.push(`export interface ${propsName} {`);
81
+ for (const prop of component.props) {
82
+ const optional = prop.optional ? '?' : '';
83
+ lines.push(` ${prop.name}${optional}: ${this.mapPropType(prop.type)};`);
84
+ }
85
+ // Add className and children by default
86
+ lines.push(' className?: string;');
87
+ lines.push(' children?: React.ReactNode;');
88
+ lines.push('}');
89
+ return lines.join('\n');
90
+ }
91
+ generateFunctionComponent(component) {
92
+ const lines = [];
93
+ const propsType = this.typescript ? `: ${component.name}Props` : '';
94
+ const destructuredProps = this.getDestructuredProps(component);
95
+ lines.push(`export function ${component.name}({ ${destructuredProps} }${propsType}) {`);
96
+ lines.push(' return (');
97
+ if (component.structure) {
98
+ lines.push(this.generateStructureJSX(component.structure, 4));
99
+ }
100
+ else {
101
+ lines.push(` <div className={cn('${this.toKebabCase(component.name)}', className)}>`);
102
+ lines.push(' {children}');
103
+ lines.push(' </div>');
104
+ }
105
+ lines.push(' );');
106
+ lines.push('}');
107
+ return lines.join('\n');
108
+ }
109
+ generateForwardRefComponent(component) {
110
+ const lines = [];
111
+ const propsType = this.typescript ? `${component.name}Props` : '';
112
+ const refType = this.typescript ? ', HTMLDivElement' : '';
113
+ const destructuredProps = this.getDestructuredProps(component);
114
+ lines.push(`export const ${component.name} = forwardRef<${refType.slice(2)}${propsType ? `, ${propsType}` : ''}>(`);
115
+ lines.push(` function ${component.name}({ ${destructuredProps} }, ref) {`);
116
+ lines.push(' return (');
117
+ if (component.structure) {
118
+ lines.push(this.generateStructureJSX(component.structure, 6, 'ref={ref}'));
119
+ }
120
+ else {
121
+ lines.push(` <div ref={ref} className={cn('${this.toKebabCase(component.name)}', className)}>`);
122
+ lines.push(' {children}');
123
+ lines.push(' </div>');
124
+ }
125
+ lines.push(' );');
126
+ lines.push(' }');
127
+ lines.push(');');
128
+ return lines.join('\n');
129
+ }
130
+ getDestructuredProps(component) {
131
+ const propNames = component.props.map((p) => p.name);
132
+ propNames.push('className', 'children');
133
+ return propNames.join(', ');
134
+ }
135
+ generateStructureJSX(structure, indent, extraProps = '') {
136
+ const spaces = ' '.repeat(indent);
137
+ const lines = [];
138
+ const props = Object.entries(structure.props || {})
139
+ .map(([k, v]) => `${k}="${v}"`)
140
+ .join(' ');
141
+ const allProps = [extraProps, props, 'className={cn(className)}'].filter(Boolean).join(' ');
142
+ if (structure.children && structure.children.length > 0) {
143
+ lines.push(`${spaces}<${structure.type} ${allProps}>`);
144
+ for (const child of structure.children) {
145
+ lines.push(this.generateStructureJSX(child, indent + 2));
146
+ }
147
+ lines.push(`${spaces}</${structure.type}>`);
148
+ }
149
+ else {
150
+ lines.push(`${spaces}<${structure.type} ${allProps}>{children}</${structure.type}>`);
151
+ }
152
+ return lines.join('\n');
153
+ }
154
+ generateVariants(component) {
155
+ const lines = [];
156
+ lines.push('// Variants');
157
+ for (const variant of component.variants) {
158
+ const variantName = `${component.name}${variant.name}`;
159
+ lines.push(`export const ${variantName} = ${component.name};`);
160
+ lines.push(`${variantName}.displayName = '${variantName}';`);
161
+ }
162
+ return lines.join('\n');
163
+ }
164
+ // ===========================================================================
165
+ // Compound Component Generation
166
+ // ===========================================================================
167
+ generateCompoundComponent(component) {
168
+ const lines = [];
169
+ const ext = this.typescript ? 'tsx' : 'jsx';
170
+ // Header
171
+ if (this.provenance) {
172
+ lines.push('// Generated by Kappa v2.5 CodeDNA');
173
+ lines.push(`// Compound Component: ${component.name}`);
174
+ lines.push('');
175
+ }
176
+ // Imports
177
+ lines.push("import { createContext, useContext } from 'react';");
178
+ lines.push("import { cn } from '@/lib/utils';");
179
+ lines.push('');
180
+ // Context
181
+ if (this.typescript) {
182
+ lines.push(`interface ${component.name}ContextValue {`);
183
+ for (const prop of component.props) {
184
+ lines.push(` ${prop.name}${prop.optional ? '?' : ''}: ${this.mapPropType(prop.type)};`);
185
+ }
186
+ lines.push('}');
187
+ lines.push('');
188
+ }
189
+ const contextType = this.typescript ? `${component.name}ContextValue | null` : '';
190
+ lines.push(`const ${component.name}Context = createContext<${contextType}>(null);`);
191
+ lines.push('');
192
+ // Hook
193
+ lines.push(`function use${component.name}() {`);
194
+ lines.push(` const context = useContext(${component.name}Context);`);
195
+ lines.push(' if (!context) {');
196
+ lines.push(` throw new Error('${component.name} compound components must be used within ${component.name}');`);
197
+ lines.push(' }');
198
+ lines.push(' return context;');
199
+ lines.push('}');
200
+ lines.push('');
201
+ // Root component props
202
+ if (this.typescript) {
203
+ lines.push(this.generatePropsInterface(component));
204
+ lines.push('');
205
+ }
206
+ // Root component
207
+ const destructuredProps = this.getDestructuredProps(component);
208
+ const propsType = this.typescript ? `: ${component.name}Props` : '';
209
+ lines.push(`function ${component.name}Root({ ${destructuredProps} }${propsType}) {`);
210
+ const contextValue = component.props.map((p) => p.name).join(', ');
211
+ lines.push(` const value = { ${contextValue} };`);
212
+ lines.push('');
213
+ lines.push(' return (');
214
+ lines.push(` <${component.name}Context.Provider value={value}>`);
215
+ lines.push(` <div className={cn('${this.toKebabCase(component.name)}', className)}>`);
216
+ lines.push(' {children}');
217
+ lines.push(' </div>');
218
+ lines.push(` </${component.name}Context.Provider>`);
219
+ lines.push(' );');
220
+ lines.push('}');
221
+ lines.push('');
222
+ // Compound parts
223
+ for (const part of component.compound) {
224
+ lines.push(this.generateCompoundPart(component.name, part));
225
+ lines.push('');
226
+ }
227
+ // Export compound object
228
+ lines.push(`export const ${component.name} = Object.assign(${component.name}Root, {`);
229
+ for (const part of component.compound) {
230
+ lines.push(` ${part.name}: ${component.name}${part.name},`);
231
+ }
232
+ lines.push('});');
233
+ return {
234
+ path: `${this.basePath}/${this.toKebabCase(component.name)}.${ext}`,
235
+ content: lines.join('\n'),
236
+ };
237
+ }
238
+ generateCompoundPart(parentName, part) {
239
+ const lines = [];
240
+ const partName = `${parentName}${part.name}`;
241
+ if (this.typescript) {
242
+ lines.push(`interface ${partName}Props {`);
243
+ lines.push(' className?: string;');
244
+ lines.push(' children?: React.ReactNode;');
245
+ if (part.props) {
246
+ for (const prop of part.props) {
247
+ lines.push(` ${prop}?: string;`);
248
+ }
249
+ }
250
+ lines.push('}');
251
+ lines.push('');
252
+ }
253
+ const propsType = this.typescript ? `: ${partName}Props` : '';
254
+ const propsStr = part.props ? `{ className, children, ${part.props.join(', ')} }` : '{ className, children }';
255
+ lines.push(`function ${partName}(${propsStr}${propsType}) {`);
256
+ lines.push(` const context = use${parentName}();`);
257
+ lines.push('');
258
+ lines.push(' return (');
259
+ lines.push(` <${part.element} className={cn('${this.toKebabCase(partName)}', className)}>`);
260
+ lines.push(' {children}');
261
+ lines.push(` </${part.element}>`);
262
+ lines.push(' );');
263
+ lines.push('}');
264
+ return lines.join('\n');
265
+ }
266
+ // ===========================================================================
267
+ // Helpers
268
+ // ===========================================================================
269
+ mapPropType(type) {
270
+ const typeMap = {
271
+ string: 'string',
272
+ number: 'number',
273
+ boolean: 'boolean',
274
+ node: 'React.ReactNode',
275
+ element: 'React.ReactElement',
276
+ func: '() => void',
277
+ array: 'unknown[]',
278
+ object: 'Record<string, unknown>',
279
+ };
280
+ return typeMap[type] || type;
281
+ }
282
+ toKebabCase(str) {
283
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
284
+ }
285
+ }
286
+ // =============================================================================
287
+ // Convenience Function
288
+ // =============================================================================
289
+ /**
290
+ * Generate component files from Kappa ComponentBlock nodes
291
+ */
292
+ export function generateComponents(components, options = {}) {
293
+ const generator = new KappaComponentGenerator(options);
294
+ return generator.generate(components);
295
+ }
@@ -0,0 +1,52 @@
1
+ import type { DesignBlock } from './kappa-ast.js';
2
+ export type DesignOutputFormat = 'css' | 'tailwind' | 'both';
3
+ export interface DesignGeneratorOptions {
4
+ /** Output format (default: 'both') */
5
+ format?: DesignOutputFormat;
6
+ /** Add provenance comments (default: true) */
7
+ provenance?: boolean;
8
+ /** CSS custom property prefix (default: '') */
9
+ prefix?: string;
10
+ /** Use HSL values instead of hex (default: false) */
11
+ hsl?: boolean;
12
+ }
13
+ export interface GeneratedDesign {
14
+ /** CSS variables file */
15
+ css?: {
16
+ path: string;
17
+ content: string;
18
+ };
19
+ /** Tailwind config extension */
20
+ tailwind?: {
21
+ path: string;
22
+ content: string;
23
+ };
24
+ }
25
+ export declare class KappaDesignGenerator {
26
+ private format;
27
+ private provenance;
28
+ private prefix;
29
+ private hsl;
30
+ constructor(options?: DesignGeneratorOptions);
31
+ /**
32
+ * Generate design files from DesignBlock AST
33
+ */
34
+ generate(design: DesignBlock): GeneratedDesign;
35
+ private generateCSS;
36
+ private generateColorVariables;
37
+ private resolveColorValue;
38
+ private generateTypographyVariables;
39
+ private generateSpacingVariables;
40
+ private generateBorderVariables;
41
+ private generateShadowVariables;
42
+ private generateMotionVariables;
43
+ private generateTailwind;
44
+ private hexToHsl;
45
+ private adjustColor;
46
+ private addAlpha;
47
+ private toKebabCase;
48
+ }
49
+ /**
50
+ * Generate design system files from Kappa DesignBlock
51
+ */
52
+ export declare function generateDesign(design: DesignBlock, options?: DesignGeneratorOptions): GeneratedDesign;