@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.
- package/dist/codedna/generators/astro.d.ts +18 -0
- package/dist/codedna/generators/astro.js +91 -0
- package/dist/codedna/generators/authjs.d.ts +18 -0
- package/dist/codedna/generators/authjs.js +68 -0
- package/dist/codedna/generators/better-auth.d.ts +18 -0
- package/dist/codedna/generators/better-auth.js +62 -0
- package/dist/codedna/generators/drizzle-orm.d.ts +18 -0
- package/dist/codedna/generators/drizzle-orm.js +65 -0
- package/dist/codedna/generators/elysia-api.d.ts +12 -0
- package/dist/codedna/generators/elysia-api.js +64 -0
- package/dist/codedna/generators/hono-api.d.ts +12 -0
- package/dist/codedna/generators/hono-api.js +64 -0
- package/dist/codedna/generators/lucia-auth.d.ts +18 -0
- package/dist/codedna/generators/lucia-auth.js +69 -0
- package/dist/codedna/generators/prisma.d.ts +18 -0
- package/dist/codedna/generators/prisma.js +64 -0
- package/dist/codedna/generators/react-router-v7.d.ts +18 -0
- package/dist/codedna/generators/react-router-v7.js +77 -0
- package/dist/codedna/generators/react19-shadcn.d.ts +21 -0
- package/dist/codedna/generators/react19-shadcn.js +367 -0
- package/dist/codedna/generators/sveltekit.d.ts +18 -0
- package/dist/codedna/generators/sveltekit.js +73 -0
- package/dist/codedna/generators/tanstack-start-drizzle.d.ts +92 -0
- package/dist/codedna/generators/tanstack-start-drizzle.js +824 -0
- package/dist/codedna/generators/trpc-api.d.ts +12 -0
- package/dist/codedna/generators/trpc-api.js +64 -0
- package/dist/codedna/index.d.ts +31 -0
- package/dist/codedna/index.js +39 -0
- package/dist/codedna/kappa-api-generator.d.ts +89 -0
- package/dist/codedna/kappa-api-generator.js +493 -0
- package/dist/codedna/kappa-ast.d.ts +552 -0
- package/dist/codedna/kappa-ast.js +141 -0
- package/dist/codedna/kappa-cli.d.ts +2 -0
- package/dist/codedna/kappa-cli.js +302 -0
- package/dist/codedna/kappa-component-generator.d.ts +47 -0
- package/dist/codedna/kappa-component-generator.js +295 -0
- package/dist/codedna/kappa-design-generator.d.ts +52 -0
- package/dist/codedna/kappa-design-generator.js +365 -0
- package/dist/codedna/kappa-drizzle-generator.d.ts +45 -0
- package/dist/codedna/kappa-drizzle-generator.js +355 -0
- package/dist/codedna/kappa-form-generator.d.ts +51 -0
- package/dist/codedna/kappa-form-generator.js +319 -0
- package/dist/codedna/kappa-lexer.d.ts +268 -0
- package/dist/codedna/kappa-lexer.js +757 -0
- package/dist/codedna/kappa-page-generator.d.ts +57 -0
- package/dist/codedna/kappa-page-generator.js +338 -0
- package/dist/codedna/kappa-parser.d.ts +261 -0
- package/dist/codedna/kappa-parser.js +2547 -0
- package/dist/codedna/kappa-provenance.d.ts +101 -0
- package/dist/codedna/kappa-provenance.js +199 -0
- package/dist/codedna/kappa-types-generator.d.ts +37 -0
- package/dist/codedna/kappa-types-generator.js +159 -0
- package/dist/codedna/kappa-validator.d.ts +86 -0
- package/dist/codedna/kappa-validator.js +638 -0
- package/dist/codedna/kappa-zod-generator.d.ts +32 -0
- package/dist/codedna/kappa-zod-generator.js +216 -0
- package/dist/handlers/codedna-handlers.d.ts +1 -1
- package/dist/handlers/kappa-handlers.d.ts +116 -0
- package/dist/handlers/kappa-handlers.js +465 -0
- package/dist/handlers/tool-handlers.js +121 -0
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.js +166 -9
- package/dist/tools.js +199 -0
- package/docs/research/2026-01-02-codedna-il-specification.md +639 -0
- package/docs/research/2026-01-02-codedna-v2-research.md +943 -0
- package/docs/research/2026-01-02-computation-foundations.md +564 -0
- package/docs/research/2026-01-02-hardware-description.md +814 -0
- package/docs/research/2026-01-02-kappa-specification.md +697 -0
- package/docs/research/2026-01-02-kappa-tanstack-example.md +527 -0
- package/docs/research/2026-01-02-kappa-v2-synthesis.md +406 -0
- package/docs/research/2026-01-02-kappa-v2.5-specification.md +1218 -0
- package/docs/research/2026-01-02-kappa-v3-specification.md +1864 -0
- package/docs/research/2026-01-02-kappa-whitepaper.md +662 -0
- package/docs/research/2026-01-02-logic-constraint.md +731 -0
- package/docs/research/2026-01-02-quantum-computation.md +635 -0
- package/package.json +4 -2
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source location for provenance tracking.
|
|
3
|
+
* Every AST node includes this to enable tracing generated code back to spec.
|
|
4
|
+
*/
|
|
5
|
+
export interface SourceLocation {
|
|
6
|
+
/** 1-based line number */
|
|
7
|
+
startLine: number;
|
|
8
|
+
/** 1-based column number */
|
|
9
|
+
startColumn: number;
|
|
10
|
+
/** 1-based line number */
|
|
11
|
+
endLine: number;
|
|
12
|
+
/** 1-based column number */
|
|
13
|
+
endColumn: number;
|
|
14
|
+
/** Character offset from start of file */
|
|
15
|
+
startOffset: number;
|
|
16
|
+
/** Character offset from start of file */
|
|
17
|
+
endOffset: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Base interface for all AST nodes
|
|
21
|
+
*/
|
|
22
|
+
export interface BaseNode {
|
|
23
|
+
/** Source location for provenance */
|
|
24
|
+
loc: SourceLocation;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Root AST node representing a complete Kappa specification
|
|
28
|
+
*/
|
|
29
|
+
export interface KappaSpec extends BaseNode {
|
|
30
|
+
kind: 'KappaSpec';
|
|
31
|
+
/** Project configuration (optional - can be inferred) */
|
|
32
|
+
project?: ProjectBlock;
|
|
33
|
+
/** Authentication configuration */
|
|
34
|
+
auth?: AuthBlock;
|
|
35
|
+
/** Entity definitions */
|
|
36
|
+
entities: EntityBlock[];
|
|
37
|
+
/** API definitions */
|
|
38
|
+
apis: APIBlock[];
|
|
39
|
+
/** User journey definitions */
|
|
40
|
+
journeys: JourneyBlock[];
|
|
41
|
+
/** Page/route definitions */
|
|
42
|
+
pages: PageBlock[];
|
|
43
|
+
/** Component definitions */
|
|
44
|
+
components: ComponentBlock[];
|
|
45
|
+
/** Form definitions */
|
|
46
|
+
forms: FormBlock[];
|
|
47
|
+
/** Design system configuration */
|
|
48
|
+
design?: DesignBlock;
|
|
49
|
+
}
|
|
50
|
+
export type StackType = 'tanstack-start' | 'next' | 'remix' | 'sveltekit' | 'astro' | 'express' | 'hono' | 'elysia';
|
|
51
|
+
export type DatabaseType = 'postgres' | 'mysql' | 'sqlite' | 'turso' | 'mongodb';
|
|
52
|
+
export type AuthType = 'jwt' | 'session' | 'oauth';
|
|
53
|
+
export type UILibrary = 'shadcn' | 'mui' | 'chakra' | 'tailwind-only';
|
|
54
|
+
/**
|
|
55
|
+
* Project configuration block
|
|
56
|
+
*/
|
|
57
|
+
export interface ProjectBlock extends BaseNode {
|
|
58
|
+
kind: 'ProjectBlock';
|
|
59
|
+
/** Project name */
|
|
60
|
+
name: string;
|
|
61
|
+
/** Semantic version */
|
|
62
|
+
version?: string;
|
|
63
|
+
/** Target stack/framework */
|
|
64
|
+
stack: StackType;
|
|
65
|
+
/** Database type */
|
|
66
|
+
database?: DatabaseType;
|
|
67
|
+
/** Authentication strategy */
|
|
68
|
+
auth?: AuthType;
|
|
69
|
+
/** UI component library */
|
|
70
|
+
ui?: UILibrary;
|
|
71
|
+
}
|
|
72
|
+
export type HashAlgorithm = 'argon2id' | 'bcrypt';
|
|
73
|
+
export interface HashConfig extends BaseNode {
|
|
74
|
+
kind: 'HashConfig';
|
|
75
|
+
algorithm: HashAlgorithm;
|
|
76
|
+
/** Memory cost for argon2id (e.g., "64mb") */
|
|
77
|
+
memory?: string;
|
|
78
|
+
/** Iterations for argon2id */
|
|
79
|
+
iterations?: number;
|
|
80
|
+
/** Parallelism for argon2id */
|
|
81
|
+
parallelism?: number;
|
|
82
|
+
/** Rounds for bcrypt */
|
|
83
|
+
rounds?: number;
|
|
84
|
+
}
|
|
85
|
+
export type RefreshStrategy = 'sliding' | 'fixed' | 'none';
|
|
86
|
+
/**
|
|
87
|
+
* JWT authentication configuration
|
|
88
|
+
*/
|
|
89
|
+
export interface JWTConfig extends BaseNode {
|
|
90
|
+
kind: 'JWTConfig';
|
|
91
|
+
/** Environment variable for secret */
|
|
92
|
+
secret: string;
|
|
93
|
+
/** Token issuer */
|
|
94
|
+
issuer?: string;
|
|
95
|
+
/** Token audience */
|
|
96
|
+
audience?: string;
|
|
97
|
+
/** Token expiration (e.g., "7d", "1h") */
|
|
98
|
+
expires: string;
|
|
99
|
+
/** Refresh token strategy */
|
|
100
|
+
refresh?: RefreshStrategy;
|
|
101
|
+
/** Password hashing configuration */
|
|
102
|
+
hash: HashConfig;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Session-based authentication configuration
|
|
106
|
+
*/
|
|
107
|
+
export interface SessionConfig extends BaseNode {
|
|
108
|
+
kind: 'SessionConfig';
|
|
109
|
+
/** Session duration */
|
|
110
|
+
duration: string;
|
|
111
|
+
/** Cookie configuration */
|
|
112
|
+
cookie?: {
|
|
113
|
+
name?: string;
|
|
114
|
+
httpOnly?: boolean;
|
|
115
|
+
secure?: boolean;
|
|
116
|
+
sameSite?: 'strict' | 'lax' | 'none';
|
|
117
|
+
};
|
|
118
|
+
/** Password hashing configuration */
|
|
119
|
+
hash: HashConfig;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Authentication block
|
|
123
|
+
*/
|
|
124
|
+
export interface AuthBlock extends BaseNode {
|
|
125
|
+
kind: 'AuthBlock';
|
|
126
|
+
type: 'jwt' | 'session';
|
|
127
|
+
jwt?: JWTConfig;
|
|
128
|
+
session?: SessionConfig;
|
|
129
|
+
}
|
|
130
|
+
export type PrimitiveType = 'string' | 'int' | 'float' | 'bool' | 'email' | 'url' | 'uuid' | 'phone' | 'slug' | 'markdown' | 'json' | 'timestamp' | 'date' | 'time' | 'duration';
|
|
131
|
+
export interface PrimitiveFieldType {
|
|
132
|
+
kind: 'primitive';
|
|
133
|
+
type: PrimitiveType;
|
|
134
|
+
/** Range constraint for strings/numbers (e.g., 2..100) */
|
|
135
|
+
range?: {
|
|
136
|
+
min?: number;
|
|
137
|
+
max?: number;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export interface EnumFieldType {
|
|
141
|
+
kind: 'enum';
|
|
142
|
+
values: string[];
|
|
143
|
+
}
|
|
144
|
+
export interface ReferenceFieldType {
|
|
145
|
+
kind: 'reference';
|
|
146
|
+
entity: string;
|
|
147
|
+
optional: boolean;
|
|
148
|
+
}
|
|
149
|
+
export interface ArrayFieldType {
|
|
150
|
+
kind: 'array';
|
|
151
|
+
itemType: FieldType;
|
|
152
|
+
}
|
|
153
|
+
export type FieldType = PrimitiveFieldType | EnumFieldType | ReferenceFieldType | ArrayFieldType;
|
|
154
|
+
export type FieldModifier = 'primary' | 'unique' | 'auto' | 'immutable' | 'internal' | 'hashed' | 'optional';
|
|
155
|
+
export interface EntityField extends BaseNode {
|
|
156
|
+
kind: 'EntityField';
|
|
157
|
+
name: string;
|
|
158
|
+
type: FieldType;
|
|
159
|
+
modifiers: FieldModifier[];
|
|
160
|
+
/** Default value expression */
|
|
161
|
+
defaultValue?: string;
|
|
162
|
+
/** Update trigger (e.g., "on_update" for updated_at) */
|
|
163
|
+
updateTrigger?: boolean;
|
|
164
|
+
}
|
|
165
|
+
export type RelationType = 'has_many' | 'has_one' | 'belongs_to' | 'many_to_many';
|
|
166
|
+
export type CascadeAction = 'delete' | 'nullify' | 'restrict';
|
|
167
|
+
export interface EntityRelationship extends BaseNode {
|
|
168
|
+
kind: 'EntityRelationship';
|
|
169
|
+
type: RelationType;
|
|
170
|
+
entity: string;
|
|
171
|
+
/** Alias for the relationship (e.g., "as owner") */
|
|
172
|
+
as?: string;
|
|
173
|
+
/** Through entity for many-to-many */
|
|
174
|
+
through?: string;
|
|
175
|
+
/** Cascade behavior on delete */
|
|
176
|
+
cascade?: CascadeAction;
|
|
177
|
+
}
|
|
178
|
+
export type CapabilityAction = 'create' | 'read' | 'update' | 'delete' | 'invite';
|
|
179
|
+
export interface Capability extends BaseNode {
|
|
180
|
+
kind: 'Capability';
|
|
181
|
+
allowed: boolean;
|
|
182
|
+
action: CapabilityAction;
|
|
183
|
+
/** Target entity (if different from self) */
|
|
184
|
+
target?: string;
|
|
185
|
+
/** Condition for the capability (e.g., "where: member_of") */
|
|
186
|
+
condition?: string;
|
|
187
|
+
/** Additional target context (e.g., "to: Team") */
|
|
188
|
+
targetContext?: string;
|
|
189
|
+
/** Unless condition for cannot (e.g., "unless: no_owned_projects") */
|
|
190
|
+
unless?: string;
|
|
191
|
+
}
|
|
192
|
+
export type LifecycleEvent = 'on_create' | 'on_update' | 'on_delete';
|
|
193
|
+
export interface LifecycleHook extends BaseNode {
|
|
194
|
+
kind: 'LifecycleHook';
|
|
195
|
+
event: LifecycleEvent;
|
|
196
|
+
/** Field that triggers update hook (optional, for on_update) */
|
|
197
|
+
field?: string;
|
|
198
|
+
/** Actions to perform */
|
|
199
|
+
actions: LifecycleAction[];
|
|
200
|
+
}
|
|
201
|
+
export type LifecycleActionType = 'send_email' | 'log_audit' | 'enqueue' | 'anonymize' | 'transfer_ownership' | 'require_reverification';
|
|
202
|
+
export interface LifecycleAction extends BaseNode {
|
|
203
|
+
kind: 'LifecycleAction';
|
|
204
|
+
type: LifecycleActionType;
|
|
205
|
+
/** Parameters for the action */
|
|
206
|
+
params: Record<string, string | string[]>;
|
|
207
|
+
}
|
|
208
|
+
export interface EntityIndex extends BaseNode {
|
|
209
|
+
kind: 'EntityIndex';
|
|
210
|
+
fields: string[];
|
|
211
|
+
unique?: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Enhanced entity block with capabilities and lifecycle
|
|
215
|
+
*/
|
|
216
|
+
export interface EntityBlock extends BaseNode {
|
|
217
|
+
kind: 'EntityBlock';
|
|
218
|
+
name: string;
|
|
219
|
+
fields: EntityField[];
|
|
220
|
+
relationships: EntityRelationship[];
|
|
221
|
+
capabilities: Capability[];
|
|
222
|
+
lifecycleHooks: LifecycleHook[];
|
|
223
|
+
indexes: EntityIndex[];
|
|
224
|
+
}
|
|
225
|
+
export type EffectType = 'DB' | 'Auth' | 'Email' | 'Audit' | 'Queue' | 'Cache' | 'External';
|
|
226
|
+
export interface APIParameter extends BaseNode {
|
|
227
|
+
kind: 'APIParameter';
|
|
228
|
+
name: string;
|
|
229
|
+
type: FieldType;
|
|
230
|
+
optional: boolean;
|
|
231
|
+
}
|
|
232
|
+
export interface APIReturnType extends BaseNode {
|
|
233
|
+
kind: 'APIReturnType';
|
|
234
|
+
/** Entity name or inline type */
|
|
235
|
+
type: string;
|
|
236
|
+
/** Is it an array? */
|
|
237
|
+
isArray: boolean;
|
|
238
|
+
/** Joined data (e.g., "Member & { user: User }") */
|
|
239
|
+
joined?: {
|
|
240
|
+
field: string;
|
|
241
|
+
entity: string;
|
|
242
|
+
}[];
|
|
243
|
+
}
|
|
244
|
+
export interface APIOperation extends BaseNode {
|
|
245
|
+
kind: 'APIOperation';
|
|
246
|
+
name: string;
|
|
247
|
+
parameters: APIParameter[];
|
|
248
|
+
effects: EffectType[];
|
|
249
|
+
returnType: APIReturnType;
|
|
250
|
+
/** Error types that can be thrown */
|
|
251
|
+
throws?: string[];
|
|
252
|
+
/** Rate limit (e.g., "10/minute") */
|
|
253
|
+
rateLimit?: string;
|
|
254
|
+
/** Permission check (e.g., "owner_of") */
|
|
255
|
+
check?: string;
|
|
256
|
+
/** Audit configuration */
|
|
257
|
+
audit?: 'always' | 'on_error' | 'never';
|
|
258
|
+
/** Cache duration */
|
|
259
|
+
cache?: string;
|
|
260
|
+
/** Deprecation message */
|
|
261
|
+
deprecated?: string;
|
|
262
|
+
}
|
|
263
|
+
export type CRUDAction = 'create' | 'read' | 'update' | 'delete' | 'list';
|
|
264
|
+
export interface CRUDShorthand extends BaseNode {
|
|
265
|
+
kind: 'CRUDShorthand';
|
|
266
|
+
entity: string;
|
|
267
|
+
actions: {
|
|
268
|
+
action: CRUDAction;
|
|
269
|
+
effects: EffectType[];
|
|
270
|
+
check?: string;
|
|
271
|
+
filter?: string;
|
|
272
|
+
scope?: string;
|
|
273
|
+
}[];
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* API definition block
|
|
277
|
+
*/
|
|
278
|
+
export interface APIBlock extends BaseNode {
|
|
279
|
+
kind: 'APIBlock';
|
|
280
|
+
name: string;
|
|
281
|
+
operations: APIOperation[];
|
|
282
|
+
crud: CRUDShorthand[];
|
|
283
|
+
}
|
|
284
|
+
export interface JourneyStep extends BaseNode {
|
|
285
|
+
kind: 'JourneyStep';
|
|
286
|
+
name: string;
|
|
287
|
+
/** Page to render */
|
|
288
|
+
page?: string;
|
|
289
|
+
/** Action to perform */
|
|
290
|
+
action?: string;
|
|
291
|
+
/** Next step name */
|
|
292
|
+
next?: string;
|
|
293
|
+
/** Wait for condition */
|
|
294
|
+
waitFor?: string;
|
|
295
|
+
/** Timeout with fallback */
|
|
296
|
+
timeout?: {
|
|
297
|
+
duration: string;
|
|
298
|
+
fallback: string;
|
|
299
|
+
};
|
|
300
|
+
/** Skip condition */
|
|
301
|
+
skipIf?: string;
|
|
302
|
+
/** Can be skipped by user */
|
|
303
|
+
skippable?: boolean;
|
|
304
|
+
/** Error handling */
|
|
305
|
+
onError?: {
|
|
306
|
+
action: string;
|
|
307
|
+
behavior: 'stay' | 'retry' | 'next';
|
|
308
|
+
};
|
|
309
|
+
/** Is this the final step? */
|
|
310
|
+
complete?: boolean;
|
|
311
|
+
}
|
|
312
|
+
export interface JourneyRecovery extends BaseNode {
|
|
313
|
+
kind: 'JourneyRecovery';
|
|
314
|
+
/** Step that triggers recovery */
|
|
315
|
+
step: string;
|
|
316
|
+
/** Recovery action (e.g., "send_reminder(after: 1h, max: 3)") */
|
|
317
|
+
action: string;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* User journey definition
|
|
321
|
+
*/
|
|
322
|
+
export interface JourneyBlock extends BaseNode {
|
|
323
|
+
kind: 'JourneyBlock';
|
|
324
|
+
name: string;
|
|
325
|
+
/** Actor type (e.g., "new_user") */
|
|
326
|
+
actor: string;
|
|
327
|
+
steps: JourneyStep[];
|
|
328
|
+
/** Events to track */
|
|
329
|
+
track?: string[];
|
|
330
|
+
/** Recovery handlers */
|
|
331
|
+
recovery: JourneyRecovery[];
|
|
332
|
+
}
|
|
333
|
+
export interface PageLoader extends BaseNode {
|
|
334
|
+
kind: 'PageLoader';
|
|
335
|
+
name: string;
|
|
336
|
+
/** API call or expression */
|
|
337
|
+
source: string;
|
|
338
|
+
}
|
|
339
|
+
export interface PageAction extends BaseNode {
|
|
340
|
+
kind: 'PageAction';
|
|
341
|
+
name: string;
|
|
342
|
+
/** Action trigger (e.g., "modal(CreateProjectForm) -> api.create_project -> refresh") */
|
|
343
|
+
handler: string;
|
|
344
|
+
}
|
|
345
|
+
export interface PageLayout extends BaseNode {
|
|
346
|
+
kind: 'PageLayout';
|
|
347
|
+
component: string;
|
|
348
|
+
props: Record<string, string>;
|
|
349
|
+
children?: PageLayout[];
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Page/route definition
|
|
353
|
+
*/
|
|
354
|
+
export interface PageBlock extends BaseNode {
|
|
355
|
+
kind: 'PageBlock';
|
|
356
|
+
name: string;
|
|
357
|
+
/** Route path (e.g., "/dashboard", "/projects/:id") */
|
|
358
|
+
route: string;
|
|
359
|
+
/** Route guard (e.g., "authenticated", "guest_only") */
|
|
360
|
+
guard?: string;
|
|
361
|
+
/** Component to render (for simple pages) */
|
|
362
|
+
component?: string;
|
|
363
|
+
/** Data loaders */
|
|
364
|
+
loaders: PageLoader[];
|
|
365
|
+
/** Layout composition */
|
|
366
|
+
layout?: PageLayout;
|
|
367
|
+
/** Page actions */
|
|
368
|
+
actions: PageAction[];
|
|
369
|
+
/** Page title (can include interpolation) */
|
|
370
|
+
title?: string;
|
|
371
|
+
/** Meta tags */
|
|
372
|
+
meta?: Record<string, string>;
|
|
373
|
+
}
|
|
374
|
+
export interface ComponentProp extends BaseNode {
|
|
375
|
+
kind: 'ComponentProp';
|
|
376
|
+
name: string;
|
|
377
|
+
type: string;
|
|
378
|
+
optional: boolean;
|
|
379
|
+
}
|
|
380
|
+
export interface ComponentStructure extends BaseNode {
|
|
381
|
+
kind: 'ComponentStructure';
|
|
382
|
+
type: string;
|
|
383
|
+
props: Record<string, string>;
|
|
384
|
+
children?: ComponentStructure[];
|
|
385
|
+
}
|
|
386
|
+
export interface ComponentVariant extends BaseNode {
|
|
387
|
+
kind: 'ComponentVariant';
|
|
388
|
+
name: string;
|
|
389
|
+
/** Modifications (e.g., "hide(body.meta, footer.avatar_group)") */
|
|
390
|
+
modifications: string[];
|
|
391
|
+
}
|
|
392
|
+
export interface CompoundPart extends BaseNode {
|
|
393
|
+
kind: 'CompoundPart';
|
|
394
|
+
name: string;
|
|
395
|
+
element: string;
|
|
396
|
+
props?: string[];
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Component definition
|
|
400
|
+
*/
|
|
401
|
+
export interface ComponentBlock extends BaseNode {
|
|
402
|
+
kind: 'ComponentBlock';
|
|
403
|
+
name: string;
|
|
404
|
+
props: ComponentProp[];
|
|
405
|
+
structure?: ComponentStructure;
|
|
406
|
+
variants: ComponentVariant[];
|
|
407
|
+
/** Compound component parts */
|
|
408
|
+
compound?: CompoundPart[];
|
|
409
|
+
/** Default composition for compound components */
|
|
410
|
+
defaultComposition?: ComponentStructure;
|
|
411
|
+
}
|
|
412
|
+
export type FormFieldType = 'text' | 'textarea' | 'email' | 'password' | 'number' | 'select' | 'multiselect' | 'checkbox' | 'radio' | 'date' | 'time' | 'datetime' | 'file';
|
|
413
|
+
export interface FormFieldOption extends BaseNode {
|
|
414
|
+
kind: 'FormFieldOption';
|
|
415
|
+
value: string;
|
|
416
|
+
label: string;
|
|
417
|
+
icon?: string;
|
|
418
|
+
}
|
|
419
|
+
export interface FormField extends BaseNode {
|
|
420
|
+
kind: 'FormField';
|
|
421
|
+
name: string;
|
|
422
|
+
type: FormFieldType;
|
|
423
|
+
label: string;
|
|
424
|
+
placeholder?: string;
|
|
425
|
+
/** Validation expression */
|
|
426
|
+
validate?: string;
|
|
427
|
+
required: boolean;
|
|
428
|
+
/** Default value */
|
|
429
|
+
defaultValue?: string;
|
|
430
|
+
/** Static options */
|
|
431
|
+
options?: FormFieldOption[];
|
|
432
|
+
/** Dynamic options source */
|
|
433
|
+
optionsFrom?: string;
|
|
434
|
+
/** Additional config (e.g., rows for textarea) */
|
|
435
|
+
config?: Record<string, string | number | boolean>;
|
|
436
|
+
}
|
|
437
|
+
export interface FormSubmit extends BaseNode {
|
|
438
|
+
kind: 'FormSubmit';
|
|
439
|
+
/** API action to call */
|
|
440
|
+
action: string;
|
|
441
|
+
/** Button text */
|
|
442
|
+
button: string;
|
|
443
|
+
/** Loading text */
|
|
444
|
+
loading?: string;
|
|
445
|
+
/** Success handler */
|
|
446
|
+
onSuccess: string;
|
|
447
|
+
/** Error handler */
|
|
448
|
+
onError: string;
|
|
449
|
+
}
|
|
450
|
+
export interface FormLayoutRow extends BaseNode {
|
|
451
|
+
kind: 'FormLayoutRow';
|
|
452
|
+
fields: string[];
|
|
453
|
+
columns?: number;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Form definition
|
|
457
|
+
*/
|
|
458
|
+
export interface FormBlock extends BaseNode {
|
|
459
|
+
kind: 'FormBlock';
|
|
460
|
+
name: string;
|
|
461
|
+
fields: FormField[];
|
|
462
|
+
submit: FormSubmit;
|
|
463
|
+
layout: FormLayoutRow[];
|
|
464
|
+
}
|
|
465
|
+
export interface ColorValue {
|
|
466
|
+
/** Hex color or reference (e.g., "#3B82F6" or "darken(primary, 10%)") */
|
|
467
|
+
value: string;
|
|
468
|
+
/** Is this a function call? */
|
|
469
|
+
isFunction: boolean;
|
|
470
|
+
/** Function name if isFunction */
|
|
471
|
+
functionName?: 'darken' | 'lighten' | 'alpha';
|
|
472
|
+
/** Function arguments if isFunction */
|
|
473
|
+
functionArgs?: (string | number)[];
|
|
474
|
+
}
|
|
475
|
+
export interface ColorPalette extends BaseNode {
|
|
476
|
+
kind: 'ColorPalette';
|
|
477
|
+
colors: Record<string, ColorValue>;
|
|
478
|
+
}
|
|
479
|
+
export interface TypographyConfig extends BaseNode {
|
|
480
|
+
kind: 'TypographyConfig';
|
|
481
|
+
fontFamily?: string;
|
|
482
|
+
fontMono?: string;
|
|
483
|
+
scale?: Record<string, string>;
|
|
484
|
+
weight?: Record<string, number>;
|
|
485
|
+
}
|
|
486
|
+
export interface SpacingConfig extends BaseNode {
|
|
487
|
+
kind: 'SpacingConfig';
|
|
488
|
+
unit?: string;
|
|
489
|
+
scale?: number[];
|
|
490
|
+
}
|
|
491
|
+
export interface BorderConfig extends BaseNode {
|
|
492
|
+
kind: 'BorderConfig';
|
|
493
|
+
radius?: Record<string, string>;
|
|
494
|
+
width?: string;
|
|
495
|
+
color?: string;
|
|
496
|
+
}
|
|
497
|
+
export interface ShadowConfig extends BaseNode {
|
|
498
|
+
kind: 'ShadowConfig';
|
|
499
|
+
shadows: Record<string, string>;
|
|
500
|
+
}
|
|
501
|
+
export interface MotionConfig extends BaseNode {
|
|
502
|
+
kind: 'MotionConfig';
|
|
503
|
+
duration?: Record<string, string>;
|
|
504
|
+
easing?: Record<string, string>;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Design system configuration
|
|
508
|
+
*/
|
|
509
|
+
export interface DesignBlock extends BaseNode {
|
|
510
|
+
kind: 'DesignBlock';
|
|
511
|
+
colors: ColorPalette;
|
|
512
|
+
/** Dark mode color overrides */
|
|
513
|
+
darkColors?: ColorPalette;
|
|
514
|
+
typography?: TypographyConfig;
|
|
515
|
+
spacing?: SpacingConfig;
|
|
516
|
+
borders?: BorderConfig;
|
|
517
|
+
shadows?: ShadowConfig;
|
|
518
|
+
motion?: MotionConfig;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* All possible AST node types
|
|
522
|
+
*/
|
|
523
|
+
export type KappaNode = KappaSpec | ProjectBlock | AuthBlock | EntityBlock | APIBlock | JourneyBlock | PageBlock | ComponentBlock | FormBlock | DesignBlock | EntityField | EntityRelationship | Capability | LifecycleHook | LifecycleAction | EntityIndex | APIOperation | APIParameter | APIReturnType | CRUDShorthand | JourneyStep | JourneyRecovery | PageLoader | PageAction | PageLayout | ComponentProp | ComponentStructure | ComponentVariant | CompoundPart | FormField | FormFieldOption | FormSubmit | FormLayoutRow | ColorPalette | TypographyConfig | SpacingConfig | BorderConfig | ShadowConfig | MotionConfig | HashConfig | JWTConfig | SessionConfig;
|
|
524
|
+
/**
|
|
525
|
+
* Extract node type from kind string
|
|
526
|
+
*/
|
|
527
|
+
export type NodeOfKind<K extends KappaNode['kind']> = Extract<KappaNode, {
|
|
528
|
+
kind: K;
|
|
529
|
+
}>;
|
|
530
|
+
/**
|
|
531
|
+
* Visitor function type for AST traversal
|
|
532
|
+
*/
|
|
533
|
+
export type NodeVisitor<T = void> = {
|
|
534
|
+
[K in KappaNode['kind']]?: (node: NodeOfKind<K>) => T;
|
|
535
|
+
};
|
|
536
|
+
export interface ParseError {
|
|
537
|
+
message: string;
|
|
538
|
+
location: SourceLocation;
|
|
539
|
+
/** Error code for programmatic handling */
|
|
540
|
+
code?: string;
|
|
541
|
+
}
|
|
542
|
+
export interface ParseResult {
|
|
543
|
+
success: boolean;
|
|
544
|
+
ast?: KappaSpec;
|
|
545
|
+
errors: ParseError[];
|
|
546
|
+
/** Warnings that don't prevent parsing */
|
|
547
|
+
warnings: ParseError[];
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Convert EntityBlock to legacy EntitySpec format for existing generators
|
|
551
|
+
*/
|
|
552
|
+
export declare function toEntitySpec(entity: EntityBlock): import('./parser.js').EntitySpec;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Kappa v2.5 Abstract Syntax Tree Types
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Complete type definitions for Kappa specification language AST.
|
|
6
|
+
// All nodes include source location tracking for provenance.
|
|
7
|
+
//
|
|
8
|
+
// Reference: docs/research/2026-01-02-kappa-v2.5-specification.md
|
|
9
|
+
//
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Backwards Compatibility with EntitySpec
|
|
12
|
+
// =============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Convert EntityBlock to legacy EntitySpec format for existing generators
|
|
15
|
+
*/
|
|
16
|
+
export function toEntitySpec(entity) {
|
|
17
|
+
return {
|
|
18
|
+
name: entity.name,
|
|
19
|
+
fields: entity.fields.map(field => ({
|
|
20
|
+
name: field.name,
|
|
21
|
+
type: fieldTypeToLegacy(field.type),
|
|
22
|
+
constraints: modifiersToConstraints(field.modifiers, field.type),
|
|
23
|
+
})),
|
|
24
|
+
hooks: lifecycleToLegacy(entity.lifecycleHooks),
|
|
25
|
+
permissions: capabilitiesToLegacy(entity.capabilities),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function fieldTypeToLegacy(type) {
|
|
29
|
+
switch (type.kind) {
|
|
30
|
+
case 'primitive':
|
|
31
|
+
const primitiveMap = {
|
|
32
|
+
string: 'string',
|
|
33
|
+
int: 'integer',
|
|
34
|
+
float: 'decimal',
|
|
35
|
+
bool: 'boolean',
|
|
36
|
+
timestamp: 'datetime',
|
|
37
|
+
date: 'datetime',
|
|
38
|
+
time: 'datetime',
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
kind: 'primitive',
|
|
42
|
+
value: (primitiveMap[type.type] || type.type),
|
|
43
|
+
};
|
|
44
|
+
case 'enum':
|
|
45
|
+
return { kind: 'enum', values: type.values };
|
|
46
|
+
case 'reference':
|
|
47
|
+
return { kind: 'reference', entity: type.entity };
|
|
48
|
+
case 'array':
|
|
49
|
+
if (type.itemType.kind === 'primitive') {
|
|
50
|
+
const itemMap = {
|
|
51
|
+
string: 'string',
|
|
52
|
+
int: 'integer',
|
|
53
|
+
float: 'decimal',
|
|
54
|
+
bool: 'boolean',
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
kind: 'array',
|
|
58
|
+
itemType: (itemMap[type.itemType.type] || 'string'),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return { kind: 'array', itemType: 'string' };
|
|
62
|
+
default:
|
|
63
|
+
return { kind: 'primitive', value: 'string' };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function modifiersToConstraints(modifiers, type) {
|
|
67
|
+
const constraints = [];
|
|
68
|
+
for (const mod of modifiers) {
|
|
69
|
+
switch (mod) {
|
|
70
|
+
case 'unique':
|
|
71
|
+
constraints.push({ kind: 'unique' });
|
|
72
|
+
break;
|
|
73
|
+
case 'hashed':
|
|
74
|
+
constraints.push({ kind: 'hashed' });
|
|
75
|
+
break;
|
|
76
|
+
case 'optional':
|
|
77
|
+
constraints.push({ kind: 'nullable' });
|
|
78
|
+
break;
|
|
79
|
+
case 'immutable':
|
|
80
|
+
constraints.push({ kind: 'immutable' });
|
|
81
|
+
break;
|
|
82
|
+
case 'primary':
|
|
83
|
+
case 'auto':
|
|
84
|
+
case 'internal':
|
|
85
|
+
// These don't map to existing constraints
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Add required if not optional
|
|
90
|
+
if (!modifiers.includes('optional')) {
|
|
91
|
+
constraints.push({ kind: 'required' });
|
|
92
|
+
}
|
|
93
|
+
// Add type-based constraints
|
|
94
|
+
if (type.kind === 'primitive') {
|
|
95
|
+
if (type.type === 'email') {
|
|
96
|
+
constraints.push({ kind: 'email' });
|
|
97
|
+
}
|
|
98
|
+
if (type.type === 'url') {
|
|
99
|
+
constraints.push({ kind: 'url' });
|
|
100
|
+
}
|
|
101
|
+
if (type.range) {
|
|
102
|
+
if (type.range.min !== undefined) {
|
|
103
|
+
constraints.push({ kind: 'min', value: type.range.min });
|
|
104
|
+
}
|
|
105
|
+
if (type.range.max !== undefined) {
|
|
106
|
+
constraints.push({ kind: 'max', value: type.range.max });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return constraints;
|
|
111
|
+
}
|
|
112
|
+
function lifecycleToLegacy(hooks) {
|
|
113
|
+
if (hooks.length === 0)
|
|
114
|
+
return undefined;
|
|
115
|
+
const result = {};
|
|
116
|
+
for (const hook of hooks) {
|
|
117
|
+
const actions = hook.actions.map(a => `${a.type}(${JSON.stringify(a.params)})`);
|
|
118
|
+
switch (hook.event) {
|
|
119
|
+
case 'on_create':
|
|
120
|
+
result.afterCreate = actions;
|
|
121
|
+
break;
|
|
122
|
+
case 'on_update':
|
|
123
|
+
result.afterUpdate = actions;
|
|
124
|
+
break;
|
|
125
|
+
case 'on_delete':
|
|
126
|
+
result.beforeDelete = actions;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
function capabilitiesToLegacy(capabilities) {
|
|
133
|
+
if (capabilities.length === 0)
|
|
134
|
+
return undefined;
|
|
135
|
+
return capabilities
|
|
136
|
+
.filter(c => c.allowed && ['create', 'read', 'update', 'delete'].includes(c.action))
|
|
137
|
+
.map(c => ({
|
|
138
|
+
action: c.action,
|
|
139
|
+
condition: c.condition,
|
|
140
|
+
}));
|
|
141
|
+
}
|