An experimental TypeSpec syntax for Lexicon
56
fork

Configure Feed

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

feat: add app.bsky.embed.external

- Port external lexicon with Main model
- Fix Main model description handling (goes on main def, not lexicon)
- Optional blob fields (thumb)
- Same-namespace refs

Tests passing (22/22)

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

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

+92 -4
+6 -4
typelex-emitter/src/emitter.ts
··· 100 100 const lexiconId = fullName; 101 101 this.currentLexiconId = lexiconId; 102 102 103 - const mainDef = this.modelToLexiconObject(mainModel, false); 104 - const description = getDoc(this.program, ns); 103 + // Include model description in the main object 104 + const mainDef = this.modelToLexiconObject(mainModel, true); 105 + const namespaceDescription = getDoc(this.program, ns); 105 106 106 107 const lexicon: LexiconDocument = { 107 108 lexicon: 1, ··· 111 112 }, 112 113 }; 113 114 114 - if (description) { 115 - lexicon.description = description; 115 + // Only add namespace description if there's no model description 116 + if (namespaceDescription && !getDoc(this.program, mainModel)) { 117 + lexicon.description = namespaceDescription; 116 118 } 117 119 118 120 // Add other models as defs
+35
typelex-emitter/test/scenarios/app-bsky-embed-external/input/main.tsp
··· 1 + import "@typelex/emitter"; 2 + 3 + namespace app.bsky.embed.external { 4 + @doc("A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post).") 5 + model Main { 6 + external: External; 7 + } 8 + 9 + model External { 10 + @lexFormat("uri") 11 + uri: string; 12 + 13 + title: string; 14 + description: string; 15 + 16 + @blobAccept(["image/*"]) 17 + @blobMaxSize(1000000) 18 + thumb?: bytes; 19 + } 20 + 21 + model View { 22 + external: ViewExternal; 23 + } 24 + 25 + model ViewExternal { 26 + @lexFormat("uri") 27 + uri: string; 28 + 29 + title: string; 30 + description: string; 31 + 32 + @lexFormat("uri") 33 + thumb?: string; 34 + } 35 + }
+51
typelex-emitter/test/scenarios/app-bsky-embed-external/output/app/bsky/embed/external.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "app.bsky.embed.external", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "description": "A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post).", 8 + "required": ["external"], 9 + "properties": { 10 + "external": { 11 + "type": "ref", 12 + "ref": "#external" 13 + } 14 + } 15 + }, 16 + "external": { 17 + "type": "object", 18 + "required": ["uri", "title", "description"], 19 + "properties": { 20 + "uri": { "type": "string", "format": "uri" }, 21 + "title": { "type": "string" }, 22 + "description": { "type": "string" }, 23 + "thumb": { 24 + "type": "blob", 25 + "accept": ["image/*"], 26 + "maxSize": 1000000 27 + } 28 + } 29 + }, 30 + "view": { 31 + "type": "object", 32 + "required": ["external"], 33 + "properties": { 34 + "external": { 35 + "type": "ref", 36 + "ref": "#viewExternal" 37 + } 38 + } 39 + }, 40 + "viewExternal": { 41 + "type": "object", 42 + "required": ["uri", "title", "description"], 43 + "properties": { 44 + "uri": { "type": "string", "format": "uri" }, 45 + "title": { "type": "string" }, 46 + "description": { "type": "string" }, 47 + "thumb": { "type": "string", "format": "uri" } 48 + } 49 + } 50 + } 51 + }