prototypey.org - atproto lexicon typescript toolkit - mirror https://github.com/tylersayshi/prototypey

fix formatting and linting

Tyler 772eb730 355c90b7

+965 -1006
+1 -1
.github/SECURITY.md
··· 4 If you have a vulnerability or other security issues to disclose: 5 6 - Thank you very much, please do! 7 - - Please send them to us by emailing `26290074+tylersayshi@users.noreply.github.com` 8 9 We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions.
··· 4 If you have a vulnerability or other security issues to disclose: 5 6 - Thank you very much, please do! 7 + - Please send them to us by emailing `hi@tylur.dev` 8 9 We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions.
+98 -101
samples/actor-namespace.json
··· 1 { 2 - "lexicon": 1, 3 - "id": "app.bsky.actor.defs", 4 - "defs": { 5 - "profileViewBasic": { 6 - "type": "object", 7 - "properties": { 8 - "did": { 9 - "type": "string", 10 - "required": true, 11 - "format": "did" 12 - }, 13 - "handle": { 14 - "type": "string", 15 - "required": true, 16 - "format": "handle" 17 - }, 18 - "displayName": { 19 - "type": "string", 20 - "maxGraphemes": 64, 21 - "maxLength": 640 22 - }, 23 - "pronouns": { 24 - "type": "string" 25 - }, 26 - "avatar": { 27 - "type": "string", 28 - "format": "uri" 29 - }, 30 - "associated": { 31 - "type": "ref", 32 - "ref": "#profileAssociated" 33 - }, 34 - "viewer": { 35 - "type": "ref", 36 - "ref": "#viewerState" 37 - }, 38 - "labels": { 39 - "type": "array", 40 - "items": { 41 - "type": "ref", 42 - "ref": "com.atproto.label.defs#label" 43 - } 44 - }, 45 - "createdAt": { 46 - "type": "string", 47 - "format": "datetime" 48 - }, 49 - "verification": { 50 - "type": "ref", 51 - "ref": "#verificationState" 52 - }, 53 - "status": { 54 - "type": "ref", 55 - "ref": "#statusView" 56 - } 57 - }, 58 - "required": [ 59 - "did", 60 - "handle" 61 - ] 62 - }, 63 - "viewerState": { 64 - "type": "object", 65 - "properties": { 66 - "muted": { 67 - "type": "boolean" 68 - }, 69 - "mutedByList": { 70 - "type": "ref", 71 - "ref": "app.bsky.graph.defs#listViewBasic" 72 - }, 73 - "blockedBy": { 74 - "type": "boolean" 75 - }, 76 - "blocking": { 77 - "type": "string", 78 - "format": "at-uri" 79 - }, 80 - "blockingByList": { 81 - "type": "ref", 82 - "ref": "app.bsky.graph.defs#listViewBasic" 83 - }, 84 - "following": { 85 - "type": "string", 86 - "format": "at-uri" 87 - }, 88 - "followedBy": { 89 - "type": "string", 90 - "format": "at-uri" 91 - }, 92 - "knownFollowers": { 93 - "type": "ref", 94 - "ref": "#knownFollowers" 95 - }, 96 - "activitySubscription": { 97 - "type": "ref", 98 - "ref": "app.bsky.notification.defs#activitySubscription" 99 - } 100 - } 101 - } 102 - } 103 }
··· 1 { 2 + "lexicon": 1, 3 + "id": "app.bsky.actor.defs", 4 + "defs": { 5 + "profileViewBasic": { 6 + "type": "object", 7 + "properties": { 8 + "did": { 9 + "type": "string", 10 + "required": true, 11 + "format": "did" 12 + }, 13 + "handle": { 14 + "type": "string", 15 + "required": true, 16 + "format": "handle" 17 + }, 18 + "displayName": { 19 + "type": "string", 20 + "maxGraphemes": 64, 21 + "maxLength": 640 22 + }, 23 + "pronouns": { 24 + "type": "string" 25 + }, 26 + "avatar": { 27 + "type": "string", 28 + "format": "uri" 29 + }, 30 + "associated": { 31 + "type": "ref", 32 + "ref": "#profileAssociated" 33 + }, 34 + "viewer": { 35 + "type": "ref", 36 + "ref": "#viewerState" 37 + }, 38 + "labels": { 39 + "type": "array", 40 + "items": { 41 + "type": "ref", 42 + "ref": "com.atproto.label.defs#label" 43 + } 44 + }, 45 + "createdAt": { 46 + "type": "string", 47 + "format": "datetime" 48 + }, 49 + "verification": { 50 + "type": "ref", 51 + "ref": "#verificationState" 52 + }, 53 + "status": { 54 + "type": "ref", 55 + "ref": "#statusView" 56 + } 57 + }, 58 + "required": ["did", "handle"] 59 + }, 60 + "viewerState": { 61 + "type": "object", 62 + "properties": { 63 + "muted": { 64 + "type": "boolean" 65 + }, 66 + "mutedByList": { 67 + "type": "ref", 68 + "ref": "app.bsky.graph.defs#listViewBasic" 69 + }, 70 + "blockedBy": { 71 + "type": "boolean" 72 + }, 73 + "blocking": { 74 + "type": "string", 75 + "format": "at-uri" 76 + }, 77 + "blockingByList": { 78 + "type": "ref", 79 + "ref": "app.bsky.graph.defs#listViewBasic" 80 + }, 81 + "following": { 82 + "type": "string", 83 + "format": "at-uri" 84 + }, 85 + "followedBy": { 86 + "type": "string", 87 + "format": "at-uri" 88 + }, 89 + "knownFollowers": { 90 + "type": "ref", 91 + "ref": "#knownFollowers" 92 + }, 93 + "activitySubscription": { 94 + "type": "ref", 95 + "ref": "app.bsky.notification.defs#activitySubscription" 96 + } 97 + } 98 + } 99 + } 100 }
+23 -23
samples/demo.json
··· 1 { 2 - "lexicon": 1, 3 - "id": "app.bsky.actor.profile", 4 - "defs": { 5 - "main": { 6 - "type": "record", 7 - "key": "self", 8 - "record": { 9 - "type": "object", 10 - "properties": { 11 - "displayName": { 12 - "type": "string", 13 - "maxLength": 64, 14 - "maxGraphemes": 64 15 - }, 16 - "description": { 17 - "type": "string", 18 - "maxLength": 256, 19 - "maxGraphemes": 256 20 - } 21 - } 22 - } 23 - } 24 - } 25 }
··· 1 { 2 + "lexicon": 1, 3 + "id": "app.bsky.actor.profile", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "key": "self", 8 + "record": { 9 + "type": "object", 10 + "properties": { 11 + "displayName": { 12 + "type": "string", 13 + "maxLength": 64, 14 + "maxGraphemes": 64 15 + }, 16 + "description": { 17 + "type": "string", 18 + "maxLength": 256, 19 + "maxGraphemes": 256 20 + } 21 + } 22 + } 23 + } 24 + } 25 }
+74 -81
samples/generator-view.json
··· 1 { 2 - "type": "object", 3 - "properties": { 4 - "uri": { 5 - "type": "string", 6 - "required": true, 7 - "format": "at-uri" 8 - }, 9 - "cid": { 10 - "type": "string", 11 - "required": true, 12 - "format": "cid" 13 - }, 14 - "did": { 15 - "type": "string", 16 - "required": true, 17 - "format": "did" 18 - }, 19 - "creator": { 20 - "type": "ref", 21 - "ref": "app.bsky.actor.defs#profileView", 22 - "required": true 23 - }, 24 - "displayName": { 25 - "type": "string", 26 - "required": true 27 - }, 28 - "description": { 29 - "type": "string", 30 - "maxGraphemes": 300, 31 - "maxLength": 3000 32 - }, 33 - "descriptionFacets": { 34 - "type": "array", 35 - "items": { 36 - "type": "ref", 37 - "ref": "app.bsky.richtext.facet" 38 - } 39 - }, 40 - "avatar": { 41 - "type": "string", 42 - "format": "uri" 43 - }, 44 - "likeCount": { 45 - "type": "integer", 46 - "minimum": 0 47 - }, 48 - "acceptsInteractions": { 49 - "type": "boolean" 50 - }, 51 - "labels": { 52 - "type": "array", 53 - "items": { 54 - "type": "ref", 55 - "ref": "com.atproto.label.defs#label" 56 - } 57 - }, 58 - "viewer": { 59 - "type": "ref", 60 - "ref": "#generatorViewerState" 61 - }, 62 - "contentMode": { 63 - "type": "string", 64 - "knownValues": [ 65 - "app.bsky.feed.defs#contentModeUnspecified", 66 - "app.bsky.feed.defs#contentModeVideo" 67 - ] 68 - }, 69 - "indexedAt": { 70 - "type": "string", 71 - "required": true, 72 - "format": "datetime" 73 - } 74 - }, 75 - "required": [ 76 - "uri", 77 - "cid", 78 - "did", 79 - "creator", 80 - "displayName", 81 - "indexedAt" 82 - ] 83 }
··· 1 { 2 + "type": "object", 3 + "properties": { 4 + "uri": { 5 + "type": "string", 6 + "required": true, 7 + "format": "at-uri" 8 + }, 9 + "cid": { 10 + "type": "string", 11 + "required": true, 12 + "format": "cid" 13 + }, 14 + "did": { 15 + "type": "string", 16 + "required": true, 17 + "format": "did" 18 + }, 19 + "creator": { 20 + "type": "ref", 21 + "ref": "app.bsky.actor.defs#profileView", 22 + "required": true 23 + }, 24 + "displayName": { 25 + "type": "string", 26 + "required": true 27 + }, 28 + "description": { 29 + "type": "string", 30 + "maxGraphemes": 300, 31 + "maxLength": 3000 32 + }, 33 + "descriptionFacets": { 34 + "type": "array", 35 + "items": { 36 + "type": "ref", 37 + "ref": "app.bsky.richtext.facet" 38 + } 39 + }, 40 + "avatar": { 41 + "type": "string", 42 + "format": "uri" 43 + }, 44 + "likeCount": { 45 + "type": "integer", 46 + "minimum": 0 47 + }, 48 + "acceptsInteractions": { 49 + "type": "boolean" 50 + }, 51 + "labels": { 52 + "type": "array", 53 + "items": { 54 + "type": "ref", 55 + "ref": "com.atproto.label.defs#label" 56 + } 57 + }, 58 + "viewer": { 59 + "type": "ref", 60 + "ref": "#generatorViewerState" 61 + }, 62 + "contentMode": { 63 + "type": "string", 64 + "knownValues": [ 65 + "app.bsky.feed.defs#contentModeUnspecified", 66 + "app.bsky.feed.defs#contentModeVideo" 67 + ] 68 + }, 69 + "indexedAt": { 70 + "type": "string", 71 + "required": true, 72 + "format": "datetime" 73 + } 74 + }, 75 + "required": ["uri", "cid", "did", "creator", "displayName", "indexedAt"] 76 }
+68 -74
samples/post-view.json
··· 1 { 2 - "type": "object", 3 - "properties": { 4 - "uri": { 5 - "type": "string", 6 - "required": true, 7 - "format": "at-uri" 8 - }, 9 - "cid": { 10 - "type": "string", 11 - "required": true, 12 - "format": "cid" 13 - }, 14 - "author": { 15 - "type": "ref", 16 - "ref": "app.bsky.actor.defs#profileViewBasic", 17 - "required": true 18 - }, 19 - "record": { 20 - "type": "unknown", 21 - "required": true 22 - }, 23 - "embed": { 24 - "type": "union", 25 - "refs": [ 26 - "app.bsky.embed.images#view", 27 - "app.bsky.embed.video#view", 28 - "app.bsky.embed.external#view", 29 - "app.bsky.embed.record#view", 30 - "app.bsky.embed.recordWithMedia#view" 31 - ] 32 - }, 33 - "bookmarkCount": { 34 - "type": "integer" 35 - }, 36 - "replyCount": { 37 - "type": "integer" 38 - }, 39 - "repostCount": { 40 - "type": "integer" 41 - }, 42 - "likeCount": { 43 - "type": "integer" 44 - }, 45 - "quoteCount": { 46 - "type": "integer" 47 - }, 48 - "indexedAt": { 49 - "type": "string", 50 - "required": true, 51 - "format": "datetime" 52 - }, 53 - "viewer": { 54 - "type": "ref", 55 - "ref": "#viewerState" 56 - }, 57 - "labels": { 58 - "type": "array", 59 - "items": { 60 - "type": "ref", 61 - "ref": "com.atproto.label.defs#label" 62 - } 63 - }, 64 - "threadgate": { 65 - "type": "ref", 66 - "ref": "#threadgateView" 67 - } 68 - }, 69 - "required": [ 70 - "uri", 71 - "cid", 72 - "author", 73 - "record", 74 - "indexedAt" 75 - ] 76 }
··· 1 { 2 + "type": "object", 3 + "properties": { 4 + "uri": { 5 + "type": "string", 6 + "required": true, 7 + "format": "at-uri" 8 + }, 9 + "cid": { 10 + "type": "string", 11 + "required": true, 12 + "format": "cid" 13 + }, 14 + "author": { 15 + "type": "ref", 16 + "ref": "app.bsky.actor.defs#profileViewBasic", 17 + "required": true 18 + }, 19 + "record": { 20 + "type": "unknown", 21 + "required": true 22 + }, 23 + "embed": { 24 + "type": "union", 25 + "refs": [ 26 + "app.bsky.embed.images#view", 27 + "app.bsky.embed.video#view", 28 + "app.bsky.embed.external#view", 29 + "app.bsky.embed.record#view", 30 + "app.bsky.embed.recordWithMedia#view" 31 + ] 32 + }, 33 + "bookmarkCount": { 34 + "type": "integer" 35 + }, 36 + "replyCount": { 37 + "type": "integer" 38 + }, 39 + "repostCount": { 40 + "type": "integer" 41 + }, 42 + "likeCount": { 43 + "type": "integer" 44 + }, 45 + "quoteCount": { 46 + "type": "integer" 47 + }, 48 + "indexedAt": { 49 + "type": "string", 50 + "required": true, 51 + "format": "datetime" 52 + }, 53 + "viewer": { 54 + "type": "ref", 55 + "ref": "#viewerState" 56 + }, 57 + "labels": { 58 + "type": "array", 59 + "items": { 60 + "type": "ref", 61 + "ref": "com.atproto.label.defs#label" 62 + } 63 + }, 64 + "threadgate": { 65 + "type": "ref", 66 + "ref": "#threadgateView" 67 + } 68 + }, 69 + "required": ["uri", "cid", "author", "record", "indexedAt"] 70 }
+7 -7
samples/primitives-array.json
··· 1 { 2 - "type": "array", 3 - "items": { 4 - "type": "string" 5 - }, 6 - "minLength": 1, 7 - "maxLength": 10, 8 - "required": true 9 }
··· 1 { 2 + "type": "array", 3 + "items": { 4 + "type": "string" 5 + }, 6 + "minLength": 1, 7 + "maxLength": 10, 8 + "required": true 9 }
+3 -6
samples/primitives-blob.json
··· 1 { 2 - "type": "blob", 3 - "accept": [ 4 - "image/png", 5 - "image/jpeg" 6 - ], 7 - "maxSize": 5000000 8 }
··· 1 { 2 + "type": "blob", 3 + "accept": ["image/png", "image/jpeg"], 4 + "maxSize": 5000000 5 }
+2 -2
samples/primitives-token.json
··· 1 { 2 - "type": "token", 3 - "description": "Request that less content like the given feed item be shown in the feed" 4 }
··· 1 { 2 + "type": "token", 3 + "description": "Request that less content like the given feed item be shown in the feed" 4 }
+52 -59
samples/procedure-create-post.json
··· 1 { 2 - "type": "procedure", 3 - "description": "Create a post", 4 - "input": { 5 - "encoding": "application/json", 6 - "schema": { 7 - "type": "object", 8 - "properties": { 9 - "repo": { 10 - "type": "string", 11 - "required": true 12 - }, 13 - "collection": { 14 - "type": "string", 15 - "required": true 16 - }, 17 - "record": { 18 - "type": "unknown", 19 - "required": true 20 - }, 21 - "validate": { 22 - "type": "boolean", 23 - "default": true 24 - } 25 - }, 26 - "required": [ 27 - "repo", 28 - "collection", 29 - "record" 30 - ] 31 - } 32 - }, 33 - "output": { 34 - "encoding": "application/json", 35 - "schema": { 36 - "type": "object", 37 - "properties": { 38 - "uri": { 39 - "type": "string", 40 - "required": true 41 - }, 42 - "cid": { 43 - "type": "string", 44 - "required": true 45 - } 46 - }, 47 - "required": [ 48 - "uri", 49 - "cid" 50 - ] 51 - } 52 - }, 53 - "errors": [ 54 - { 55 - "name": "InvalidSwap" 56 - }, 57 - { 58 - "name": "InvalidRecord" 59 - } 60 - ] 61 }
··· 1 { 2 + "type": "procedure", 3 + "description": "Create a post", 4 + "input": { 5 + "encoding": "application/json", 6 + "schema": { 7 + "type": "object", 8 + "properties": { 9 + "repo": { 10 + "type": "string", 11 + "required": true 12 + }, 13 + "collection": { 14 + "type": "string", 15 + "required": true 16 + }, 17 + "record": { 18 + "type": "unknown", 19 + "required": true 20 + }, 21 + "validate": { 22 + "type": "boolean", 23 + "default": true 24 + } 25 + }, 26 + "required": ["repo", "collection", "record"] 27 + } 28 + }, 29 + "output": { 30 + "encoding": "application/json", 31 + "schema": { 32 + "type": "object", 33 + "properties": { 34 + "uri": { 35 + "type": "string", 36 + "required": true 37 + }, 38 + "cid": { 39 + "type": "string", 40 + "required": true 41 + } 42 + }, 43 + "required": ["uri", "cid"] 44 + } 45 + }, 46 + "errors": [ 47 + { 48 + "name": "InvalidSwap" 49 + }, 50 + { 51 + "name": "InvalidRecord" 52 + } 53 + ] 54 }
+23 -23
samples/profile-namespace.json
··· 1 { 2 - "lexicon": 1, 3 - "id": "app.bsky.actor.profile", 4 - "defs": { 5 - "main": { 6 - "type": "record", 7 - "key": "self", 8 - "record": { 9 - "type": "object", 10 - "properties": { 11 - "displayName": { 12 - "type": "string", 13 - "maxLength": 64, 14 - "maxGraphemes": 64 15 - }, 16 - "description": { 17 - "type": "string", 18 - "maxLength": 256, 19 - "maxGraphemes": 256 20 - } 21 - } 22 - } 23 - } 24 - } 25 }
··· 1 { 2 + "lexicon": 1, 3 + "id": "app.bsky.actor.profile", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "key": "self", 8 + "record": { 9 + "type": "object", 10 + "properties": { 11 + "displayName": { 12 + "type": "string", 13 + "maxLength": 64, 14 + "maxGraphemes": 64 15 + }, 16 + "description": { 17 + "type": "string", 18 + "maxLength": 256, 19 + "maxGraphemes": 256 20 + } 21 + } 22 + } 23 + } 24 + } 25 }
+53 -56
samples/profile-view-basic.json
··· 1 { 2 - "type": "object", 3 - "properties": { 4 - "did": { 5 - "type": "string", 6 - "required": true, 7 - "format": "did" 8 - }, 9 - "handle": { 10 - "type": "string", 11 - "required": true, 12 - "format": "handle" 13 - }, 14 - "displayName": { 15 - "type": "string", 16 - "maxGraphemes": 64, 17 - "maxLength": 640 18 - }, 19 - "pronouns": { 20 - "type": "string" 21 - }, 22 - "avatar": { 23 - "type": "string", 24 - "format": "uri" 25 - }, 26 - "associated": { 27 - "type": "ref", 28 - "ref": "#profileAssociated" 29 - }, 30 - "viewer": { 31 - "type": "ref", 32 - "ref": "#viewerState" 33 - }, 34 - "labels": { 35 - "type": "array", 36 - "items": { 37 - "type": "ref", 38 - "ref": "com.atproto.label.defs#label" 39 - } 40 - }, 41 - "createdAt": { 42 - "type": "string", 43 - "format": "datetime" 44 - }, 45 - "verification": { 46 - "type": "ref", 47 - "ref": "#verificationState" 48 - }, 49 - "status": { 50 - "type": "ref", 51 - "ref": "#statusView" 52 - } 53 - }, 54 - "required": [ 55 - "did", 56 - "handle" 57 - ] 58 }
··· 1 { 2 + "type": "object", 3 + "properties": { 4 + "did": { 5 + "type": "string", 6 + "required": true, 7 + "format": "did" 8 + }, 9 + "handle": { 10 + "type": "string", 11 + "required": true, 12 + "format": "handle" 13 + }, 14 + "displayName": { 15 + "type": "string", 16 + "maxGraphemes": 64, 17 + "maxLength": 640 18 + }, 19 + "pronouns": { 20 + "type": "string" 21 + }, 22 + "avatar": { 23 + "type": "string", 24 + "format": "uri" 25 + }, 26 + "associated": { 27 + "type": "ref", 28 + "ref": "#profileAssociated" 29 + }, 30 + "viewer": { 31 + "type": "ref", 32 + "ref": "#viewerState" 33 + }, 34 + "labels": { 35 + "type": "array", 36 + "items": { 37 + "type": "ref", 38 + "ref": "com.atproto.label.defs#label" 39 + } 40 + }, 41 + "createdAt": { 42 + "type": "string", 43 + "format": "datetime" 44 + }, 45 + "verification": { 46 + "type": "ref", 47 + "ref": "#verificationState" 48 + }, 49 + "status": { 50 + "type": "ref", 51 + "ref": "#statusView" 52 + } 53 + }, 54 + "required": ["did", "handle"] 55 }
+54 -61
samples/query-search-posts.json
··· 1 { 2 - "type": "query", 3 - "description": "Find posts matching search criteria", 4 - "parameters": { 5 - "type": "params", 6 - "properties": { 7 - "q": { 8 - "type": "string", 9 - "required": true 10 - }, 11 - "sort": { 12 - "type": "string", 13 - "enum": [ 14 - "top", 15 - "latest" 16 - ], 17 - "default": "latest" 18 - }, 19 - "limit": { 20 - "type": "integer", 21 - "minimum": 1, 22 - "maximum": 100, 23 - "default": 25 24 - }, 25 - "cursor": { 26 - "type": "string" 27 - } 28 - }, 29 - "required": [ 30 - "q" 31 - ] 32 - }, 33 - "output": { 34 - "encoding": "application/json", 35 - "schema": { 36 - "type": "object", 37 - "properties": { 38 - "cursor": { 39 - "type": "string" 40 - }, 41 - "hitsTotal": { 42 - "type": "integer" 43 - }, 44 - "posts": { 45 - "type": "array", 46 - "items": { 47 - "type": "ref", 48 - "ref": "app.bsky.feed.defs#postView" 49 - }, 50 - "required": true 51 - } 52 - }, 53 - "required": [ 54 - "posts" 55 - ] 56 - } 57 - }, 58 - "errors": [ 59 - { 60 - "name": "BadQueryString" 61 - } 62 - ] 63 }
··· 1 { 2 + "type": "query", 3 + "description": "Find posts matching search criteria", 4 + "parameters": { 5 + "type": "params", 6 + "properties": { 7 + "q": { 8 + "type": "string", 9 + "required": true 10 + }, 11 + "sort": { 12 + "type": "string", 13 + "enum": ["top", "latest"], 14 + "default": "latest" 15 + }, 16 + "limit": { 17 + "type": "integer", 18 + "minimum": 1, 19 + "maximum": 100, 20 + "default": 25 21 + }, 22 + "cursor": { 23 + "type": "string" 24 + } 25 + }, 26 + "required": ["q"] 27 + }, 28 + "output": { 29 + "encoding": "application/json", 30 + "schema": { 31 + "type": "object", 32 + "properties": { 33 + "cursor": { 34 + "type": "string" 35 + }, 36 + "hitsTotal": { 37 + "type": "integer" 38 + }, 39 + "posts": { 40 + "type": "array", 41 + "items": { 42 + "type": "ref", 43 + "ref": "app.bsky.feed.defs#postView" 44 + }, 45 + "required": true 46 + } 47 + }, 48 + "required": ["posts"] 49 + } 50 + }, 51 + "errors": [ 52 + { 53 + "name": "BadQueryString" 54 + } 55 + ] 56 }
+33 -33
samples/subscription-repos.json
··· 1 { 2 - "type": "subscription", 3 - "description": "Repository event stream, aka Firehose endpoint", 4 - "parameters": { 5 - "type": "params", 6 - "properties": { 7 - "cursor": { 8 - "type": "integer" 9 - } 10 - } 11 - }, 12 - "message": { 13 - "description": "Represents an update of repository state", 14 - "schema": { 15 - "type": "union", 16 - "refs": [ 17 - "#commit", 18 - "#identity", 19 - "#account", 20 - "#handle", 21 - "#migrate", 22 - "#tombstone", 23 - "#info" 24 - ] 25 - } 26 - }, 27 - "errors": [ 28 - { 29 - "name": "FutureCursor" 30 - }, 31 - { 32 - "name": "ConsumerTooSlow" 33 - } 34 - ] 35 }
··· 1 { 2 + "type": "subscription", 3 + "description": "Repository event stream, aka Firehose endpoint", 4 + "parameters": { 5 + "type": "params", 6 + "properties": { 7 + "cursor": { 8 + "type": "integer" 9 + } 10 + } 11 + }, 12 + "message": { 13 + "description": "Represents an update of repository state", 14 + "schema": { 15 + "type": "union", 16 + "refs": [ 17 + "#commit", 18 + "#identity", 19 + "#account", 20 + "#handle", 21 + "#migrate", 22 + "#tombstone", 23 + "#info" 24 + ] 25 + } 26 + }, 27 + "errors": [ 28 + { 29 + "name": "FutureCursor" 30 + }, 31 + { 32 + "name": "ConsumerTooSlow" 33 + } 34 + ] 35 }
+81 -75
src/infer.ts
··· 1 - // deno-lint-ignore-file ban-types 2 - type InferType<T> = T extends { type: "record" } ? InferRecord<T> 3 - : T extends { type: "object" } ? InferObject<T> 4 - : T extends { type: "array" } ? InferArray<T> 5 - : T extends { type: "params" } ? InferParams<T> 6 - : T extends { type: "union" } ? InferUnion<T> 7 - : T extends { type: "token" } ? InferToken<T> 8 - : T extends { type: "ref" } ? InferRef<T> 9 - : T extends { type: "unknown" } ? unknown 10 - : T extends { type: "null" } ? null 11 - : T extends { type: "boolean" } ? boolean 12 - : T extends { type: "integer" } ? number 13 - : T extends { type: "string" } ? string 14 - : T extends { type: "bytes" } ? Uint8Array 15 - : T extends { type: "cid-link" } ? string 16 - : T extends { type: "blob" } ? Blob 17 - : never; 18 19 type InferToken<T> = T extends { enum: readonly (infer U)[] } ? U : string; 20 ··· 22 type GetNullable<T> = T extends { nullable: readonly (infer N)[] } ? N : never; 23 24 type InferObject< 25 - T, 26 - Nullable extends string = GetNullable<T> & string, 27 - Required extends string = GetRequired<T> & string, 28 - NullableAndRequired extends string = Required & Nullable & string, 29 - Normal extends string = "properties" extends keyof T 30 - ? Exclude<keyof T["properties"], Required | Nullable> & string 31 - : never, 32 > = Prettify< 33 - T extends { properties: infer P } ? 34 - & { 35 - -readonly [ 36 - K in Normal 37 - ]?: InferType< 38 - P[K & keyof P] 39 - >; 40 - } 41 - & ({ 42 - -readonly [K in Exclude<Required, NullableAndRequired>]-?: InferType< 43 - P[K & keyof P] 44 - >; 45 - }) 46 - & ({ 47 - -readonly [K in Exclude<Nullable, NullableAndRequired>]?: 48 - | InferType< 49 - P[K & keyof P] 50 - > 51 - | null; 52 - }) 53 - & ({ 54 - -readonly [K in NullableAndRequired]: 55 - | InferType< 56 - P[K & keyof P] 57 - > 58 - | null; 59 - }) 60 - : {} 61 >; 62 63 - type InferArray<T> = T extends { items: infer Items } ? InferType<Items>[] 64 - : never[]; 65 66 type InferUnion<T> = T extends { refs: readonly (infer R)[] } 67 - ? R extends string ? { $type: R; [key: string]: unknown } : never 68 - : never; 69 70 type InferRef<T> = T extends { ref: infer R } 71 - ? R extends string ? { $type: R; [key: string]: unknown } : unknown 72 - : unknown; 73 74 - type InferParams<T> = T extends { properties: infer P } ? InferObject<T> 75 - : never; 76 77 type InferRecord<T> = T extends { record: infer R } 78 - ? R extends { type: "object" } ? InferObject<R> 79 - : R extends { type: "union" } ? InferUnion<R> 80 - : unknown 81 - : unknown; 82 83 - type Prettify<T> = 84 - & { 85 - [K in keyof T]: T[K]; 86 - } 87 - & {}; 88 89 - export type InferDefs<T extends Record<string, unknown>> = Prettify< 90 - { 91 - -readonly [K in keyof T]: InferType<T[K]>; 92 - } 93 - >; 94 95 export type InferNS<T extends { id: string; defs: Record<string, unknown> }> = 96 - InferDefs<T["defs"]>;
··· 1 + /* eslint-disable @typescript-eslint/no-empty-object-type */ 2 + type InferType<T> = T extends { type: "record" } 3 + ? InferRecord<T> 4 + : T extends { type: "object" } 5 + ? InferObject<T> 6 + : T extends { type: "array" } 7 + ? InferArray<T> 8 + : T extends { type: "params" } 9 + ? InferParams<T> 10 + : T extends { type: "union" } 11 + ? InferUnion<T> 12 + : T extends { type: "token" } 13 + ? InferToken<T> 14 + : T extends { type: "ref" } 15 + ? InferRef<T> 16 + : T extends { type: "unknown" } 17 + ? unknown 18 + : T extends { type: "null" } 19 + ? null 20 + : T extends { type: "boolean" } 21 + ? boolean 22 + : T extends { type: "integer" } 23 + ? number 24 + : T extends { type: "string" } 25 + ? string 26 + : T extends { type: "bytes" } 27 + ? Uint8Array 28 + : T extends { type: "cid-link" } 29 + ? string 30 + : T extends { type: "blob" } 31 + ? Blob 32 + : never; 33 34 type InferToken<T> = T extends { enum: readonly (infer U)[] } ? U : string; 35 ··· 37 type GetNullable<T> = T extends { nullable: readonly (infer N)[] } ? N : never; 38 39 type InferObject< 40 + T, 41 + Nullable extends string = GetNullable<T> & string, 42 + Required extends string = GetRequired<T> & string, 43 + NullableAndRequired extends string = Required & Nullable & string, 44 + Normal extends string = "properties" extends keyof T 45 + ? Exclude<keyof T["properties"], Required | Nullable> & string 46 + : never, 47 > = Prettify< 48 + T extends { properties: infer P } 49 + ? { 50 + -readonly [K in Normal]?: InferType<P[K & keyof P]>; 51 + } & { 52 + -readonly [K in Exclude<Required, NullableAndRequired>]-?: InferType< 53 + P[K & keyof P] 54 + >; 55 + } & { 56 + -readonly [K in Exclude<Nullable, NullableAndRequired>]?: InferType< 57 + P[K & keyof P] 58 + > | null; 59 + } & { 60 + -readonly [K in NullableAndRequired]: InferType<P[K & keyof P]> | null; 61 + } 62 + : {} 63 >; 64 65 + type InferArray<T> = T extends { items: infer Items } 66 + ? InferType<Items>[] 67 + : never[]; 68 69 type InferUnion<T> = T extends { refs: readonly (infer R)[] } 70 + ? R extends string 71 + ? { $type: R; [key: string]: unknown } 72 + : never 73 + : never; 74 75 type InferRef<T> = T extends { ref: infer R } 76 + ? R extends string 77 + ? { $type: R; [key: string]: unknown } 78 + : unknown 79 + : unknown; 80 81 + type InferParams<T> = T extends { properties: infer P } 82 + ? InferObject<P> 83 + : never; 84 85 type InferRecord<T> = T extends { record: infer R } 86 + ? R extends { type: "object" } 87 + ? InferObject<R> 88 + : R extends { type: "union" } 89 + ? InferUnion<R> 90 + : unknown 91 + : unknown; 92 93 + type Prettify<T> = { 94 + [K in keyof T]: T[K]; 95 + } & {}; 96 97 + export type InferDefs<T extends Record<string, unknown>> = Prettify<{ 98 + -readonly [K in keyof T]: InferType<T[K]>; 99 + }>; 100 101 export type InferNS<T extends { id: string; defs: Record<string, unknown> }> = 102 + InferDefs<T["defs"]>;
+393 -399
src/lib.ts
··· 1 // deno-lint-ignore-file ban-types 2 /** @see https://atproto.com/specs/lexicon#overview-of-types */ 3 type LexiconType = 4 - // Concrete types 5 - | "null" 6 - | "boolean" 7 - | "integer" 8 - | "string" 9 - | "bytes" 10 - | "cid-link" 11 - | "blob" 12 - // Container types 13 - | "array" 14 - | "object" 15 - | "params" 16 - // Meta types 17 - | "token" 18 - | "ref" 19 - | "union" 20 - | "unknown" 21 - // Primary types 22 - | "record" 23 - | "query" 24 - | "procedure" 25 - | "subscription"; 26 27 /** 28 * Common options available for lexicon items. 29 * @see https://atproto.com/specs/lexicon#string-formats 30 */ 31 interface LexiconItemCommonOptions { 32 - /** Indicates this field must be provided */ 33 - required?: boolean; 34 - /** Indicates this field can be explicitly set to null */ 35 - nullable?: boolean; 36 } 37 38 /** ··· 40 * @see https://atproto.com/specs/lexicon#overview-of-types 41 */ 42 interface LexiconItem extends LexiconItemCommonOptions { 43 - type: LexiconType; 44 } 45 46 /** 47 * Definition in a lexicon namespace. 48 * @see https://atproto.com/specs/lexicon#lexicon-document 49 */ 50 - type Def = { 51 - type: LexiconType; 52 - }; 53 54 /** 55 * Lexicon namespace document structure. 56 * @see https://atproto.com/specs/lexicon#lexicon-document 57 */ 58 interface LexiconNamespace { 59 - /** Namespaced identifier (NSID) for this lexicon */ 60 - id: string; 61 - /** Named definitions within this namespace */ 62 - defs: { 63 - [name: string]: Def; 64 - }; 65 } 66 67 /** ··· 69 * @see https://atproto.com/specs/lexicon#string 70 */ 71 interface StringOptions extends LexiconItemCommonOptions { 72 - /** 73 - * Semantic string format constraint. 74 - * @see https://atproto.com/specs/lexicon#string-formats 75 - */ 76 - format?: 77 - | "at-identifier" // Handle or DID 78 - | "at-uri" // AT Protocol URI 79 - | "cid" // Content Identifier 80 - | "datetime" // Timestamp (UTC, ISO 8601) 81 - | "did" // Decentralized Identifier 82 - | "handle" // User handle identifier 83 - | "nsid" // Namespaced Identifier 84 - | "tid" // Timestamp Identifier 85 - | "record-key" // Repository record key 86 - | "uri" // Generic URI 87 - | "language"; // IETF BCP 47 language tag 88 - /** Maximum string length in bytes */ 89 - maxLength?: number; 90 - /** Minimum string length in bytes */ 91 - minLength?: number; 92 - /** Maximum string length in Unicode graphemes */ 93 - maxGraphemes?: number; 94 - /** Minimum string length in Unicode graphemes */ 95 - minGraphemes?: number; 96 - /** Hints at expected values, not enforced */ 97 - knownValues?: string[]; 98 - /** Restricts to an exact set of string values */ 99 - enum?: string[]; 100 - /** Default value if not provided */ 101 - default?: string; 102 - /** Fixed, unchangeable value */ 103 - const?: string; 104 } 105 106 /** ··· 108 * @see https://atproto.com/specs/lexicon#boolean 109 */ 110 interface BooleanOptions extends LexiconItemCommonOptions { 111 - /** Default value if not provided */ 112 - default?: boolean; 113 - /** Fixed, unchangeable value */ 114 - const?: boolean; 115 } 116 117 /** ··· 119 * @see https://atproto.com/specs/lexicon#integer 120 */ 121 interface IntegerOptions extends LexiconItemCommonOptions { 122 - /** Minimum allowed value (inclusive) */ 123 - minimum?: number; 124 - /** Maximum allowed value (inclusive) */ 125 - maximum?: number; 126 - /** Restricts to an exact set of integer values */ 127 - enum?: number[]; 128 - /** Default value if not provided */ 129 - default?: number; 130 - /** Fixed, unchangeable value */ 131 - const?: number; 132 } 133 134 /** ··· 136 * @see https://atproto.com/specs/lexicon#bytes 137 */ 138 interface BytesOptions extends LexiconItemCommonOptions { 139 - /** Minimum byte array length */ 140 - minLength?: number; 141 - /** Maximum byte array length */ 142 - maxLength?: number; 143 } 144 145 /** ··· 147 * @see https://atproto.com/specs/lexicon#blob 148 */ 149 interface BlobOptions extends LexiconItemCommonOptions { 150 - /** Allowed MIME types (e.g., ["image/png", "image/jpeg"]) */ 151 - accept?: string[]; 152 - /** Maximum blob size in bytes */ 153 - maxSize?: number; 154 } 155 156 /** ··· 158 * @see https://atproto.com/specs/lexicon#array 159 */ 160 interface ArrayOptions extends LexiconItemCommonOptions { 161 - /** Minimum array length */ 162 - minLength?: number; 163 - /** Maximum array length */ 164 - maxLength?: number; 165 } 166 167 /** ··· 169 * @see https://atproto.com/specs/lexicon#record 170 */ 171 interface RecordOptions { 172 - /** Record key strategy: "self" for self-describing or "tid" for timestamp IDs */ 173 - key: "self" | "tid"; 174 - /** Object schema defining the record structure */ 175 - record: { type: "object" }; 176 - /** Human-readable description */ 177 - description?: string; 178 } 179 180 /** ··· 182 * @see https://atproto.com/specs/lexicon#union 183 */ 184 interface UnionOptions extends LexiconItemCommonOptions { 185 - /** If true, only listed refs are allowed; if false, additional types may be added */ 186 - closed?: boolean; 187 } 188 189 /** 190 * Map of property names to their lexicon item definitions. 191 * @see https://atproto.com/specs/lexicon#object 192 */ 193 - interface ObjectProperties { 194 - [key: string]: LexiconItem; 195 - } 196 197 /** 198 * Resulting object schema with required and nullable fields extracted. 199 * @see https://atproto.com/specs/lexicon#object 200 */ 201 interface ObjectResult<T extends ObjectProperties> { 202 - type: "object"; 203 - /** Property definitions */ 204 - properties: T; 205 - /** List of required property names */ 206 - required?: string[]; 207 - /** List of nullable property names */ 208 - nullable?: string[]; 209 } 210 211 /** 212 * Map of parameter names to their lexicon item definitions. 213 * @see https://atproto.com/specs/lexicon#params 214 */ 215 - interface ParamsProperties { 216 - [key: string]: LexiconItem; 217 - } 218 219 /** 220 * Resulting params schema with required fields extracted. 221 * @see https://atproto.com/specs/lexicon#params 222 */ 223 interface ParamsResult<T extends ParamsProperties> { 224 - type: "params"; 225 - /** Parameter definitions */ 226 - properties: T; 227 - /** List of required parameter names */ 228 - required?: string[]; 229 } 230 231 /** ··· 233 * @see https://atproto.com/specs/lexicon#http-endpoints 234 */ 235 interface BodySchema { 236 - /** MIME type encoding (typically "application/json") */ 237 - encoding: "application/json" | (string & {}); 238 - /** Human-readable description */ 239 - description?: string; 240 - /** Object schema defining the body structure */ 241 - schema?: ObjectResult<ObjectProperties>; 242 } 243 244 /** ··· 246 * @see https://atproto.com/specs/lexicon#http-endpoints 247 */ 248 interface ErrorDef { 249 - /** Error name/code */ 250 - name: string; 251 - /** Human-readable error description */ 252 - description?: string; 253 } 254 255 /** ··· 257 * @see https://atproto.com/specs/lexicon#query 258 */ 259 interface QueryOptions { 260 - /** Human-readable description */ 261 - description?: string; 262 - /** Query string parameters */ 263 - parameters?: ParamsResult<ParamsProperties>; 264 - /** Response body schema */ 265 - output?: BodySchema; 266 - /** Possible error responses */ 267 - errors?: ErrorDef[]; 268 } 269 270 /** ··· 272 * @see https://atproto.com/specs/lexicon#procedure 273 */ 274 interface ProcedureOptions { 275 - /** Human-readable description */ 276 - description?: string; 277 - /** Query string parameters */ 278 - parameters?: ParamsResult<ParamsProperties>; 279 - /** Request body schema */ 280 - input?: BodySchema; 281 - /** Response body schema */ 282 - output?: BodySchema; 283 - /** Possible error responses */ 284 - errors?: ErrorDef[]; 285 } 286 287 /** ··· 289 * @see https://atproto.com/specs/lexicon#subscription 290 */ 291 interface MessageSchema { 292 - /** Human-readable description */ 293 - description?: string; 294 - /** Union of possible message types */ 295 - schema: { type: "union"; refs: readonly string[] }; 296 } 297 298 /** ··· 300 * @see https://atproto.com/specs/lexicon#subscription 301 */ 302 interface SubscriptionOptions { 303 - /** Human-readable description */ 304 - description?: string; 305 - /** Query string parameters */ 306 - parameters?: ParamsResult<ParamsProperties>; 307 - /** Message schema for events */ 308 - message?: MessageSchema; 309 - /** Possible error responses */ 310 - errors?: ErrorDef[]; 311 } 312 313 /** ··· 315 * @see https://atproto.com/specs/lexicon 316 */ 317 export const lx = { 318 - /** 319 - * Creates a null type. 320 - * @see https://atproto.com/specs/lexicon#null 321 - */ 322 - null( 323 - options?: LexiconItemCommonOptions, 324 - ): { type: "null" } & LexiconItemCommonOptions { 325 - return { 326 - type: "null", 327 - ...options, 328 - }; 329 - }, 330 - /** 331 - * Creates a boolean type with optional constraints. 332 - * @see https://atproto.com/specs/lexicon#boolean 333 - */ 334 - boolean<T extends BooleanOptions>(options?: T): T & { type: "boolean" } { 335 - return { 336 - type: "boolean", 337 - ...options, 338 - } as T & { type: "boolean" }; 339 - }, 340 - /** 341 - * Creates an integer type with optional min/max and enum constraints. 342 - * @see https://atproto.com/specs/lexicon#integer 343 - */ 344 - integer<T extends IntegerOptions>(options?: T): T & { type: "integer" } { 345 - return { 346 - type: "integer", 347 - ...options, 348 - } as T & { type: "integer" }; 349 - }, 350 - /** 351 - * Creates a string type with optional format, length, and value constraints. 352 - * @see https://atproto.com/specs/lexicon#string 353 - */ 354 - string<T extends StringOptions>(options?: T): T & { type: "string" } { 355 - return { 356 - type: "string", 357 - ...options, 358 - } as T & { type: "string" }; 359 - }, 360 - /** 361 - * Creates an unknown type for flexible, unvalidated objects. 362 - * @see https://atproto.com/specs/lexicon#unknown 363 - */ 364 - unknown( 365 - options?: LexiconItemCommonOptions, 366 - ): { type: "unknown" } & LexiconItemCommonOptions { 367 - return { 368 - type: "unknown", 369 - ...options, 370 - }; 371 - }, 372 - /** 373 - * Creates a bytes type for arbitrary byte arrays. 374 - * @see https://atproto.com/specs/lexicon#bytes 375 - */ 376 - bytes<T extends BytesOptions>(options?: T): T & { type: "bytes" } { 377 - return { 378 - type: "bytes", 379 - ...options, 380 - } as T & { type: "bytes" }; 381 - }, 382 - /** 383 - * Creates a CID link reference to content-addressed data. 384 - * @see https://atproto.com/specs/lexicon#cid-link 385 - */ 386 - cidLink<Link extends string>(link: Link): { type: "cid-link"; $link: Link } { 387 - return { 388 - type: "cid-link", 389 - $link: link, 390 - }; 391 - }, 392 - /** 393 - * Creates a blob type for binary data with MIME type constraints. 394 - * @see https://atproto.com/specs/lexicon#blob 395 - */ 396 - blob<T extends BlobOptions>(options?: T): T & { type: "blob" } { 397 - return { 398 - type: "blob", 399 - ...options, 400 - } as T & { type: "blob" }; 401 - }, 402 - /** 403 - * Creates an array type with item schema and length constraints. 404 - * @see https://atproto.com/specs/lexicon#array 405 - */ 406 - array<Items extends LexiconItem, Options extends ArrayOptions>( 407 - items: Items, 408 - options?: Options, 409 - ): Options & { type: "array"; items: Items } { 410 - return { 411 - type: "array", 412 - items, 413 - ...options, 414 - } as Options & { type: "array"; items: Items }; 415 - }, 416 - /** 417 - * Creates a token type for symbolic values in unions. 418 - * @see https://atproto.com/specs/lexicon#token 419 - */ 420 - token<Description extends string>( 421 - description: Description, 422 - ): { type: "token"; description: Description } { 423 - return { type: "token", description }; 424 - }, 425 - /** 426 - * Creates a reference to another schema definition. 427 - * @see https://atproto.com/specs/lexicon#ref 428 - */ 429 - ref<Ref extends string>( 430 - ref: Ref, 431 - options?: LexiconItemCommonOptions, 432 - ): LexiconItemCommonOptions & { type: "ref"; ref: Ref } { 433 - return { 434 - type: "ref", 435 - ref, 436 - ...options, 437 - } as LexiconItemCommonOptions & { type: "ref"; ref: Ref }; 438 - }, 439 - /** 440 - * Creates a union type for multiple possible type variants. 441 - * @see https://atproto.com/specs/lexicon#union 442 - */ 443 - union<const Refs extends readonly string[], Options extends UnionOptions>( 444 - refs: Refs, 445 - options?: Options, 446 - ): Options & { type: "union"; refs: Refs } { 447 - return { 448 - type: "union", 449 - refs, 450 - ...options, 451 - } as Options & { type: "union"; refs: Refs }; 452 - }, 453 - /** 454 - * Creates a record type for repository records. 455 - * @see https://atproto.com/specs/lexicon#record 456 - */ 457 - record<T extends RecordOptions>(options: T): T & { type: "record" } { 458 - return { 459 - type: "record", 460 - ...options, 461 - }; 462 - }, 463 - /** 464 - * Creates an object type with defined properties. 465 - * @see https://atproto.com/specs/lexicon#object 466 - */ 467 - object<T extends ObjectProperties>(options: T): ObjectResult<T> { 468 - const required = Object.keys(options).filter( 469 - (key) => options[key].required, 470 - ); 471 - const nullable = Object.keys(options).filter( 472 - (key) => options[key].nullable, 473 - ); 474 - const result: ObjectResult<T> = { 475 - type: "object", 476 - properties: options, 477 - }; 478 - if (required.length > 0) { 479 - result.required = required; 480 - } 481 - if (nullable.length > 0) { 482 - result.nullable = nullable; 483 - } 484 - return result; 485 - }, 486 - /** 487 - * Creates a params type for query string parameters. 488 - * @see https://atproto.com/specs/lexicon#params 489 - */ 490 - params<Properties extends ParamsProperties>( 491 - properties: Properties, 492 - ): ParamsResult<Properties> { 493 - const required = Object.keys(properties).filter( 494 - (key) => properties[key].required, 495 - ); 496 - const result: { 497 - type: "params"; 498 - properties: Properties; 499 - required?: string[]; 500 - } = { 501 - type: "params", 502 - properties, 503 - }; 504 - if (required.length > 0) { 505 - result.required = required; 506 - } 507 - return result; 508 - }, 509 - /** 510 - * Creates a query endpoint definition (HTTP GET). 511 - * @see https://atproto.com/specs/lexicon#query 512 - */ 513 - query<T extends QueryOptions>(options?: T): T & { type: "query" } { 514 - return { 515 - type: "query", 516 - ...options, 517 - } as T & { type: "query" }; 518 - }, 519 - /** 520 - * Creates a procedure endpoint definition (HTTP POST). 521 - * @see https://atproto.com/specs/lexicon#procedure 522 - */ 523 - procedure<T extends ProcedureOptions>( 524 - options?: T, 525 - ): T & { type: "procedure" } { 526 - return { 527 - type: "procedure", 528 - ...options, 529 - } as T & { type: "procedure" }; 530 - }, 531 - /** 532 - * Creates a subscription endpoint definition (WebSocket). 533 - * @see https://atproto.com/specs/lexicon#subscription 534 - */ 535 - subscription<T extends SubscriptionOptions>( 536 - options?: T, 537 - ): T & { type: "subscription" } { 538 - return { 539 - type: "subscription", 540 - ...options, 541 - } as T & { type: "subscription" }; 542 - }, 543 - /** 544 - * Creates a lexicon namespace document. 545 - * @see https://atproto.com/specs/lexicon#lexicon-document 546 - */ 547 - namespace<ID extends string, D extends LexiconNamespace["defs"]>( 548 - id: ID, 549 - defs: D, 550 - ): { lexicon: 1; id: ID; defs: D } { 551 - return { 552 - lexicon: 1, 553 - id, 554 - defs, 555 - }; 556 - }, 557 };
··· 1 // deno-lint-ignore-file ban-types 2 /** @see https://atproto.com/specs/lexicon#overview-of-types */ 3 type LexiconType = 4 + // Concrete types 5 + | "null" 6 + | "boolean" 7 + | "integer" 8 + | "string" 9 + | "bytes" 10 + | "cid-link" 11 + | "blob" 12 + // Container types 13 + | "array" 14 + | "object" 15 + | "params" 16 + // Meta types 17 + | "token" 18 + | "ref" 19 + | "union" 20 + | "unknown" 21 + // Primary types 22 + | "record" 23 + | "query" 24 + | "procedure" 25 + | "subscription"; 26 27 /** 28 * Common options available for lexicon items. 29 * @see https://atproto.com/specs/lexicon#string-formats 30 */ 31 interface LexiconItemCommonOptions { 32 + /** Indicates this field must be provided */ 33 + required?: boolean; 34 + /** Indicates this field can be explicitly set to null */ 35 + nullable?: boolean; 36 } 37 38 /** ··· 40 * @see https://atproto.com/specs/lexicon#overview-of-types 41 */ 42 interface LexiconItem extends LexiconItemCommonOptions { 43 + type: LexiconType; 44 } 45 46 /** 47 * Definition in a lexicon namespace. 48 * @see https://atproto.com/specs/lexicon#lexicon-document 49 */ 50 + interface Def { 51 + type: LexiconType; 52 + } 53 54 /** 55 * Lexicon namespace document structure. 56 * @see https://atproto.com/specs/lexicon#lexicon-document 57 */ 58 interface LexiconNamespace { 59 + /** Namespaced identifier (NSID) for this lexicon */ 60 + id: string; 61 + /** Named definitions within this namespace */ 62 + defs: Record<string, Def>; 63 } 64 65 /** ··· 67 * @see https://atproto.com/specs/lexicon#string 68 */ 69 interface StringOptions extends LexiconItemCommonOptions { 70 + /** 71 + * Semantic string format constraint. 72 + * @see https://atproto.com/specs/lexicon#string-formats 73 + */ 74 + format?: 75 + | "at-identifier" // Handle or DID 76 + | "at-uri" // AT Protocol URI 77 + | "cid" // Content Identifier 78 + | "datetime" // Timestamp (UTC, ISO 8601) 79 + | "did" // Decentralized Identifier 80 + | "handle" // User handle identifier 81 + | "nsid" // Namespaced Identifier 82 + | "tid" // Timestamp Identifier 83 + | "record-key" // Repository record key 84 + | "uri" // Generic URI 85 + | "language"; // IETF BCP 47 language tag 86 + /** Maximum string length in bytes */ 87 + maxLength?: number; 88 + /** Minimum string length in bytes */ 89 + minLength?: number; 90 + /** Maximum string length in Unicode graphemes */ 91 + maxGraphemes?: number; 92 + /** Minimum string length in Unicode graphemes */ 93 + minGraphemes?: number; 94 + /** Hints at expected values, not enforced */ 95 + knownValues?: string[]; 96 + /** Restricts to an exact set of string values */ 97 + enum?: string[]; 98 + /** Default value if not provided */ 99 + default?: string; 100 + /** Fixed, unchangeable value */ 101 + const?: string; 102 } 103 104 /** ··· 106 * @see https://atproto.com/specs/lexicon#boolean 107 */ 108 interface BooleanOptions extends LexiconItemCommonOptions { 109 + /** Default value if not provided */ 110 + default?: boolean; 111 + /** Fixed, unchangeable value */ 112 + const?: boolean; 113 } 114 115 /** ··· 117 * @see https://atproto.com/specs/lexicon#integer 118 */ 119 interface IntegerOptions extends LexiconItemCommonOptions { 120 + /** Minimum allowed value (inclusive) */ 121 + minimum?: number; 122 + /** Maximum allowed value (inclusive) */ 123 + maximum?: number; 124 + /** Restricts to an exact set of integer values */ 125 + enum?: number[]; 126 + /** Default value if not provided */ 127 + default?: number; 128 + /** Fixed, unchangeable value */ 129 + const?: number; 130 } 131 132 /** ··· 134 * @see https://atproto.com/specs/lexicon#bytes 135 */ 136 interface BytesOptions extends LexiconItemCommonOptions { 137 + /** Minimum byte array length */ 138 + minLength?: number; 139 + /** Maximum byte array length */ 140 + maxLength?: number; 141 } 142 143 /** ··· 145 * @see https://atproto.com/specs/lexicon#blob 146 */ 147 interface BlobOptions extends LexiconItemCommonOptions { 148 + /** Allowed MIME types (e.g., ["image/png", "image/jpeg"]) */ 149 + accept?: string[]; 150 + /** Maximum blob size in bytes */ 151 + maxSize?: number; 152 } 153 154 /** ··· 156 * @see https://atproto.com/specs/lexicon#array 157 */ 158 interface ArrayOptions extends LexiconItemCommonOptions { 159 + /** Minimum array length */ 160 + minLength?: number; 161 + /** Maximum array length */ 162 + maxLength?: number; 163 } 164 165 /** ··· 167 * @see https://atproto.com/specs/lexicon#record 168 */ 169 interface RecordOptions { 170 + /** Record key strategy: "self" for self-describing or "tid" for timestamp IDs */ 171 + key: "self" | "tid"; 172 + /** Object schema defining the record structure */ 173 + record: { type: "object" }; 174 + /** Human-readable description */ 175 + description?: string; 176 } 177 178 /** ··· 180 * @see https://atproto.com/specs/lexicon#union 181 */ 182 interface UnionOptions extends LexiconItemCommonOptions { 183 + /** If true, only listed refs are allowed; if false, additional types may be added */ 184 + closed?: boolean; 185 } 186 187 /** 188 * Map of property names to their lexicon item definitions. 189 * @see https://atproto.com/specs/lexicon#object 190 */ 191 + type ObjectProperties = Record<string, LexiconItem>; 192 193 /** 194 * Resulting object schema with required and nullable fields extracted. 195 * @see https://atproto.com/specs/lexicon#object 196 */ 197 interface ObjectResult<T extends ObjectProperties> { 198 + type: "object"; 199 + /** Property definitions */ 200 + properties: T; 201 + /** List of required property names */ 202 + required?: string[]; 203 + /** List of nullable property names */ 204 + nullable?: string[]; 205 } 206 207 /** 208 * Map of parameter names to their lexicon item definitions. 209 * @see https://atproto.com/specs/lexicon#params 210 */ 211 + type ParamsProperties = Record<string, LexiconItem>; 212 213 /** 214 * Resulting params schema with required fields extracted. 215 * @see https://atproto.com/specs/lexicon#params 216 */ 217 interface ParamsResult<T extends ParamsProperties> { 218 + type: "params"; 219 + /** Parameter definitions */ 220 + properties: T; 221 + /** List of required parameter names */ 222 + required?: string[]; 223 } 224 225 /** ··· 227 * @see https://atproto.com/specs/lexicon#http-endpoints 228 */ 229 interface BodySchema { 230 + /** MIME type encoding (typically "application/json") */ 231 + encoding: "application/json" | (string & {}); 232 + /** Human-readable description */ 233 + description?: string; 234 + /** Object schema defining the body structure */ 235 + schema?: ObjectResult<ObjectProperties>; 236 } 237 238 /** ··· 240 * @see https://atproto.com/specs/lexicon#http-endpoints 241 */ 242 interface ErrorDef { 243 + /** Error name/code */ 244 + name: string; 245 + /** Human-readable error description */ 246 + description?: string; 247 } 248 249 /** ··· 251 * @see https://atproto.com/specs/lexicon#query 252 */ 253 interface QueryOptions { 254 + /** Human-readable description */ 255 + description?: string; 256 + /** Query string parameters */ 257 + parameters?: ParamsResult<ParamsProperties>; 258 + /** Response body schema */ 259 + output?: BodySchema; 260 + /** Possible error responses */ 261 + errors?: ErrorDef[]; 262 } 263 264 /** ··· 266 * @see https://atproto.com/specs/lexicon#procedure 267 */ 268 interface ProcedureOptions { 269 + /** Human-readable description */ 270 + description?: string; 271 + /** Query string parameters */ 272 + parameters?: ParamsResult<ParamsProperties>; 273 + /** Request body schema */ 274 + input?: BodySchema; 275 + /** Response body schema */ 276 + output?: BodySchema; 277 + /** Possible error responses */ 278 + errors?: ErrorDef[]; 279 } 280 281 /** ··· 283 * @see https://atproto.com/specs/lexicon#subscription 284 */ 285 interface MessageSchema { 286 + /** Human-readable description */ 287 + description?: string; 288 + /** Union of possible message types */ 289 + schema: { type: "union"; refs: readonly string[] }; 290 } 291 292 /** ··· 294 * @see https://atproto.com/specs/lexicon#subscription 295 */ 296 interface SubscriptionOptions { 297 + /** Human-readable description */ 298 + description?: string; 299 + /** Query string parameters */ 300 + parameters?: ParamsResult<ParamsProperties>; 301 + /** Message schema for events */ 302 + message?: MessageSchema; 303 + /** Possible error responses */ 304 + errors?: ErrorDef[]; 305 } 306 307 /** ··· 309 * @see https://atproto.com/specs/lexicon 310 */ 311 export const lx = { 312 + /** 313 + * Creates a null type. 314 + * @see https://atproto.com/specs/lexicon#null 315 + */ 316 + null( 317 + options?: LexiconItemCommonOptions, 318 + ): { type: "null" } & LexiconItemCommonOptions { 319 + return { 320 + type: "null", 321 + ...options, 322 + }; 323 + }, 324 + /** 325 + * Creates a boolean type with optional constraints. 326 + * @see https://atproto.com/specs/lexicon#boolean 327 + */ 328 + boolean<T extends BooleanOptions>(options?: T): T & { type: "boolean" } { 329 + return { 330 + type: "boolean", 331 + ...options, 332 + } as T & { type: "boolean" }; 333 + }, 334 + /** 335 + * Creates an integer type with optional min/max and enum constraints. 336 + * @see https://atproto.com/specs/lexicon#integer 337 + */ 338 + integer<T extends IntegerOptions>(options?: T): T & { type: "integer" } { 339 + return { 340 + type: "integer", 341 + ...options, 342 + } as T & { type: "integer" }; 343 + }, 344 + /** 345 + * Creates a string type with optional format, length, and value constraints. 346 + * @see https://atproto.com/specs/lexicon#string 347 + */ 348 + string<T extends StringOptions>(options?: T): T & { type: "string" } { 349 + return { 350 + type: "string", 351 + ...options, 352 + } as T & { type: "string" }; 353 + }, 354 + /** 355 + * Creates an unknown type for flexible, unvalidated objects. 356 + * @see https://atproto.com/specs/lexicon#unknown 357 + */ 358 + unknown( 359 + options?: LexiconItemCommonOptions, 360 + ): { type: "unknown" } & LexiconItemCommonOptions { 361 + return { 362 + type: "unknown", 363 + ...options, 364 + }; 365 + }, 366 + /** 367 + * Creates a bytes type for arbitrary byte arrays. 368 + * @see https://atproto.com/specs/lexicon#bytes 369 + */ 370 + bytes<T extends BytesOptions>(options?: T): T & { type: "bytes" } { 371 + return { 372 + type: "bytes", 373 + ...options, 374 + } as T & { type: "bytes" }; 375 + }, 376 + /** 377 + * Creates a CID link reference to content-addressed data. 378 + * @see https://atproto.com/specs/lexicon#cid-link 379 + */ 380 + cidLink<Link extends string>(link: Link): { type: "cid-link"; $link: Link } { 381 + return { 382 + type: "cid-link", 383 + $link: link, 384 + }; 385 + }, 386 + /** 387 + * Creates a blob type for binary data with MIME type constraints. 388 + * @see https://atproto.com/specs/lexicon#blob 389 + */ 390 + blob<T extends BlobOptions>(options?: T): T & { type: "blob" } { 391 + return { 392 + type: "blob", 393 + ...options, 394 + } as T & { type: "blob" }; 395 + }, 396 + /** 397 + * Creates an array type with item schema and length constraints. 398 + * @see https://atproto.com/specs/lexicon#array 399 + */ 400 + array<Items extends LexiconItem, Options extends ArrayOptions>( 401 + items: Items, 402 + options?: Options, 403 + ): Options & { type: "array"; items: Items } { 404 + return { 405 + type: "array", 406 + items, 407 + ...options, 408 + } as Options & { type: "array"; items: Items }; 409 + }, 410 + /** 411 + * Creates a token type for symbolic values in unions. 412 + * @see https://atproto.com/specs/lexicon#token 413 + */ 414 + token<Description extends string>( 415 + description: Description, 416 + ): { type: "token"; description: Description } { 417 + return { type: "token", description }; 418 + }, 419 + /** 420 + * Creates a reference to another schema definition. 421 + * @see https://atproto.com/specs/lexicon#ref 422 + */ 423 + ref<Ref extends string>( 424 + ref: Ref, 425 + options?: LexiconItemCommonOptions, 426 + ): LexiconItemCommonOptions & { type: "ref"; ref: Ref } { 427 + return { 428 + type: "ref", 429 + ref, 430 + ...options, 431 + } as LexiconItemCommonOptions & { type: "ref"; ref: Ref }; 432 + }, 433 + /** 434 + * Creates a union type for multiple possible type variants. 435 + * @see https://atproto.com/specs/lexicon#union 436 + */ 437 + union<const Refs extends readonly string[], Options extends UnionOptions>( 438 + refs: Refs, 439 + options?: Options, 440 + ): Options & { type: "union"; refs: Refs } { 441 + return { 442 + type: "union", 443 + refs, 444 + ...options, 445 + } as Options & { type: "union"; refs: Refs }; 446 + }, 447 + /** 448 + * Creates a record type for repository records. 449 + * @see https://atproto.com/specs/lexicon#record 450 + */ 451 + record<T extends RecordOptions>(options: T): T & { type: "record" } { 452 + return { 453 + type: "record", 454 + ...options, 455 + }; 456 + }, 457 + /** 458 + * Creates an object type with defined properties. 459 + * @see https://atproto.com/specs/lexicon#object 460 + */ 461 + object<T extends ObjectProperties>(options: T): ObjectResult<T> { 462 + const required = Object.keys(options).filter( 463 + (key) => options[key].required, 464 + ); 465 + const nullable = Object.keys(options).filter( 466 + (key) => options[key].nullable, 467 + ); 468 + const result: ObjectResult<T> = { 469 + type: "object", 470 + properties: options, 471 + }; 472 + if (required.length > 0) { 473 + result.required = required; 474 + } 475 + if (nullable.length > 0) { 476 + result.nullable = nullable; 477 + } 478 + return result; 479 + }, 480 + /** 481 + * Creates a params type for query string parameters. 482 + * @see https://atproto.com/specs/lexicon#params 483 + */ 484 + params<Properties extends ParamsProperties>( 485 + properties: Properties, 486 + ): ParamsResult<Properties> { 487 + const required = Object.keys(properties).filter( 488 + (key) => properties[key].required, 489 + ); 490 + const result: { 491 + type: "params"; 492 + properties: Properties; 493 + required?: string[]; 494 + } = { 495 + type: "params", 496 + properties, 497 + }; 498 + if (required.length > 0) { 499 + result.required = required; 500 + } 501 + return result; 502 + }, 503 + /** 504 + * Creates a query endpoint definition (HTTP GET). 505 + * @see https://atproto.com/specs/lexicon#query 506 + */ 507 + query<T extends QueryOptions>(options?: T): T & { type: "query" } { 508 + return { 509 + type: "query", 510 + ...options, 511 + } as T & { type: "query" }; 512 + }, 513 + /** 514 + * Creates a procedure endpoint definition (HTTP POST). 515 + * @see https://atproto.com/specs/lexicon#procedure 516 + */ 517 + procedure<T extends ProcedureOptions>( 518 + options?: T, 519 + ): T & { type: "procedure" } { 520 + return { 521 + type: "procedure", 522 + ...options, 523 + } as T & { type: "procedure" }; 524 + }, 525 + /** 526 + * Creates a subscription endpoint definition (WebSocket). 527 + * @see https://atproto.com/specs/lexicon#subscription 528 + */ 529 + subscription<T extends SubscriptionOptions>( 530 + options?: T, 531 + ): T & { type: "subscription" } { 532 + return { 533 + type: "subscription", 534 + ...options, 535 + } as T & { type: "subscription" }; 536 + }, 537 + /** 538 + * Creates a lexicon namespace document. 539 + * @see https://atproto.com/specs/lexicon#lexicon-document 540 + */ 541 + namespace<ID extends string, D extends LexiconNamespace["defs"]>( 542 + id: ID, 543 + defs: D, 544 + ): { lexicon: 1; id: ID; defs: D } { 545 + return { 546 + lexicon: 1, 547 + id, 548 + defs, 549 + }; 550 + }, 551 };
-5
src/test-usage.ts
··· 1 - import type { Schema } from "./test.ts"; 2 - 3 - const schema: Schema = { 4 - main: {}, 5 - };
···