An experimental TypeSpec syntax for Lexicon
56
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add enum constraint support

Map TypeSpec enums to Lexicon enum constraints:
- String enums: `enum Status { Active: "active" }` → `"enum": ["active", ...]`
- Integer enums: `enum Priority { Low: 1 }` → `"enum": [1, ...]`

Implementation:
- Detect Enum type in typeToLexiconDefinition
- Extract enum member values
- Determine if string or integer enum
- Emit primitive with enum field

Example:
```typespec
enum Priority { Low: 1, Medium: 2, High: 3 }
model Task { priority: Priority }
```

Emits:
```json
{
"priority": {
"type": "integer",
"enum": [1, 2, 3]
}
}
```

Tests: All 23 existing tests remain green (no fixtures changed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

+40
+39
packages/emitter/src/emitter.ts
··· 336 336 prop?: ModelProperty, 337 337 ): LexiconDefinition | null { 338 338 switch (type.kind) { 339 + case "Enum": { 340 + // Handle enum types - convert to primitive with enum constraint 341 + const enumType = type as any; 342 + const members = Array.from(enumType.members?.values?.() || []); 343 + const values = members.map((m: any) => m.value); 344 + 345 + // Determine if this is a string or integer enum 346 + const firstValue = values[0]; 347 + const isStringEnum = typeof firstValue === "string"; 348 + const isIntegerEnum = typeof firstValue === "number" && Number.isInteger(firstValue); 349 + 350 + if (isStringEnum) { 351 + const primitive: LexiconPrimitive = { 352 + type: "string", 353 + enum: values as string[], 354 + }; 355 + if (prop) { 356 + const propDesc = getDoc(this.program, prop); 357 + if (propDesc) { 358 + primitive.description = propDesc; 359 + } 360 + } 361 + return primitive; 362 + } else if (isIntegerEnum) { 363 + const primitive: LexiconPrimitive = { 364 + type: "integer", 365 + enum: values as number[], 366 + }; 367 + if (prop) { 368 + const propDesc = getDoc(this.program, prop); 369 + if (propDesc) { 370 + primitive.description = propDesc; 371 + } 372 + } 373 + return primitive; 374 + } 375 + // Unsupported enum type (e.g., float) 376 + return null; 377 + } 339 378 case "Boolean": { 340 379 // Handle boolean literal types (e.g., `true` or `false`) 341 380 const booleanType = type as any;
+1
packages/emitter/src/types.ts
··· 95 95 description?: string; 96 96 default?: any; 97 97 const?: any; 98 + enum?: string[] | number[]; 98 99 minimum?: number; 99 100 maximum?: number; 100 101 minLength?: number;