An experimental TypeSpec syntax for Lexicon

ok

+10005
+40
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/defs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.defs { 4 + model StatusAttr { 5 + @required 6 + applied: boolean; 7 + 8 + ref?: string; 9 + } 10 + 11 + model AccountView { 12 + @required did: did; 13 + @required handle: handle; 14 + email?: string; 15 + relatedRecords?: unknown[]; 16 + @required indexedAt: datetime; 17 + invitedBy?: com.atproto.server.defs.InviteCode; 18 + invites?: com.atproto.server.defs.InviteCode[]; 19 + invitesDisabled?: boolean; 20 + emailConfirmedAt?: datetime; 21 + inviteNote?: string; 22 + deactivatedAt?: datetime; 23 + threatSignatures?: ThreatSignature[]; 24 + } 25 + 26 + model RepoRef { 27 + @required did: did; 28 + } 29 + 30 + model RepoBlobRef { 31 + @required did: did; 32 + @required cid: cid; 33 + recordUri?: atUri; 34 + } 35 + 36 + model ThreatSignature { 37 + @required property: string; 38 + @required value: string; 39 + } 40 + }
+9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/deleteAccount.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.deleteAccount { 4 + @doc("Delete a user account as an administrator.") 5 + @procedure 6 + op main(input: { 7 + @required did: did; 8 + }): void; 9 + }
+12
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/disableAccountInvites.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.disableAccountInvites { 4 + @doc("Disable an account from receiving new invite codes, but does not invalidate existing codes.") 5 + @procedure 6 + op main(input: { 7 + @required account: did; 8 + 9 + @doc("Optional reason for disabled invites.") 10 + note?: string; 11 + }): void; 12 + }
+10
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/disableInviteCodes.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.disableInviteCodes { 4 + @doc("Disable some set of codes and/or all codes associated with a set of users.") 5 + @procedure 6 + op main(input: { 7 + codes?: string[]; 8 + accounts?: string[]; 9 + }): void; 10 + }
+12
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/enableAccountInvites.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.enableAccountInvites { 4 + @doc("Re-enable an account's ability to receive invite codes.") 5 + @procedure 6 + op main(input: { 7 + @required account: did; 8 + 9 + @doc("Optional reason for enabled invites.") 10 + note?: string; 11 + }): void; 12 + }
+9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getAccountInfo.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.getAccountInfo { 4 + @doc("Get details about an account.") 5 + @query 6 + op main( 7 + @required did: did 8 + ): com.atproto.admin.defs.AccountView; 9 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getAccountInfos.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.getAccountInfos { 4 + @doc("Get details about some accounts.") 5 + @query 6 + op main( 7 + @required dids: did[] 8 + ): { 9 + @required infos: com.atproto.admin.defs.AccountView[]; 10 + }; 11 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getInviteCodes.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.getInviteCodes { 4 + @doc("Get an admin view of invite codes.") 5 + @query 6 + op main( 7 + sort?: "recent" | "usage" | string = "recent", 8 + 9 + @minValue(1) 10 + @maxValue(500) 11 + limit?: int32 = 100, 12 + 13 + cursor?: string 14 + ): { 15 + cursor?: string; 16 + @required codes: com.atproto.server.defs.InviteCode[]; 17 + }; 18 + }
+22
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getSubjectStatus.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.getSubjectStatus { 4 + @doc("Get the service-specific admin status of a subject (account, record, or blob).") 5 + @query 6 + op main( 7 + did?: did, 8 + uri?: atUri, 9 + blob?: cid 10 + ): { 11 + @required 12 + subject: ( 13 + com.atproto.admin.defs.RepoRef | 14 + com.atproto.repo.strongRef.Main | 15 + com.atproto.admin.defs.RepoBlobRef | 16 + unknown 17 + ); 18 + 19 + takedown?: com.atproto.admin.defs.StatusAttr; 20 + deactivated?: com.atproto.admin.defs.StatusAttr; 21 + }; 22 + }
+17
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/searchAccounts.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.searchAccounts { 4 + @doc("Get list of accounts that matches your search query.") 5 + @query 6 + op main( 7 + email?: string, 8 + cursor?: string, 9 + 10 + @minValue(1) 11 + @maxValue(100) 12 + limit?: int32 = 50 13 + ): { 14 + cursor?: string; 15 + @required accounts: com.atproto.admin.defs.AccountView[]; 16 + }; 17 + }
+17
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/sendEmail.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.sendEmail { 4 + @doc("Send email to a user's account email address.") 5 + @procedure 6 + op main(input: { 7 + @required recipientDid: did; 8 + @required content: string; 9 + subject?: string; 10 + @required senderDid: did; 11 + 12 + @doc("Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers") 13 + comment?: string; 14 + }): { 15 + @required sent: boolean; 16 + }; 17 + }
+13
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountEmail.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.updateAccountEmail { 4 + @doc("Administrative action to update an account's email.") 5 + @procedure 6 + op main(input: { 7 + @doc("The handle or DID of the repo.") 8 + @required 9 + account: atIdentifier; 10 + 11 + @required email: string; 12 + }): void; 13 + }
+10
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountHandle.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.updateAccountHandle { 4 + @doc("Administrative action to update an account's handle.") 5 + @procedure 6 + op main(input: { 7 + @required did: did; 8 + @required handle: handle; 9 + }): void; 10 + }
+10
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountPassword.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.updateAccountPassword { 4 + @doc("Update the password for a user account as an administrator.") 5 + @procedure 6 + op main(input: { 7 + @required did: did; 8 + @required password: string; 9 + }): void; 10 + }
+13
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountSigningKey.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.updateAccountSigningKey { 4 + @doc("Administrative action to update an account's signing key in their Did document.") 5 + @procedure 6 + op main(input: { 7 + @required did: did; 8 + 9 + @doc("Did-key formatted public key") 10 + @required 11 + signingKey: did; 12 + }): void; 13 + }
+28
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateSubjectStatus.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.admin.updateSubjectStatus { 4 + @doc("Update the service-specific admin status of a subject (account, record, or blob).") 5 + @procedure 6 + op main(input: { 7 + @required 8 + subject: ( 9 + com.atproto.admin.defs.RepoRef | 10 + com.atproto.repo.strongRef.Main | 11 + com.atproto.admin.defs.RepoBlobRef | 12 + unknown 13 + ); 14 + 15 + takedown?: com.atproto.admin.defs.StatusAttr; 16 + deactivated?: com.atproto.admin.defs.StatusAttr; 17 + }): { 18 + @required 19 + subject: ( 20 + com.atproto.admin.defs.RepoRef | 21 + com.atproto.repo.strongRef.Main | 22 + com.atproto.admin.defs.RepoBlobRef | 23 + unknown 24 + ); 25 + 26 + takedown?: com.atproto.admin.defs.StatusAttr; 27 + }; 28 + }
+15
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/defs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.defs { 4 + model IdentityInfo { 5 + @required did: did; 6 + 7 + @doc("The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document.") 8 + @required 9 + handle: handle; 10 + 11 + @doc("The complete DID document for the identity.") 12 + @required 13 + didDoc: unknown; 14 + } 15 + }
+14
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/getRecommendedDidCredentials.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.getRecommendedDidCredentials { 4 + @doc("Describe the credentials that should be included in the DID doc of an account that is migrating to this service.") 5 + @query 6 + op main(): { 7 + @doc("Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.") 8 + rotationKeys?: string[]; 9 + 10 + alsoKnownAs?: string[]; 11 + verificationMethods?: unknown; 12 + services?: unknown; 13 + }; 14 + }
+19
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/refreshIdentity.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.refreshIdentity { 4 + @doc("The resolution process confirmed that the handle does not resolve to any DID.") 5 + model HandleNotFound {} 6 + 7 + @doc("The DID resolution process confirmed that there is no current DID.") 8 + model DidNotFound {} 9 + 10 + @doc("The DID previously existed, but has been deactivated.") 11 + model DidDeactivated {} 12 + 13 + @doc("Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server.") 14 + @procedure 15 + @errors(HandleNotFound, DidNotFound, DidDeactivated) 16 + op main(input: { 17 + @required identifier: atIdentifier; 18 + }): com.atproto.identity.defs.IdentityInfo; 19 + }
+7
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/requestPlcOperationSignature.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.requestPlcOperationSignature { 4 + @doc("Request an email with a code to in order to request a signed PLC operation. Requires Auth.") 5 + @procedure 6 + op main(): void; 7 + }
+22
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveDid.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.resolveDid { 4 + @doc("Resolves DID to DID document. Does not bi-directionally verify handle.") 5 + @query 6 + @errors(DidNotFound, DidDeactivated) 7 + op main( 8 + @doc("DID to resolve.") 9 + @required 10 + did: did 11 + ): { 12 + @doc("The complete DID document for the identity.") 13 + @required 14 + didDoc: unknown; 15 + }; 16 + 17 + @doc("The DID resolution process confirmed that there is no current DID.") 18 + model DidNotFound {} 19 + 20 + @doc("The DID previously existed, but has been deactivated.") 21 + model DidDeactivated {} 22 + }
+17
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveHandle.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.resolveHandle { 4 + @doc("Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document.") 5 + @query 6 + @errors(HandleNotFound) 7 + op main( 8 + @doc("The handle to resolve.") 9 + @required 10 + handle: handle 11 + ): { 12 + @required did: did; 13 + }; 14 + 15 + @doc("The resolution process confirmed that the handle does not resolve to any DID.") 16 + model HandleNotFound {} 17 + }
+21
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveIdentity.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.resolveIdentity { 4 + @doc("The resolution process confirmed that the handle does not resolve to any DID.") 5 + model HandleNotFound {} 6 + 7 + @doc("The DID resolution process confirmed that there is no current DID.") 8 + model DidNotFound {} 9 + 10 + @doc("The DID previously existed, but has been deactivated.") 11 + model DidDeactivated {} 12 + 13 + @doc("Resolves an identity (DID or Handle) to a full identity (DID document and verified handle).") 14 + @query 15 + @errors(HandleNotFound, DidNotFound, DidDeactivated) 16 + op main( 17 + @doc("Handle or DID to resolve.") 18 + @required 19 + identifier: atIdentifier 20 + ): com.atproto.identity.defs.IdentityInfo; 21 + }
+22
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/signPlcOperation.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.signPlcOperation { 4 + @doc("Signs a PLC operation to update some value(s) in the requesting DID's document.") 5 + @procedure 6 + op main(input: { 7 + @doc("A token received through com.atproto.identity.requestPlcOperationSignature") 8 + token?: string; 9 + 10 + rotationKeys?: string[]; 11 + 12 + alsoKnownAs?: string[]; 13 + 14 + verificationMethods?: unknown; 15 + 16 + services?: unknown; 17 + }): { 18 + @doc("A signed DID PLC operation.") 19 + @required 20 + operation: unknown; 21 + }; 22 + }
+9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/submitPlcOperation.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.submitPlcOperation { 4 + @doc("Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry") 5 + @procedure 6 + op main(input: { 7 + @required operation: unknown; 8 + }): void; 9 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/updateHandle.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.identity.updateHandle { 4 + @doc("Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth.") 5 + @procedure 6 + op main(input: { 7 + @doc("The new handle.") 8 + @required 9 + handle: handle; 10 + }): void; 11 + }
+113
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/defs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.label.defs { 4 + @doc("Metadata tag on an atproto resource (eg, repo or record).") 5 + model Label { 6 + @doc("The AT Protocol version of the label object.") 7 + ver?: integer; 8 + 9 + @doc("DID of the actor who created this label.") 10 + @required 11 + src: did; 12 + 13 + @doc("AT URI of the record, repository (account), or other resource that this label applies to.") 14 + @required 15 + uri: uri; 16 + 17 + @doc("Optionally, CID specifying the specific version of 'uri' resource this label applies to.") 18 + cid?: cid; 19 + 20 + @doc("The short string name of the value or type of this label.") 21 + @maxLength(128) 22 + @required 23 + val: string; 24 + 25 + @doc("If true, this is a negation label, overwriting a previous label.") 26 + neg?: boolean; 27 + 28 + @doc("Timestamp when this label was created.") 29 + @required 30 + cts: datetime; 31 + 32 + @doc("Timestamp at which this label expires (no longer applies).") 33 + exp?: datetime; 34 + 35 + @doc("Signature of dag-cbor encoded label.") 36 + sig?: bytes; 37 + } 38 + 39 + @doc("Metadata tags on an atproto record, published by the author within the record.") 40 + model SelfLabels { 41 + @maxItems(10) 42 + @required 43 + values: SelfLabel[]; 44 + } 45 + 46 + @doc("Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.") 47 + model SelfLabel { 48 + @doc("The short string name of the value or type of this label.") 49 + @maxLength(128) 50 + @required 51 + val: string; 52 + } 53 + 54 + @doc("Declares a label value and its expected interpretations and behaviors.") 55 + model LabelValueDefinition { 56 + @doc("The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).") 57 + @maxLength(100) 58 + @maxGraphemes(100) 59 + @required 60 + identifier: string; 61 + 62 + @doc("How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.") 63 + @required 64 + severity: "inform" | "alert" | "none" | string; 65 + 66 + @doc("What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.") 67 + @required 68 + blurs: "content" | "media" | "none" | string; 69 + 70 + @doc("The default setting for this label.") 71 + defaultSetting?: "ignore" | "warn" | "hide" | string = "warn"; 72 + 73 + @doc("Does the user need to have adult content enabled in order to configure this label?") 74 + adultOnly?: boolean; 75 + 76 + @required 77 + locales: LabelValueDefinitionStrings[]; 78 + } 79 + 80 + @doc("Strings which describe the label in the UI, localized into a specific language.") 81 + model LabelValueDefinitionStrings { 82 + @doc("The code of the language these strings are written in.") 83 + @required 84 + lang: language; 85 + 86 + @doc("A short human-readable name for the label.") 87 + @maxGraphemes(64) 88 + @maxLength(640) 89 + @required 90 + name: string; 91 + 92 + @doc("A longer description of what the label means and why it might be applied.") 93 + @maxGraphemes(10000) 94 + @maxLength(100000) 95 + @required 96 + description: string; 97 + } 98 + 99 + union LabelValue { 100 + "!hide", 101 + "!no-promote", 102 + "!warn", 103 + "!no-unauthenticated", 104 + "dmca-violation", 105 + "doxxing", 106 + "porn", 107 + "sexual", 108 + "nudity", 109 + "nsfl", 110 + "gore", 111 + string, 112 + } 113 + }
+23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/queryLabels.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.label.queryLabels { 4 + @doc("Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth.") 5 + @query 6 + op main( 7 + @doc("List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI.") 8 + @required 9 + uriPatterns: string[], 10 + 11 + @doc("Optional list of label sources (DIDs) to filter on.") 12 + sources?: did[], 13 + 14 + @minValue(1) 15 + @maxValue(250) 16 + limit?: int32 = 50, 17 + 18 + cursor?: string 19 + ): { 20 + cursor?: string; 21 + @required labels: com.atproto.label.defs.Label[]; 22 + }; 23 + }
+23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/subscribeLabels.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.label.subscribeLabels { 4 + model FutureCursor {} 5 + 6 + model Labels { 7 + @required seq: integer; 8 + @required labels: com.atproto.label.defs.Label[]; 9 + } 10 + 11 + model Info { 12 + @required name: "OutdatedCursor" | string; 13 + message?: string; 14 + } 15 + 16 + @doc("Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream.") 17 + @subscription 18 + @errors(FutureCursor) 19 + op main( 20 + @doc("The last known event seq number to backfill from.") 21 + cursor?: integer 22 + ): (Labels | Info); 23 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/lexicon/schema.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.lexicon.schema { 4 + @doc("Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc).") 5 + @rec("nsid") 6 + model Main { 7 + @doc("Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system.") 8 + @required 9 + lexicon: integer; 10 + } 11 + }
+52
packages/emitter/test/integration/lexicon-examples/input/com/atproto/moderation/createReport.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.moderation.createReport { 4 + @doc("Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth.") 5 + @procedure 6 + op main(input: { 7 + @doc("Indicates the broad category of violation the report is for.") 8 + @required 9 + reasonType: com.atproto.moderation.defs.ReasonType; 10 + 11 + @maxGraphemes(2000) 12 + @maxLength(20000) 13 + @doc("Additional context about the content and violation.") 14 + reason?: string; 15 + 16 + @required 17 + subject: ( 18 + | com.atproto.admin.defs.RepoRef 19 + | com.atproto.repo.strongRef.Main 20 + | unknown 21 + ); 22 + 23 + modTool?: ModTool; 24 + }): { 25 + @required id: integer; 26 + @required reasonType: com.atproto.moderation.defs.ReasonType; 27 + 28 + @maxGraphemes(2000) 29 + @maxLength(20000) 30 + reason?: string; 31 + 32 + @required 33 + subject: ( 34 + | com.atproto.admin.defs.RepoRef 35 + | com.atproto.repo.strongRef.Main 36 + | unknown 37 + ); 38 + 39 + @required reportedBy: did; 40 + @required createdAt: datetime; 41 + }; 42 + 43 + @doc("Moderation tool information for tracing the source of the action") 44 + model ModTool { 45 + @doc("Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome')") 46 + @required 47 + name: string; 48 + 49 + @doc("Additional arbitrary metadata about the source") 50 + meta?: unknown; 51 + } 52 + }
+104
packages/emitter/test/integration/lexicon-examples/input/com/atproto/moderation/defs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.moderation.defs { 4 + union ReasonType { 5 + string, 6 + 7 + ReasonSpam: "com.atproto.moderation.defs#reasonSpam", 8 + ReasonViolation: "com.atproto.moderation.defs#reasonViolation", 9 + ReasonMisleading: "com.atproto.moderation.defs#reasonMisleading", 10 + ReasonSexual: "com.atproto.moderation.defs#reasonSexual", 11 + ReasonRude: "com.atproto.moderation.defs#reasonRude", 12 + ReasonOther: "com.atproto.moderation.defs#reasonOther", 13 + ReasonAppeal: "com.atproto.moderation.defs#reasonAppeal", 14 + 15 + ToolsOzoneReportReasonAppeal: "tools.ozone.report.defs#reasonAppeal", 16 + 17 + ToolsOzoneReportReasonViolenceAnimalWelfare: "tools.ozone.report.defs#reasonViolenceAnimalWelfare", 18 + ToolsOzoneReportReasonViolenceThreats: "tools.ozone.report.defs#reasonViolenceThreats", 19 + ToolsOzoneReportReasonViolenceGraphicContent: "tools.ozone.report.defs#reasonViolenceGraphicContent", 20 + ToolsOzoneReportReasonViolenceSelfHarm: "tools.ozone.report.defs#reasonViolenceSelfHarm", 21 + ToolsOzoneReportReasonViolenceGlorification: "tools.ozone.report.defs#reasonViolenceGlorification", 22 + ToolsOzoneReportReasonViolenceExtremistContent: "tools.ozone.report.defs#reasonViolenceExtremistContent", 23 + ToolsOzoneReportReasonViolenceTrafficking: "tools.ozone.report.defs#reasonViolenceTrafficking", 24 + ToolsOzoneReportReasonViolenceOther: "tools.ozone.report.defs#reasonViolenceOther", 25 + 26 + ToolsOzoneReportReasonSexualAbuseContent: "tools.ozone.report.defs#reasonSexualAbuseContent", 27 + ToolsOzoneReportReasonSexualNCII: "tools.ozone.report.defs#reasonSexualNCII", 28 + ToolsOzoneReportReasonSexualSextortion: "tools.ozone.report.defs#reasonSexualSextortion", 29 + ToolsOzoneReportReasonSexualDeepfake: "tools.ozone.report.defs#reasonSexualDeepfake", 30 + ToolsOzoneReportReasonSexualAnimal: "tools.ozone.report.defs#reasonSexualAnimal", 31 + ToolsOzoneReportReasonSexualUnlabeled: "tools.ozone.report.defs#reasonSexualUnlabeled", 32 + ToolsOzoneReportReasonSexualOther: "tools.ozone.report.defs#reasonSexualOther", 33 + 34 + ToolsOzoneReportReasonChildSafetyCSAM: "tools.ozone.report.defs#reasonChildSafetyCSAM", 35 + ToolsOzoneReportReasonChildSafetyGroom: "tools.ozone.report.defs#reasonChildSafetyGroom", 36 + ToolsOzoneReportReasonChildSafetyMinorPrivacy: "tools.ozone.report.defs#reasonChildSafetyMinorPrivacy", 37 + ToolsOzoneReportReasonChildSafetyEndangerment: "tools.ozone.report.defs#reasonChildSafetyEndangerment", 38 + ToolsOzoneReportReasonChildSafetyHarassment: "tools.ozone.report.defs#reasonChildSafetyHarassment", 39 + ToolsOzoneReportReasonChildSafetyPromotion: "tools.ozone.report.defs#reasonChildSafetyPromotion", 40 + ToolsOzoneReportReasonChildSafetyOther: "tools.ozone.report.defs#reasonChildSafetyOther", 41 + 42 + ToolsOzoneReportReasonHarassmentTroll: "tools.ozone.report.defs#reasonHarassmentTroll", 43 + ToolsOzoneReportReasonHarassmentTargeted: "tools.ozone.report.defs#reasonHarassmentTargeted", 44 + ToolsOzoneReportReasonHarassmentHateSpeech: "tools.ozone.report.defs#reasonHarassmentHateSpeech", 45 + ToolsOzoneReportReasonHarassmentDoxxing: "tools.ozone.report.defs#reasonHarassmentDoxxing", 46 + ToolsOzoneReportReasonHarassmentOther: "tools.ozone.report.defs#reasonHarassmentOther", 47 + 48 + ToolsOzoneReportReasonMisleadingBot: "tools.ozone.report.defs#reasonMisleadingBot", 49 + ToolsOzoneReportReasonMisleadingImpersonation: "tools.ozone.report.defs#reasonMisleadingImpersonation", 50 + ToolsOzoneReportReasonMisleadingSpam: "tools.ozone.report.defs#reasonMisleadingSpam", 51 + ToolsOzoneReportReasonMisleadingScam: "tools.ozone.report.defs#reasonMisleadingScam", 52 + ToolsOzoneReportReasonMisleadingSyntheticContent: "tools.ozone.report.defs#reasonMisleadingSyntheticContent", 53 + ToolsOzoneReportReasonMisleadingMisinformation: "tools.ozone.report.defs#reasonMisleadingMisinformation", 54 + ToolsOzoneReportReasonMisleadingOther: "tools.ozone.report.defs#reasonMisleadingOther", 55 + 56 + ToolsOzoneReportReasonRuleSiteSecurity: "tools.ozone.report.defs#reasonRuleSiteSecurity", 57 + ToolsOzoneReportReasonRuleStolenContent: "tools.ozone.report.defs#reasonRuleStolenContent", 58 + ToolsOzoneReportReasonRuleProhibitedSales: "tools.ozone.report.defs#reasonRuleProhibitedSales", 59 + ToolsOzoneReportReasonRuleBanEvasion: "tools.ozone.report.defs#reasonRuleBanEvasion", 60 + ToolsOzoneReportReasonRuleOther: "tools.ozone.report.defs#reasonRuleOther", 61 + 62 + ToolsOzoneReportReasonCivicElectoralProcess: "tools.ozone.report.defs#reasonCivicElectoralProcess", 63 + ToolsOzoneReportReasonCivicDisclosure: "tools.ozone.report.defs#reasonCivicDisclosure", 64 + ToolsOzoneReportReasonCivicInterference: "tools.ozone.report.defs#reasonCivicInterference", 65 + ToolsOzoneReportReasonCivicMisinformation: "tools.ozone.report.defs#reasonCivicMisinformation", 66 + ToolsOzoneReportReasonCivicImpersonation: "tools.ozone.report.defs#reasonCivicImpersonation", 67 + } 68 + 69 + @doc("Spam: frequent unwanted promotion, replies, mentions. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingSpam`.") 70 + @token 71 + model ReasonSpam {} 72 + 73 + @doc("Direct violation of server rules, laws, terms of service. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`.") 74 + @token 75 + model ReasonViolation {} 76 + 77 + @doc("Misleading identity, affiliation, or content. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingOther`.") 78 + @token 79 + model ReasonMisleading {} 80 + 81 + @doc("Unwanted or mislabeled sexual content. Prefer new lexicon definition `tools.ozone.report.defs#reasonSexualUnlabeled`.") 82 + @token 83 + model ReasonSexual {} 84 + 85 + @doc("Rude, harassing, explicit, or otherwise unwelcoming behavior. Prefer new lexicon definition `tools.ozone.report.defs#reasonHarassmentOther`.") 86 + @token 87 + model ReasonRude {} 88 + 89 + @doc("Reports not falling under another report category. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`.") 90 + @token 91 + model ReasonOther {} 92 + 93 + @doc("Appeal a previously taken moderation action") 94 + @token 95 + model ReasonAppeal {} 96 + 97 + @doc("Tag describing a type of subject that might be reported.") 98 + union SubjectType { 99 + "account", 100 + "record", 101 + "chat", 102 + string, 103 + } 104 + }
+81
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/applyWrites.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.applyWrites { 4 + @doc("Indicates that the 'swapCommit' parameter did not match current commit.") 5 + model InvalidSwap {} 6 + 7 + @closed 8 + @inline 9 + union WriteAction { 10 + Create, 11 + Update, 12 + Delete, 13 + } 14 + 15 + @closed 16 + @inline 17 + union WriteResult { 18 + CreateResult, 19 + UpdateResult, 20 + DeleteResult, 21 + } 22 + 23 + @doc("Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.") 24 + @procedure 25 + @errors(InvalidSwap) 26 + op main(input: { 27 + @doc("The handle or DID of the repo (aka, current account).") 28 + @required 29 + repo: atIdentifier; 30 + 31 + @doc("Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons.") 32 + validate?: boolean; 33 + 34 + @required 35 + writes: WriteAction[]; 36 + 37 + @doc("If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.") 38 + swapCommit?: cid; 39 + }): { 40 + commit?: com.atproto.repo.defs.CommitMeta; 41 + results?: WriteResult[]; 42 + }; 43 + 44 + @doc("Operation which creates a new record.") 45 + model Create { 46 + @required collection: nsid; 47 + 48 + @doc("NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.") 49 + @maxLength(512) 50 + rkey?: recordKey; 51 + 52 + @required value: unknown; 53 + } 54 + 55 + @doc("Operation which updates an existing record.") 56 + model Update { 57 + @required collection: nsid; 58 + @required rkey: recordKey; 59 + @required value: unknown; 60 + } 61 + 62 + @doc("Operation which deletes an existing record.") 63 + model Delete { 64 + @required collection: nsid; 65 + @required rkey: recordKey; 66 + } 67 + 68 + model CreateResult { 69 + @required uri: atUri; 70 + @required cid: cid; 71 + validationStatus?: "valid" | "unknown" | string; 72 + } 73 + 74 + model UpdateResult { 75 + @required uri: atUri; 76 + @required cid: cid; 77 + validationStatus?: "valid" | "unknown" | string; 78 + } 79 + 80 + model DeleteResult {} 81 + }
+38
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/createRecord.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.createRecord { 4 + @doc("Create a single new repository record. Requires auth, implemented by PDS.") 5 + @errors(InvalidSwap) 6 + @procedure 7 + op main(input: { 8 + @doc("The handle or DID of the repo (aka, current account).") 9 + @required 10 + repo: atIdentifier; 11 + 12 + @doc("The NSID of the record collection.") 13 + @required 14 + collection: nsid; 15 + 16 + @doc("The Record Key.") 17 + @maxLength(512) 18 + rkey?: recordKey; 19 + 20 + @doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.") 21 + validate?: boolean; 22 + 23 + @doc("The record itself. Must contain a $type field.") 24 + @required 25 + record: unknown; 26 + 27 + @doc("Compare and swap with the previous commit by CID.") 28 + swapCommit?: cid; 29 + }): { 30 + @required uri: atUri; 31 + @required cid: cid; 32 + commit?: com.atproto.repo.defs.CommitMeta; 33 + validationStatus?: "valid" | "unknown" | string; 34 + }; 35 + 36 + @doc("Indicates that 'swapCommit' didn't match current repo commit.") 37 + model InvalidSwap {} 38 + }
+8
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/defs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.defs { 4 + model CommitMeta { 5 + @required cid: cid; 6 + @required rev: tid; 7 + } 8 + }
+30
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/deleteRecord.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.deleteRecord { 4 + @doc("Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.") 5 + @errors(InvalidSwap) 6 + @procedure 7 + op main(input: { 8 + @doc("The handle or DID of the repo (aka, current account).") 9 + @required 10 + repo: atIdentifier; 11 + 12 + @doc("The NSID of the record collection.") 13 + @required 14 + collection: nsid; 15 + 16 + @doc("The Record Key.") 17 + @required 18 + rkey: recordKey; 19 + 20 + @doc("Compare and swap with the previous record by CID.") 21 + swapRecord?: cid; 22 + 23 + @doc("Compare and swap with the previous commit by CID.") 24 + swapCommit?: cid; 25 + }): { 26 + commit?: com.atproto.repo.defs.CommitMeta; 27 + }; 28 + 29 + model InvalidSwap {} 30 + }
+26
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/describeRepo.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.describeRepo { 4 + @doc("Get information about an account and repository, including the list of collections. Does not require auth.") 5 + @query 6 + op main( 7 + @doc("The handle or DID of the repo.") 8 + @required 9 + repo: atIdentifier 10 + ): { 11 + @required handle: handle; 12 + @required did: did; 13 + 14 + @doc("The complete DID document for this account.") 15 + @required 16 + didDoc: unknown; 17 + 18 + @doc("List of all the collections (NSIDs) for which this repo contains at least one record.") 19 + @required 20 + collections: nsid[]; 21 + 22 + @doc("Indicates if handle is currently valid (resolves bi-directionally)") 23 + @required 24 + handleIsCorrect: boolean; 25 + }; 26 + }
+29
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/getRecord.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.getRecord { 4 + @doc("Get a single record from a repository. Does not require auth.") 5 + @query 6 + @errors(RecordNotFound) 7 + op main( 8 + @doc("The handle or DID of the repo.") 9 + @required 10 + repo: atIdentifier, 11 + 12 + @doc("The NSID of the record collection.") 13 + @required 14 + collection: nsid, 15 + 16 + @doc("The Record Key.") 17 + @required 18 + rkey: recordKey, 19 + 20 + @doc("The CID of the version of the record. If not specified, then return the most recent version.") 21 + cid?: cid 22 + ): { 23 + @required uri: atUri; 24 + cid?: cid; 25 + @required value: unknown; 26 + }; 27 + 28 + model RecordNotFound {} 29 + }
+10
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/importRepo.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.importRepo { 4 + @doc("Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.") 5 + @procedure 6 + op main( 7 + @encoding("application/vnd.ipld.car") 8 + input: void 9 + ): void; 10 + }
+22
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/listMissingBlobs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.listMissingBlobs { 4 + @doc("Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.") 5 + @query 6 + op main( 7 + @minValue(1) 8 + @maxValue(1000) 9 + limit?: int32 = 500, 10 + 11 + cursor?: string 12 + ): { 13 + cursor?: string; 14 + 15 + @required blobs: RecordBlob[]; 16 + }; 17 + 18 + model RecordBlob { 19 + @required cid: cid; 20 + @required recordUri: atUri; 21 + } 22 + }
+34
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/listRecords.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.listRecords { 4 + @doc("List a range of records in a repository, matching a specific collection. Does not require auth.") 5 + @query 6 + op main( 7 + @doc("The handle or DID of the repo.") 8 + @required 9 + repo: atIdentifier, 10 + 11 + @doc("The NSID of the record type.") 12 + @required 13 + collection: nsid, 14 + 15 + @doc("The number of records to return.") 16 + @minValue(1) 17 + @maxValue(100) 18 + limit?: int32 = 50, 19 + 20 + cursor?: string, 21 + 22 + @doc("Flag to reverse the order of the returned records.") 23 + reverse?: boolean 24 + ): { 25 + cursor?: string; 26 + @required records: Record[]; 27 + }; 28 + 29 + model Record { 30 + @required uri: atUri; 31 + @required cid: cid; 32 + @required value: unknown; 33 + } 34 + }
+41
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/putRecord.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.putRecord { 4 + @doc("Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.") 5 + @errors(InvalidSwap) 6 + @procedure 7 + op main(input: { 8 + @doc("The handle or DID of the repo (aka, current account).") 9 + @required 10 + repo: atIdentifier; 11 + 12 + @doc("The NSID of the record collection.") 13 + @required 14 + collection: nsid; 15 + 16 + @doc("The Record Key.") 17 + @maxLength(512) 18 + @required 19 + rkey: recordKey; 20 + 21 + @doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.") 22 + validate?: boolean; 23 + 24 + @doc("The record to write.") 25 + @required 26 + record: unknown; 27 + 28 + @doc("Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation") 29 + swapRecord?: cid | null; 30 + 31 + @doc("Compare and swap with the previous commit by CID.") 32 + swapCommit?: cid; 33 + }): { 34 + @required uri: atUri; 35 + @required cid: cid; 36 + commit?: com.atproto.repo.defs.CommitMeta; 37 + validationStatus?: "valid" | "unknown" | string; 38 + }; 39 + 40 + model InvalidSwap {} 41 + }
+9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/strongRef.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + @doc("A URI with a content-hash fingerprint.") 4 + namespace com.atproto.repo.strongRef { 5 + model Main { 6 + @required uri: atUri; 7 + @required cid: cid; 8 + } 9 + }
+12
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/uploadBlob.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.repo.uploadBlob { 4 + @doc("Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.") 5 + @procedure 6 + op main( 7 + @encoding("*/*") 8 + input: void 9 + ): { 10 + @required blob: Blob<#[], 0>; 11 + }; 12 + }
+7
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/activateAccount.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.activateAccount { 4 + @doc("Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup.") 5 + @procedure 6 + op main(): void; 7 + }
+17
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/checkAccountStatus.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.checkAccountStatus { 4 + @doc("Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself.") 5 + @query 6 + op main(): { 7 + @required activated: boolean; 8 + @required validDid: boolean; 9 + @required repoCommit: cid; 10 + @required repoRev: string; 11 + @required repoBlocks: integer; 12 + @required indexedRecords: integer; 13 + @required privateStateValues: integer; 14 + @required expectedBlobs: integer; 15 + @required importedBlobs: integer; 16 + }; 17 + }
+16
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/confirmEmail.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.confirmEmail { 4 + model AccountNotFound {} 5 + model ExpiredToken {} 6 + model InvalidToken {} 7 + model InvalidEmail {} 8 + 9 + @doc("Confirm an email using a token from com.atproto.server.requestEmailConfirmation.") 10 + @procedure 11 + @errors(AccountNotFound, ExpiredToken, InvalidToken, InvalidEmail) 12 + op main(input: { 13 + @required email: string; 14 + @required token: string; 15 + }): void; 16 + }
+53
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createAccount.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.createAccount { 4 + model InvalidHandle {} 5 + model InvalidPassword {} 6 + model InvalidInviteCode {} 7 + model HandleNotAvailable {} 8 + model UnsupportedDomain {} 9 + model UnresolvableDid {} 10 + model IncompatibleDidDoc {} 11 + 12 + @doc("Account login session returned on successful account creation.") 13 + @inline 14 + model Output { 15 + @required accessJwt: string; 16 + @required refreshJwt: string; 17 + @required handle: handle; 18 + 19 + @doc("The DID of the new account.") 20 + @required 21 + did: did; 22 + 23 + @doc("Complete DID document.") 24 + didDoc?: unknown; 25 + } 26 + 27 + @doc("Create an account. Implemented by PDS.") 28 + @procedure 29 + @errors(InvalidHandle, InvalidPassword, InvalidInviteCode, HandleNotAvailable, UnsupportedDomain, UnresolvableDid, IncompatibleDidDoc) 30 + op main(input: { 31 + email?: string; 32 + 33 + @doc("Requested handle for the account.") 34 + @required 35 + handle: handle; 36 + 37 + @doc("Pre-existing atproto DID, being imported to a new account.") 38 + did?: did; 39 + 40 + inviteCode?: string; 41 + verificationCode?: string; 42 + verificationPhone?: string; 43 + 44 + @doc("Initial account password. May need to meet instance-specific password strength requirements.") 45 + password?: string; 46 + 47 + @doc("DID PLC rotation key (aka, recovery key) to be included in PLC creation operation.") 48 + recoveryKey?: string; 49 + 50 + @doc("A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented.") 51 + plcOp?: unknown; 52 + }): Output; 53 + }
+24
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createAppPassword.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.createAppPassword { 4 + model AccountTakedown {} 5 + 6 + model AppPassword { 7 + @required name: string; 8 + @required password: string; 9 + @required createdAt: datetime; 10 + privileged?: boolean; 11 + } 12 + 13 + @doc("Create an App Password.") 14 + @procedure 15 + @errors(AccountTakedown) 16 + op main(input: { 17 + @doc("A short name for the App Password, to help distinguish them.") 18 + @required 19 + name: string; 20 + 21 + @doc("If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients.") 22 + privileged?: boolean; 23 + }): AppPassword; 24 + }
+12
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createInviteCode.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.createInviteCode { 4 + @doc("Create an invite code.") 5 + @procedure 6 + op main(input: { 7 + @required useCount: integer; 8 + forAccount?: did; 9 + }): { 10 + @required code: string; 11 + }; 12 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createInviteCodes.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.createInviteCodes { 4 + model AccountCodes { 5 + @required account: string; 6 + @required codes: string[]; 7 + } 8 + 9 + @doc("Create invite codes.") 10 + @procedure 11 + op main(input: { 12 + @required codeCount: integer = 1; 13 + @required useCount: integer; 14 + forAccounts?: did[]; 15 + }): { 16 + @required codes: AccountCodes[]; 17 + }; 18 + }
+36
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createSession.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.createSession { 4 + model AccountTakedown {} 5 + 6 + model AuthFactorTokenRequired {} 7 + 8 + @doc("Create an authentication session.") 9 + @procedure 10 + @errors(AccountTakedown, AuthFactorTokenRequired) 11 + op main(input: { 12 + @doc("Handle or other identifier supported by the server for the authenticating user.") 13 + @required 14 + identifier: string; 15 + 16 + @required password: string; 17 + 18 + authFactorToken?: string; 19 + 20 + @doc("When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned") 21 + allowTakendown?: boolean; 22 + }): { 23 + @required accessJwt: string; 24 + @required refreshJwt: string; 25 + @required handle: handle; 26 + @required did: did; 27 + didDoc?: unknown; 28 + email?: string; 29 + emailConfirmed?: boolean; 30 + emailAuthFactor?: boolean; 31 + active?: boolean; 32 + 33 + @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.") 34 + status?: "takendown" | "suspended" | "deactivated" | string; 35 + }; 36 + }
+10
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deactivateAccount.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.deactivateAccount { 4 + @doc("Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host.") 5 + @procedure 6 + op main(input: { 7 + @doc("A recommendation to server as to how long they should hold onto the deactivated account before deleting.") 8 + deleteAfter?: datetime; 9 + }): void; 10 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/defs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.defs { 4 + model InviteCode { 5 + @required code: string; 6 + @required available: integer; 7 + @required disabled: boolean; 8 + @required forAccount: string; 9 + @required createdBy: string; 10 + @required createdAt: datetime; 11 + @required uses: InviteCodeUse[]; 12 + } 13 + 14 + model InviteCodeUse { 15 + @required usedBy: did; 16 + @required usedAt: datetime; 17 + } 18 + }
+15
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deleteAccount.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.deleteAccount { 4 + model ExpiredToken {} 5 + model InvalidToken {} 6 + 7 + @doc("Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth.") 8 + @procedure 9 + @errors(ExpiredToken, InvalidToken) 10 + op main(input: { 11 + @required did: did; 12 + @required password: string; 13 + @required token: string; 14 + }): void; 15 + }
+7
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deleteSession.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.deleteSession { 4 + @doc("Delete the current session. Requires auth.") 5 + @procedure 6 + op main(): void; 7 + }
+34
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/describeServer.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.describeServer { 4 + @doc("Describes the server's account creation requirements and capabilities. Implemented by PDS.") 5 + @query 6 + op main(): { 7 + @required did: did; 8 + 9 + @doc("If true, an invite code must be supplied to create an account on this instance.") 10 + inviteCodeRequired?: boolean; 11 + 12 + @doc("If true, a phone verification token must be supplied to create an account on this instance.") 13 + phoneVerificationRequired?: boolean; 14 + 15 + @doc("List of domain suffixes that can be used in account handles.") 16 + @required 17 + availableUserDomains: string[]; 18 + 19 + @doc("URLs of service policy documents.") 20 + links?: Links; 21 + 22 + @doc("Contact information") 23 + contact?: Contact; 24 + }; 25 + 26 + model Links { 27 + privacyPolicy?: uri; 28 + termsOfService?: uri; 29 + } 30 + 31 + model Contact { 32 + email?: string; 33 + } 34 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getAccountInviteCodes.tsp
··· 1 + import "@tylex/emitter"; 2 + import "./defs.tsp"; 3 + 4 + namespace com.atproto.server.getAccountInviteCodes { 5 + model DuplicateCreate {} 6 + 7 + @doc("Get all invite codes for the current account. Requires auth.") 8 + @query 9 + @errors(DuplicateCreate) 10 + op main( 11 + includeUsed?: boolean = true, 12 + 13 + @doc("Controls whether any new 'earned' but not 'created' invites should be created.") 14 + createAvailable?: boolean = true 15 + ): { 16 + @required codes: com.atproto.server.defs.InviteCode[]; 17 + }; 18 + }
+23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getServiceAuth.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.getServiceAuth { 4 + @doc("Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes.") 5 + model BadExpiration {} 6 + 7 + @doc("Get a signed token on behalf of the requesting DID for the requested service.") 8 + @query 9 + @errors(BadExpiration) 10 + op main( 11 + @doc("The DID of the service that the token will be used to authenticate with") 12 + @required 13 + aud: did, 14 + 15 + @doc("The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope.") 16 + exp?: integer, 17 + 18 + @doc("Lexicon (XRPC) method to bind the requested token to") 19 + lxm?: nsid 20 + ): { 21 + @required token: string; 22 + }; 23 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getSession.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.getSession { 4 + @doc("Get information about the current auth session. Requires auth.") 5 + @query 6 + op main(): { 7 + @required handle: handle; 8 + @required did: did; 9 + email?: string; 10 + emailConfirmed?: boolean; 11 + emailAuthFactor?: boolean; 12 + didDoc?: unknown; 13 + active?: boolean; 14 + 15 + @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.") 16 + status?: "takendown" | "suspended" | "deactivated" | string; 17 + }; 18 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/listAppPasswords.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.listAppPasswords { 4 + model AccountTakedown {} 5 + 6 + model AppPassword { 7 + @required name: string; 8 + @required createdAt: datetime; 9 + privileged?: boolean; 10 + } 11 + 12 + @doc("List all App Passwords.") 13 + @query 14 + @errors(AccountTakedown) 15 + op main(): { 16 + @required passwords: AppPassword[]; 17 + }; 18 + }
+20
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/refreshSession.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.refreshSession { 4 + model AccountTakedown {} 5 + 6 + @doc("Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt').") 7 + @procedure 8 + @errors(AccountTakedown) 9 + op main(): { 10 + @required accessJwt: string; 11 + @required refreshJwt: string; 12 + @required handle: handle; 13 + @required did: did; 14 + didDoc?: unknown; 15 + active?: boolean; 16 + 17 + @doc("Hosting status of the account. If not specified, then assume 'active'.") 18 + status?: "takendown" | "suspended" | "deactivated" | string; 19 + }; 20 + }
+7
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestAccountDelete.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.requestAccountDelete { 4 + @doc("Initiate a user account deletion via email.") 5 + @procedure 6 + op main(): void; 7 + }
+7
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestEmailConfirmation.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.requestEmailConfirmation { 4 + @doc("Request an email with a code to confirm ownership of email.") 5 + @procedure 6 + op main(): void; 7 + }
+9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestEmailUpdate.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.requestEmailUpdate { 4 + @doc("Request a token in order to update email.") 5 + @procedure 6 + op main(): { 7 + @required tokenRequired: boolean; 8 + }; 9 + }
+9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestPasswordReset.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.requestPasswordReset { 4 + @doc("Initiate a user account password reset via email.") 5 + @procedure 6 + op main(input: { 7 + @required email: string; 8 + }): void; 9 + }
+14
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/reserveSigningKey.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.reserveSigningKey { 4 + @doc("Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented.") 5 + @procedure 6 + op main(input: { 7 + @doc("The DID to reserve a key for.") 8 + did?: did; 9 + }): { 10 + @doc("The public key for the reserved signing key, in did:key serialization.") 11 + @required 12 + signingKey: string; 13 + }; 14 + }
+14
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/resetPassword.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.resetPassword { 4 + model ExpiredToken {} 5 + model InvalidToken {} 6 + 7 + @doc("Reset a user account password using a token.") 8 + @procedure 9 + @errors(ExpiredToken, InvalidToken) 10 + op main(input: { 11 + @required token: string; 12 + @required password: string; 13 + }): void; 14 + }
+9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/revokeAppPassword.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.revokeAppPassword { 4 + @doc("Revoke an App Password by name.") 5 + @procedure 6 + op main(input: { 7 + @required name: string; 8 + }): void; 9 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/updateEmail.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.server.updateEmail { 4 + model ExpiredToken {} 5 + model InvalidToken {} 6 + model TokenRequired {} 7 + 8 + @doc("Update an account's email.") 9 + @procedure 10 + @errors(ExpiredToken, InvalidToken, TokenRequired) 11 + op main(input: { 12 + @required email: string; 13 + emailAuthFactor?: boolean; 14 + 15 + @doc("Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed.") 16 + token?: string; 17 + }): void; 18 + }
+12
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/defs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.defs { 4 + union HostStatus { 5 + "active", 6 + "idle", 7 + "offline", 8 + "throttled", 9 + "banned", 10 + string, 11 + } 12 + }
+23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getBlob.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getBlob { 4 + @doc("Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS.") 5 + @query 6 + @encoding("*/*") 7 + @errors(BlobNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated) 8 + op main( 9 + @doc("The DID of the account.") 10 + @required 11 + did: did, 12 + 13 + @doc("The CID of the blob to fetch") 14 + @required 15 + cid: cid 16 + ): void; 17 + 18 + model BlobNotFound {} 19 + model RepoNotFound {} 20 + model RepoTakendown {} 21 + model RepoSuspended {} 22 + model RepoDeactivated {} 23 + }
+21
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getBlocks.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getBlocks { 4 + @doc("Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS.") 5 + @query 6 + @encoding("application/vnd.ipld.car") 7 + @errors(BlockNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated) 8 + op main( 9 + @doc("The DID of the repo.") 10 + @required 11 + did: did, 12 + 13 + @required cids: cid[] 14 + ): void; 15 + 16 + model BlockNotFound {} 17 + model RepoNotFound {} 18 + model RepoTakendown {} 19 + model RepoSuspended {} 20 + model RepoDeactivated {} 21 + }
+12
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getCheckout.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getCheckout { 4 + @doc("DEPRECATED - please use com.atproto.sync.getRepo instead") 5 + @query 6 + @encoding("application/vnd.ipld.car") 7 + op main( 8 + @doc("The DID of the repo.") 9 + @required 10 + did: did 11 + ): void; 12 + }
+16
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getHead.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getHead { 4 + @doc("DEPRECATED - please use com.atproto.sync.getLatestCommit instead") 5 + @query 6 + @errors(HeadNotFound) 7 + op main( 8 + @doc("The DID of the repo.") 9 + @required 10 + did: did 11 + ): { 12 + @required root: cid; 13 + }; 14 + 15 + model HeadNotFound {} 16 + }
+25
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getHostStatus.tsp
··· 1 + import "@tylex/emitter"; 2 + import "./defs.tsp"; 3 + 4 + namespace com.atproto.sync.getHostStatus { 5 + @doc("Returns information about a specified upstream host, as consumed by the server. Implemented by relays.") 6 + @query 7 + @errors(HostNotFound) 8 + op main( 9 + @doc("Hostname of the host (eg, PDS or relay) being queried.") 10 + @required 11 + hostname: string 12 + ): { 13 + @required hostname: string; 14 + 15 + @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).") 16 + seq?: integer; 17 + 18 + @doc("Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts.") 19 + accountCount?: integer; 20 + 21 + status?: com.atproto.sync.defs.HostStatus; 22 + }; 23 + 24 + model HostNotFound {} 25 + }
+20
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getLatestCommit.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getLatestCommit { 4 + @doc("Get the current commit CID & revision of the specified repo. Does not require auth.") 5 + @query 6 + @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated) 7 + op main( 8 + @doc("The DID of the repo.") 9 + @required 10 + did: did 11 + ): { 12 + @required cid: cid; 13 + @required rev: tid; 14 + }; 15 + 16 + model RepoNotFound {} 17 + model RepoTakendown {} 18 + model RepoSuspended {} 19 + model RepoDeactivated {} 20 + }
+25
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRecord.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getRecord { 4 + @doc("Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth.") 5 + @query 6 + @encoding("application/vnd.ipld.car") 7 + @errors(RecordNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated) 8 + op main( 9 + @doc("The DID of the repo.") 10 + @required 11 + did: did, 12 + 13 + @required collection: nsid, 14 + 15 + @doc("Record Key") 16 + @required 17 + rkey: recordKey 18 + ): void; 19 + 20 + model RecordNotFound {} 21 + model RepoNotFound {} 22 + model RepoTakendown {} 23 + model RepoSuspended {} 24 + model RepoDeactivated {} 25 + }
+21
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRepo.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getRepo { 4 + @doc("Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.") 5 + @query 6 + @encoding("application/vnd.ipld.car") 7 + @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated) 8 + op main( 9 + @doc("The DID of the repo.") 10 + @required 11 + did: did, 12 + 13 + @doc("The revision ('rev') of the repo to create a diff from.") 14 + since?: tid 15 + ): void; 16 + 17 + model RepoNotFound {} 18 + model RepoTakendown {} 19 + model RepoSuspended {} 20 + model RepoDeactivated {} 21 + }
+23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRepoStatus.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.getRepoStatus { 4 + @doc("Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay.") 5 + @query 6 + @errors(RepoNotFound) 7 + op main( 8 + @doc("The DID of the repo.") 9 + @required 10 + did: did 11 + ): { 12 + @required did: did; 13 + @required active: boolean; 14 + 15 + @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.") 16 + status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string; 17 + 18 + @doc("Optional field, the current rev of the repo, if active=true") 19 + rev?: tid; 20 + }; 21 + 22 + model RepoNotFound {} 23 + }
+29
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listBlobs.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.listBlobs { 4 + @doc("List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS.") 5 + @query 6 + @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated) 7 + op main( 8 + @doc("The DID of the repo.") 9 + @required 10 + did: did, 11 + 12 + @doc("Optional revision of the repo to list blobs since.") 13 + since?: tid, 14 + 15 + @minValue(1) 16 + @maxValue(1000) 17 + limit?: int32 = 500, 18 + 19 + cursor?: string 20 + ): { 21 + cursor?: string; 22 + @required cids: cid[]; 23 + }; 24 + 25 + model RepoNotFound {} 26 + model RepoTakendown {} 27 + model RepoSuspended {} 28 + model RepoDeactivated {} 29 + }
+32
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listHosts.tsp
··· 1 + import "@tylex/emitter"; 2 + import "./defs.tsp"; 3 + 4 + namespace com.atproto.sync.listHosts { 5 + @doc("Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays.") 6 + @query 7 + op main( 8 + @minValue(1) 9 + @maxValue(1000) 10 + limit?: int32 = 200, 11 + 12 + cursor?: string 13 + ): { 14 + cursor?: string; 15 + 16 + @doc("Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first.") 17 + @required 18 + hosts: Host[]; 19 + }; 20 + 21 + model Host { 22 + @doc("hostname of server; not a URL (no scheme)") 23 + @required 24 + hostname: string; 25 + 26 + @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).") 27 + seq?: integer; 28 + 29 + accountCount?: integer; 30 + status?: com.atproto.sync.defs.HostStatus; 31 + } 32 + }
+30
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listRepos.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.listRepos { 4 + @doc("Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay.") 5 + @query 6 + op main( 7 + @minValue(1) 8 + @maxValue(1000) 9 + limit?: int32 = 500, 10 + 11 + cursor?: string 12 + ): { 13 + cursor?: string; 14 + @required repos: Repo[]; 15 + }; 16 + 17 + model Repo { 18 + @required did: did; 19 + 20 + @doc("Current repo commit CID") 21 + @required 22 + head: cid; 23 + 24 + @required rev: tid; 25 + active?: boolean; 26 + 27 + @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.") 28 + status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string; 29 + } 30 + }
+23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listReposByCollection.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.listReposByCollection { 4 + @doc("Enumerates all the DIDs which have records with the given collection NSID.") 5 + @query 6 + op main( 7 + @required collection: nsid, 8 + 9 + @doc("Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists.") 10 + @minValue(1) 11 + @maxValue(2000) 12 + limit?: int32 = 500, 13 + 14 + cursor?: string 15 + ): { 16 + cursor?: string; 17 + @required repos: Repo[]; 18 + }; 19 + 20 + model Repo { 21 + @required did: did; 22 + } 23 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/notifyOfUpdate.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.notifyOfUpdate { 4 + @doc("Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl") 5 + @procedure 6 + op main(input: { 7 + @doc("Hostname of the current service (usually a PDS) that is notifying of update.") 8 + @required 9 + hostname: string; 10 + }): void; 11 + }
+14
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/requestCrawl.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.requestCrawl { 4 + @doc("Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth.") 5 + @procedure 6 + @errors(HostBanned) 7 + op main(input: { 8 + @doc("Hostname of the current service (eg, PDS) that is requesting to be crawled.") 9 + @required 10 + hostname: string; 11 + }): void; 12 + 13 + model HostBanned {} 14 + }
+133
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/subscribeRepos.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.sync.subscribeRepos { 4 + @subscription 5 + @errors(FutureCursor, ConsumerTooSlow) 6 + @doc("Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay.") 7 + op main( 8 + @doc("The last known event seq number to backfill from.") 9 + cursor?: integer 10 + ): (Commit | Sync | Identity | Account | Info | unknown); 11 + 12 + model FutureCursor {} 13 + 14 + @doc("If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection.") 15 + model ConsumerTooSlow {} 16 + 17 + @doc("Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature.") 18 + model Commit { 19 + @doc("The stream sequence number of this message.") 20 + @required 21 + seq: integer; 22 + 23 + @doc("DEPRECATED -- unused") 24 + @required 25 + rebase: boolean; 26 + 27 + @doc("DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data.") 28 + @required 29 + tooBig: boolean; 30 + 31 + @doc("The repo this event comes from. Note that all other message types name this field 'did'.") 32 + @required 33 + repo: did; 34 + 35 + @doc("Repo commit object CID.") 36 + @required 37 + commit: cidLink; 38 + 39 + @doc("The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event.") 40 + @required 41 + rev: tid; 42 + 43 + @doc("The rev of the last emitted commit from this repo (if any).") 44 + @required 45 + since: tid | null; 46 + 47 + @doc("CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list.") 48 + @maxBytes(2000000) 49 + @required 50 + blocks: bytes; 51 + 52 + @maxItems(200) 53 + @required 54 + @doc("List of repo mutation operations in this commit (eg, records created, updated, or deleted).") 55 + ops: RepoOp[]; 56 + 57 + @doc("DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.") 58 + @required blobs: cidLink[]; 59 + 60 + @doc("The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose.") 61 + prevData?: cidLink; 62 + 63 + @doc("Timestamp of when this message was originally broadcast.") 64 + @required 65 + time: datetime; 66 + } 67 + 68 + @doc("Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository.") 69 + model Sync { 70 + @doc("The stream sequence number of this message.") 71 + @required 72 + seq: integer; 73 + 74 + @doc("The account this repo event corresponds to. Must match that in the commit object.") 75 + @required 76 + did: did; 77 + 78 + @doc("CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.") 79 + @maxBytes(10000) 80 + @required 81 + blocks: bytes; 82 + 83 + @doc("The rev of the commit. This value must match that in the commit object.") 84 + @required 85 + rev: string; 86 + 87 + @doc("Timestamp of when this message was originally broadcast.") 88 + @required 89 + time: datetime; 90 + } 91 + 92 + @doc("Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache.") 93 + model Identity { 94 + @required seq: integer; 95 + @required did: did; 96 + @required time: datetime; 97 + 98 + @doc("The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details.") 99 + handle?: handle; 100 + } 101 + 102 + @doc("Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active.") 103 + model Account { 104 + @required seq: integer; 105 + @required did: did; 106 + @required time: datetime; 107 + 108 + @doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.") 109 + @required 110 + active: boolean; 111 + 112 + @doc("If active=false, this optional field indicates a reason for why the account is not active.") 113 + status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string; 114 + } 115 + 116 + model Info { 117 + @required name: "OutdatedCursor" | string; 118 + message?: string; 119 + } 120 + 121 + @doc("A repo operation, ie a mutation of a single record.") 122 + model RepoOp { 123 + @required action: "create" | "update" | "delete" | string; 124 + @required path: string; 125 + 126 + @doc("For creates and updates, the new record CID. For deletions, null.") 127 + @required 128 + cid: cidLink | null; 129 + 130 + @doc("For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined.") 131 + prev?: cidLink; 132 + } 133 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/addReservedHandle.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.temp.addReservedHandle { 4 + @doc("Add a handle to the set of reserved handles.") 5 + @procedure 6 + op main( 7 + input: { 8 + @required handle: string; 9 + } 10 + ): {}; 11 + }
+44
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/checkHandleAvailability.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.temp.checkHandleAvailability { 4 + @doc("An invalid email was provided.") 5 + model InvalidEmail {} 6 + 7 + @doc("Indicates the provided handle is available.") 8 + model ResultAvailable {} 9 + 10 + @doc("Indicates the provided handle is unavailable and gives suggestions of available handles.") 11 + model ResultUnavailable { 12 + @doc("List of suggested handles based on the provided inputs.") 13 + @required 14 + suggestions: Suggestion[]; 15 + } 16 + 17 + model Suggestion { 18 + @required handle: handle; 19 + 20 + @doc("Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics.") 21 + @required 22 + method: string; 23 + } 24 + 25 + @doc("Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions.") 26 + @query 27 + @errors(InvalidEmail) 28 + op main( 29 + @doc("Tentative handle. Will be checked for availability or used to build handle suggestions.") 30 + handle: handle, 31 + 32 + @doc("User-provided email. Might be used to build handle suggestions.") 33 + email?: string, 34 + 35 + @doc("User-provided birth date. Might be used to build handle suggestions.") 36 + birthDate?: datetime 37 + ): { 38 + @doc("Echo of the input handle.") 39 + @required 40 + handle: handle; 41 + 42 + @required result: ResultAvailable | ResultUnavailable; 43 + }; 44 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/checkSignupQueue.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.temp.checkSignupQueue { 4 + @doc("Check accounts location in signup queue.") 5 + @query 6 + op main(): { 7 + @required activated: boolean; 8 + placeInQueue?: integer; 9 + estimatedTimeMs?: integer; 10 + }; 11 + }
+18
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/dereferenceScope.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.temp.dereferenceScope { 4 + @doc("An invalid scope reference was provided.") 5 + model InvalidScopeReference {} 6 + 7 + @doc("Allows finding the oauth permission scope from a reference") 8 + @query 9 + @errors(InvalidScopeReference) 10 + op main( 11 + @doc("The scope reference (starts with 'ref:')") 12 + scope: string 13 + ): { 14 + @doc("The full oauth permission scope") 15 + @required 16 + scope: string; 17 + }; 18 + }
+15
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/fetchLabels.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.temp.fetchLabels { 4 + @doc("DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date.") 5 + @query 6 + op main( 7 + since?: integer, 8 + 9 + @minValue(1) 10 + @maxValue(250) 11 + limit?: integer = 50 12 + ): { 13 + @required labels: com.atproto.label.defs.Label[]; 14 + }; 15 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/requestPhoneVerification.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.temp.requestPhoneVerification { 4 + @doc("Request a verification code to be sent to the supplied phone number") 5 + @procedure 6 + op main( 7 + input: { 8 + @required phoneNumber: string; 9 + } 10 + ): void; 11 + }
+11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/revokeAccountCredentials.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace com.atproto.temp.revokeAccountCredentials { 4 + @doc("Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset.") 5 + @procedure 6 + op main( 7 + input: { 8 + @required account: atIdentifier; 9 + } 10 + ): void; 11 + }
+8
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/blockquote.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.blockquote { 4 + model Main { 5 + @required plaintext: string; 6 + facets?: `pub`.leaflet.richtext.facet.Main[]; 7 + } 8 + }
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/bskyPost.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.bskyPost { 4 + model Main { 5 + @required postRef: com.atproto.repo.strongRef.Main; 6 + } 7 + }
+10
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/code.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.code { 4 + model Main { 5 + @required plaintext: string; 6 + 7 + language?: string; 8 + syntaxHighlightingTheme?: string; 9 + } 10 + }
+12
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/header.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.header { 4 + model Main { 5 + @minValue(1) 6 + @maxValue(6) 7 + level?: integer; 8 + 9 + @required plaintext: string; 10 + facets?: `pub`.leaflet.richtext.facet.Main[]; 11 + } 12 + }
+5
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/horizontalRule.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.horizontalRule { 4 + model Main {} 5 + }
+11
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/iframe.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.iframe { 4 + model Main { 5 + @required url: uri; 6 + 7 + @minValue(16) 8 + @maxValue(1600) 9 + height?: integer; 10 + } 11 + }
+17
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/image.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.image { 4 + model Main { 5 + @required image: Blob<#["image/*"], 1000000>; 6 + 7 + @doc("Alt text description of the image, for accessibility.") 8 + alt?: string; 9 + 10 + @required aspectRatio: AspectRatio; 11 + } 12 + 13 + model AspectRatio { 14 + @required width: integer; 15 + @required height: integer; 16 + } 17 + }
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/math.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.math { 4 + model Main { 5 + @required tex: string; 6 + } 7 + }
+8
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/text.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.text { 4 + model Main { 5 + @required plaintext: string; 6 + facets?: `pub`.leaflet.richtext.facet.Main[]; 7 + } 8 + }
+12
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/unorderedList.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.unorderedList { 4 + model Main { 5 + @required children: ListItem[]; 6 + } 7 + 8 + model ListItem { 9 + @required content: (`pub`.leaflet.blocks.text.Main | `pub`.leaflet.blocks.header.Main | `pub`.leaflet.blocks.image.Main | unknown); 10 + children?: ListItem[]; 11 + } 12 + }
+12
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/website.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.blocks.website { 4 + model Main { 5 + previewImage?: Blob<#["image/*"], 1000000>; 6 + 7 + title?: string; 8 + description?: string; 9 + 10 + @required src: uri; 11 + } 12 + }
+28
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/comment.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + @doc("A lexicon for comments on documents") 4 + namespace `pub`.leaflet.comment { 5 + @doc("Record containing a comment") 6 + @rec("tid") 7 + model Main { 8 + @required subject: atUri; 9 + @required createdAt: datetime; 10 + 11 + reply?: ReplyRef; 12 + 13 + @required plaintext: string; 14 + 15 + facets?: `pub`.leaflet.richtext.facet.Main[]; 16 + 17 + attachment?: (LinearDocumentQuote | unknown); 18 + } 19 + 20 + model LinearDocumentQuote { 21 + @required document: atUri; 22 + @required quote: `pub`.leaflet.pages.linearDocument.Quote; 23 + } 24 + 25 + model ReplyRef { 26 + @required parent: atUri; 27 + } 28 + }
+25
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/document.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + @doc("A lexicon for long form rich media documents") 4 + namespace `pub`.leaflet.document { 5 + @doc("Record containing a document") 6 + @rec("tid") 7 + model Main { 8 + @maxGraphemes(128) 9 + @maxLength(1280) 10 + @required 11 + title: string; 12 + 13 + postRef?: com.atproto.repo.strongRef.Main; 14 + 15 + @maxGraphemes(300) 16 + @maxLength(3000) 17 + description?: string; 18 + 19 + publishedAt?: datetime; 20 + 21 + @required publication: atUri; 22 + @required author: atIdentifier; 23 + @required pages: (`pub`.leaflet.pages.linearDocument.Main | unknown)[]; 24 + } 25 + }
+9
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/graph/subscription.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.graph.subscription { 4 + @doc("Record declaring a subscription to a publication") 5 + @rec("tid") 6 + model Main { 7 + @required publication: atUri; 8 + } 9 + }
+45
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/pages/linearDocument.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.pages.linearDocument { 4 + model Main { 5 + blocks?: Block[]; 6 + } 7 + 8 + model Block { 9 + @required block: ( 10 + | `pub`.leaflet.blocks.iframe.Main 11 + | `pub`.leaflet.blocks.text.Main 12 + | `pub`.leaflet.blocks.blockquote.Main 13 + | `pub`.leaflet.blocks.header.Main 14 + | `pub`.leaflet.blocks.image.Main 15 + | `pub`.leaflet.blocks.unorderedList.Main 16 + | `pub`.leaflet.blocks.website.Main 17 + | `pub`.leaflet.blocks.math.Main 18 + | `pub`.leaflet.blocks.code.Main 19 + | `pub`.leaflet.blocks.horizontalRule.Main 20 + | `pub`.leaflet.blocks.bskyPost.Main 21 + | unknown 22 + ); 23 + 24 + alignment?: "#textAlignLeft" | "#textAlignCenter" | "#textAlignRight" | "#textAlignJustify" | string; 25 + } 26 + 27 + @token 28 + model TextAlignLeft {} 29 + 30 + @token 31 + model TextAlignCenter {} 32 + 33 + @token 34 + model TextAlignRight {} 35 + 36 + model Quote { 37 + @required start: Position; 38 + @required end: Position; 39 + } 40 + 41 + model Position { 42 + @required block: integer[]; 43 + @required offset: integer; 44 + } 45 + }
+36
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/publication.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.publication { 4 + @doc("Record declaring a publication") 5 + @rec("tid") 6 + model Main { 7 + @maxLength(2000) 8 + @required 9 + name: string; 10 + 11 + base_path?: uri; 12 + 13 + @maxLength(2000) 14 + description?: string; 15 + 16 + icon?: Blob<#["image/*"], 1000000>; 17 + 18 + theme?: Theme; 19 + preferences?: Preferences; 20 + } 21 + 22 + model Preferences { 23 + showInDiscover?: boolean = true; 24 + showComments?: boolean = true; 25 + } 26 + 27 + model Theme { 28 + backgroundColor?: (`pub`.leaflet.theme.color.Rgba | `pub`.leaflet.theme.color.Rgb | unknown); 29 + backgroundImage?: `pub`.leaflet.theme.backgroundImage.Main; 30 + primary?: (`pub`.leaflet.theme.color.Rgba | `pub`.leaflet.theme.color.Rgb | unknown); 31 + pageBackground?: (`pub`.leaflet.theme.color.Rgba | `pub`.leaflet.theme.color.Rgb | unknown); 32 + showPageBackground?: boolean = false; 33 + accentBackground?: (`pub`.leaflet.theme.color.Rgba | `pub`.leaflet.theme.color.Rgb | unknown); 34 + accentText?: (`pub`.leaflet.theme.color.Rgba | `pub`.leaflet.theme.color.Rgb | unknown); 35 + } 36 + }
+48
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/richtext/facet.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.richtext.facet { 4 + @doc("Annotation of a sub-string within rich text.") 5 + model Main { 6 + @required index: ByteSlice; 7 + @required features: (Link | Code | Highlight | Underline | Strikethrough | Id | Bold | Italic | unknown)[]; 8 + } 9 + 10 + @doc("Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.") 11 + model ByteSlice { 12 + @minValue(0) 13 + @required 14 + byteStart: integer; 15 + 16 + @minValue(0) 17 + @required 18 + byteEnd: integer; 19 + } 20 + 21 + @doc("Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.") 22 + model Link { 23 + @required uri: uri; 24 + } 25 + 26 + @doc("Facet feature for inline code.") 27 + model Code {} 28 + 29 + @doc("Facet feature for highlighted text.") 30 + model Highlight {} 31 + 32 + @doc("Facet feature for underline markup") 33 + model Underline {} 34 + 35 + @doc("Facet feature for strikethrough markup") 36 + model Strikethrough {} 37 + 38 + @doc("Facet feature for an identifier. Used for linking to a segment") 39 + model Id { 40 + id?: string; 41 + } 42 + 43 + @doc("Facet feature for bold text") 44 + model Bold {} 45 + 46 + @doc("Facet feature for italic text") 47 + model Italic {} 48 + }
+10
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/theme/backgroundImage.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.theme.backgroundImage { 4 + model Main { 5 + @required image: Blob<#["image/*"], 1000000>; 6 + 7 + width?: integer; 8 + repeat?: boolean; 9 + } 10 + }
+45
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/theme/color.tsp
··· 1 + import "@tylex/emitter"; 2 + 3 + namespace `pub`.leaflet.theme.color { 4 + // Dummy Main to satisfy namespace requirements - actual defs are Rgba and Rgb 5 + model Main {} 6 + 7 + model Rgba { 8 + @minValue(0) 9 + @maxValue(255) 10 + @required 11 + r: integer; 12 + 13 + @minValue(0) 14 + @maxValue(255) 15 + @required 16 + g: integer; 17 + 18 + @minValue(0) 19 + @maxValue(255) 20 + @required 21 + b: integer; 22 + 23 + @minValue(0) 24 + @maxValue(100) 25 + @required 26 + a: integer; 27 + } 28 + 29 + model Rgb { 30 + @minValue(0) 31 + @maxValue(255) 32 + @required 33 + r: integer; 34 + 35 + @minValue(0) 36 + @maxValue(255) 37 + @required 38 + g: integer; 39 + 40 + @minValue(0) 41 + @maxValue(255) 42 + @required 43 + b: integer; 44 + } 45 + }
+71
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.defs", 4 + "defs": { 5 + "statusAttr": { 6 + "type": "object", 7 + "required": ["applied"], 8 + "properties": { 9 + "applied": { "type": "boolean" }, 10 + "ref": { "type": "string" } 11 + } 12 + }, 13 + "accountView": { 14 + "type": "object", 15 + "required": ["did", "handle", "indexedAt"], 16 + "properties": { 17 + "did": { "type": "string", "format": "did" }, 18 + "handle": { "type": "string", "format": "handle" }, 19 + "email": { "type": "string" }, 20 + "relatedRecords": { "type": "array", "items": { "type": "unknown" } }, 21 + "indexedAt": { "type": "string", "format": "datetime" }, 22 + "invitedBy": { 23 + "type": "ref", 24 + "ref": "com.atproto.server.defs#inviteCode" 25 + }, 26 + "invites": { 27 + "type": "array", 28 + "items": { 29 + "type": "ref", 30 + "ref": "com.atproto.server.defs#inviteCode" 31 + } 32 + }, 33 + "invitesDisabled": { "type": "boolean" }, 34 + "emailConfirmedAt": { "type": "string", "format": "datetime" }, 35 + "inviteNote": { "type": "string" }, 36 + "deactivatedAt": { "type": "string", "format": "datetime" }, 37 + "threatSignatures": { 38 + "type": "array", 39 + "items": { 40 + "type": "ref", 41 + "ref": "#threatSignature" 42 + } 43 + } 44 + } 45 + }, 46 + "repoRef": { 47 + "type": "object", 48 + "required": ["did"], 49 + "properties": { 50 + "did": { "type": "string", "format": "did" } 51 + } 52 + }, 53 + "repoBlobRef": { 54 + "type": "object", 55 + "required": ["did", "cid"], 56 + "properties": { 57 + "did": { "type": "string", "format": "did" }, 58 + "cid": { "type": "string", "format": "cid" }, 59 + "recordUri": { "type": "string", "format": "at-uri" } 60 + } 61 + }, 62 + "threatSignature": { 63 + "type": "object", 64 + "required": ["property", "value"], 65 + "properties": { 66 + "property": { "type": "string" }, 67 + "value": { "type": "string" } 68 + } 69 + } 70 + } 71 + }
+20
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/deleteAccount.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.deleteAccount", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Delete a user account as an administrator.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["did"], 13 + "properties": { 14 + "did": { "type": "string", "format": "did" } 15 + } 16 + } 17 + } 18 + } 19 + } 20 + }
+24
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/disableAccountInvites.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.disableAccountInvites", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Disable an account from receiving new invite codes, but does not invalidate existing codes.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["account"], 13 + "properties": { 14 + "account": { "type": "string", "format": "did" }, 15 + "note": { 16 + "type": "string", 17 + "description": "Optional reason for disabled invites." 18 + } 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
+26
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/disableInviteCodes.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.disableInviteCodes", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Disable some set of codes and/or all codes associated with a set of users.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "properties": { 13 + "codes": { 14 + "type": "array", 15 + "items": { "type": "string" } 16 + }, 17 + "accounts": { 18 + "type": "array", 19 + "items": { "type": "string" } 20 + } 21 + } 22 + } 23 + } 24 + } 25 + } 26 + }
+24
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/enableAccountInvites.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.enableAccountInvites", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Re-enable an account's ability to receive invite codes.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["account"], 13 + "properties": { 14 + "account": { "type": "string", "format": "did" }, 15 + "note": { 16 + "type": "string", 17 + "description": "Optional reason for enabled invites." 18 + } 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
+24
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/getAccountInfo.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.getAccountInfo", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get details about an account.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { "type": "string", "format": "did" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "ref", 19 + "ref": "com.atproto.admin.defs#accountView" 20 + } 21 + } 22 + } 23 + } 24 + }
+36
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/getAccountInfos.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.getAccountInfos", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get details about some accounts.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["dids"], 11 + "properties": { 12 + "dids": { 13 + "type": "array", 14 + "items": { "type": "string", "format": "did" } 15 + } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "required": ["infos"], 23 + "properties": { 24 + "infos": { 25 + "type": "array", 26 + "items": { 27 + "type": "ref", 28 + "ref": "com.atproto.admin.defs#accountView" 29 + } 30 + } 31 + } 32 + } 33 + } 34 + } 35 + } 36 + }
+44
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/getInviteCodes.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.getInviteCodes", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get an admin view of invite codes.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "sort": { 12 + "type": "string", 13 + "knownValues": ["recent", "usage"], 14 + "default": "recent" 15 + }, 16 + "limit": { 17 + "type": "integer", 18 + "minimum": 1, 19 + "maximum": 500, 20 + "default": 100 21 + }, 22 + "cursor": { "type": "string" } 23 + } 24 + }, 25 + "output": { 26 + "encoding": "application/json", 27 + "schema": { 28 + "type": "object", 29 + "required": ["codes"], 30 + "properties": { 31 + "cursor": { "type": "string" }, 32 + "codes": { 33 + "type": "array", 34 + "items": { 35 + "type": "ref", 36 + "ref": "com.atproto.server.defs#inviteCode" 37 + } 38 + } 39 + } 40 + } 41 + } 42 + } 43 + } 44 + }
+43
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/getSubjectStatus.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.getSubjectStatus", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get the service-specific admin status of a subject (account, record, or blob).", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "did": { "type": "string", "format": "did" }, 12 + "uri": { "type": "string", "format": "at-uri" }, 13 + "blob": { "type": "string", "format": "cid" } 14 + } 15 + }, 16 + "output": { 17 + "encoding": "application/json", 18 + "schema": { 19 + "type": "object", 20 + "required": ["subject"], 21 + "properties": { 22 + "subject": { 23 + "type": "union", 24 + "refs": [ 25 + "com.atproto.admin.defs#repoRef", 26 + "com.atproto.repo.strongRef", 27 + "com.atproto.admin.defs#repoBlobRef" 28 + ] 29 + }, 30 + "takedown": { 31 + "type": "ref", 32 + "ref": "com.atproto.admin.defs#statusAttr" 33 + }, 34 + "deactivated": { 35 + "type": "ref", 36 + "ref": "com.atproto.admin.defs#statusAttr" 37 + } 38 + } 39 + } 40 + } 41 + } 42 + } 43 + }
+40
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/searchAccounts.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.searchAccounts", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get list of accounts that matches your search query.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "email": { "type": "string" }, 12 + "cursor": { "type": "string" }, 13 + "limit": { 14 + "type": "integer", 15 + "minimum": 1, 16 + "maximum": 100, 17 + "default": 50 18 + } 19 + } 20 + }, 21 + "output": { 22 + "encoding": "application/json", 23 + "schema": { 24 + "type": "object", 25 + "required": ["accounts"], 26 + "properties": { 27 + "cursor": { "type": "string" }, 28 + "accounts": { 29 + "type": "array", 30 + "items": { 31 + "type": "ref", 32 + "ref": "com.atproto.admin.defs#accountView" 33 + } 34 + } 35 + } 36 + } 37 + } 38 + } 39 + } 40 + }
+37
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/sendEmail.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.sendEmail", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Send email to a user's account email address.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["recipientDid", "content", "senderDid"], 13 + "properties": { 14 + "recipientDid": { "type": "string", "format": "did" }, 15 + "content": { "type": "string" }, 16 + "subject": { "type": "string" }, 17 + "senderDid": { "type": "string", "format": "did" }, 18 + "comment": { 19 + "type": "string", 20 + "description": "Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers" 21 + } 22 + } 23 + } 24 + }, 25 + "output": { 26 + "encoding": "application/json", 27 + "schema": { 28 + "type": "object", 29 + "required": ["sent"], 30 + "properties": { 31 + "sent": { "type": "boolean" } 32 + } 33 + } 34 + } 35 + } 36 + } 37 + }
+25
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/updateAccountEmail.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.updateAccountEmail", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Administrative action to update an account's email.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["account", "email"], 13 + "properties": { 14 + "account": { 15 + "type": "string", 16 + "format": "at-identifier", 17 + "description": "The handle or DID of the repo." 18 + }, 19 + "email": { "type": "string" } 20 + } 21 + } 22 + } 23 + } 24 + } 25 + }
+21
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/updateAccountHandle.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.updateAccountHandle", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Administrative action to update an account's handle.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["did", "handle"], 13 + "properties": { 14 + "did": { "type": "string", "format": "did" }, 15 + "handle": { "type": "string", "format": "handle" } 16 + } 17 + } 18 + } 19 + } 20 + } 21 + }
+21
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/updateAccountPassword.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.updateAccountPassword", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Update the password for a user account as an administrator.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["did", "password"], 13 + "properties": { 14 + "did": { "type": "string", "format": "did" }, 15 + "password": { "type": "string" } 16 + } 17 + } 18 + } 19 + } 20 + } 21 + }
+25
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/updateAccountSigningKey.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.updateAccountSigningKey", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Administrative action to update an account's signing key in their Did document.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["did", "signingKey"], 13 + "properties": { 14 + "did": { "type": "string", "format": "did" }, 15 + "signingKey": { 16 + "type": "string", 17 + "format": "did", 18 + "description": "Did-key formatted public key" 19 + } 20 + } 21 + } 22 + } 23 + } 24 + } 25 + }
+56
packages/emitter/test/integration/lexicon-examples/output/com/atproto/admin/updateSubjectStatus.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.admin.updateSubjectStatus", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Update the service-specific admin status of a subject (account, record, or blob).", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["subject"], 13 + "properties": { 14 + "subject": { 15 + "type": "union", 16 + "refs": [ 17 + "com.atproto.admin.defs#repoRef", 18 + "com.atproto.repo.strongRef", 19 + "com.atproto.admin.defs#repoBlobRef" 20 + ] 21 + }, 22 + "takedown": { 23 + "type": "ref", 24 + "ref": "com.atproto.admin.defs#statusAttr" 25 + }, 26 + "deactivated": { 27 + "type": "ref", 28 + "ref": "com.atproto.admin.defs#statusAttr" 29 + } 30 + } 31 + } 32 + }, 33 + "output": { 34 + "encoding": "application/json", 35 + "schema": { 36 + "type": "object", 37 + "required": ["subject"], 38 + "properties": { 39 + "subject": { 40 + "type": "union", 41 + "refs": [ 42 + "com.atproto.admin.defs#repoRef", 43 + "com.atproto.repo.strongRef", 44 + "com.atproto.admin.defs#repoBlobRef" 45 + ] 46 + }, 47 + "takedown": { 48 + "type": "ref", 49 + "ref": "com.atproto.admin.defs#statusAttr" 50 + } 51 + } 52 + } 53 + } 54 + } 55 + } 56 + }
+22
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.defs", 4 + "defs": { 5 + "identityInfo": { 6 + "type": "object", 7 + "required": ["did", "handle", "didDoc"], 8 + "properties": { 9 + "did": { "type": "string", "format": "did" }, 10 + "handle": { 11 + "type": "string", 12 + "format": "handle", 13 + "description": "The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document." 14 + }, 15 + "didDoc": { 16 + "type": "unknown", 17 + "description": "The complete DID document for the identity." 18 + } 19 + } 20 + } 21 + } 22 + }
+29
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/getRecommendedDidCredentials.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.getRecommendedDidCredentials", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Describe the credentials that should be included in the DID doc of an account that is migrating to this service.", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "properties": { 13 + "rotationKeys": { 14 + "description": "Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.", 15 + "type": "array", 16 + "items": { "type": "string" } 17 + }, 18 + "alsoKnownAs": { 19 + "type": "array", 20 + "items": { "type": "string" } 21 + }, 22 + "verificationMethods": { "type": "unknown" }, 23 + "services": { "type": "unknown" } 24 + } 25 + } 26 + } 27 + } 28 + } 29 + }
+44
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/refreshIdentity.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.refreshIdentity", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["identifier"], 13 + "properties": { 14 + "identifier": { 15 + "type": "string", 16 + "format": "at-identifier" 17 + } 18 + } 19 + } 20 + }, 21 + "output": { 22 + "encoding": "application/json", 23 + "schema": { 24 + "type": "ref", 25 + "ref": "com.atproto.identity.defs#identityInfo" 26 + } 27 + }, 28 + "errors": [ 29 + { 30 + "name": "HandleNotFound", 31 + "description": "The resolution process confirmed that the handle does not resolve to any DID." 32 + }, 33 + { 34 + "name": "DidNotFound", 35 + "description": "The DID resolution process confirmed that there is no current DID." 36 + }, 37 + { 38 + "name": "DidDeactivated", 39 + "description": "The DID previously existed, but has been deactivated." 40 + } 41 + ] 42 + } 43 + } 44 + }
+10
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/requestPlcOperationSignature.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.requestPlcOperationSignature", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Request an email with a code to in order to request a signed PLC operation. Requires Auth." 8 + } 9 + } 10 + }
+44
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/resolveDid.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.resolveDid", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Resolves DID to DID document. Does not bi-directionally verify handle.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "DID to resolve." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": ["didDoc"], 24 + "properties": { 25 + "didDoc": { 26 + "type": "unknown", 27 + "description": "The complete DID document for the identity." 28 + } 29 + } 30 + } 31 + }, 32 + "errors": [ 33 + { 34 + "name": "DidNotFound", 35 + "description": "The DID resolution process confirmed that there is no current DID." 36 + }, 37 + { 38 + "name": "DidDeactivated", 39 + "description": "The DID previously existed, but has been deactivated." 40 + } 41 + ] 42 + } 43 + } 44 + }
+37
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/resolveHandle.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.resolveHandle", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["handle"], 11 + "properties": { 12 + "handle": { 13 + "type": "string", 14 + "format": "handle", 15 + "description": "The handle to resolve." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": ["did"], 24 + "properties": { 25 + "did": { "type": "string", "format": "did" } 26 + } 27 + } 28 + }, 29 + "errors": [ 30 + { 31 + "name": "HandleNotFound", 32 + "description": "The resolution process confirmed that the handle does not resolve to any DID." 33 + } 34 + ] 35 + } 36 + } 37 + }
+42
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/resolveIdentity.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.resolveIdentity", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Resolves an identity (DID or Handle) to a full identity (DID document and verified handle).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["identifier"], 11 + "properties": { 12 + "identifier": { 13 + "type": "string", 14 + "format": "at-identifier", 15 + "description": "Handle or DID to resolve." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "ref", 23 + "ref": "com.atproto.identity.defs#identityInfo" 24 + } 25 + }, 26 + "errors": [ 27 + { 28 + "name": "HandleNotFound", 29 + "description": "The resolution process confirmed that the handle does not resolve to any DID." 30 + }, 31 + { 32 + "name": "DidNotFound", 33 + "description": "The DID resolution process confirmed that there is no current DID." 34 + }, 35 + { 36 + "name": "DidDeactivated", 37 + "description": "The DID previously existed, but has been deactivated." 38 + } 39 + ] 40 + } 41 + } 42 + }
+45
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/signPlcOperation.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.signPlcOperation", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Signs a PLC operation to update some value(s) in the requesting DID's document.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "properties": { 13 + "token": { 14 + "description": "A token received through com.atproto.identity.requestPlcOperationSignature", 15 + "type": "string" 16 + }, 17 + "rotationKeys": { 18 + "type": "array", 19 + "items": { "type": "string" } 20 + }, 21 + "alsoKnownAs": { 22 + "type": "array", 23 + "items": { "type": "string" } 24 + }, 25 + "verificationMethods": { "type": "unknown" }, 26 + "services": { "type": "unknown" } 27 + } 28 + } 29 + }, 30 + "output": { 31 + "encoding": "application/json", 32 + "schema": { 33 + "type": "object", 34 + "required": ["operation"], 35 + "properties": { 36 + "operation": { 37 + "type": "unknown", 38 + "description": "A signed DID PLC operation." 39 + } 40 + } 41 + } 42 + } 43 + } 44 + } 45 + }
+20
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/submitPlcOperation.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.submitPlcOperation", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["operation"], 13 + "properties": { 14 + "operation": { "type": "unknown" } 15 + } 16 + } 17 + } 18 + } 19 + } 20 + }
+24
packages/emitter/test/integration/lexicon-examples/output/com/atproto/identity/updateHandle.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.identity.updateHandle", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["handle"], 13 + "properties": { 14 + "handle": { 15 + "type": "string", 16 + "format": "handle", 17 + "description": "The new handle." 18 + } 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
+156
packages/emitter/test/integration/lexicon-examples/output/com/atproto/label/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.label.defs", 4 + "defs": { 5 + "label": { 6 + "type": "object", 7 + "description": "Metadata tag on an atproto resource (eg, repo or record).", 8 + "required": ["src", "uri", "val", "cts"], 9 + "properties": { 10 + "ver": { 11 + "type": "integer", 12 + "description": "The AT Protocol version of the label object." 13 + }, 14 + "src": { 15 + "type": "string", 16 + "format": "did", 17 + "description": "DID of the actor who created this label." 18 + }, 19 + "uri": { 20 + "type": "string", 21 + "format": "uri", 22 + "description": "AT URI of the record, repository (account), or other resource that this label applies to." 23 + }, 24 + "cid": { 25 + "type": "string", 26 + "format": "cid", 27 + "description": "Optionally, CID specifying the specific version of 'uri' resource this label applies to." 28 + }, 29 + "val": { 30 + "type": "string", 31 + "maxLength": 128, 32 + "description": "The short string name of the value or type of this label." 33 + }, 34 + "neg": { 35 + "type": "boolean", 36 + "description": "If true, this is a negation label, overwriting a previous label." 37 + }, 38 + "cts": { 39 + "type": "string", 40 + "format": "datetime", 41 + "description": "Timestamp when this label was created." 42 + }, 43 + "exp": { 44 + "type": "string", 45 + "format": "datetime", 46 + "description": "Timestamp at which this label expires (no longer applies)." 47 + }, 48 + "sig": { 49 + "type": "bytes", 50 + "description": "Signature of dag-cbor encoded label." 51 + } 52 + } 53 + }, 54 + "selfLabels": { 55 + "type": "object", 56 + "description": "Metadata tags on an atproto record, published by the author within the record.", 57 + "required": ["values"], 58 + "properties": { 59 + "values": { 60 + "type": "array", 61 + "items": { "type": "ref", "ref": "#selfLabel" }, 62 + "maxLength": 10 63 + } 64 + } 65 + }, 66 + "selfLabel": { 67 + "type": "object", 68 + "description": "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.", 69 + "required": ["val"], 70 + "properties": { 71 + "val": { 72 + "type": "string", 73 + "maxLength": 128, 74 + "description": "The short string name of the value or type of this label." 75 + } 76 + } 77 + }, 78 + "labelValueDefinition": { 79 + "type": "object", 80 + "description": "Declares a label value and its expected interpretations and behaviors.", 81 + "required": ["identifier", "severity", "blurs", "locales"], 82 + "properties": { 83 + "identifier": { 84 + "type": "string", 85 + "description": "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).", 86 + "maxLength": 100, 87 + "maxGraphemes": 100 88 + }, 89 + "severity": { 90 + "type": "string", 91 + "description": "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.", 92 + "knownValues": ["inform", "alert", "none"] 93 + }, 94 + "blurs": { 95 + "type": "string", 96 + "description": "What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.", 97 + "knownValues": ["content", "media", "none"] 98 + }, 99 + "defaultSetting": { 100 + "type": "string", 101 + "description": "The default setting for this label.", 102 + "knownValues": ["ignore", "warn", "hide"], 103 + "default": "warn" 104 + }, 105 + "adultOnly": { 106 + "type": "boolean", 107 + "description": "Does the user need to have adult content enabled in order to configure this label?" 108 + }, 109 + "locales": { 110 + "type": "array", 111 + "items": { "type": "ref", "ref": "#labelValueDefinitionStrings" } 112 + } 113 + } 114 + }, 115 + "labelValueDefinitionStrings": { 116 + "type": "object", 117 + "description": "Strings which describe the label in the UI, localized into a specific language.", 118 + "required": ["lang", "name", "description"], 119 + "properties": { 120 + "lang": { 121 + "type": "string", 122 + "description": "The code of the language these strings are written in.", 123 + "format": "language" 124 + }, 125 + "name": { 126 + "type": "string", 127 + "description": "A short human-readable name for the label.", 128 + "maxGraphemes": 64, 129 + "maxLength": 640 130 + }, 131 + "description": { 132 + "type": "string", 133 + "description": "A longer description of what the label means and why it might be applied.", 134 + "maxGraphemes": 10000, 135 + "maxLength": 100000 136 + } 137 + } 138 + }, 139 + "labelValue": { 140 + "type": "string", 141 + "knownValues": [ 142 + "!hide", 143 + "!no-promote", 144 + "!warn", 145 + "!no-unauthenticated", 146 + "dmca-violation", 147 + "doxxing", 148 + "porn", 149 + "sexual", 150 + "nudity", 151 + "nsfl", 152 + "gore" 153 + ] 154 + } 155 + } 156 + }
+47
packages/emitter/test/integration/lexicon-examples/output/com/atproto/label/queryLabels.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.label.queryLabels", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["uriPatterns"], 11 + "properties": { 12 + "uriPatterns": { 13 + "type": "array", 14 + "items": { "type": "string" }, 15 + "description": "List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI." 16 + }, 17 + "sources": { 18 + "type": "array", 19 + "items": { "type": "string", "format": "did" }, 20 + "description": "Optional list of label sources (DIDs) to filter on." 21 + }, 22 + "limit": { 23 + "type": "integer", 24 + "minimum": 1, 25 + "maximum": 250, 26 + "default": 50 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + }, 31 + "output": { 32 + "encoding": "application/json", 33 + "schema": { 34 + "type": "object", 35 + "required": ["labels"], 36 + "properties": { 37 + "cursor": { "type": "string" }, 38 + "labels": { 39 + "type": "array", 40 + "items": { "type": "ref", "ref": "com.atproto.label.defs#label" } 41 + } 42 + } 43 + } 44 + } 45 + } 46 + } 47 + }
+50
packages/emitter/test/integration/lexicon-examples/output/com/atproto/label/subscribeLabels.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.label.subscribeLabels", 4 + "defs": { 5 + "main": { 6 + "type": "subscription", 7 + "description": "Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "cursor": { 12 + "type": "integer", 13 + "description": "The last known event seq number to backfill from." 14 + } 15 + } 16 + }, 17 + "message": { 18 + "schema": { 19 + "type": "union", 20 + "refs": ["#labels", "#info"] 21 + } 22 + }, 23 + "errors": [{ "name": "FutureCursor" }] 24 + }, 25 + "labels": { 26 + "type": "object", 27 + "required": ["seq", "labels"], 28 + "properties": { 29 + "seq": { "type": "integer" }, 30 + "labels": { 31 + "type": "array", 32 + "items": { "type": "ref", "ref": "com.atproto.label.defs#label" } 33 + } 34 + } 35 + }, 36 + "info": { 37 + "type": "object", 38 + "required": ["name"], 39 + "properties": { 40 + "name": { 41 + "type": "string", 42 + "knownValues": ["OutdatedCursor"] 43 + }, 44 + "message": { 45 + "type": "string" 46 + } 47 + } 48 + } 49 + } 50 + }
+21
packages/emitter/test/integration/lexicon-examples/output/com/atproto/lexicon/schema.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.lexicon.schema", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "description": "Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc).", 8 + "key": "nsid", 9 + "record": { 10 + "type": "object", 11 + "required": ["lexicon"], 12 + "properties": { 13 + "lexicon": { 14 + "type": "integer", 15 + "description": "Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system." 16 + } 17 + } 18 + } 19 + } 20 + } 21 + }
+90
packages/emitter/test/integration/lexicon-examples/output/com/atproto/moderation/createReport.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.moderation.createReport", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["reasonType", "subject"], 13 + "properties": { 14 + "reasonType": { 15 + "type": "ref", 16 + "description": "Indicates the broad category of violation the report is for.", 17 + "ref": "com.atproto.moderation.defs#reasonType" 18 + }, 19 + "reason": { 20 + "type": "string", 21 + "maxGraphemes": 2000, 22 + "maxLength": 20000, 23 + "description": "Additional context about the content and violation." 24 + }, 25 + "subject": { 26 + "type": "union", 27 + "refs": [ 28 + "com.atproto.admin.defs#repoRef", 29 + "com.atproto.repo.strongRef" 30 + ] 31 + }, 32 + "modTool": { 33 + "type": "ref", 34 + "ref": "#modTool" 35 + } 36 + } 37 + } 38 + }, 39 + "output": { 40 + "encoding": "application/json", 41 + "schema": { 42 + "type": "object", 43 + "required": [ 44 + "id", 45 + "reasonType", 46 + "subject", 47 + "reportedBy", 48 + "createdAt" 49 + ], 50 + "properties": { 51 + "id": { "type": "integer" }, 52 + "reasonType": { 53 + "type": "ref", 54 + "ref": "com.atproto.moderation.defs#reasonType" 55 + }, 56 + "reason": { 57 + "type": "string", 58 + "maxGraphemes": 2000, 59 + "maxLength": 20000 60 + }, 61 + "subject": { 62 + "type": "union", 63 + "refs": [ 64 + "com.atproto.admin.defs#repoRef", 65 + "com.atproto.repo.strongRef" 66 + ] 67 + }, 68 + "reportedBy": { "type": "string", "format": "did" }, 69 + "createdAt": { "type": "string", "format": "datetime" } 70 + } 71 + } 72 + } 73 + }, 74 + "modTool": { 75 + "type": "object", 76 + "description": "Moderation tool information for tracing the source of the action", 77 + "required": ["name"], 78 + "properties": { 79 + "name": { 80 + "type": "string", 81 + "description": "Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome')" 82 + }, 83 + "meta": { 84 + "type": "unknown", 85 + "description": "Additional arbitrary metadata about the source" 86 + } 87 + } 88 + } 89 + } 90 + }
+104
packages/emitter/test/integration/lexicon-examples/output/com/atproto/moderation/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.moderation.defs", 4 + "defs": { 5 + "reasonType": { 6 + "type": "string", 7 + "knownValues": [ 8 + "com.atproto.moderation.defs#reasonSpam", 9 + "com.atproto.moderation.defs#reasonViolation", 10 + "com.atproto.moderation.defs#reasonMisleading", 11 + "com.atproto.moderation.defs#reasonSexual", 12 + "com.atproto.moderation.defs#reasonRude", 13 + "com.atproto.moderation.defs#reasonOther", 14 + "com.atproto.moderation.defs#reasonAppeal", 15 + 16 + "tools.ozone.report.defs#reasonAppeal", 17 + 18 + "tools.ozone.report.defs#reasonViolenceAnimalWelfare", 19 + "tools.ozone.report.defs#reasonViolenceThreats", 20 + "tools.ozone.report.defs#reasonViolenceGraphicContent", 21 + "tools.ozone.report.defs#reasonViolenceSelfHarm", 22 + "tools.ozone.report.defs#reasonViolenceGlorification", 23 + "tools.ozone.report.defs#reasonViolenceExtremistContent", 24 + "tools.ozone.report.defs#reasonViolenceTrafficking", 25 + "tools.ozone.report.defs#reasonViolenceOther", 26 + 27 + "tools.ozone.report.defs#reasonSexualAbuseContent", 28 + "tools.ozone.report.defs#reasonSexualNCII", 29 + "tools.ozone.report.defs#reasonSexualSextortion", 30 + "tools.ozone.report.defs#reasonSexualDeepfake", 31 + "tools.ozone.report.defs#reasonSexualAnimal", 32 + "tools.ozone.report.defs#reasonSexualUnlabeled", 33 + "tools.ozone.report.defs#reasonSexualOther", 34 + 35 + "tools.ozone.report.defs#reasonChildSafetyCSAM", 36 + "tools.ozone.report.defs#reasonChildSafetyGroom", 37 + "tools.ozone.report.defs#reasonChildSafetyMinorPrivacy", 38 + "tools.ozone.report.defs#reasonChildSafetyEndangerment", 39 + "tools.ozone.report.defs#reasonChildSafetyHarassment", 40 + "tools.ozone.report.defs#reasonChildSafetyPromotion", 41 + "tools.ozone.report.defs#reasonChildSafetyOther", 42 + 43 + "tools.ozone.report.defs#reasonHarassmentTroll", 44 + "tools.ozone.report.defs#reasonHarassmentTargeted", 45 + "tools.ozone.report.defs#reasonHarassmentHateSpeech", 46 + "tools.ozone.report.defs#reasonHarassmentDoxxing", 47 + "tools.ozone.report.defs#reasonHarassmentOther", 48 + 49 + "tools.ozone.report.defs#reasonMisleadingBot", 50 + "tools.ozone.report.defs#reasonMisleadingImpersonation", 51 + "tools.ozone.report.defs#reasonMisleadingSpam", 52 + "tools.ozone.report.defs#reasonMisleadingScam", 53 + "tools.ozone.report.defs#reasonMisleadingSyntheticContent", 54 + "tools.ozone.report.defs#reasonMisleadingMisinformation", 55 + "tools.ozone.report.defs#reasonMisleadingOther", 56 + 57 + "tools.ozone.report.defs#reasonRuleSiteSecurity", 58 + "tools.ozone.report.defs#reasonRuleStolenContent", 59 + "tools.ozone.report.defs#reasonRuleProhibitedSales", 60 + "tools.ozone.report.defs#reasonRuleBanEvasion", 61 + "tools.ozone.report.defs#reasonRuleOther", 62 + 63 + "tools.ozone.report.defs#reasonCivicElectoralProcess", 64 + "tools.ozone.report.defs#reasonCivicDisclosure", 65 + "tools.ozone.report.defs#reasonCivicInterference", 66 + "tools.ozone.report.defs#reasonCivicMisinformation", 67 + "tools.ozone.report.defs#reasonCivicImpersonation" 68 + ] 69 + }, 70 + "reasonSpam": { 71 + "type": "token", 72 + "description": "Spam: frequent unwanted promotion, replies, mentions. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingSpam`." 73 + }, 74 + "reasonViolation": { 75 + "type": "token", 76 + "description": "Direct violation of server rules, laws, terms of service. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`." 77 + }, 78 + "reasonMisleading": { 79 + "type": "token", 80 + "description": "Misleading identity, affiliation, or content. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingOther`." 81 + }, 82 + "reasonSexual": { 83 + "type": "token", 84 + "description": "Unwanted or mislabeled sexual content. Prefer new lexicon definition `tools.ozone.report.defs#reasonSexualUnlabeled`." 85 + }, 86 + "reasonRude": { 87 + "type": "token", 88 + "description": "Rude, harassing, explicit, or otherwise unwelcoming behavior. Prefer new lexicon definition `tools.ozone.report.defs#reasonHarassmentOther`." 89 + }, 90 + "reasonOther": { 91 + "type": "token", 92 + "description": "Reports not falling under another report category. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`." 93 + }, 94 + "reasonAppeal": { 95 + "type": "token", 96 + "description": "Appeal a previously taken moderation action" 97 + }, 98 + "subjectType": { 99 + "type": "string", 100 + "description": "Tag describing a type of subject that might be reported.", 101 + "knownValues": ["account", "record", "chat"] 102 + } 103 + } 104 + }
+129
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/applyWrites.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.applyWrites", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["repo", "writes"], 13 + "properties": { 14 + "repo": { 15 + "type": "string", 16 + "format": "at-identifier", 17 + "description": "The handle or DID of the repo (aka, current account)." 18 + }, 19 + "validate": { 20 + "type": "boolean", 21 + "description": "Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons." 22 + }, 23 + "writes": { 24 + "type": "array", 25 + "items": { 26 + "type": "union", 27 + "refs": ["#create", "#update", "#delete"], 28 + "closed": true 29 + } 30 + }, 31 + "swapCommit": { 32 + "type": "string", 33 + "description": "If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.", 34 + "format": "cid" 35 + } 36 + } 37 + } 38 + }, 39 + "output": { 40 + "encoding": "application/json", 41 + "schema": { 42 + "type": "object", 43 + "properties": { 44 + "commit": { 45 + "type": "ref", 46 + "ref": "com.atproto.repo.defs#commitMeta" 47 + }, 48 + "results": { 49 + "type": "array", 50 + "items": { 51 + "type": "union", 52 + "refs": ["#createResult", "#updateResult", "#deleteResult"], 53 + "closed": true 54 + } 55 + } 56 + } 57 + } 58 + }, 59 + "errors": [ 60 + { 61 + "name": "InvalidSwap", 62 + "description": "Indicates that the 'swapCommit' parameter did not match current commit." 63 + } 64 + ] 65 + }, 66 + "create": { 67 + "type": "object", 68 + "description": "Operation which creates a new record.", 69 + "required": ["collection", "value"], 70 + "properties": { 71 + "collection": { "type": "string", "format": "nsid" }, 72 + "rkey": { 73 + "type": "string", 74 + "maxLength": 512, 75 + "format": "record-key", 76 + "description": "NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility." 77 + }, 78 + "value": { "type": "unknown" } 79 + } 80 + }, 81 + "update": { 82 + "type": "object", 83 + "description": "Operation which updates an existing record.", 84 + "required": ["collection", "rkey", "value"], 85 + "properties": { 86 + "collection": { "type": "string", "format": "nsid" }, 87 + "rkey": { "type": "string", "format": "record-key" }, 88 + "value": { "type": "unknown" } 89 + } 90 + }, 91 + "delete": { 92 + "type": "object", 93 + "description": "Operation which deletes an existing record.", 94 + "required": ["collection", "rkey"], 95 + "properties": { 96 + "collection": { "type": "string", "format": "nsid" }, 97 + "rkey": { "type": "string", "format": "record-key" } 98 + } 99 + }, 100 + "createResult": { 101 + "type": "object", 102 + "required": ["uri", "cid"], 103 + "properties": { 104 + "uri": { "type": "string", "format": "at-uri" }, 105 + "cid": { "type": "string", "format": "cid" }, 106 + "validationStatus": { 107 + "type": "string", 108 + "knownValues": ["valid", "unknown"] 109 + } 110 + } 111 + }, 112 + "updateResult": { 113 + "type": "object", 114 + "required": ["uri", "cid"], 115 + "properties": { 116 + "uri": { "type": "string", "format": "at-uri" }, 117 + "cid": { "type": "string", "format": "cid" }, 118 + "validationStatus": { 119 + "type": "string", 120 + "knownValues": ["valid", "unknown"] 121 + } 122 + } 123 + }, 124 + "deleteResult": { 125 + "type": "object", 126 + "properties": {} 127 + } 128 + } 129 + }
+73
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/createRecord.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.createRecord", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Create a single new repository record. Requires auth, implemented by PDS.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["repo", "collection", "record"], 13 + "properties": { 14 + "repo": { 15 + "type": "string", 16 + "format": "at-identifier", 17 + "description": "The handle or DID of the repo (aka, current account)." 18 + }, 19 + "collection": { 20 + "type": "string", 21 + "format": "nsid", 22 + "description": "The NSID of the record collection." 23 + }, 24 + "rkey": { 25 + "type": "string", 26 + "format": "record-key", 27 + "description": "The Record Key.", 28 + "maxLength": 512 29 + }, 30 + "validate": { 31 + "type": "boolean", 32 + "description": "Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons." 33 + }, 34 + "record": { 35 + "type": "unknown", 36 + "description": "The record itself. Must contain a $type field." 37 + }, 38 + "swapCommit": { 39 + "type": "string", 40 + "format": "cid", 41 + "description": "Compare and swap with the previous commit by CID." 42 + } 43 + } 44 + } 45 + }, 46 + "output": { 47 + "encoding": "application/json", 48 + "schema": { 49 + "type": "object", 50 + "required": ["uri", "cid"], 51 + "properties": { 52 + "uri": { "type": "string", "format": "at-uri" }, 53 + "cid": { "type": "string", "format": "cid" }, 54 + "commit": { 55 + "type": "ref", 56 + "ref": "com.atproto.repo.defs#commitMeta" 57 + }, 58 + "validationStatus": { 59 + "type": "string", 60 + "knownValues": ["valid", "unknown"] 61 + } 62 + } 63 + } 64 + }, 65 + "errors": [ 66 + { 67 + "name": "InvalidSwap", 68 + "description": "Indicates that 'swapCommit' didn't match current repo commit." 69 + } 70 + ] 71 + } 72 + } 73 + }
+14
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.defs", 4 + "defs": { 5 + "commitMeta": { 6 + "type": "object", 7 + "required": ["cid", "rev"], 8 + "properties": { 9 + "cid": { "type": "string", "format": "cid" }, 10 + "rev": { "type": "string", "format": "tid" } 11 + } 12 + } 13 + } 14 + }
+57
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/deleteRecord.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.deleteRecord", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["repo", "collection", "rkey"], 13 + "properties": { 14 + "repo": { 15 + "type": "string", 16 + "format": "at-identifier", 17 + "description": "The handle or DID of the repo (aka, current account)." 18 + }, 19 + "collection": { 20 + "type": "string", 21 + "format": "nsid", 22 + "description": "The NSID of the record collection." 23 + }, 24 + "rkey": { 25 + "type": "string", 26 + "format": "record-key", 27 + "description": "The Record Key." 28 + }, 29 + "swapRecord": { 30 + "type": "string", 31 + "format": "cid", 32 + "description": "Compare and swap with the previous record by CID." 33 + }, 34 + "swapCommit": { 35 + "type": "string", 36 + "format": "cid", 37 + "description": "Compare and swap with the previous commit by CID." 38 + } 39 + } 40 + } 41 + }, 42 + "output": { 43 + "encoding": "application/json", 44 + "schema": { 45 + "type": "object", 46 + "properties": { 47 + "commit": { 48 + "type": "ref", 49 + "ref": "com.atproto.repo.defs#commitMeta" 50 + } 51 + } 52 + } 53 + }, 54 + "errors": [{ "name": "InvalidSwap" }] 55 + } 56 + } 57 + }
+51
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/describeRepo.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.describeRepo", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get information about an account and repository, including the list of collections. Does not require auth.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["repo"], 11 + "properties": { 12 + "repo": { 13 + "type": "string", 14 + "format": "at-identifier", 15 + "description": "The handle or DID of the repo." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": [ 24 + "handle", 25 + "did", 26 + "didDoc", 27 + "collections", 28 + "handleIsCorrect" 29 + ], 30 + "properties": { 31 + "handle": { "type": "string", "format": "handle" }, 32 + "did": { "type": "string", "format": "did" }, 33 + "didDoc": { 34 + "type": "unknown", 35 + "description": "The complete DID document for this account." 36 + }, 37 + "collections": { 38 + "type": "array", 39 + "description": "List of all the collections (NSIDs) for which this repo contains at least one record.", 40 + "items": { "type": "string", "format": "nsid" } 41 + }, 42 + "handleIsCorrect": { 43 + "type": "boolean", 44 + "description": "Indicates if handle is currently valid (resolves bi-directionally)" 45 + } 46 + } 47 + } 48 + } 49 + } 50 + } 51 + }
+49
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/getRecord.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.getRecord", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a single record from a repository. Does not require auth.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["repo", "collection", "rkey"], 11 + "properties": { 12 + "repo": { 13 + "type": "string", 14 + "format": "at-identifier", 15 + "description": "The handle or DID of the repo." 16 + }, 17 + "collection": { 18 + "type": "string", 19 + "format": "nsid", 20 + "description": "The NSID of the record collection." 21 + }, 22 + "rkey": { 23 + "type": "string", 24 + "description": "The Record Key.", 25 + "format": "record-key" 26 + }, 27 + "cid": { 28 + "type": "string", 29 + "format": "cid", 30 + "description": "The CID of the version of the record. If not specified, then return the most recent version." 31 + } 32 + } 33 + }, 34 + "output": { 35 + "encoding": "application/json", 36 + "schema": { 37 + "type": "object", 38 + "required": ["uri", "value"], 39 + "properties": { 40 + "uri": { "type": "string", "format": "at-uri" }, 41 + "cid": { "type": "string", "format": "cid" }, 42 + "value": { "type": "unknown" } 43 + } 44 + } 45 + }, 46 + "errors": [{ "name": "RecordNotFound" }] 47 + } 48 + } 49 + }
+13
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/importRepo.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.importRepo", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.", 8 + "input": { 9 + "encoding": "application/vnd.ipld.car" 10 + } 11 + } 12 + } 13 + }
+44
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/listMissingBlobs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.listMissingBlobs", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { 12 + "type": "integer", 13 + "minimum": 1, 14 + "maximum": 1000, 15 + "default": 500 16 + }, 17 + "cursor": { "type": "string" } 18 + } 19 + }, 20 + "output": { 21 + "encoding": "application/json", 22 + "schema": { 23 + "type": "object", 24 + "required": ["blobs"], 25 + "properties": { 26 + "cursor": { "type": "string" }, 27 + "blobs": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "#recordBlob" } 30 + } 31 + } 32 + } 33 + } 34 + }, 35 + "recordBlob": { 36 + "type": "object", 37 + "required": ["cid", "recordUri"], 38 + "properties": { 39 + "cid": { "type": "string", "format": "cid" }, 40 + "recordUri": { "type": "string", "format": "at-uri" } 41 + } 42 + } 43 + } 44 + }
+61
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/listRecords.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.listRecords", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "List a range of records in a repository, matching a specific collection. Does not require auth.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["repo", "collection"], 11 + "properties": { 12 + "repo": { 13 + "type": "string", 14 + "format": "at-identifier", 15 + "description": "The handle or DID of the repo." 16 + }, 17 + "collection": { 18 + "type": "string", 19 + "format": "nsid", 20 + "description": "The NSID of the record type." 21 + }, 22 + "limit": { 23 + "type": "integer", 24 + "minimum": 1, 25 + "maximum": 100, 26 + "default": 50, 27 + "description": "The number of records to return." 28 + }, 29 + "cursor": { "type": "string" }, 30 + "reverse": { 31 + "type": "boolean", 32 + "description": "Flag to reverse the order of the returned records." 33 + } 34 + } 35 + }, 36 + "output": { 37 + "encoding": "application/json", 38 + "schema": { 39 + "type": "object", 40 + "required": ["records"], 41 + "properties": { 42 + "cursor": { "type": "string" }, 43 + "records": { 44 + "type": "array", 45 + "items": { "type": "ref", "ref": "#record" } 46 + } 47 + } 48 + } 49 + } 50 + }, 51 + "record": { 52 + "type": "object", 53 + "required": ["uri", "cid", "value"], 54 + "properties": { 55 + "uri": { "type": "string", "format": "at-uri" }, 56 + "cid": { "type": "string", "format": "cid" }, 57 + "value": { "type": "unknown" } 58 + } 59 + } 60 + } 61 + }
+74
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/putRecord.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.putRecord", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["repo", "collection", "rkey", "record"], 13 + "nullable": ["swapRecord"], 14 + "properties": { 15 + "repo": { 16 + "type": "string", 17 + "format": "at-identifier", 18 + "description": "The handle or DID of the repo (aka, current account)." 19 + }, 20 + "collection": { 21 + "type": "string", 22 + "format": "nsid", 23 + "description": "The NSID of the record collection." 24 + }, 25 + "rkey": { 26 + "type": "string", 27 + "format": "record-key", 28 + "description": "The Record Key.", 29 + "maxLength": 512 30 + }, 31 + "validate": { 32 + "type": "boolean", 33 + "description": "Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons." 34 + }, 35 + "record": { 36 + "type": "unknown", 37 + "description": "The record to write." 38 + }, 39 + "swapRecord": { 40 + "type": "string", 41 + "format": "cid", 42 + "description": "Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation" 43 + }, 44 + "swapCommit": { 45 + "type": "string", 46 + "format": "cid", 47 + "description": "Compare and swap with the previous commit by CID." 48 + } 49 + } 50 + } 51 + }, 52 + "output": { 53 + "encoding": "application/json", 54 + "schema": { 55 + "type": "object", 56 + "required": ["uri", "cid"], 57 + "properties": { 58 + "uri": { "type": "string", "format": "at-uri" }, 59 + "cid": { "type": "string", "format": "cid" }, 60 + "commit": { 61 + "type": "ref", 62 + "ref": "com.atproto.repo.defs#commitMeta" 63 + }, 64 + "validationStatus": { 65 + "type": "string", 66 + "knownValues": ["valid", "unknown"] 67 + } 68 + } 69 + } 70 + }, 71 + "errors": [{ "name": "InvalidSwap" }] 72 + } 73 + } 74 + }
+15
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/strongRef.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.strongRef", 4 + "description": "A URI with a content-hash fingerprint.", 5 + "defs": { 6 + "main": { 7 + "type": "object", 8 + "required": ["uri", "cid"], 9 + "properties": { 10 + "uri": { "type": "string", "format": "at-uri" }, 11 + "cid": { "type": "string", "format": "cid" } 12 + } 13 + } 14 + } 15 + }
+23
packages/emitter/test/integration/lexicon-examples/output/com/atproto/repo/uploadBlob.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.repo.uploadBlob", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.", 8 + "input": { 9 + "encoding": "*/*" 10 + }, 11 + "output": { 12 + "encoding": "application/json", 13 + "schema": { 14 + "type": "object", 15 + "required": ["blob"], 16 + "properties": { 17 + "blob": { "type": "blob" } 18 + } 19 + } 20 + } 21 + } 22 + } 23 + }
+10
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/activateAccount.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.activateAccount", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup." 8 + } 9 + } 10 + }
+38
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/checkAccountStatus.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.checkAccountStatus", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself.", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": [ 13 + "activated", 14 + "validDid", 15 + "repoCommit", 16 + "repoRev", 17 + "repoBlocks", 18 + "indexedRecords", 19 + "privateStateValues", 20 + "expectedBlobs", 21 + "importedBlobs" 22 + ], 23 + "properties": { 24 + "activated": { "type": "boolean" }, 25 + "validDid": { "type": "boolean" }, 26 + "repoCommit": { "type": "string", "format": "cid" }, 27 + "repoRev": { "type": "string" }, 28 + "repoBlocks": { "type": "integer" }, 29 + "indexedRecords": { "type": "integer" }, 30 + "privateStateValues": { "type": "integer" }, 31 + "expectedBlobs": { "type": "integer" }, 32 + "importedBlobs": { "type": "integer" } 33 + } 34 + } 35 + } 36 + } 37 + } 38 + }
+27
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/confirmEmail.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.confirmEmail", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Confirm an email using a token from com.atproto.server.requestEmailConfirmation.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["email", "token"], 13 + "properties": { 14 + "email": { "type": "string" }, 15 + "token": { "type": "string" } 16 + } 17 + } 18 + }, 19 + "errors": [ 20 + { "name": "AccountNotFound" }, 21 + { "name": "ExpiredToken" }, 22 + { "name": "InvalidToken" }, 23 + { "name": "InvalidEmail" } 24 + ] 25 + } 26 + } 27 + }
+76
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/createAccount.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.createAccount", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Create an account. Implemented by PDS.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["handle"], 13 + "properties": { 14 + "email": { "type": "string" }, 15 + "handle": { 16 + "type": "string", 17 + "format": "handle", 18 + "description": "Requested handle for the account." 19 + }, 20 + "did": { 21 + "type": "string", 22 + "format": "did", 23 + "description": "Pre-existing atproto DID, being imported to a new account." 24 + }, 25 + "inviteCode": { "type": "string" }, 26 + "verificationCode": { "type": "string" }, 27 + "verificationPhone": { "type": "string" }, 28 + "password": { 29 + "type": "string", 30 + "description": "Initial account password. May need to meet instance-specific password strength requirements." 31 + }, 32 + "recoveryKey": { 33 + "type": "string", 34 + "description": "DID PLC rotation key (aka, recovery key) to be included in PLC creation operation." 35 + }, 36 + "plcOp": { 37 + "type": "unknown", 38 + "description": "A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented." 39 + } 40 + } 41 + } 42 + }, 43 + "output": { 44 + "encoding": "application/json", 45 + "schema": { 46 + "type": "object", 47 + "description": "Account login session returned on successful account creation.", 48 + "required": ["accessJwt", "refreshJwt", "handle", "did"], 49 + "properties": { 50 + "accessJwt": { "type": "string" }, 51 + "refreshJwt": { "type": "string" }, 52 + "handle": { "type": "string", "format": "handle" }, 53 + "did": { 54 + "type": "string", 55 + "format": "did", 56 + "description": "The DID of the new account." 57 + }, 58 + "didDoc": { 59 + "type": "unknown", 60 + "description": "Complete DID document." 61 + } 62 + } 63 + } 64 + }, 65 + "errors": [ 66 + { "name": "InvalidHandle" }, 67 + { "name": "InvalidPassword" }, 68 + { "name": "InvalidInviteCode" }, 69 + { "name": "HandleNotAvailable" }, 70 + { "name": "UnsupportedDomain" }, 71 + { "name": "UnresolvableDid" }, 72 + { "name": "IncompatibleDidDoc" } 73 + ] 74 + } 75 + } 76 + }
+45
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/createAppPassword.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.createAppPassword", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Create an App Password.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["name"], 13 + "properties": { 14 + "name": { 15 + "type": "string", 16 + "description": "A short name for the App Password, to help distinguish them." 17 + }, 18 + "privileged": { 19 + "type": "boolean", 20 + "description": "If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients." 21 + } 22 + } 23 + } 24 + }, 25 + "output": { 26 + "encoding": "application/json", 27 + "schema": { 28 + "type": "ref", 29 + "ref": "#appPassword" 30 + } 31 + }, 32 + "errors": [{ "name": "AccountTakedown" }] 33 + }, 34 + "appPassword": { 35 + "type": "object", 36 + "required": ["name", "password", "createdAt"], 37 + "properties": { 38 + "name": { "type": "string" }, 39 + "password": { "type": "string" }, 40 + "createdAt": { "type": "string", "format": "datetime" }, 41 + "privileged": { "type": "boolean" } 42 + } 43 + } 44 + } 45 + }
+31
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/createInviteCode.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.createInviteCode", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Create an invite code.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["useCount"], 13 + "properties": { 14 + "useCount": { "type": "integer" }, 15 + "forAccount": { "type": "string", "format": "did" } 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": ["code"], 24 + "properties": { 25 + "code": { "type": "string" } 26 + } 27 + } 28 + } 29 + } 30 + } 31 + }
+49
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/createInviteCodes.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.createInviteCodes", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Create invite codes.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["codeCount", "useCount"], 13 + "properties": { 14 + "codeCount": { "type": "integer", "default": 1 }, 15 + "useCount": { "type": "integer" }, 16 + "forAccounts": { 17 + "type": "array", 18 + "items": { "type": "string", "format": "did" } 19 + } 20 + } 21 + } 22 + }, 23 + "output": { 24 + "encoding": "application/json", 25 + "schema": { 26 + "type": "object", 27 + "required": ["codes"], 28 + "properties": { 29 + "codes": { 30 + "type": "array", 31 + "items": { "type": "ref", "ref": "#accountCodes" } 32 + } 33 + } 34 + } 35 + } 36 + }, 37 + "accountCodes": { 38 + "type": "object", 39 + "required": ["account", "codes"], 40 + "properties": { 41 + "account": { "type": "string" }, 42 + "codes": { 43 + "type": "array", 44 + "items": { "type": "string" } 45 + } 46 + } 47 + } 48 + } 49 + }
+56
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/createSession.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.createSession", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Create an authentication session.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["identifier", "password"], 13 + "properties": { 14 + "identifier": { 15 + "type": "string", 16 + "description": "Handle or other identifier supported by the server for the authenticating user." 17 + }, 18 + "password": { "type": "string" }, 19 + "authFactorToken": { "type": "string" }, 20 + "allowTakendown": { 21 + "type": "boolean", 22 + "description": "When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned" 23 + } 24 + } 25 + } 26 + }, 27 + "output": { 28 + "encoding": "application/json", 29 + "schema": { 30 + "type": "object", 31 + "required": ["accessJwt", "refreshJwt", "handle", "did"], 32 + "properties": { 33 + "accessJwt": { "type": "string" }, 34 + "refreshJwt": { "type": "string" }, 35 + "handle": { "type": "string", "format": "handle" }, 36 + "did": { "type": "string", "format": "did" }, 37 + "didDoc": { "type": "unknown" }, 38 + "email": { "type": "string" }, 39 + "emailConfirmed": { "type": "boolean" }, 40 + "emailAuthFactor": { "type": "boolean" }, 41 + "active": { "type": "boolean" }, 42 + "status": { 43 + "type": "string", 44 + "description": "If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.", 45 + "knownValues": ["takendown", "suspended", "deactivated"] 46 + } 47 + } 48 + } 49 + }, 50 + "errors": [ 51 + { "name": "AccountTakedown" }, 52 + { "name": "AuthFactorTokenRequired" } 53 + ] 54 + } 55 + } 56 + }
+23
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/deactivateAccount.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.deactivateAccount", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "properties": { 13 + "deleteAfter": { 14 + "type": "string", 15 + "format": "datetime", 16 + "description": "A recommendation to server as to how long they should hold onto the deactivated account before deleting." 17 + } 18 + } 19 + } 20 + } 21 + } 22 + } 23 + }
+38
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.defs", 4 + "defs": { 5 + "inviteCode": { 6 + "type": "object", 7 + "required": [ 8 + "code", 9 + "available", 10 + "disabled", 11 + "forAccount", 12 + "createdBy", 13 + "createdAt", 14 + "uses" 15 + ], 16 + "properties": { 17 + "code": { "type": "string" }, 18 + "available": { "type": "integer" }, 19 + "disabled": { "type": "boolean" }, 20 + "forAccount": { "type": "string" }, 21 + "createdBy": { "type": "string" }, 22 + "createdAt": { "type": "string", "format": "datetime" }, 23 + "uses": { 24 + "type": "array", 25 + "items": { "type": "ref", "ref": "#inviteCodeUse" } 26 + } 27 + } 28 + }, 29 + "inviteCodeUse": { 30 + "type": "object", 31 + "required": ["usedBy", "usedAt"], 32 + "properties": { 33 + "usedBy": { "type": "string", "format": "did" }, 34 + "usedAt": { "type": "string", "format": "datetime" } 35 + } 36 + } 37 + } 38 + }
+23
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/deleteAccount.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.deleteAccount", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["did", "password", "token"], 13 + "properties": { 14 + "did": { "type": "string", "format": "did" }, 15 + "password": { "type": "string" }, 16 + "token": { "type": "string" } 17 + } 18 + } 19 + }, 20 + "errors": [{ "name": "ExpiredToken" }, { "name": "InvalidToken" }] 21 + } 22 + } 23 + }
+10
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/deleteSession.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.deleteSession", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Delete the current session. Requires auth." 8 + } 9 + } 10 + }
+59
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/describeServer.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.describeServer", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Describes the server's account creation requirements and capabilities. Implemented by PDS.", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["did", "availableUserDomains"], 13 + "properties": { 14 + "inviteCodeRequired": { 15 + "type": "boolean", 16 + "description": "If true, an invite code must be supplied to create an account on this instance." 17 + }, 18 + "phoneVerificationRequired": { 19 + "type": "boolean", 20 + "description": "If true, a phone verification token must be supplied to create an account on this instance." 21 + }, 22 + "availableUserDomains": { 23 + "type": "array", 24 + "description": "List of domain suffixes that can be used in account handles.", 25 + "items": { "type": "string" } 26 + }, 27 + "links": { 28 + "type": "ref", 29 + "description": "URLs of service policy documents.", 30 + "ref": "#links" 31 + }, 32 + "contact": { 33 + "type": "ref", 34 + "description": "Contact information", 35 + "ref": "#contact" 36 + }, 37 + "did": { 38 + "type": "string", 39 + "format": "did" 40 + } 41 + } 42 + } 43 + } 44 + }, 45 + "links": { 46 + "type": "object", 47 + "properties": { 48 + "privacyPolicy": { "type": "string", "format": "uri" }, 49 + "termsOfService": { "type": "string", "format": "uri" } 50 + } 51 + }, 52 + "contact": { 53 + "type": "object", 54 + "properties": { 55 + "email": { "type": "string" } 56 + } 57 + } 58 + } 59 + }
+38
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/getAccountInviteCodes.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.getAccountInviteCodes", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get all invite codes for the current account. Requires auth.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "includeUsed": { "type": "boolean", "default": true }, 12 + "createAvailable": { 13 + "type": "boolean", 14 + "default": true, 15 + "description": "Controls whether any new 'earned' but not 'created' invites should be created." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": ["codes"], 24 + "properties": { 25 + "codes": { 26 + "type": "array", 27 + "items": { 28 + "type": "ref", 29 + "ref": "com.atproto.server.defs#inviteCode" 30 + } 31 + } 32 + } 33 + } 34 + }, 35 + "errors": [{ "name": "DuplicateCreate" }] 36 + } 37 + } 38 + }
+48
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/getServiceAuth.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.getServiceAuth", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a signed token on behalf of the requesting DID for the requested service.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["aud"], 11 + "properties": { 12 + "aud": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the service that the token will be used to authenticate with" 16 + }, 17 + "exp": { 18 + "type": "integer", 19 + "description": "The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope." 20 + }, 21 + "lxm": { 22 + "type": "string", 23 + "format": "nsid", 24 + "description": "Lexicon (XRPC) method to bind the requested token to" 25 + } 26 + } 27 + }, 28 + "output": { 29 + "encoding": "application/json", 30 + "schema": { 31 + "type": "object", 32 + "required": ["token"], 33 + "properties": { 34 + "token": { 35 + "type": "string" 36 + } 37 + } 38 + } 39 + }, 40 + "errors": [ 41 + { 42 + "name": "BadExpiration", 43 + "description": "Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes." 44 + } 45 + ] 46 + } 47 + } 48 + }
+31
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/getSession.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.getSession", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get information about the current auth session. Requires auth.", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["handle", "did"], 13 + "properties": { 14 + "handle": { "type": "string", "format": "handle" }, 15 + "did": { "type": "string", "format": "did" }, 16 + "email": { "type": "string" }, 17 + "emailConfirmed": { "type": "boolean" }, 18 + "emailAuthFactor": { "type": "boolean" }, 19 + "didDoc": { "type": "unknown" }, 20 + "active": { "type": "boolean" }, 21 + "status": { 22 + "type": "string", 23 + "description": "If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.", 24 + "knownValues": ["takendown", "suspended", "deactivated"] 25 + } 26 + } 27 + } 28 + } 29 + } 30 + } 31 + }
+33
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/listAppPasswords.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.listAppPasswords", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "List all App Passwords.", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["passwords"], 13 + "properties": { 14 + "passwords": { 15 + "type": "array", 16 + "items": { "type": "ref", "ref": "#appPassword" } 17 + } 18 + } 19 + } 20 + }, 21 + "errors": [{ "name": "AccountTakedown" }] 22 + }, 23 + "appPassword": { 24 + "type": "object", 25 + "required": ["name", "createdAt"], 26 + "properties": { 27 + "name": { "type": "string" }, 28 + "createdAt": { "type": "string", "format": "datetime" }, 29 + "privileged": { "type": "boolean" } 30 + } 31 + } 32 + } 33 + }
+31
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/refreshSession.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.refreshSession", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt').", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["accessJwt", "refreshJwt", "handle", "did"], 13 + "properties": { 14 + "accessJwt": { "type": "string" }, 15 + "refreshJwt": { "type": "string" }, 16 + "handle": { "type": "string", "format": "handle" }, 17 + "did": { "type": "string", "format": "did" }, 18 + "didDoc": { "type": "unknown" }, 19 + "active": { "type": "boolean" }, 20 + "status": { 21 + "type": "string", 22 + "description": "Hosting status of the account. If not specified, then assume 'active'.", 23 + "knownValues": ["takendown", "suspended", "deactivated"] 24 + } 25 + } 26 + } 27 + }, 28 + "errors": [{ "name": "AccountTakedown" }] 29 + } 30 + } 31 + }
+10
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/requestAccountDelete.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.requestAccountDelete", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Initiate a user account deletion via email." 8 + } 9 + } 10 + }
+10
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/requestEmailConfirmation.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.requestEmailConfirmation", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Request an email with a code to confirm ownership of email." 8 + } 9 + } 10 + }
+20
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/requestEmailUpdate.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.requestEmailUpdate", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Request a token in order to update email.", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["tokenRequired"], 13 + "properties": { 14 + "tokenRequired": { "type": "boolean" } 15 + } 16 + } 17 + } 18 + } 19 + } 20 + }
+20
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/requestPasswordReset.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.requestPasswordReset", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Initiate a user account password reset via email.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["email"], 13 + "properties": { 14 + "email": { "type": "string" } 15 + } 16 + } 17 + } 18 + } 19 + } 20 + }
+36
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/reserveSigningKey.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.reserveSigningKey", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "properties": { 13 + "did": { 14 + "type": "string", 15 + "format": "did", 16 + "description": "The DID to reserve a key for." 17 + } 18 + } 19 + } 20 + }, 21 + "output": { 22 + "encoding": "application/json", 23 + "schema": { 24 + "type": "object", 25 + "required": ["signingKey"], 26 + "properties": { 27 + "signingKey": { 28 + "type": "string", 29 + "description": "The public key for the reserved signing key, in did:key serialization." 30 + } 31 + } 32 + } 33 + } 34 + } 35 + } 36 + }
+22
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/resetPassword.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.resetPassword", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Reset a user account password using a token.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["token", "password"], 13 + "properties": { 14 + "token": { "type": "string" }, 15 + "password": { "type": "string" } 16 + } 17 + } 18 + }, 19 + "errors": [{ "name": "ExpiredToken" }, { "name": "InvalidToken" }] 20 + } 21 + } 22 + }
+20
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/revokeAppPassword.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.revokeAppPassword", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Revoke an App Password by name.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["name"], 13 + "properties": { 14 + "name": { "type": "string" } 15 + } 16 + } 17 + } 18 + } 19 + } 20 + }
+30
packages/emitter/test/integration/lexicon-examples/output/com/atproto/server/updateEmail.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.server.updateEmail", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Update an account's email.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["email"], 13 + "properties": { 14 + "email": { "type": "string" }, 15 + "emailAuthFactor": { "type": "boolean" }, 16 + "token": { 17 + "type": "string", 18 + "description": "Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed." 19 + } 20 + } 21 + } 22 + }, 23 + "errors": [ 24 + { "name": "ExpiredToken" }, 25 + { "name": "InvalidToken" }, 26 + { "name": "TokenRequired" } 27 + ] 28 + } 29 + } 30 + }
+10
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.defs", 4 + "defs": { 5 + "hostStatus": { 6 + "type": "string", 7 + "knownValues": ["active", "idle", "offline", "throttled", "banned"] 8 + } 9 + } 10 + }
+36
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getBlob.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getBlob", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did", "cid"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the account." 16 + }, 17 + "cid": { 18 + "type": "string", 19 + "format": "cid", 20 + "description": "The CID of the blob to fetch" 21 + } 22 + } 23 + }, 24 + "output": { 25 + "encoding": "*/*" 26 + }, 27 + "errors": [ 28 + { "name": "BlobNotFound" }, 29 + { "name": "RepoNotFound" }, 30 + { "name": "RepoTakendown" }, 31 + { "name": "RepoSuspended" }, 32 + { "name": "RepoDeactivated" } 33 + ] 34 + } 35 + } 36 + }
+35
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getBlocks.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getBlocks", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did", "cids"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + }, 17 + "cids": { 18 + "type": "array", 19 + "items": { "type": "string", "format": "cid" } 20 + } 21 + } 22 + }, 23 + "output": { 24 + "encoding": "application/vnd.ipld.car" 25 + }, 26 + "errors": [ 27 + { "name": "BlockNotFound" }, 28 + { "name": "RepoNotFound" }, 29 + { "name": "RepoTakendown" }, 30 + { "name": "RepoSuspended" }, 31 + { "name": "RepoDeactivated" } 32 + ] 33 + } 34 + } 35 + }
+24
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getCheckout.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getCheckout", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "DEPRECATED - please use com.atproto.sync.getRepo instead", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/vnd.ipld.car" 21 + } 22 + } 23 + } 24 + }
+32
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getHead.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getHead", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "DEPRECATED - please use com.atproto.sync.getLatestCommit instead", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": ["root"], 24 + "properties": { 25 + "root": { "type": "string", "format": "cid" } 26 + } 27 + } 28 + }, 29 + "errors": [{ "name": "HeadNotFound" }] 30 + } 31 + } 32 + }
+43
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getHostStatus.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getHostStatus", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Returns information about a specified upstream host, as consumed by the server. Implemented by relays.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["hostname"], 11 + "properties": { 12 + "hostname": { 13 + "type": "string", 14 + "description": "Hostname of the host (eg, PDS or relay) being queried." 15 + } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "required": ["hostname"], 23 + "properties": { 24 + "hostname": { "type": "string" }, 25 + "seq": { 26 + "type": "integer", 27 + "description": "Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor)." 28 + }, 29 + "accountCount": { 30 + "type": "integer", 31 + "description": "Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts." 32 + }, 33 + "status": { 34 + "type": "ref", 35 + "ref": "com.atproto.sync.defs#hostStatus" 36 + } 37 + } 38 + } 39 + }, 40 + "errors": [{ "name": "HostNotFound" }] 41 + } 42 + } 43 + }
+38
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getLatestCommit.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getLatestCommit", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get the current commit CID & revision of the specified repo. Does not require auth.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": ["cid", "rev"], 24 + "properties": { 25 + "cid": { "type": "string", "format": "cid" }, 26 + "rev": { "type": "string", "format": "tid" } 27 + } 28 + } 29 + }, 30 + "errors": [ 31 + { "name": "RepoNotFound" }, 32 + { "name": "RepoTakendown" }, 33 + { "name": "RepoSuspended" }, 34 + { "name": "RepoDeactivated" } 35 + ] 36 + } 37 + } 38 + }
+37
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getRecord.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getRecord", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did", "collection", "rkey"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + }, 17 + "collection": { "type": "string", "format": "nsid" }, 18 + "rkey": { 19 + "type": "string", 20 + "description": "Record Key", 21 + "format": "record-key" 22 + } 23 + } 24 + }, 25 + "output": { 26 + "encoding": "application/vnd.ipld.car" 27 + }, 28 + "errors": [ 29 + { "name": "RecordNotFound" }, 30 + { "name": "RepoNotFound" }, 31 + { "name": "RepoTakendown" }, 32 + { "name": "RepoSuspended" }, 33 + { "name": "RepoDeactivated" } 34 + ] 35 + } 36 + } 37 + }
+35
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getRepo.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getRepo", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + }, 17 + "since": { 18 + "type": "string", 19 + "format": "tid", 20 + "description": "The revision ('rev') of the repo to create a diff from." 21 + } 22 + } 23 + }, 24 + "output": { 25 + "encoding": "application/vnd.ipld.car" 26 + }, 27 + "errors": [ 28 + { "name": "RepoNotFound" }, 29 + { "name": "RepoTakendown" }, 30 + { "name": "RepoSuspended" }, 31 + { "name": "RepoDeactivated" } 32 + ] 33 + } 34 + } 35 + }
+50
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/getRepoStatus.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getRepoStatus", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + } 17 + } 18 + }, 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "type": "object", 23 + "required": ["did", "active"], 24 + "properties": { 25 + "did": { "type": "string", "format": "did" }, 26 + "active": { "type": "boolean" }, 27 + "status": { 28 + "type": "string", 29 + "description": "If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.", 30 + "knownValues": [ 31 + "takendown", 32 + "suspended", 33 + "deleted", 34 + "deactivated", 35 + "desynchronized", 36 + "throttled" 37 + ] 38 + }, 39 + "rev": { 40 + "type": "string", 41 + "format": "tid", 42 + "description": "Optional field, the current rev of the repo, if active=true" 43 + } 44 + } 45 + } 46 + }, 47 + "errors": [{ "name": "RepoNotFound" }] 48 + } 49 + } 50 + }
+53
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/listBlobs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.listBlobs", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + }, 17 + "since": { 18 + "type": "string", 19 + "format": "tid", 20 + "description": "Optional revision of the repo to list blobs since." 21 + }, 22 + "limit": { 23 + "type": "integer", 24 + "minimum": 1, 25 + "maximum": 1000, 26 + "default": 500 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + }, 31 + "output": { 32 + "encoding": "application/json", 33 + "schema": { 34 + "type": "object", 35 + "required": ["cids"], 36 + "properties": { 37 + "cursor": { "type": "string" }, 38 + "cids": { 39 + "type": "array", 40 + "items": { "type": "string", "format": "cid" } 41 + } 42 + } 43 + } 44 + }, 45 + "errors": [ 46 + { "name": "RepoNotFound" }, 47 + { "name": "RepoTakendown" }, 48 + { "name": "RepoSuspended" }, 49 + { "name": "RepoDeactivated" } 50 + ] 51 + } 52 + } 53 + }
+56
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/listHosts.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.listHosts", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { 12 + "type": "integer", 13 + "minimum": 1, 14 + "maximum": 1000, 15 + "default": 200 16 + }, 17 + "cursor": { "type": "string" } 18 + } 19 + }, 20 + "output": { 21 + "encoding": "application/json", 22 + "schema": { 23 + "type": "object", 24 + "required": ["hosts"], 25 + "properties": { 26 + "cursor": { "type": "string" }, 27 + "hosts": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "#host" }, 30 + "description": "Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first." 31 + } 32 + } 33 + } 34 + } 35 + }, 36 + "host": { 37 + "type": "object", 38 + "required": ["hostname"], 39 + "properties": { 40 + "hostname": { 41 + "type": "string", 42 + "description": "hostname of server; not a URL (no scheme)" 43 + }, 44 + "seq": { 45 + "type": "integer", 46 + "description": "Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor)." 47 + }, 48 + "accountCount": { "type": "integer" }, 49 + "status": { 50 + "type": "ref", 51 + "ref": "com.atproto.sync.defs#hostStatus" 52 + } 53 + } 54 + } 55 + } 56 + }
+62
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/listRepos.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.listRepos", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { 12 + "type": "integer", 13 + "minimum": 1, 14 + "maximum": 1000, 15 + "default": 500 16 + }, 17 + "cursor": { "type": "string" } 18 + } 19 + }, 20 + "output": { 21 + "encoding": "application/json", 22 + "schema": { 23 + "type": "object", 24 + "required": ["repos"], 25 + "properties": { 26 + "cursor": { "type": "string" }, 27 + "repos": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "#repo" } 30 + } 31 + } 32 + } 33 + } 34 + }, 35 + "repo": { 36 + "type": "object", 37 + "required": ["did", "head", "rev"], 38 + "properties": { 39 + "did": { "type": "string", "format": "did" }, 40 + "head": { 41 + "type": "string", 42 + "format": "cid", 43 + "description": "Current repo commit CID" 44 + }, 45 + "rev": { "type": "string", "format": "tid" }, 46 + "active": { "type": "boolean" }, 47 + "status": { 48 + "type": "string", 49 + "description": "If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.", 50 + "knownValues": [ 51 + "takendown", 52 + "suspended", 53 + "deleted", 54 + "deactivated", 55 + "desynchronized", 56 + "throttled" 57 + ] 58 + } 59 + } 60 + } 61 + } 62 + }
+46
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/listReposByCollection.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.listReposByCollection", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Enumerates all the DIDs which have records with the given collection NSID.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["collection"], 11 + "properties": { 12 + "collection": { "type": "string", "format": "nsid" }, 13 + "limit": { 14 + "type": "integer", 15 + "description": "Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists.", 16 + "minimum": 1, 17 + "maximum": 2000, 18 + "default": 500 19 + }, 20 + "cursor": { "type": "string" } 21 + } 22 + }, 23 + "output": { 24 + "encoding": "application/json", 25 + "schema": { 26 + "type": "object", 27 + "required": ["repos"], 28 + "properties": { 29 + "cursor": { "type": "string" }, 30 + "repos": { 31 + "type": "array", 32 + "items": { "type": "ref", "ref": "#repo" } 33 + } 34 + } 35 + } 36 + } 37 + }, 38 + "repo": { 39 + "type": "object", 40 + "required": ["did"], 41 + "properties": { 42 + "did": { "type": "string", "format": "did" } 43 + } 44 + } 45 + } 46 + }
+23
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/notifyOfUpdate.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.notifyOfUpdate", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["hostname"], 13 + "properties": { 14 + "hostname": { 15 + "type": "string", 16 + "description": "Hostname of the current service (usually a PDS) that is notifying of update." 17 + } 18 + } 19 + } 20 + } 21 + } 22 + } 23 + }
+24
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/requestCrawl.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.requestCrawl", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["hostname"], 13 + "properties": { 14 + "hostname": { 15 + "type": "string", 16 + "description": "Hostname of the current service (eg, PDS) that is requesting to be crawled." 17 + } 18 + } 19 + } 20 + }, 21 + "errors": [{ "name": "HostBanned" }] 22 + } 23 + } 24 + }
+215
packages/emitter/test/integration/lexicon-examples/output/com/atproto/sync/subscribeRepos.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.subscribeRepos", 4 + "defs": { 5 + "main": { 6 + "type": "subscription", 7 + "description": "Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "cursor": { 12 + "type": "integer", 13 + "description": "The last known event seq number to backfill from." 14 + } 15 + } 16 + }, 17 + "message": { 18 + "schema": { 19 + "type": "union", 20 + "refs": ["#commit", "#sync", "#identity", "#account", "#info"] 21 + } 22 + }, 23 + "errors": [ 24 + { "name": "FutureCursor" }, 25 + { 26 + "name": "ConsumerTooSlow", 27 + "description": "If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection." 28 + } 29 + ] 30 + }, 31 + "commit": { 32 + "type": "object", 33 + "description": "Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature.", 34 + "required": [ 35 + "seq", 36 + "rebase", 37 + "tooBig", 38 + "repo", 39 + "commit", 40 + "rev", 41 + "since", 42 + "blocks", 43 + "ops", 44 + "blobs", 45 + "time" 46 + ], 47 + "nullable": ["since"], 48 + "properties": { 49 + "seq": { 50 + "type": "integer", 51 + "description": "The stream sequence number of this message." 52 + }, 53 + "rebase": { "type": "boolean", "description": "DEPRECATED -- unused" }, 54 + "tooBig": { 55 + "type": "boolean", 56 + "description": "DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data." 57 + }, 58 + "repo": { 59 + "type": "string", 60 + "format": "did", 61 + "description": "The repo this event comes from. Note that all other message types name this field 'did'." 62 + }, 63 + "commit": { 64 + "type": "cid-link", 65 + "description": "Repo commit object CID." 66 + }, 67 + "rev": { 68 + "type": "string", 69 + "format": "tid", 70 + "description": "The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event." 71 + }, 72 + "since": { 73 + "type": "string", 74 + "format": "tid", 75 + "description": "The rev of the last emitted commit from this repo (if any)." 76 + }, 77 + "blocks": { 78 + "type": "bytes", 79 + "description": "CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list.", 80 + "maxLength": 2000000 81 + }, 82 + "ops": { 83 + "type": "array", 84 + "description": "List of repo mutation operations in this commit (eg, records created, updated, or deleted).", 85 + "items": { 86 + "type": "ref", 87 + "ref": "#repoOp" 88 + }, 89 + "maxLength": 200 90 + }, 91 + "blobs": { 92 + "type": "array", 93 + "description": "DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.", 94 + "items": { 95 + "type": "cid-link" 96 + } 97 + }, 98 + "prevData": { 99 + "type": "cid-link", 100 + "description": "The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose." 101 + }, 102 + "time": { 103 + "type": "string", 104 + "format": "datetime", 105 + "description": "Timestamp of when this message was originally broadcast." 106 + } 107 + } 108 + }, 109 + "sync": { 110 + "type": "object", 111 + "description": "Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository.", 112 + "required": ["seq", "did", "blocks", "rev", "time"], 113 + "properties": { 114 + "seq": { 115 + "type": "integer", 116 + "description": "The stream sequence number of this message." 117 + }, 118 + "did": { 119 + "type": "string", 120 + "format": "did", 121 + "description": "The account this repo event corresponds to. Must match that in the commit object." 122 + }, 123 + "blocks": { 124 + "type": "bytes", 125 + "description": "CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.", 126 + "maxLength": 10000 127 + }, 128 + "rev": { 129 + "type": "string", 130 + "description": "The rev of the commit. This value must match that in the commit object." 131 + }, 132 + "time": { 133 + "type": "string", 134 + "format": "datetime", 135 + "description": "Timestamp of when this message was originally broadcast." 136 + } 137 + } 138 + }, 139 + "identity": { 140 + "type": "object", 141 + "description": "Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache.", 142 + "required": ["seq", "did", "time"], 143 + "properties": { 144 + "seq": { "type": "integer" }, 145 + "did": { "type": "string", "format": "did" }, 146 + "time": { "type": "string", "format": "datetime" }, 147 + "handle": { 148 + "type": "string", 149 + "format": "handle", 150 + "description": "The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details." 151 + } 152 + } 153 + }, 154 + "account": { 155 + "type": "object", 156 + "description": "Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active.", 157 + "required": ["seq", "did", "time", "active"], 158 + "properties": { 159 + "seq": { "type": "integer" }, 160 + "did": { "type": "string", "format": "did" }, 161 + "time": { "type": "string", "format": "datetime" }, 162 + "active": { 163 + "type": "boolean", 164 + "description": "Indicates that the account has a repository which can be fetched from the host that emitted this event." 165 + }, 166 + "status": { 167 + "type": "string", 168 + "description": "If active=false, this optional field indicates a reason for why the account is not active.", 169 + "knownValues": [ 170 + "takendown", 171 + "suspended", 172 + "deleted", 173 + "deactivated", 174 + "desynchronized", 175 + "throttled" 176 + ] 177 + } 178 + } 179 + }, 180 + "info": { 181 + "type": "object", 182 + "required": ["name"], 183 + "properties": { 184 + "name": { 185 + "type": "string", 186 + "knownValues": ["OutdatedCursor"] 187 + }, 188 + "message": { 189 + "type": "string" 190 + } 191 + } 192 + }, 193 + "repoOp": { 194 + "type": "object", 195 + "description": "A repo operation, ie a mutation of a single record.", 196 + "required": ["action", "path", "cid"], 197 + "nullable": ["cid"], 198 + "properties": { 199 + "action": { 200 + "type": "string", 201 + "knownValues": ["create", "update", "delete"] 202 + }, 203 + "path": { "type": "string" }, 204 + "cid": { 205 + "type": "cid-link", 206 + "description": "For creates and updates, the new record CID. For deletions, null." 207 + }, 208 + "prev": { 209 + "type": "cid-link", 210 + "description": "For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined." 211 + } 212 + } 213 + } 214 + } 215 + }
+27
packages/emitter/test/integration/lexicon-examples/output/com/atproto/temp/addReservedHandle.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.temp.addReservedHandle", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Add a handle to the set of reserved handles.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["handle"], 13 + "properties": { 14 + "handle": { "type": "string" } 15 + } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "properties": {} 23 + } 24 + } 25 + } 26 + } 27 + }
+88
packages/emitter/test/integration/lexicon-examples/output/com/atproto/temp/checkHandleAvailability.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.temp.checkHandleAvailability", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["handle"], 11 + "properties": { 12 + "handle": { 13 + "type": "string", 14 + "format": "handle", 15 + "description": "Tentative handle. Will be checked for availability or used to build handle suggestions." 16 + }, 17 + "email": { 18 + "type": "string", 19 + "description": "User-provided email. Might be used to build handle suggestions." 20 + }, 21 + "birthDate": { 22 + "type": "string", 23 + "format": "datetime", 24 + "description": "User-provided birth date. Might be used to build handle suggestions." 25 + } 26 + } 27 + }, 28 + "output": { 29 + "encoding": "application/json", 30 + "schema": { 31 + "type": "object", 32 + "required": ["handle", "result"], 33 + "properties": { 34 + "handle": { 35 + "type": "string", 36 + "format": "handle", 37 + "description": "Echo of the input handle." 38 + }, 39 + "result": { 40 + "type": "union", 41 + "refs": ["#resultAvailable", "#resultUnavailable"] 42 + } 43 + } 44 + } 45 + }, 46 + "errors": [ 47 + { 48 + "name": "InvalidEmail", 49 + "description": "An invalid email was provided." 50 + } 51 + ] 52 + }, 53 + "resultAvailable": { 54 + "type": "object", 55 + "description": "Indicates the provided handle is available.", 56 + "properties": {} 57 + }, 58 + "resultUnavailable": { 59 + "type": "object", 60 + "description": "Indicates the provided handle is unavailable and gives suggestions of available handles.", 61 + "required": ["suggestions"], 62 + "properties": { 63 + "suggestions": { 64 + "type": "array", 65 + "description": "List of suggested handles based on the provided inputs.", 66 + "items": { 67 + "type": "ref", 68 + "ref": "#suggestion" 69 + } 70 + } 71 + } 72 + }, 73 + "suggestion": { 74 + "type": "object", 75 + "required": ["handle", "method"], 76 + "properties": { 77 + "handle": { 78 + "type": "string", 79 + "format": "handle" 80 + }, 81 + "method": { 82 + "type": "string", 83 + "description": "Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics." 84 + } 85 + } 86 + } 87 + } 88 + }
+22
packages/emitter/test/integration/lexicon-examples/output/com/atproto/temp/checkSignupQueue.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.temp.checkSignupQueue", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Check accounts location in signup queue.", 8 + "output": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["activated"], 13 + "properties": { 14 + "activated": { "type": "boolean" }, 15 + "placeInQueue": { "type": "integer" }, 16 + "estimatedTimeMs": { "type": "integer" } 17 + } 18 + } 19 + } 20 + } 21 + } 22 + }
+39
packages/emitter/test/integration/lexicon-examples/output/com/atproto/temp/dereferenceScope.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.temp.dereferenceScope", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Allows finding the oauth permission scope from a reference", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["scope"], 11 + "properties": { 12 + "scope": { 13 + "type": "string", 14 + "description": "The scope reference (starts with 'ref:')" 15 + } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "required": ["scope"], 23 + "properties": { 24 + "scope": { 25 + "type": "string", 26 + "description": "The full oauth permission scope" 27 + } 28 + } 29 + } 30 + }, 31 + "errors": [ 32 + { 33 + "name": "InvalidScopeReference", 34 + "description": "An invalid scope reference was provided." 35 + } 36 + ] 37 + } 38 + } 39 + }
+35
packages/emitter/test/integration/lexicon-examples/output/com/atproto/temp/fetchLabels.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.temp.fetchLabels", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "since": { "type": "integer" }, 12 + "limit": { 13 + "type": "integer", 14 + "minimum": 1, 15 + "maximum": 250, 16 + "default": 50 17 + } 18 + } 19 + }, 20 + "output": { 21 + "encoding": "application/json", 22 + "schema": { 23 + "type": "object", 24 + "required": ["labels"], 25 + "properties": { 26 + "labels": { 27 + "type": "array", 28 + "items": { "type": "ref", "ref": "com.atproto.label.defs#label" } 29 + } 30 + } 31 + } 32 + } 33 + } 34 + } 35 + }
+20
packages/emitter/test/integration/lexicon-examples/output/com/atproto/temp/requestPhoneVerification.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.temp.requestPhoneVerification", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Request a verification code to be sent to the supplied phone number", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["phoneNumber"], 13 + "properties": { 14 + "phoneNumber": { "type": "string" } 15 + } 16 + } 17 + } 18 + } 19 + } 20 + }
+23
packages/emitter/test/integration/lexicon-examples/output/com/atproto/temp/revokeAccountCredentials.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.temp.revokeAccountCredentials", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["account"], 13 + "properties": { 14 + "account": { 15 + "type": "string", 16 + "format": "at-identifier" 17 + } 18 + } 19 + } 20 + } 21 + } 22 + } 23 + }
+24
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/blockquote.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.blockquote", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "plaintext" 9 + ], 10 + "properties": { 11 + "plaintext": { 12 + "type": "string" 13 + }, 14 + "facets": { 15 + "type": "array", 16 + "items": { 17 + "type": "ref", 18 + "ref": "pub.leaflet.richtext.facet" 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
+18
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/bskyPost.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.bskyPost", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "postRef" 9 + ], 10 + "properties": { 11 + "postRef": { 12 + "type": "ref", 13 + "ref": "com.atproto.repo.strongRef" 14 + } 15 + } 16 + } 17 + } 18 + }
+23
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/code.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.code", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "plaintext" 9 + ], 10 + "properties": { 11 + "plaintext": { 12 + "type": "string" 13 + }, 14 + "language": { 15 + "type": "string" 16 + }, 17 + "syntaxHighlightingTheme": { 18 + "type": "string" 19 + } 20 + } 21 + } 22 + } 23 + }
+29
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/header.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.header", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "plaintext" 9 + ], 10 + "properties": { 11 + "level": { 12 + "type": "integer", 13 + "minimum": 1, 14 + "maximum": 6 15 + }, 16 + "plaintext": { 17 + "type": "string" 18 + }, 19 + "facets": { 20 + "type": "array", 21 + "items": { 22 + "type": "ref", 23 + "ref": "pub.leaflet.richtext.facet" 24 + } 25 + } 26 + } 27 + } 28 + } 29 + }
+10
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/horizontalRule.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.horizontalRule", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "properties": {} 8 + } 9 + } 10 + }
+23
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/iframe.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.iframe", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "url" 9 + ], 10 + "properties": { 11 + "url": { 12 + "type": "string", 13 + "format": "uri" 14 + }, 15 + "height": { 16 + "type": "integer", 17 + "minimum": 16, 18 + "maximum": 1600 19 + } 20 + } 21 + } 22 + } 23 + }
+45
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/image.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.image", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "image", 9 + "aspectRatio" 10 + ], 11 + "properties": { 12 + "image": { 13 + "type": "blob", 14 + "accept": [ 15 + "image/*" 16 + ], 17 + "maxSize": 1000000 18 + }, 19 + "alt": { 20 + "type": "string", 21 + "description": "Alt text description of the image, for accessibility." 22 + }, 23 + "aspectRatio": { 24 + "type": "ref", 25 + "ref": "#aspectRatio" 26 + } 27 + } 28 + }, 29 + "aspectRatio": { 30 + "type": "object", 31 + "required": [ 32 + "width", 33 + "height" 34 + ], 35 + "properties": { 36 + "width": { 37 + "type": "integer" 38 + }, 39 + "height": { 40 + "type": "integer" 41 + } 42 + } 43 + } 44 + } 45 + }
+17
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/math.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.math", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "tex" 9 + ], 10 + "properties": { 11 + "tex": { 12 + "type": "string" 13 + } 14 + } 15 + } 16 + } 17 + }
+24
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/text.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.text", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "plaintext" 9 + ], 10 + "properties": { 11 + "plaintext": { 12 + "type": "string" 13 + }, 14 + "facets": { 15 + "type": "array", 16 + "items": { 17 + "type": "ref", 18 + "ref": "pub.leaflet.richtext.facet" 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
+44
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/unorderedList.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.unorderedList", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "children" 9 + ], 10 + "properties": { 11 + "children": { 12 + "type": "array", 13 + "items": { 14 + "type": "ref", 15 + "ref": "#listItem" 16 + } 17 + } 18 + } 19 + }, 20 + "listItem": { 21 + "type": "object", 22 + "required": [ 23 + "content" 24 + ], 25 + "properties": { 26 + "content": { 27 + "type": "union", 28 + "refs": [ 29 + "pub.leaflet.blocks.text", 30 + "pub.leaflet.blocks.header", 31 + "pub.leaflet.blocks.image" 32 + ] 33 + }, 34 + "children": { 35 + "type": "array", 36 + "items": { 37 + "type": "ref", 38 + "ref": "#listItem" 39 + } 40 + } 41 + } 42 + } 43 + } 44 + }
+31
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/blocks/website.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.website", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "src" 9 + ], 10 + "properties": { 11 + "previewImage": { 12 + "type": "blob", 13 + "accept": [ 14 + "image/*" 15 + ], 16 + "maxSize": 1000000 17 + }, 18 + "title": { 19 + "type": "string" 20 + }, 21 + "description": { 22 + "type": "string" 23 + }, 24 + "src": { 25 + "type": "string", 26 + "format": "uri" 27 + } 28 + } 29 + } 30 + } 31 + }
+79
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/comment.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.comment", 4 + "description": "A lexicon for comments on documents", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "key": "tid", 9 + "description": "Record containing a comment", 10 + "record": { 11 + "type": "object", 12 + "required": [ 13 + "subject", 14 + "createdAt", 15 + "plaintext" 16 + ], 17 + "properties": { 18 + "subject": { 19 + "type": "string", 20 + "format": "at-uri" 21 + }, 22 + "createdAt": { 23 + "type": "string", 24 + "format": "datetime" 25 + }, 26 + "reply": { 27 + "type": "ref", 28 + "ref": "#replyRef" 29 + }, 30 + "plaintext": { 31 + "type": "string" 32 + }, 33 + "facets": { 34 + "type": "array", 35 + "items": { 36 + "type": "ref", 37 + "ref": "pub.leaflet.richtext.facet" 38 + } 39 + }, 40 + "attachment": { 41 + "type": "union", 42 + "refs": [ 43 + "#linearDocumentQuote" 44 + ] 45 + } 46 + } 47 + } 48 + }, 49 + "linearDocumentQuote": { 50 + "type": "object", 51 + "required": [ 52 + "document", 53 + "quote" 54 + ], 55 + "properties": { 56 + "document": { 57 + "type": "string", 58 + "format": "at-uri" 59 + }, 60 + "quote": { 61 + "type": "ref", 62 + "ref": "pub.leaflet.pages.linearDocument#quote" 63 + } 64 + } 65 + }, 66 + "replyRef": { 67 + "type": "object", 68 + "required": [ 69 + "parent" 70 + ], 71 + "properties": { 72 + "parent": { 73 + "type": "string", 74 + "format": "at-uri" 75 + } 76 + } 77 + } 78 + } 79 + }
+58
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/document.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.document", 4 + "description": "A lexicon for long form rich media documents", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "key": "tid", 9 + "description": "Record containing a document", 10 + "record": { 11 + "type": "object", 12 + "required": [ 13 + "title", 14 + "publication", 15 + "author", 16 + "pages" 17 + ], 18 + "properties": { 19 + "title": { 20 + "type": "string", 21 + "maxLength": 1280, 22 + "maxGraphemes": 128 23 + }, 24 + "postRef": { 25 + "type": "ref", 26 + "ref": "com.atproto.repo.strongRef" 27 + }, 28 + "description": { 29 + "type": "string", 30 + "maxLength": 3000, 31 + "maxGraphemes": 300 32 + }, 33 + "publishedAt": { 34 + "type": "string", 35 + "format": "datetime" 36 + }, 37 + "publication": { 38 + "type": "string", 39 + "format": "at-uri" 40 + }, 41 + "author": { 42 + "type": "string", 43 + "format": "at-identifier" 44 + }, 45 + "pages": { 46 + "type": "array", 47 + "items": { 48 + "type": "union", 49 + "refs": [ 50 + "pub.leaflet.pages.linearDocument" 51 + ] 52 + } 53 + } 54 + } 55 + } 56 + } 57 + } 58 + }
+23
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/graph/subscription.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.graph.subscription", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "key": "tid", 8 + "description": "Record declaring a subscription to a publication", 9 + "record": { 10 + "type": "object", 11 + "required": [ 12 + "publication" 13 + ], 14 + "properties": { 15 + "publication": { 16 + "type": "string", 17 + "format": "at-uri" 18 + } 19 + } 20 + } 21 + } 22 + } 23 + }
+95
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/pages/linearDocument.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.pages.linearDocument", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "properties": { 8 + "blocks": { 9 + "type": "array", 10 + "items": { 11 + "type": "ref", 12 + "ref": "#block" 13 + } 14 + } 15 + } 16 + }, 17 + "block": { 18 + "type": "object", 19 + "required": [ 20 + "block" 21 + ], 22 + "properties": { 23 + "block": { 24 + "type": "union", 25 + "refs": [ 26 + "pub.leaflet.blocks.iframe", 27 + "pub.leaflet.blocks.text", 28 + "pub.leaflet.blocks.blockquote", 29 + "pub.leaflet.blocks.header", 30 + "pub.leaflet.blocks.image", 31 + "pub.leaflet.blocks.unorderedList", 32 + "pub.leaflet.blocks.website", 33 + "pub.leaflet.blocks.math", 34 + "pub.leaflet.blocks.code", 35 + "pub.leaflet.blocks.horizontalRule", 36 + "pub.leaflet.blocks.bskyPost" 37 + ] 38 + }, 39 + "alignment": { 40 + "type": "string", 41 + "knownValues": [ 42 + "#textAlignLeft", 43 + "#textAlignCenter", 44 + "#textAlignRight", 45 + "#textAlignJustify" 46 + ] 47 + } 48 + } 49 + }, 50 + "textAlignLeft": { 51 + "type": "token" 52 + }, 53 + "textAlignCenter": { 54 + "type": "token" 55 + }, 56 + "textAlignRight": { 57 + "type": "token" 58 + }, 59 + "quote": { 60 + "type": "object", 61 + "required": [ 62 + "start", 63 + "end" 64 + ], 65 + "properties": { 66 + "start": { 67 + "type": "ref", 68 + "ref": "#position" 69 + }, 70 + "end": { 71 + "type": "ref", 72 + "ref": "#position" 73 + } 74 + } 75 + }, 76 + "position": { 77 + "type": "object", 78 + "required": [ 79 + "block", 80 + "offset" 81 + ], 82 + "properties": { 83 + "block": { 84 + "type": "array", 85 + "items": { 86 + "type": "integer" 87 + } 88 + }, 89 + "offset": { 90 + "type": "integer" 91 + } 92 + } 93 + } 94 + } 95 + }
+107
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/publication.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.publication", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "key": "tid", 8 + "description": "Record declaring a publication", 9 + "record": { 10 + "type": "object", 11 + "required": [ 12 + "name" 13 + ], 14 + "properties": { 15 + "name": { 16 + "type": "string", 17 + "maxLength": 2000 18 + }, 19 + "base_path": { 20 + "type": "string", 21 + "format": "uri" 22 + }, 23 + "description": { 24 + "type": "string", 25 + "maxLength": 2000 26 + }, 27 + "icon": { 28 + "type": "blob", 29 + "accept": [ 30 + "image/*" 31 + ], 32 + "maxSize": 1000000 33 + }, 34 + "theme": { 35 + "type": "ref", 36 + "ref": "#theme" 37 + }, 38 + "preferences": { 39 + "type": "ref", 40 + "ref": "#preferences" 41 + } 42 + } 43 + } 44 + }, 45 + "preferences": { 46 + "type": "object", 47 + "properties": { 48 + "showInDiscover": { 49 + "type": "boolean", 50 + "default": true 51 + }, 52 + "showComments": { 53 + "type": "boolean", 54 + "default": true 55 + } 56 + } 57 + }, 58 + "theme": { 59 + "type": "object", 60 + "properties": { 61 + "backgroundColor": { 62 + "type": "union", 63 + "refs": [ 64 + "pub.leaflet.theme.color#rgba", 65 + "pub.leaflet.theme.color#rgb" 66 + ] 67 + }, 68 + "backgroundImage": { 69 + "type": "ref", 70 + "ref": "pub.leaflet.theme.backgroundImage" 71 + }, 72 + "primary": { 73 + "type": "union", 74 + "refs": [ 75 + "pub.leaflet.theme.color#rgba", 76 + "pub.leaflet.theme.color#rgb" 77 + ] 78 + }, 79 + "pageBackground": { 80 + "type": "union", 81 + "refs": [ 82 + "pub.leaflet.theme.color#rgba", 83 + "pub.leaflet.theme.color#rgb" 84 + ] 85 + }, 86 + "showPageBackground": { 87 + "type": "boolean", 88 + "default": false 89 + }, 90 + "accentBackground": { 91 + "type": "union", 92 + "refs": [ 93 + "pub.leaflet.theme.color#rgba", 94 + "pub.leaflet.theme.color#rgb" 95 + ] 96 + }, 97 + "accentText": { 98 + "type": "union", 99 + "refs": [ 100 + "pub.leaflet.theme.color#rgba", 101 + "pub.leaflet.theme.color#rgb" 102 + ] 103 + } 104 + } 105 + } 106 + } 107 + }
+106
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/richtext/facet.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.richtext.facet", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "description": "Annotation of a sub-string within rich text.", 8 + "required": [ 9 + "index", 10 + "features" 11 + ], 12 + "properties": { 13 + "index": { 14 + "type": "ref", 15 + "ref": "#byteSlice" 16 + }, 17 + "features": { 18 + "type": "array", 19 + "items": { 20 + "type": "union", 21 + "refs": [ 22 + "#link", 23 + "#code", 24 + "#highlight", 25 + "#underline", 26 + "#strikethrough", 27 + "#id", 28 + "#bold", 29 + "#italic" 30 + ] 31 + } 32 + } 33 + } 34 + }, 35 + "byteSlice": { 36 + "type": "object", 37 + "description": "Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.", 38 + "required": [ 39 + "byteStart", 40 + "byteEnd" 41 + ], 42 + "properties": { 43 + "byteStart": { 44 + "type": "integer", 45 + "minimum": 0 46 + }, 47 + "byteEnd": { 48 + "type": "integer", 49 + "minimum": 0 50 + } 51 + } 52 + }, 53 + "link": { 54 + "type": "object", 55 + "description": "Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.", 56 + "required": [ 57 + "uri" 58 + ], 59 + "properties": { 60 + "uri": { 61 + "type": "string", 62 + "format": "uri" 63 + } 64 + } 65 + }, 66 + "code": { 67 + "type": "object", 68 + "description": "Facet feature for inline code.", 69 + "properties": {} 70 + }, 71 + "highlight": { 72 + "type": "object", 73 + "description": "Facet feature for highlighted text.", 74 + "properties": {} 75 + }, 76 + "underline": { 77 + "type": "object", 78 + "description": "Facet feature for underline markup", 79 + "properties": {} 80 + }, 81 + "strikethrough": { 82 + "type": "object", 83 + "description": "Facet feature for strikethrough markup", 84 + "properties": {} 85 + }, 86 + "id": { 87 + "type": "object", 88 + "description": "Facet feature for an identifier. Used for linking to a segment", 89 + "properties": { 90 + "id": { 91 + "type": "string" 92 + } 93 + } 94 + }, 95 + "bold": { 96 + "type": "object", 97 + "description": "Facet feature for bold text", 98 + "properties": {} 99 + }, 100 + "italic": { 101 + "type": "object", 102 + "description": "Facet feature for italic text", 103 + "properties": {} 104 + } 105 + } 106 + }
+27
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/theme/backgroundImage.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.theme.backgroundImage", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "image" 9 + ], 10 + "properties": { 11 + "image": { 12 + "type": "blob", 13 + "accept": [ 14 + "image/*" 15 + ], 16 + "maxSize": 1000000 17 + }, 18 + "width": { 19 + "type": "integer" 20 + }, 21 + "repeat": { 22 + "type": "boolean" 23 + } 24 + } 25 + } 26 + } 27 + }
+57
packages/emitter/test/integration/lexicon-examples/output/pub/leaflet/theme/color.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.theme.color", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "properties": {} 8 + }, 9 + "rgba": { 10 + "type": "object", 11 + "required": ["r", "g", "b", "a"], 12 + "properties": { 13 + "r": { 14 + "type": "integer", 15 + "maximum": 255, 16 + "minimum": 0 17 + }, 18 + "g": { 19 + "type": "integer", 20 + "maximum": 255, 21 + "minimum": 0 22 + }, 23 + "b": { 24 + "type": "integer", 25 + "maximum": 255, 26 + "minimum": 0 27 + }, 28 + "a": { 29 + "type": "integer", 30 + "maximum": 100, 31 + "minimum": 0 32 + } 33 + } 34 + }, 35 + "rgb": { 36 + "type": "object", 37 + "required": ["r", "g", "b"], 38 + "properties": { 39 + "r": { 40 + "type": "integer", 41 + "maximum": 255, 42 + "minimum": 0 43 + }, 44 + "g": { 45 + "type": "integer", 46 + "maximum": 255, 47 + "minimum": 0 48 + }, 49 + "b": { 50 + "type": "integer", 51 + "maximum": 255, 52 + "minimum": 0 53 + } 54 + } 55 + } 56 + } 57 + }
+24
packages/website/.gitignore
··· 1 + # build output 2 + dist/ 3 + # generated types 4 + .astro/ 5 + 6 + # dependencies 7 + node_modules/ 8 + 9 + # logs 10 + npm-debug.log* 11 + yarn-debug.log* 12 + yarn-error.log* 13 + pnpm-debug.log* 14 + 15 + 16 + # environment variables 17 + .env 18 + .env.production 19 + 20 + # macOS-specific files 21 + .DS_Store 22 + 23 + # jetbrains setting folder 24 + .idea/
+62
packages/website/README.md
··· 1 + # Tylex Website 2 + 3 + Landing page for tylex - TypeSpec for AT Protocol Lexicons. 4 + 5 + ## Features 6 + 7 + - **Live Examples**: TypeSpec examples are compiled during build to show real Lexicon JSON output 8 + - **Syntax Highlighting**: Using Shiki for beautiful code highlighting 9 + - **Interactive Playground**: Try tylex in the browser (coming soon) 10 + 11 + ## Development 12 + 13 + ```sh 14 + pnpm install 15 + pnpm run dev 16 + ``` 17 + 18 + ## Building 19 + 20 + The build process automatically: 21 + 1. Compiles TypeSpec examples **in memory** during the Astro build 22 + 2. Reads TypeSpec source files 23 + 3. Syntax-highlights and displays them side-by-side with generated JSON 24 + 25 + ```sh 26 + pnpm run build 27 + ``` 28 + 29 + No intermediate files are generated - everything happens in memory! 30 + 31 + ## Adding Examples 32 + 33 + 1. Create a new `.tsp` file in `src/examples/` 34 + 2. Add it to the examples array in `src/pages/index.astro` 35 + 3. Run `pnpm run build` to see it on the site 36 + 37 + ## Commands 38 + 39 + | Command | Action | 40 + | :------------------------ | :----------------------------------------------- | 41 + | `pnpm install` | Installs dependencies | 42 + | `pnpm dev` | Starts local dev server at `localhost:4321` | 43 + | `pnpm build` | Build your production site to `./dist/` | 44 + | `pnpm preview` | Preview your build locally, before deploying | 45 + 46 + ## Structure 47 + 48 + ``` 49 + / 50 + ├── src/ 51 + │ ├── examples/ # TypeSpec examples 52 + │ │ ├── profile.tsp 53 + │ │ ├── getQuotes.tsp 54 + │ │ └── ... 55 + │ ├── pages/ 56 + │ │ └── index.astro # Landing page 57 + │ ├── components/ 58 + │ │ └── Playground.tsx 59 + │ └── utils/ 60 + │ └── compile.ts # In-memory TypeSpec compiler 61 + └── package.json 62 + ```
+11
packages/website/astro.config.mjs
··· 1 + // @ts-check 2 + import { defineConfig } from 'astro/config'; 3 + import react from '@astrojs/react'; 4 + 5 + // https://astro.build/config 6 + export default defineConfig({ 7 + integrations: [react()], 8 + vite: { 9 + // Vite config accessible for future playground tweaks 10 + } 11 + });
+25
packages/website/package.json
··· 1 + { 2 + "name": "website", 3 + "type": "module", 4 + "version": "0.0.1", 5 + "scripts": { 6 + "dev": "astro dev", 7 + "build": "astro build", 8 + "preview": "astro preview", 9 + "astro": "astro" 10 + }, 11 + "dependencies": { 12 + "@astrojs/react": "^4.4.0", 13 + "@tylex/emitter": "workspace:*", 14 + "astro": "^5.14.1", 15 + "json-stringify-pretty-compact": "^4.0.0", 16 + "react": "^19.2.0", 17 + "react-dom": "^19.2.0", 18 + "shiki": "^3.13.0" 19 + }, 20 + "devDependencies": { 21 + "@types/react": "^19.2.0", 22 + "@types/react-dom": "^19.2.0", 23 + "@typespec/compiler": "^1.4.0" 24 + } 25 + }
+9
packages/website/public/favicon.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128"> 2 + <path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" /> 3 + <style> 4 + path { fill: #000; } 5 + @media (prefers-color-scheme: dark) { 6 + path { fill: #FFF; } 7 + } 8 + </style> 9 + </svg>
+87
packages/website/src/components/Playground.tsx
··· 1 + import { useState } from 'react'; 2 + 3 + export default function Playground() { 4 + const [tylexCode, setTylexCode] = useState(`@lexicon("1") 5 + @nsid("app.bsky.feed.post") 6 + namespace AppBskyFeedPost; 7 + 8 + @record 9 + @key("tid") 10 + model Main { 11 + @required text: string; 12 + @required createdAt: datetime; 13 + }`); 14 + 15 + const [lexiconOutput] = useState('// Playground coming soon...'); 16 + 17 + return ( 18 + <div style={{ 19 + background: 'white', 20 + borderRadius: '12px', 21 + boxShadow: '0 4px 6px rgba(0, 0, 0, 0.05)', 22 + overflow: 'hidden', 23 + }}> 24 + <div style={{ 25 + display: 'grid', 26 + gridTemplateColumns: '1fr 1fr', 27 + borderBottom: '2px solid #f8fafc', 28 + background: '#fafafa', 29 + }}> 30 + <h3 style={{ 31 + padding: '1rem', 32 + textAlign: 'center', 33 + fontSize: '1rem', 34 + color: '#64748b', 35 + fontWeight: 600, 36 + margin: 0, 37 + }}> 38 + Tylex Input 39 + </h3> 40 + <h3 style={{ 41 + padding: '1rem', 42 + textAlign: 'center', 43 + fontSize: '1rem', 44 + color: '#64748b', 45 + fontWeight: 600, 46 + margin: 0, 47 + }}> 48 + Lexicon Output 49 + </h3> 50 + </div> 51 + 52 + <div style={{ 53 + display: 'grid', 54 + gridTemplateColumns: '1fr 1fr', 55 + minHeight: '400px', 56 + }}> 57 + <div style={{ borderRight: '1px solid #f8fafc' }}> 58 + <textarea 59 + value={tylexCode} 60 + onChange={(e) => setTylexCode(e.target.value)} 61 + style={{ 62 + width: '100%', 63 + height: '100%', 64 + padding: '1.5rem', 65 + border: 'none', 66 + fontFamily: 'Monaco, Menlo, monospace', 67 + fontSize: '0.875rem', 68 + resize: 'none', 69 + outline: 'none', 70 + }} 71 + placeholder="Enter Tylex code here..." 72 + /> 73 + </div> 74 + 75 + <div style={{ 76 + padding: '1.5rem', 77 + fontFamily: 'Monaco, Menlo, monospace', 78 + fontSize: '0.875rem', 79 + color: '#64748b', 80 + overflowX: 'auto', 81 + }}> 82 + <pre style={{ margin: 0 }}>{lexiconOutput}</pre> 83 + </div> 84 + </div> 85 + </div> 86 + ); 87 + }
+1059
packages/website/src/pages/index.astro
··· 1 + --- 2 + import Playground from '../components/Playground'; 3 + import { highlightCode } from '../utils/shiki'; 4 + import { compileToJson } from '../utils/compile'; 5 + import stringify from 'json-stringify-pretty-compact'; 6 + import { mkdtempSync, writeFileSync, rmSync } from 'fs'; 7 + import { join } from 'path'; 8 + import { tmpdir } from 'os'; 9 + 10 + // Define examples inline 11 + const examples = [ 12 + { 13 + title: "Records and properties", 14 + tylex: `import "@tylex/emitter"; 15 + 16 + namespace fm.teal.alpha.feed.play { 17 + @rec("tid") 18 + model Main { 19 + @maxItems(10) 20 + artistNames?: string[]; 21 + 22 + @required 23 + @minLength(1) 24 + @maxLength(256) 25 + trackName: string; 26 + 27 + @required 28 + playedTime: datetime; 29 + } 30 + }`, 31 + }, 32 + { 33 + title: "Refs and unions", 34 + tylex: `import "@tylex/emitter"; 35 + 36 + namespace app.bsky.feed.post { 37 + @rec("tid") 38 + model Main { 39 + @required 40 + @maxLength(3000) 41 + @maxGraphemes(300) 42 + text: string; 43 + 44 + @maxItems(3) 45 + langs?: language[]; 46 + 47 + embed?: Images | Video | unknown; 48 + } 49 + 50 + model Images { 51 + @required 52 + @maxItems(4) 53 + images: Image[]; 54 + } 55 + 56 + model Image { 57 + @required image: Blob<#["image/*"], 1000000>; 58 + @required alt: string; 59 + } 60 + 61 + model Video { 62 + @required video: Blob<#["video/mp4"], 100000000>; 63 + alt?: string; 64 + } 65 + }`, 66 + }, 67 + { 68 + title: "Queries and params", 69 + tylex: `import "@tylex/emitter"; 70 + 71 + namespace com.atproto.repo.listRecords { 72 + @query 73 + op main( 74 + @required repo: did, 75 + @required collection: string, 76 + 77 + @minValue(1) 78 + @maxValue(100) 79 + limit?: integer = 50, 80 + 81 + cursor?: string, 82 + reverse?: boolean 83 + ): ListOutput; 84 + 85 + @inline 86 + model ListOutput { 87 + cursor?: string; 88 + 89 + @required 90 + records: Record[]; 91 + } 92 + 93 + model Record { 94 + @required uri: atUri; 95 + @required cid: cid; 96 + @required value: unknown; 97 + } 98 + }`, 99 + }, 100 + ]; 101 + 102 + // Compile examples 103 + const highlighted = await Promise.all( 104 + examples.map(async (ex) => { 105 + // Create temporary file for compilation 106 + const tmpDir = mkdtempSync(join(tmpdir(), 'tylex-')); 107 + const tmpFile = join(tmpDir, 'example.tsp'); 108 + writeFileSync(tmpFile, ex.tylex); 109 + 110 + try { 111 + const lexiconJson = await compileToJson(tmpFile); 112 + const lexicon = stringify(JSON.parse(lexiconJson), { maxLength: 80 }); 113 + 114 + return { 115 + ...ex, 116 + tylexHtml: await highlightCode(ex.tylex, 'typespec'), 117 + lexiconHtml: await highlightCode(lexicon, 'json'), 118 + }; 119 + } finally { 120 + rmSync(tmpDir, { recursive: true, force: true }); 121 + } 122 + }) 123 + ); 124 + --- 125 + 126 + <!DOCTYPE html> 127 + <html lang="en"> 128 + <head> 129 + <meta charset="utf-8" /> 130 + <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 131 + <meta name="viewport" content="width=device-width" /> 132 + <meta name="generator" content={Astro.generator} /> 133 + <title>tylex – TypeSpec for AT Protocol Lexicons</title> 134 + </head> 135 + <body> 136 + <div class="container"> 137 + <header> 138 + <h1>typelex</h1> 139 + <p class="tagline">An experimental <a href="https://typespec.io" target="_blank" rel="noopener noreferrer">TypeSpec</a> emitter for <a href="https://atproto.com/specs/lexicon" target="_blank" rel="noopener noreferrer">Lexicon</a></p> 140 + 141 + <div class="hero-comparison"> 142 + <div class="comparison-content"> 143 + <div class="hero-panel"> 144 + <h3 class="hero-header"> 145 + Typelex 146 + </h3> 147 + <div class="hero-code" set:html={await highlightCode(`import "@tylex/emitter"; 148 + 149 + namespace app.bsky.actor.profile { 150 + @rec("self") 151 + model Main { 152 + @maxLength(64) 153 + @maxGraphemes(64) 154 + displayName?: string; 155 + 156 + @maxLength(256) 157 + @maxGraphemes(256) 158 + description?: string; 159 + } 160 + }`, 'typespec')} /> 161 + </div> 162 + <div class="hero-panel"> 163 + <h3 class="hero-header"> 164 + Lexicon 165 + </h3> 166 + <div class="hero-code" set:html={await highlightCode(stringify({ 167 + "lexicon": 1, 168 + "id": "app.bsky.actor.profile", 169 + "defs": { 170 + "main": { 171 + "type": "record", 172 + "key": "self", 173 + "record": { 174 + "type": "object", 175 + "properties": { 176 + "displayName": { 177 + "type": "string", 178 + "maxLength": 64, 179 + "maxGraphemes": 64 180 + }, 181 + "description": { 182 + "type": "string", 183 + "maxLength": 256, 184 + "maxGraphemes": 256 185 + } 186 + } 187 + } 188 + } 189 + } 190 + }, { maxLength: 50 }), 'json')} /> 191 + </div> 192 + </div> 193 + </div> 194 + 195 + <p class="hero-description"> 196 + Typelex lets you write AT <a href="https://atproto.com/specs/lexicon">Lexicons</a> in a more readable syntax. <br /> 197 + It uses <a href="https://typespec.io/">TypeSpec</a> for syntax, adding conventions for Lexicons. 198 + </p> 199 + 200 + <div class="hero-actions"> 201 + <a href="#install" class="install-cta">Install</a> 202 + <a href="https://tangled.org/@danabra.mov/typlex" target="_blank" rel="noopener noreferrer" class="star-btn"> 203 + Read Documentation 204 + </a> 205 + </div> 206 + </header> 207 + 208 + <div class="separator"></div> 209 + 210 + {highlighted.map(({ title, tylexHtml, lexiconHtml }) => ( 211 + <section> 212 + <h2>{title}</h2> 213 + <div class="comparison"> 214 + <div class="comparison-content"> 215 + <div class="code-panel"> 216 + <h3 class="code-header"> 217 + Typelex 218 + </h3> 219 + <div class="code-block" set:html={tylexHtml} /> 220 + </div> 221 + <div class="code-panel"> 222 + <h3 class="code-header"> 223 + Lexicon 224 + </h3> 225 + <div class="code-block" set:html={lexiconHtml} /> 226 + </div> 227 + </div> 228 + </div> 229 + </section> 230 + ))} 231 + 232 + <div class="separator"></div> 233 + 234 + <section class="playground-section"> 235 + <h2>Playground</h2> 236 + <Playground client:load /> 237 + </section> 238 + 239 + <div class="separator"></div> 240 + 241 + <section class="install-section" id="install"> 242 + <h2>Install</h2> 243 + <div class="install-grid"> 244 + <div class="install-notice"> 245 + <p class="notice-text">This is an early alpha software. If you ship with borked lexicons, it’s not my fault.</p> 246 + </div> 247 + <div class="install-step"> 248 + <div class="step-number">1</div> 249 + <div class="step-content"> 250 + <h3>Install packages</h3> 251 + <div class="install-box" set:html={await highlightCode('npm install -D @typespec/compiler @tylex/emitter', 'bash')} /> 252 + </div> 253 + </div> 254 + 255 + <div class="install-step"> 256 + <div class="step-number">2</div> 257 + <div class="step-content"> 258 + <h3>Add <a href="https://typespec.io/docs/handbook/configuration/configuration/" target="_blank" rel="noopener noreferrer">tspconfig.yaml</a></h3> 259 + <div class="install-box" set:html={await highlightCode(`emit: 260 + - "@tylex/emitter" 261 + options: 262 + "@tylex/emitter": 263 + output-dir: "./lexicon"`, 'yaml')} /> 264 + </div> 265 + </div> 266 + 267 + <div class="install-step"> 268 + <div class="step-number">3</div> 269 + <div class="step-content"> 270 + <h3>Configure scripts</h3> 271 + <div class="install-box" set:html={await highlightCode(`{ 272 + "scripts": { 273 + "build": "npm run build:lexicon && npm run build:codegen", 274 + "build:lexicon": "tsp compile . && tsp format **/*.tsp", 275 + "build:codegen": "lex gen-api --yes ./src lexicon/app/example/*.json" 276 + } 277 + }`, 'json')} /> 278 + </div> 279 + </div> 280 + 281 + <div class="install-step"> 282 + <div class="step-number">4</div> 283 + <div class="step-content"> 284 + <h3>Set up VS Code</h3> 285 + <p class="step-description">Install the <a href="https://typespec.io/docs/introduction/editor/vscode/" target="_blank" rel="noopener noreferrer">TypeSpec for VS Code extension</a> for syntax highlighting and IntelliSense.</p> 286 + </div> 287 + </div> 288 + </div> 289 + </section> 290 + 291 + <footer> 292 + </footer> 293 + </div> 294 + 295 + <script> 296 + document.addEventListener('DOMContentLoaded', () => { 297 + const scrollables = document.querySelectorAll('.code-panel:last-child .code-block, .hero-panel:last-child .hero-code'); 298 + 299 + // Update gradient mask based on scroll position 300 + scrollables.forEach(block => { 301 + const updateMask = () => { 302 + const isAtBottom = block.scrollHeight - block.scrollTop <= block.clientHeight + 5; 303 + if (isAtBottom) { 304 + block.style.maskImage = 'none'; 305 + block.style.webkitMaskImage = 'none'; 306 + } else { 307 + block.style.maskImage = 'linear-gradient(to bottom, black calc(100% - 150px), transparent 100%)'; 308 + block.style.webkitMaskImage = 'linear-gradient(to bottom, black calc(100% - 150px), transparent 100%)'; 309 + } 310 + }; 311 + 312 + block.addEventListener('scroll', updateMask); 313 + updateMask(); // Initial check 314 + }); 315 + 316 + // Freeze inner scrollable blocks while scrolling the page 317 + let scrollTimeout; 318 + const freezeInnerScroll = () => { 319 + document.body.classList.add('outer-scrolling'); 320 + 321 + clearTimeout(scrollTimeout); 322 + scrollTimeout = setTimeout(() => { 323 + document.body.classList.remove('outer-scrolling'); 324 + }, 150); 325 + }; 326 + 327 + // Listen for both scroll and wheel events to catch scrolling early 328 + window.addEventListener('scroll', freezeInnerScroll, { passive: true }); 329 + window.addEventListener('wheel', (e) => { 330 + // Only freeze if the wheel event is not inside a scrollable block 331 + const target = e.target; 332 + const isInsideScrollable = target.closest('.code-panel:last-child .code-block, .hero-panel:last-child .hero-code'); 333 + if (!isInsideScrollable) { 334 + freezeInnerScroll(); 335 + } 336 + }, { passive: true }); 337 + }); 338 + </script> 339 + </body> 340 + </html> 341 + 342 + <style is:global> 343 + * { 344 + margin: 0; 345 + padding: 0; 346 + box-sizing: border-box; 347 + } 348 + 349 + html { 350 + scroll-behavior: smooth; 351 + } 352 + 353 + body { 354 + font-family: system-ui, -apple-system, sans-serif; 355 + line-height: 1.6; 356 + color: #1e293b; 357 + background: #f8fafc; 358 + font-size: 16px; 359 + position: relative; 360 + overflow-x: hidden; 361 + } 362 + 363 + body::before { 364 + content: ''; 365 + position: fixed; 366 + top: -100px; 367 + right: -100px; 368 + width: 300px; 369 + height: 300px; 370 + background: radial-gradient(circle, rgba(255, 133, 193, 0.15) 0%, rgba(255, 133, 193, 0.08) 40%, transparent 70%); 371 + border-radius: 50%; 372 + pointer-events: none; 373 + z-index: 0; 374 + } 375 + 376 + @media (min-width: 768px) { 377 + body { 378 + font-size: 17px; 379 + } 380 + } 381 + 382 + .container { 383 + max-width: 1200px; 384 + margin: 0 auto; 385 + padding: 1rem; 386 + position: relative; 387 + z-index: 1; 388 + } 389 + 390 + @media (min-width: 768px) { 391 + .container { 392 + padding: 2rem; 393 + } 394 + } 395 + 396 + header { 397 + text-align: center; 398 + padding: 3rem 1rem 2rem; 399 + margin: 0 auto; 400 + } 401 + 402 + @media (min-width: 768px) { 403 + header { 404 + padding: 4rem 1rem 3rem; 405 + } 406 + } 407 + 408 + header > h1, 409 + header > .tagline { 410 + max-width: 680px; 411 + margin-left: auto; 412 + margin-right: auto; 413 + } 414 + 415 + h1 { 416 + font-size: 2.5rem; 417 + font-weight: 800; 418 + background: linear-gradient(90deg, #4a9eff 0%, #7a8ef7 40%, #ff85c1 70%, #9b7ef7 100%); 419 + -webkit-background-clip: text; 420 + -webkit-text-fill-color: transparent; 421 + background-clip: text; 422 + margin-bottom: 0.5rem; 423 + } 424 + 425 + @media (min-width: 768px) { 426 + h1 { 427 + font-size: 4rem; 428 + margin-bottom: 0.75rem; 429 + } 430 + } 431 + 432 + .tagline { 433 + font-size: 1.1875rem; 434 + color: #64748b; 435 + margin-bottom: 1.25rem; 436 + font-weight: 500; 437 + line-height: 1.5; 438 + } 439 + 440 + .tagline a { 441 + color: inherit; 442 + text-decoration: none; 443 + transition: color 0.2s ease; 444 + } 445 + 446 + .tagline a:first-of-type:hover { 447 + color: #7a8ef7; 448 + } 449 + 450 + .tagline a:last-of-type:hover { 451 + color: #e879b9; 452 + } 453 + 454 + @media (min-width: 768px) { 455 + .tagline { 456 + font-size: 1.625rem; 457 + margin-bottom: 1.5rem; 458 + } 459 + } 460 + 461 + .hero-comparison { 462 + margin-top: 2.5rem; 463 + background: #1e1b29; 464 + border-radius: 12px; 465 + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 466 + overflow: hidden; 467 + margin-left: -1rem; 468 + margin-right: -1rem; 469 + } 470 + 471 + @media (min-width: 768px) { 472 + .hero-comparison { 473 + margin-top: 3rem; 474 + margin-left: 0; 475 + margin-right: 0; 476 + } 477 + } 478 + 479 + .hero-description { 480 + margin-top: 2rem; 481 + font-size: 1.125rem; 482 + line-height: 1.7; 483 + color: #475569; 484 + max-width: 680px; 485 + margin-left: auto; 486 + margin-right: auto; 487 + } 488 + 489 + .hero-description a { 490 + color: #6366f1; 491 + text-decoration: none; 492 + border-bottom: 1px solid #c7d2fe; 493 + transition: border-color 0.2s ease, color 0.2s ease; 494 + } 495 + 496 + .hero-description a:hover { 497 + color: #4f46e5; 498 + border-bottom-color: #6366f1; 499 + } 500 + 501 + @media (min-width: 768px) { 502 + .hero-description { 503 + margin-top: 2.5rem; 504 + font-size: 1.25rem; 505 + } 506 + } 507 + 508 + .alpha-disclaimer { 509 + margin-top: 1.5rem; 510 + font-size: 1rem; 511 + color: #64748b; 512 + max-width: 680px; 513 + margin-left: auto; 514 + margin-right: auto; 515 + font-weight: 500; 516 + display: flex; 517 + align-items: center; 518 + justify-content: center; 519 + gap: 0.625rem; 520 + } 521 + 522 + .alpha-badge { 523 + display: inline-block; 524 + padding: 0.25rem 0.625rem; 525 + background: linear-gradient(135deg, #fbbf24, #f59e0b); 526 + color: white; 527 + font-size: 0.75rem; 528 + font-weight: 700; 529 + text-transform: uppercase; 530 + letter-spacing: 0.05em; 531 + border-radius: 6px; 532 + box-shadow: 0 1px 3px rgba(251, 191, 36, 0.3); 533 + } 534 + 535 + @media (min-width: 768px) { 536 + .alpha-disclaimer { 537 + font-size: 1.125rem; 538 + margin-top: 1.75rem; 539 + } 540 + 541 + .alpha-badge { 542 + font-size: 0.8125rem; 543 + padding: 0.3125rem 0.75rem; 544 + } 545 + } 546 + 547 + .hero-actions { 548 + display: flex; 549 + flex-direction: column; 550 + gap: 1rem; 551 + margin-top: 2.5rem; 552 + align-items: center; 553 + } 554 + 555 + @media (min-width: 640px) { 556 + .hero-actions { 557 + flex-direction: row; 558 + justify-content: center; 559 + gap: 1rem; 560 + } 561 + } 562 + 563 + .install-cta { 564 + display: inline-block; 565 + padding: 0.75rem 1.75rem; 566 + background: linear-gradient(135deg, #7a8ef7 0%, #9483f7 70%, #b87ed8 100%); 567 + color: white; 568 + text-decoration: none; 569 + border-radius: 8px; 570 + font-weight: 700; 571 + font-size: 1.125rem; 572 + letter-spacing: 0.01em; 573 + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); 574 + box-shadow: 575 + 0 1px 0 0 rgba(255, 255, 255, 0.25) inset, 576 + 0 -1px 0 0 rgba(0, 0, 0, 0.1) inset, 577 + 0 0 0 1px rgba(122, 142, 247, 0.3), 578 + 0 2px 4px rgba(122, 142, 247, 0.35), 579 + 0 3px 6px rgba(0, 0, 0, 0.1); 580 + border: none; 581 + position: relative; 582 + } 583 + 584 + .install-cta:hover { 585 + background: linear-gradient(135deg, #7384e7 0%, #8d7ce7 70%, #b175d1 100%); 586 + box-shadow: 587 + 0 1px 0 0 rgba(255, 255, 255, 0.3) inset, 588 + 0 -1px 0 0 rgba(0, 0, 0, 0.12) inset, 589 + 0 0 0 1px rgba(122, 142, 247, 0.4), 590 + 0 3px 6px rgba(122, 142, 247, 0.4), 591 + 0 4px 8px rgba(0, 0, 0, 0.12); 592 + } 593 + 594 + .install-cta:active { 595 + background: linear-gradient(135deg, #6a7ee5 0%, #8473e5 70%, #a86ec8 100%); 596 + box-shadow: 597 + 0 0 0 1px rgba(122, 142, 247, 0.5), 598 + 0 1px 2px rgba(0, 0, 0, 0.2) inset, 599 + 0 2px 4px rgba(0, 0, 0, 0.15); 600 + transform: translateY(1px); 601 + } 602 + 603 + .star-btn { 604 + display: inline-flex; 605 + align-items: center; 606 + gap: 0.625rem; 607 + padding: 0.75rem 1.75rem; 608 + background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%); 609 + color: #334155; 610 + text-decoration: none; 611 + border-radius: 8px; 612 + font-weight: 700; 613 + font-size: 1.125rem; 614 + letter-spacing: 0.01em; 615 + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); 616 + box-shadow: 617 + 0 1px 0 0 rgba(255, 255, 255, 0.6) inset, 618 + 0 -1px 0 0 rgba(0, 0, 0, 0.05) inset, 619 + 0 0 0 1px #cbd5e1, 620 + 0 2px 4px rgba(0, 0, 0, 0.08), 621 + 0 3px 6px rgba(0, 0, 0, 0.05); 622 + border: none; 623 + } 624 + 625 + .star-btn:hover { 626 + background: linear-gradient(180deg, #ffffff 0%, #f5f5f5 100%); 627 + color: #1e293b; 628 + box-shadow: 629 + 0 1px 0 0 rgba(255, 255, 255, 0.7) inset, 630 + 0 -1px 0 0 rgba(0, 0, 0, 0.06) inset, 631 + 0 0 0 1px #94a3b8, 632 + 0 3px 6px rgba(0, 0, 0, 0.1), 633 + 0 4px 8px rgba(0, 0, 0, 0.07); 634 + } 635 + 636 + .star-btn:active { 637 + background: linear-gradient(180deg, #f5f5f5 0%, #e5e7eb 100%); 638 + box-shadow: 639 + 0 0 0 1px #94a3b8, 640 + 0 1px 2px rgba(0, 0, 0, 0.15) inset, 641 + 0 2px 4px rgba(0, 0, 0, 0.08); 642 + transform: translateY(1px); 643 + } 644 + 645 + .star-icon { 646 + font-size: 1.125rem; 647 + color: #fbbf24; 648 + } 649 + 650 + @media (min-width: 768px) { 651 + .install-cta { 652 + padding: 0.875rem 2.25rem; 653 + font-size: 1.3125rem; 654 + } 655 + 656 + .star-btn { 657 + padding: 0.875rem 2rem; 658 + font-size: 1.3125rem; 659 + } 660 + 661 + .star-icon { 662 + font-size: 1.375rem; 663 + } 664 + } 665 + 666 + .separator { 667 + height: 1px; 668 + background: linear-gradient(to right, transparent, #e2e8f0 20%, #e2e8f0 80%, transparent); 669 + margin: 4rem 0; 670 + } 671 + 672 + @media (min-width: 768px) { 673 + .separator { 674 + margin: 5rem 0; 675 + } 676 + } 677 + 678 + .install-section { 679 + margin: 0; 680 + padding: 0; 681 + } 682 + 683 + .install-section h2 { 684 + text-align: left; 685 + font-size: 1.75rem; 686 + margin-bottom: 2rem; 687 + color: #1e293b; 688 + font-weight: 700; 689 + max-width: 700px; 690 + margin-left: auto; 691 + margin-right: auto; 692 + } 693 + 694 + .install-notice { 695 + padding: 1rem 1.5rem; 696 + background: #fef3c7; 697 + border: 1px solid #fbbf24; 698 + border-radius: 10px; 699 + text-align: center; 700 + } 701 + 702 + .notice-text { 703 + margin: 0; 704 + font-size: 1.0625rem; 705 + line-height: 1.5; 706 + font-weight: 600; 707 + color: #92400e; 708 + } 709 + 710 + .install-grid { 711 + display: grid; 712 + grid-template-columns: 1fr; 713 + gap: 2.5rem; 714 + max-width: 700px; 715 + margin: 0 auto; 716 + padding: 0; 717 + } 718 + 719 + .install-step { 720 + position: relative; 721 + } 722 + 723 + .step-number { 724 + position: absolute; 725 + left: -3.5rem; 726 + top: 0.125rem; 727 + width: 2.25rem; 728 + height: 2.25rem; 729 + background: linear-gradient(135deg, #7a8ef7, #ff85c1); 730 + color: white; 731 + border-radius: 50%; 732 + display: flex; 733 + align-items: center; 734 + justify-content: center; 735 + font-weight: 700; 736 + font-size: 0.9375rem; 737 + } 738 + 739 + .step-content { 740 + width: 100%; 741 + } 742 + 743 + .step-content h3 { 744 + font-size: 1.25rem; 745 + margin: 0 0 1.25rem 0; 746 + color: #1e293b; 747 + font-weight: 600; 748 + } 749 + 750 + .step-content h3 a { 751 + color: inherit; 752 + text-decoration: none; 753 + border-bottom: 1px solid #cbd5e1; 754 + transition: border-color 0.2s ease, color 0.2s ease; 755 + } 756 + 757 + .step-content h3 a:hover { 758 + color: #6366f1; 759 + border-bottom-color: #6366f1; 760 + } 761 + 762 + .step-description { 763 + margin-top: 1rem; 764 + font-size: 1rem; 765 + color: #64748b; 766 + line-height: 1.7; 767 + } 768 + 769 + .step-description a { 770 + color: #6366f1; 771 + text-decoration: none; 772 + border-bottom: 1px solid #c7d2fe; 773 + transition: border-color 0.2s ease, color 0.2s ease; 774 + } 775 + 776 + .step-description a:hover { 777 + color: #4f46e5; 778 + border-bottom-color: #6366f1; 779 + } 780 + 781 + .install-box { 782 + background: #1e1b29; 783 + border-radius: 8px; 784 + overflow: hidden; 785 + } 786 + 787 + .install-box + .step-description { 788 + margin-top: 1.25rem; 789 + } 790 + 791 + .install-box pre { 792 + margin: 0; 793 + padding: 0.875rem 1rem; 794 + overflow-x: auto; 795 + background: transparent !important; 796 + } 797 + 798 + .install-box code { 799 + font-family: 'Monaco', 'Menlo', monospace; 800 + font-size: 0.8125rem !important; 801 + line-height: 1.6; 802 + } 803 + 804 + .install-box pre code, 805 + .install-box pre code * { 806 + font-size: inherit !important; 807 + } 808 + 809 + @media (min-width: 768px) { 810 + .install-section h2 { 811 + font-size: 2rem; 812 + margin-bottom: 2rem; 813 + } 814 + 815 + .install-notice { 816 + padding: 1.5rem 2rem; 817 + } 818 + 819 + .notice-text { 820 + font-size: 1.1875rem; 821 + } 822 + 823 + .install-grid { 824 + gap: 3.5rem; 825 + } 826 + 827 + .step-number { 828 + left: -4rem; 829 + width: 2.5rem; 830 + height: 2.5rem; 831 + font-size: 1rem; 832 + } 833 + 834 + .step-content h3 { 835 + font-size: 1.375rem; 836 + margin-bottom: 1.5rem; 837 + } 838 + 839 + .step-description { 840 + font-size: 1.0625rem; 841 + } 842 + 843 + .install-box pre { 844 + padding: 1rem 1.25rem; 845 + } 846 + 847 + .install-box code { 848 + font-size: 0.875rem !important; 849 + } 850 + } 851 + 852 + .comparison, 853 + .hero-comparison { 854 + background: #1e1b29; 855 + border-radius: 12px; 856 + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 857 + overflow: hidden; 858 + } 859 + 860 + .comparison { 861 + margin: 0 auto 2rem; 862 + max-width: 100%; 863 + } 864 + 865 + .comparison-content { 866 + position: relative; 867 + padding: 0.75rem; 868 + display: grid; 869 + grid-template-columns: 1fr; 870 + gap: 1.5rem; 871 + } 872 + 873 + @media (min-width: 768px) { 874 + .comparison-content { 875 + padding: 1rem; 876 + grid-template-columns: 1fr 1fr; 877 + gap: 2rem; 878 + } 879 + } 880 + 881 + .code-panel, 882 + .hero-panel { 883 + position: relative; 884 + min-width: 0; 885 + overflow: hidden; 886 + text-align: left; 887 + } 888 + 889 + .code-header, 890 + .hero-header { 891 + padding: 0.5rem 1rem; 892 + background: #252231; 893 + border-radius: 8px 8px 0 0; 894 + font-size: 0.75rem; 895 + font-weight: 600; 896 + text-transform: uppercase; 897 + letter-spacing: 0.05em; 898 + margin: 0; 899 + color: #94a3b8; 900 + } 901 + 902 + .code-header a, 903 + .hero-header a { 904 + color: #94a3b8; 905 + text-decoration: none; 906 + transition: color 0.2s ease; 907 + } 908 + 909 + .code-header a:hover, 910 + .hero-header a:hover { 911 + color: #cbd5e1; 912 + } 913 + 914 + @media (min-width: 768px) { 915 + .code-header, 916 + .hero-header { 917 + font-size: 0.8125rem; 918 + padding: 0.625rem 1rem; 919 + } 920 + } 921 + 922 + .code-block, 923 + .hero-code { 924 + position: relative; 925 + text-align: left; 926 + } 927 + 928 + .code-panel:last-child .code-block, 929 + .hero-panel:last-child .hero-code { 930 + overflow-y: auto; 931 + max-height: 400px; 932 + -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 100px), transparent 100%); 933 + mask-image: linear-gradient(to bottom, black calc(100% - 100px), transparent 100%); 934 + } 935 + 936 + /* Freeze inner scrollables when scrolling the page */ 937 + body.outer-scrolling .code-panel:last-child .code-block, 938 + body.outer-scrolling .hero-panel:last-child .hero-code { 939 + pointer-events: none; 940 + overflow-y: hidden; 941 + } 942 + 943 + @media (min-width: 768px) { 944 + .code-panel:first-child, 945 + .hero-panel:first-child { 946 + position: relative; 947 + z-index: 1; 948 + } 949 + 950 + .code-panel:last-child, 951 + .hero-panel:last-child { 952 + position: absolute; 953 + top: 1rem; 954 + bottom: 1rem; 955 + right: 1rem; 956 + left: calc(50% + 1rem); 957 + } 958 + 959 + .code-panel:last-child .code-block, 960 + .hero-panel:last-child .hero-code { 961 + max-height: none; 962 + height: 100%; 963 + padding-bottom: 1.5rem; 964 + -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 150px), transparent 100%); 965 + mask-image: linear-gradient(to bottom, black calc(100% - 150px), transparent 100%); 966 + } 967 + 968 + body.outer-scrolling .code-panel:last-child .code-block, 969 + body.outer-scrolling .hero-panel:last-child .hero-code { 970 + pointer-events: none; 971 + overflow-y: hidden; 972 + } 973 + } 974 + 975 + .code-block pre, 976 + .hero-code pre { 977 + margin: 0; 978 + padding: 1rem; 979 + background: transparent !important; 980 + overflow-x: auto; 981 + overflow-y: visible; 982 + -webkit-overflow-scrolling: touch; 983 + max-width: 100%; 984 + } 985 + 986 + @media (min-width: 768px) { 987 + .code-block pre, 988 + .hero-code pre { 989 + padding: 1.5rem; 990 + } 991 + } 992 + 993 + .code-block code, 994 + .hero-code code { 995 + font-family: 'Monaco', 'Menlo', monospace; 996 + font-size: 0.8125rem !important; 997 + line-height: 1.6; 998 + white-space: pre; 999 + text-align: left; 1000 + } 1001 + 1002 + @media (min-width: 768px) { 1003 + .code-block code, 1004 + .hero-code code { 1005 + font-size: 0.9375rem !important; 1006 + } 1007 + } 1008 + 1009 + .code-block pre code, 1010 + .code-block pre code *, 1011 + .hero-code pre code, 1012 + .hero-code pre code * { 1013 + font-size: inherit !important; 1014 + } 1015 + 1016 + section { 1017 + margin: 3rem 0 0; 1018 + } 1019 + 1020 + section h2 { 1021 + font-size: 1.5rem; 1022 + margin-bottom: 1.5rem; 1023 + text-align: left; 1024 + color: #1e293b; 1025 + font-weight: 700; 1026 + max-width: 700px; 1027 + margin-left: auto; 1028 + margin-right: auto; 1029 + } 1030 + 1031 + @media (min-width: 768px) { 1032 + section { 1033 + margin: 4rem 0 0; 1034 + } 1035 + 1036 + section h2 { 1037 + font-size: 2rem; 1038 + margin-bottom: 2.5rem; 1039 + } 1040 + } 1041 + 1042 + .playground-section { 1043 + margin: 0; 1044 + } 1045 + 1046 + footer { 1047 + text-align: center; 1048 + padding: 4rem 1rem 3rem; 1049 + color: #64748b; 1050 + margin-top: 4rem; 1051 + } 1052 + 1053 + @media (min-width: 768px) { 1054 + footer { 1055 + padding: 5rem 1rem 4rem; 1056 + margin-top: 5rem; 1057 + } 1058 + } 1059 + </style>
+1430
packages/website/src/typespec-grammar.json
··· 1 + { 2 + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 + "name": "TypeSpec", 4 + "scopeName": "source.tsp", 5 + "fileTypes": [ 6 + "tsp" 7 + ], 8 + "patterns": [ 9 + { 10 + "include": "#statement" 11 + } 12 + ], 13 + "repository": { 14 + "alias-id": { 15 + "name": "meta.alias-id.typespec", 16 + "begin": "(=)\\s*", 17 + "beginCaptures": { 18 + "1": { 19 + "name": "keyword.operator.assignment.tsp" 20 + } 21 + }, 22 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 23 + "patterns": [ 24 + { 25 + "include": "#expression" 26 + } 27 + ] 28 + }, 29 + "alias-statement": { 30 + "name": "meta.alias-statement.typespec", 31 + "begin": "\\b(alias)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)\\s*", 32 + "beginCaptures": { 33 + "1": { 34 + "name": "keyword.other.tsp" 35 + }, 36 + "2": { 37 + "name": "entity.name.type.tsp" 38 + } 39 + }, 40 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 41 + "patterns": [ 42 + { 43 + "include": "#alias-id" 44 + }, 45 + { 46 + "include": "#type-parameters" 47 + } 48 + ] 49 + }, 50 + "augment-decorator-statement": { 51 + "name": "meta.augment-decorator-statement.typespec", 52 + "begin": "((@@)\\b[_$[:alpha:]](?:[_$[:alnum:]]|\\.[_$[:alpha:]])*\\b)", 53 + "beginCaptures": { 54 + "1": { 55 + "name": "entity.name.tag.tsp" 56 + }, 57 + "2": { 58 + "name": "entity.name.tag.tsp" 59 + } 60 + }, 61 + "end": "(?=([_$[:alpha:]]|`))|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 62 + "patterns": [ 63 + { 64 + "include": "#token" 65 + }, 66 + { 67 + "include": "#parenthesized-expression" 68 + } 69 + ] 70 + }, 71 + "block-comment": { 72 + "name": "comment.block.tsp", 73 + "begin": "/\\*", 74 + "end": "\\*/" 75 + }, 76 + "boolean-literal": { 77 + "name": "constant.language.tsp", 78 + "match": "\\b(true|false)\\b" 79 + }, 80 + "callExpression": { 81 + "name": "meta.callExpression.typespec", 82 + "begin": "(\\b[_$[:alpha:]](?:[_$[:alnum:]]|\\.[_$[:alpha:]])*\\b)\\s*(\\()", 83 + "beginCaptures": { 84 + "1": { 85 + "name": "entity.name.function.tsp" 86 + }, 87 + "2": { 88 + "name": "punctuation.parenthesis.open.tsp" 89 + } 90 + }, 91 + "end": "\\)", 92 + "endCaptures": { 93 + "0": { 94 + "name": "punctuation.parenthesis.close.tsp" 95 + } 96 + }, 97 + "patterns": [ 98 + { 99 + "include": "#token" 100 + }, 101 + { 102 + "include": "#expression" 103 + }, 104 + { 105 + "include": "#punctuation-comma" 106 + } 107 + ] 108 + }, 109 + "const-statement": { 110 + "name": "meta.const-statement.typespec", 111 + "begin": "\\b(const)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 112 + "beginCaptures": { 113 + "1": { 114 + "name": "keyword.other.tsp" 115 + }, 116 + "2": { 117 + "name": "variable.name.tsp" 118 + } 119 + }, 120 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 121 + "patterns": [ 122 + { 123 + "include": "#type-annotation" 124 + }, 125 + { 126 + "include": "#operator-assignment" 127 + }, 128 + { 129 + "include": "#expression" 130 + } 131 + ] 132 + }, 133 + "decorator": { 134 + "name": "meta.decorator.typespec", 135 + "begin": "((@)\\b[_$[:alpha:]](?:[_$[:alnum:]]|\\.[_$[:alpha:]])*\\b)", 136 + "beginCaptures": { 137 + "1": { 138 + "name": "entity.name.tag.tsp" 139 + }, 140 + "2": { 141 + "name": "entity.name.tag.tsp" 142 + } 143 + }, 144 + "end": "(?=([_$[:alpha:]]|`))|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 145 + "patterns": [ 146 + { 147 + "include": "#token" 148 + }, 149 + { 150 + "include": "#parenthesized-expression" 151 + } 152 + ] 153 + }, 154 + "decorator-declaration-statement": { 155 + "name": "meta.decorator-declaration-statement.typespec", 156 + "begin": "(?:(extern)\\s+)?\\b(dec)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 157 + "beginCaptures": { 158 + "1": { 159 + "name": "keyword.other.tsp" 160 + }, 161 + "2": { 162 + "name": "keyword.other.tsp" 163 + }, 164 + "3": { 165 + "name": "entity.name.function.tsp" 166 + } 167 + }, 168 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 169 + "patterns": [ 170 + { 171 + "include": "#token" 172 + }, 173 + { 174 + "include": "#operation-parameters" 175 + } 176 + ] 177 + }, 178 + "directive": { 179 + "name": "meta.directive.typespec", 180 + "begin": "\\s*(#\\b[_$[:alpha:]][_$[:alnum:]]*\\b)", 181 + "beginCaptures": { 182 + "1": { 183 + "name": "keyword.directive.name.tsp" 184 + } 185 + }, 186 + "end": "$|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 187 + "patterns": [ 188 + { 189 + "include": "#string-literal" 190 + }, 191 + { 192 + "include": "#identifier-expression" 193 + } 194 + ] 195 + }, 196 + "doc-comment": { 197 + "name": "comment.block.tsp", 198 + "begin": "/\\*\\*", 199 + "beginCaptures": { 200 + "0": { 201 + "name": "comment.block.tsp" 202 + } 203 + }, 204 + "end": "\\*/", 205 + "endCaptures": { 206 + "0": { 207 + "name": "comment.block.tsp" 208 + } 209 + }, 210 + "patterns": [ 211 + { 212 + "include": "#doc-comment-block" 213 + } 214 + ] 215 + }, 216 + "doc-comment-block": { 217 + "patterns": [ 218 + { 219 + "include": "#doc-comment-param" 220 + }, 221 + { 222 + "include": "#doc-comment-return-tag" 223 + }, 224 + { 225 + "include": "#doc-comment-unknown-tag" 226 + } 227 + ] 228 + }, 229 + "doc-comment-param": { 230 + "name": "comment.block.tsp", 231 + "match": "(?x)((@)(?:param|template|prop))\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)\\b", 232 + "captures": { 233 + "1": { 234 + "name": "keyword.tag.tspdoc" 235 + }, 236 + "2": { 237 + "name": "keyword.tag.tspdoc" 238 + }, 239 + "3": { 240 + "name": "variable.name.tsp" 241 + } 242 + } 243 + }, 244 + "doc-comment-return-tag": { 245 + "name": "comment.block.tsp", 246 + "match": "(?x)((@)(?:returns))\\b", 247 + "captures": { 248 + "1": { 249 + "name": "keyword.tag.tspdoc" 250 + }, 251 + "2": { 252 + "name": "keyword.tag.tspdoc" 253 + } 254 + } 255 + }, 256 + "doc-comment-unknown-tag": { 257 + "name": "comment.block.tsp", 258 + "match": "(?x)((@)(?:\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`))\\b", 259 + "captures": { 260 + "1": { 261 + "name": "entity.name.tag.tsp" 262 + }, 263 + "2": { 264 + "name": "entity.name.tag.tsp" 265 + } 266 + } 267 + }, 268 + "enum-body": { 269 + "name": "meta.enum-body.typespec", 270 + "begin": "\\{", 271 + "beginCaptures": { 272 + "0": { 273 + "name": "punctuation.curlybrace.open.tsp" 274 + } 275 + }, 276 + "end": "\\}", 277 + "endCaptures": { 278 + "0": { 279 + "name": "punctuation.curlybrace.close.tsp" 280 + } 281 + }, 282 + "patterns": [ 283 + { 284 + "include": "#enum-member" 285 + }, 286 + { 287 + "include": "#token" 288 + }, 289 + { 290 + "include": "#directive" 291 + }, 292 + { 293 + "include": "#decorator" 294 + }, 295 + { 296 + "include": "#punctuation-comma" 297 + } 298 + ] 299 + }, 300 + "enum-member": { 301 + "name": "meta.enum-member.typespec", 302 + "begin": "(?:(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)\\s*(:?))", 303 + "beginCaptures": { 304 + "1": { 305 + "name": "variable.name.tsp" 306 + }, 307 + "2": { 308 + "name": "keyword.operator.type.annotation.tsp" 309 + } 310 + }, 311 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 312 + "patterns": [ 313 + { 314 + "include": "#token" 315 + }, 316 + { 317 + "include": "#type-annotation" 318 + } 319 + ] 320 + }, 321 + "enum-statement": { 322 + "name": "meta.enum-statement.typespec", 323 + "begin": "\\b(enum)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 324 + "beginCaptures": { 325 + "1": { 326 + "name": "keyword.other.tsp" 327 + }, 328 + "2": { 329 + "name": "entity.name.type.tsp" 330 + } 331 + }, 332 + "end": "(?<=\\})|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 333 + "patterns": [ 334 + { 335 + "include": "#token" 336 + }, 337 + { 338 + "include": "#enum-body" 339 + } 340 + ] 341 + }, 342 + "escape-character": { 343 + "name": "constant.character.escape.tsp", 344 + "match": "\\\\." 345 + }, 346 + "expression": { 347 + "patterns": [ 348 + { 349 + "include": "#token" 350 + }, 351 + { 352 + "include": "#directive" 353 + }, 354 + { 355 + "include": "#parenthesized-expression" 356 + }, 357 + { 358 + "include": "#valueof" 359 + }, 360 + { 361 + "include": "#typeof" 362 + }, 363 + { 364 + "include": "#type-arguments" 365 + }, 366 + { 367 + "include": "#object-literal" 368 + }, 369 + { 370 + "include": "#tuple-literal" 371 + }, 372 + { 373 + "include": "#tuple-expression" 374 + }, 375 + { 376 + "include": "#model-expression" 377 + }, 378 + { 379 + "include": "#callExpression" 380 + }, 381 + { 382 + "include": "#identifier-expression" 383 + } 384 + ] 385 + }, 386 + "function-declaration-statement": { 387 + "name": "meta.function-declaration-statement.typespec", 388 + "begin": "(?:(extern)\\s+)?\\b(fn)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 389 + "beginCaptures": { 390 + "1": { 391 + "name": "keyword.other.tsp" 392 + }, 393 + "2": { 394 + "name": "keyword.other.tsp" 395 + }, 396 + "3": { 397 + "name": "entity.name.function.tsp" 398 + } 399 + }, 400 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 401 + "patterns": [ 402 + { 403 + "include": "#token" 404 + }, 405 + { 406 + "include": "#operation-parameters" 407 + }, 408 + { 409 + "include": "#type-annotation" 410 + } 411 + ] 412 + }, 413 + "identifier-expression": { 414 + "name": "entity.name.type.tsp", 415 + "match": "\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`" 416 + }, 417 + "import-statement": { 418 + "name": "meta.import-statement.typespec", 419 + "begin": "\\b(import)\\b", 420 + "beginCaptures": { 421 + "1": { 422 + "name": "keyword.other.tsp" 423 + } 424 + }, 425 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 426 + "patterns": [ 427 + { 428 + "include": "#token" 429 + } 430 + ] 431 + }, 432 + "interface-body": { 433 + "name": "meta.interface-body.typespec", 434 + "begin": "\\{", 435 + "beginCaptures": { 436 + "0": { 437 + "name": "punctuation.curlybrace.open.tsp" 438 + } 439 + }, 440 + "end": "\\}", 441 + "endCaptures": { 442 + "0": { 443 + "name": "punctuation.curlybrace.close.tsp" 444 + } 445 + }, 446 + "patterns": [ 447 + { 448 + "include": "#token" 449 + }, 450 + { 451 + "include": "#directive" 452 + }, 453 + { 454 + "include": "#decorator" 455 + }, 456 + { 457 + "include": "#interface-member" 458 + }, 459 + { 460 + "include": "#punctuation-semicolon" 461 + } 462 + ] 463 + }, 464 + "interface-heritage": { 465 + "name": "meta.interface-heritage.typespec", 466 + "begin": "\\b(extends)\\b", 467 + "beginCaptures": { 468 + "1": { 469 + "name": "keyword.other.tsp" 470 + } 471 + }, 472 + "end": "((?=\\{)|(?=;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b))", 473 + "patterns": [ 474 + { 475 + "include": "#expression" 476 + }, 477 + { 478 + "include": "#punctuation-comma" 479 + } 480 + ] 481 + }, 482 + "interface-member": { 483 + "name": "meta.interface-member.typespec", 484 + "begin": "(?:\\b(op)\\b\\s+)?(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 485 + "beginCaptures": { 486 + "1": { 487 + "name": "keyword.other.tsp" 488 + }, 489 + "2": { 490 + "name": "entity.name.function.tsp" 491 + } 492 + }, 493 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 494 + "patterns": [ 495 + { 496 + "include": "#token" 497 + }, 498 + { 499 + "include": "#operation-signature" 500 + } 501 + ] 502 + }, 503 + "interface-statement": { 504 + "name": "meta.interface-statement.typespec", 505 + "begin": "\\b(interface)\\b", 506 + "beginCaptures": { 507 + "1": { 508 + "name": "keyword.other.tsp" 509 + } 510 + }, 511 + "end": "(?<=\\})|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 512 + "patterns": [ 513 + { 514 + "include": "#token" 515 + }, 516 + { 517 + "include": "#type-parameters" 518 + }, 519 + { 520 + "include": "#interface-heritage" 521 + }, 522 + { 523 + "include": "#interface-body" 524 + }, 525 + { 526 + "include": "#expression" 527 + } 528 + ] 529 + }, 530 + "line-comment": { 531 + "name": "comment.line.double-slash.tsp", 532 + "match": "//.*$" 533 + }, 534 + "model-expression": { 535 + "name": "meta.model-expression.typespec", 536 + "begin": "\\{", 537 + "beginCaptures": { 538 + "0": { 539 + "name": "punctuation.curlybrace.open.tsp" 540 + } 541 + }, 542 + "end": "\\}", 543 + "endCaptures": { 544 + "0": { 545 + "name": "punctuation.curlybrace.close.tsp" 546 + } 547 + }, 548 + "patterns": [ 549 + { 550 + "include": "#model-property" 551 + }, 552 + { 553 + "include": "#token" 554 + }, 555 + { 556 + "include": "#directive" 557 + }, 558 + { 559 + "include": "#decorator" 560 + }, 561 + { 562 + "include": "#spread-operator" 563 + }, 564 + { 565 + "include": "#punctuation-semicolon" 566 + } 567 + ] 568 + }, 569 + "model-heritage": { 570 + "name": "meta.model-heritage.typespec", 571 + "begin": "\\b(extends|is)\\b", 572 + "beginCaptures": { 573 + "1": { 574 + "name": "keyword.other.tsp" 575 + } 576 + }, 577 + "end": "((?=\\{)|(?=;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b))", 578 + "patterns": [ 579 + { 580 + "include": "#expression" 581 + }, 582 + { 583 + "include": "#punctuation-comma" 584 + } 585 + ] 586 + }, 587 + "model-property": { 588 + "name": "meta.model-property.typespec", 589 + "begin": "(?:(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)|(\\\"(?:[^\\\"\\\\]|\\\\.)*\\\"))", 590 + "beginCaptures": { 591 + "1": { 592 + "name": "variable.name.tsp" 593 + }, 594 + "2": { 595 + "name": "string.quoted.double.tsp" 596 + } 597 + }, 598 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 599 + "patterns": [ 600 + { 601 + "include": "#token" 602 + }, 603 + { 604 + "include": "#type-annotation" 605 + }, 606 + { 607 + "include": "#operator-assignment" 608 + }, 609 + { 610 + "include": "#expression" 611 + } 612 + ] 613 + }, 614 + "model-statement": { 615 + "name": "meta.model-statement.typespec", 616 + "begin": "\\b(model)\\b", 617 + "beginCaptures": { 618 + "1": { 619 + "name": "keyword.other.tsp" 620 + } 621 + }, 622 + "end": "(?<=\\})|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 623 + "patterns": [ 624 + { 625 + "include": "#token" 626 + }, 627 + { 628 + "include": "#type-parameters" 629 + }, 630 + { 631 + "include": "#model-heritage" 632 + }, 633 + { 634 + "include": "#expression" 635 + } 636 + ] 637 + }, 638 + "namespace-body": { 639 + "name": "meta.namespace-body.typespec", 640 + "begin": "\\{", 641 + "beginCaptures": { 642 + "0": { 643 + "name": "punctuation.curlybrace.open.tsp" 644 + } 645 + }, 646 + "end": "\\}", 647 + "endCaptures": { 648 + "0": { 649 + "name": "punctuation.curlybrace.close.tsp" 650 + } 651 + }, 652 + "patterns": [ 653 + { 654 + "include": "#statement" 655 + } 656 + ] 657 + }, 658 + "namespace-name": { 659 + "name": "meta.namespace-name.typespec", 660 + "begin": "(?=([_$[:alpha:]]|`))", 661 + "end": "((?=\\{)|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b))", 662 + "patterns": [ 663 + { 664 + "include": "#identifier-expression" 665 + }, 666 + { 667 + "include": "#punctuation-accessor" 668 + } 669 + ] 670 + }, 671 + "namespace-statement": { 672 + "name": "meta.namespace-statement.typespec", 673 + "begin": "\\b(namespace)\\b", 674 + "beginCaptures": { 675 + "1": { 676 + "name": "keyword.other.tsp" 677 + } 678 + }, 679 + "end": "((?<=\\})|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b))", 680 + "patterns": [ 681 + { 682 + "include": "#token" 683 + }, 684 + { 685 + "include": "#namespace-name" 686 + }, 687 + { 688 + "include": "#namespace-body" 689 + } 690 + ] 691 + }, 692 + "numeric-literal": { 693 + "name": "constant.numeric.tsp", 694 + "match": "(?:\\b(?<!\\$)0(?:x|X)[0-9a-fA-F][0-9a-fA-F_]*(n)?\\b(?!\\$)|\\b(?<!\\$)0(?:b|B)[01][01_]*(n)?\\b(?!\\$)|(?<!\\$)(?:(?:\\b[0-9][0-9_]*(\\.)[0-9][0-9_]*[eE][+-]?[0-9][0-9_]*(n)?\\b)|(?:\\b[0-9][0-9_]*(\\.)[eE][+-]?[0-9][0-9_]*(n)?\\b)|(?:\\B(\\.)[0-9][0-9_]*[eE][+-]?[0-9][0-9_]*(n)?\\b)|(?:\\b[0-9][0-9_]*[eE][+-]?[0-9][0-9_]*(n)?\\b)|(?:\\b[0-9][0-9_]*(\\.)[0-9][0-9_]*(n)?\\b)|(?:\\b[0-9][0-9_]*(\\.)(n)?\\B)|(?:\\B(\\.)[0-9][0-9_]*(n)?\\b)|(?:\\b[0-9][0-9_]*(n)?\\b(?!\\.)))(?!\\$))" 695 + }, 696 + "object-literal": { 697 + "name": "meta.object-literal.typespec", 698 + "begin": "#\\{", 699 + "beginCaptures": { 700 + "0": { 701 + "name": "punctuation.hashcurlybrace.open.tsp" 702 + } 703 + }, 704 + "end": "\\}", 705 + "endCaptures": { 706 + "0": { 707 + "name": "punctuation.curlybrace.close.tsp" 708 + } 709 + }, 710 + "patterns": [ 711 + { 712 + "include": "#token" 713 + }, 714 + { 715 + "include": "#object-literal-property" 716 + }, 717 + { 718 + "include": "#directive" 719 + }, 720 + { 721 + "include": "#spread-operator" 722 + }, 723 + { 724 + "include": "#punctuation-comma" 725 + } 726 + ] 727 + }, 728 + "object-literal-property": { 729 + "name": "meta.object-literal-property.typespec", 730 + "begin": "(?:(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)\\s*(:))", 731 + "beginCaptures": { 732 + "1": { 733 + "name": "variable.name.tsp" 734 + }, 735 + "2": { 736 + "name": "keyword.operator.type.annotation.tsp" 737 + } 738 + }, 739 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 740 + "patterns": [ 741 + { 742 + "include": "#token" 743 + }, 744 + { 745 + "include": "#expression" 746 + } 747 + ] 748 + }, 749 + "operation-heritage": { 750 + "name": "meta.operation-heritage.typespec", 751 + "begin": "\\b(is)\\b", 752 + "beginCaptures": { 753 + "1": { 754 + "name": "keyword.other.tsp" 755 + } 756 + }, 757 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 758 + "patterns": [ 759 + { 760 + "include": "#expression" 761 + } 762 + ] 763 + }, 764 + "operation-parameters": { 765 + "name": "meta.operation-parameters.typespec", 766 + "begin": "\\(", 767 + "beginCaptures": { 768 + "0": { 769 + "name": "punctuation.parenthesis.open.tsp" 770 + } 771 + }, 772 + "end": "\\)", 773 + "endCaptures": { 774 + "0": { 775 + "name": "punctuation.parenthesis.close.tsp" 776 + } 777 + }, 778 + "patterns": [ 779 + { 780 + "include": "#token" 781 + }, 782 + { 783 + "include": "#decorator" 784 + }, 785 + { 786 + "include": "#model-property" 787 + }, 788 + { 789 + "include": "#spread-operator" 790 + }, 791 + { 792 + "include": "#punctuation-comma" 793 + } 794 + ] 795 + }, 796 + "operation-signature": { 797 + "patterns": [ 798 + { 799 + "include": "#type-parameters" 800 + }, 801 + { 802 + "include": "#operation-heritage" 803 + }, 804 + { 805 + "include": "#operation-parameters" 806 + }, 807 + { 808 + "include": "#type-annotation" 809 + } 810 + ] 811 + }, 812 + "operation-statement": { 813 + "name": "meta.operation-statement.typespec", 814 + "begin": "\\b(op)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 815 + "beginCaptures": { 816 + "1": { 817 + "name": "keyword.other.tsp" 818 + }, 819 + "2": { 820 + "name": "entity.name.function.tsp" 821 + } 822 + }, 823 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 824 + "patterns": [ 825 + { 826 + "include": "#token" 827 + }, 828 + { 829 + "include": "#operation-signature" 830 + } 831 + ] 832 + }, 833 + "operator-assignment": { 834 + "name": "keyword.operator.assignment.tsp", 835 + "match": "=" 836 + }, 837 + "parenthesized-expression": { 838 + "name": "meta.parenthesized-expression.typespec", 839 + "begin": "\\(", 840 + "beginCaptures": { 841 + "0": { 842 + "name": "punctuation.parenthesis.open.tsp" 843 + } 844 + }, 845 + "end": "\\)", 846 + "endCaptures": { 847 + "0": { 848 + "name": "punctuation.parenthesis.close.tsp" 849 + } 850 + }, 851 + "patterns": [ 852 + { 853 + "include": "#expression" 854 + }, 855 + { 856 + "include": "#punctuation-comma" 857 + } 858 + ] 859 + }, 860 + "punctuation-accessor": { 861 + "name": "punctuation.accessor.tsp", 862 + "match": "\\." 863 + }, 864 + "punctuation-comma": { 865 + "name": "punctuation.comma.tsp", 866 + "match": "," 867 + }, 868 + "punctuation-semicolon": { 869 + "name": "punctuation.terminator.statement.tsp", 870 + "match": ";" 871 + }, 872 + "scalar-body": { 873 + "name": "meta.scalar-body.typespec", 874 + "begin": "\\{", 875 + "beginCaptures": { 876 + "0": { 877 + "name": "punctuation.curlybrace.open.tsp" 878 + } 879 + }, 880 + "end": "\\}", 881 + "endCaptures": { 882 + "0": { 883 + "name": "punctuation.curlybrace.close.tsp" 884 + } 885 + }, 886 + "patterns": [ 887 + { 888 + "include": "#token" 889 + }, 890 + { 891 + "include": "#directive" 892 + }, 893 + { 894 + "include": "#scalar-constructor" 895 + }, 896 + { 897 + "include": "#punctuation-semicolon" 898 + } 899 + ] 900 + }, 901 + "scalar-constructor": { 902 + "name": "meta.scalar-constructor.typespec", 903 + "begin": "\\b(init)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 904 + "beginCaptures": { 905 + "1": { 906 + "name": "keyword.other.tsp" 907 + }, 908 + "2": { 909 + "name": "entity.name.function.tsp" 910 + } 911 + }, 912 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 913 + "patterns": [ 914 + { 915 + "include": "#token" 916 + }, 917 + { 918 + "include": "#operation-parameters" 919 + } 920 + ] 921 + }, 922 + "scalar-extends": { 923 + "name": "meta.scalar-extends.typespec", 924 + "begin": "\\b(extends)\\b", 925 + "beginCaptures": { 926 + "1": { 927 + "name": "keyword.other.tsp" 928 + } 929 + }, 930 + "end": "(?=;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 931 + "patterns": [ 932 + { 933 + "include": "#expression" 934 + }, 935 + { 936 + "include": "#punctuation-comma" 937 + } 938 + ] 939 + }, 940 + "scalar-statement": { 941 + "name": "meta.scalar-statement.typespec", 942 + "begin": "\\b(scalar)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 943 + "beginCaptures": { 944 + "1": { 945 + "name": "keyword.other.tsp" 946 + }, 947 + "2": { 948 + "name": "entity.name.type.tsp" 949 + } 950 + }, 951 + "end": "(?<=\\})|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 952 + "patterns": [ 953 + { 954 + "include": "#token" 955 + }, 956 + { 957 + "include": "#type-parameters" 958 + }, 959 + { 960 + "include": "#scalar-extends" 961 + }, 962 + { 963 + "include": "#scalar-body" 964 + } 965 + ] 966 + }, 967 + "spread-operator": { 968 + "name": "meta.spread-operator.typespec", 969 + "begin": "\\.\\.\\.", 970 + "beginCaptures": { 971 + "0": { 972 + "name": "keyword.operator.spread.tsp" 973 + } 974 + }, 975 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 976 + "patterns": [ 977 + { 978 + "include": "#expression" 979 + } 980 + ] 981 + }, 982 + "statement": { 983 + "patterns": [ 984 + { 985 + "include": "#token" 986 + }, 987 + { 988 + "include": "#directive" 989 + }, 990 + { 991 + "include": "#augment-decorator-statement" 992 + }, 993 + { 994 + "include": "#decorator" 995 + }, 996 + { 997 + "include": "#model-statement" 998 + }, 999 + { 1000 + "include": "#scalar-statement" 1001 + }, 1002 + { 1003 + "include": "#union-statement" 1004 + }, 1005 + { 1006 + "include": "#interface-statement" 1007 + }, 1008 + { 1009 + "include": "#enum-statement" 1010 + }, 1011 + { 1012 + "include": "#alias-statement" 1013 + }, 1014 + { 1015 + "include": "#const-statement" 1016 + }, 1017 + { 1018 + "include": "#namespace-statement" 1019 + }, 1020 + { 1021 + "include": "#operation-statement" 1022 + }, 1023 + { 1024 + "include": "#import-statement" 1025 + }, 1026 + { 1027 + "include": "#using-statement" 1028 + }, 1029 + { 1030 + "include": "#decorator-declaration-statement" 1031 + }, 1032 + { 1033 + "include": "#function-declaration-statement" 1034 + }, 1035 + { 1036 + "include": "#punctuation-semicolon" 1037 + } 1038 + ] 1039 + }, 1040 + "string-literal": { 1041 + "name": "string.quoted.double.tsp", 1042 + "begin": "\"", 1043 + "end": "\"|$", 1044 + "patterns": [ 1045 + { 1046 + "include": "#template-expression" 1047 + }, 1048 + { 1049 + "include": "#escape-character" 1050 + } 1051 + ] 1052 + }, 1053 + "template-expression": { 1054 + "name": "meta.template-expression.typespec", 1055 + "begin": "\\$\\{", 1056 + "beginCaptures": { 1057 + "0": { 1058 + "name": "punctuation.definition.template-expression.begin.tsp" 1059 + } 1060 + }, 1061 + "end": "\\}", 1062 + "endCaptures": { 1063 + "0": { 1064 + "name": "punctuation.definition.template-expression.end.tsp" 1065 + } 1066 + }, 1067 + "patterns": [ 1068 + { 1069 + "include": "#expression" 1070 + } 1071 + ] 1072 + }, 1073 + "token": { 1074 + "patterns": [ 1075 + { 1076 + "include": "#doc-comment" 1077 + }, 1078 + { 1079 + "include": "#line-comment" 1080 + }, 1081 + { 1082 + "include": "#block-comment" 1083 + }, 1084 + { 1085 + "include": "#triple-quoted-string-literal" 1086 + }, 1087 + { 1088 + "include": "#string-literal" 1089 + }, 1090 + { 1091 + "include": "#boolean-literal" 1092 + }, 1093 + { 1094 + "include": "#numeric-literal" 1095 + } 1096 + ] 1097 + }, 1098 + "triple-quoted-string-literal": { 1099 + "name": "string.quoted.triple.tsp", 1100 + "begin": "\"\"\"", 1101 + "end": "\"\"\"", 1102 + "patterns": [ 1103 + { 1104 + "include": "#template-expression" 1105 + }, 1106 + { 1107 + "include": "#escape-character" 1108 + } 1109 + ] 1110 + }, 1111 + "tuple-expression": { 1112 + "name": "meta.tuple-expression.typespec", 1113 + "begin": "\\[", 1114 + "beginCaptures": { 1115 + "0": { 1116 + "name": "punctuation.squarebracket.open.tsp" 1117 + } 1118 + }, 1119 + "end": "\\]", 1120 + "endCaptures": { 1121 + "0": { 1122 + "name": "punctuation.squarebracket.close.tsp" 1123 + } 1124 + }, 1125 + "patterns": [ 1126 + { 1127 + "include": "#expression" 1128 + } 1129 + ] 1130 + }, 1131 + "tuple-literal": { 1132 + "name": "meta.tuple-literal.typespec", 1133 + "begin": "#\\[", 1134 + "beginCaptures": { 1135 + "0": { 1136 + "name": "punctuation.hashsquarebracket.open.tsp" 1137 + } 1138 + }, 1139 + "end": "\\]", 1140 + "endCaptures": { 1141 + "0": { 1142 + "name": "punctuation.squarebracket.close.tsp" 1143 + } 1144 + }, 1145 + "patterns": [ 1146 + { 1147 + "include": "#expression" 1148 + }, 1149 + { 1150 + "include": "#punctuation-comma" 1151 + } 1152 + ] 1153 + }, 1154 + "type-annotation": { 1155 + "name": "meta.type-annotation.typespec", 1156 + "begin": "\\s*(\\??)\\s*(:)", 1157 + "beginCaptures": { 1158 + "1": { 1159 + "name": "keyword.operator.optional.tsp" 1160 + }, 1161 + "2": { 1162 + "name": "keyword.operator.type.annotation.tsp" 1163 + } 1164 + }, 1165 + "end": "(?=,|;|@|\\)|\\}|=|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1166 + "patterns": [ 1167 + { 1168 + "include": "#expression" 1169 + } 1170 + ] 1171 + }, 1172 + "type-argument": { 1173 + "name": "meta.type-argument.typespec", 1174 + "begin": "(?:(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)\\s*(=))", 1175 + "beginCaptures": { 1176 + "1": { 1177 + "name": "entity.name.type.tsp" 1178 + }, 1179 + "2": { 1180 + "name": "keyword.operator.assignment.tsp" 1181 + } 1182 + }, 1183 + "end": "(?=>)|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1184 + "endCaptures": { 1185 + "0": { 1186 + "name": "keyword.operator.assignment.tsp" 1187 + } 1188 + }, 1189 + "patterns": [ 1190 + { 1191 + "include": "#token" 1192 + }, 1193 + { 1194 + "include": "#expression" 1195 + }, 1196 + { 1197 + "include": "#punctuation-comma" 1198 + } 1199 + ] 1200 + }, 1201 + "type-arguments": { 1202 + "name": "meta.type-arguments.typespec", 1203 + "begin": "<", 1204 + "beginCaptures": { 1205 + "0": { 1206 + "name": "punctuation.definition.typeparameters.begin.tsp" 1207 + } 1208 + }, 1209 + "end": ">", 1210 + "endCaptures": { 1211 + "0": { 1212 + "name": "punctuation.definition.typeparameters.end.tsp" 1213 + } 1214 + }, 1215 + "patterns": [ 1216 + { 1217 + "include": "#type-argument" 1218 + }, 1219 + { 1220 + "include": "#expression" 1221 + }, 1222 + { 1223 + "include": "#punctuation-comma" 1224 + } 1225 + ] 1226 + }, 1227 + "type-parameter": { 1228 + "name": "meta.type-parameter.typespec", 1229 + "begin": "(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 1230 + "beginCaptures": { 1231 + "1": { 1232 + "name": "entity.name.type.tsp" 1233 + } 1234 + }, 1235 + "end": "(?=>)|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1236 + "patterns": [ 1237 + { 1238 + "include": "#token" 1239 + }, 1240 + { 1241 + "include": "#type-parameter-constraint" 1242 + }, 1243 + { 1244 + "include": "#type-parameter-default" 1245 + } 1246 + ] 1247 + }, 1248 + "type-parameter-constraint": { 1249 + "name": "meta.type-parameter-constraint.typespec", 1250 + "begin": "extends", 1251 + "beginCaptures": { 1252 + "0": { 1253 + "name": "keyword.other.tsp" 1254 + } 1255 + }, 1256 + "end": "(?=>)|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1257 + "patterns": [ 1258 + { 1259 + "include": "#expression" 1260 + } 1261 + ] 1262 + }, 1263 + "type-parameter-default": { 1264 + "name": "meta.type-parameter-default.typespec", 1265 + "begin": "=", 1266 + "beginCaptures": { 1267 + "0": { 1268 + "name": "keyword.operator.assignment.tsp" 1269 + } 1270 + }, 1271 + "end": "(?=>)|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1272 + "patterns": [ 1273 + { 1274 + "include": "#expression" 1275 + } 1276 + ] 1277 + }, 1278 + "type-parameters": { 1279 + "name": "meta.type-parameters.typespec", 1280 + "begin": "<", 1281 + "beginCaptures": { 1282 + "0": { 1283 + "name": "punctuation.definition.typeparameters.begin.tsp" 1284 + } 1285 + }, 1286 + "end": ">", 1287 + "endCaptures": { 1288 + "0": { 1289 + "name": "punctuation.definition.typeparameters.end.tsp" 1290 + } 1291 + }, 1292 + "patterns": [ 1293 + { 1294 + "include": "#type-parameter" 1295 + }, 1296 + { 1297 + "include": "#punctuation-comma" 1298 + } 1299 + ] 1300 + }, 1301 + "typeof": { 1302 + "name": "meta.typeof.typespec", 1303 + "begin": "\\b(typeof)", 1304 + "beginCaptures": { 1305 + "1": { 1306 + "name": "keyword.other.tsp" 1307 + } 1308 + }, 1309 + "end": "(?=>)|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1310 + "patterns": [ 1311 + { 1312 + "include": "#expression" 1313 + } 1314 + ] 1315 + }, 1316 + "union-body": { 1317 + "name": "meta.union-body.typespec", 1318 + "begin": "\\{", 1319 + "beginCaptures": { 1320 + "0": { 1321 + "name": "punctuation.curlybrace.open.tsp" 1322 + } 1323 + }, 1324 + "end": "\\}", 1325 + "endCaptures": { 1326 + "0": { 1327 + "name": "punctuation.curlybrace.close.tsp" 1328 + } 1329 + }, 1330 + "patterns": [ 1331 + { 1332 + "include": "#union-variant" 1333 + }, 1334 + { 1335 + "include": "#token" 1336 + }, 1337 + { 1338 + "include": "#directive" 1339 + }, 1340 + { 1341 + "include": "#decorator" 1342 + }, 1343 + { 1344 + "include": "#expression" 1345 + }, 1346 + { 1347 + "include": "#punctuation-comma" 1348 + } 1349 + ] 1350 + }, 1351 + "union-statement": { 1352 + "name": "meta.union-statement.typespec", 1353 + "begin": "\\b(union)\\b\\s+(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)", 1354 + "beginCaptures": { 1355 + "1": { 1356 + "name": "keyword.other.tsp" 1357 + }, 1358 + "2": { 1359 + "name": "entity.name.type.tsp" 1360 + } 1361 + }, 1362 + "end": "(?<=\\})|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1363 + "patterns": [ 1364 + { 1365 + "include": "#token" 1366 + }, 1367 + { 1368 + "include": "#union-body" 1369 + } 1370 + ] 1371 + }, 1372 + "union-variant": { 1373 + "name": "meta.union-variant.typespec", 1374 + "begin": "(?:(\\b[_$[:alpha:]][_$[:alnum:]]*\\b|`(?:[^`\\\\]|\\\\.)*`)\\s*(:))", 1375 + "beginCaptures": { 1376 + "1": { 1377 + "name": "variable.name.tsp" 1378 + }, 1379 + "2": { 1380 + "name": "keyword.operator.type.annotation.tsp" 1381 + } 1382 + }, 1383 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1384 + "patterns": [ 1385 + { 1386 + "include": "#token" 1387 + }, 1388 + { 1389 + "include": "#expression" 1390 + } 1391 + ] 1392 + }, 1393 + "using-statement": { 1394 + "name": "meta.using-statement.typespec", 1395 + "begin": "\\b(using)\\b", 1396 + "beginCaptures": { 1397 + "1": { 1398 + "name": "keyword.other.tsp" 1399 + } 1400 + }, 1401 + "end": "(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1402 + "patterns": [ 1403 + { 1404 + "include": "#token" 1405 + }, 1406 + { 1407 + "include": "#identifier-expression" 1408 + }, 1409 + { 1410 + "include": "#punctuation-accessor" 1411 + } 1412 + ] 1413 + }, 1414 + "valueof": { 1415 + "name": "meta.valueof.typespec", 1416 + "begin": "\\b(valueof)", 1417 + "beginCaptures": { 1418 + "1": { 1419 + "name": "keyword.other.tsp" 1420 + } 1421 + }, 1422 + "end": "(?=>)|(?=,|;|@|\\)|\\}|\\b(?:extern)\\b|\\b(?:namespace|model|op|using|import|enum|alias|union|interface|dec|fn)\\b)", 1423 + "patterns": [ 1424 + { 1425 + "include": "#expression" 1426 + } 1427 + ] 1428 + } 1429 + } 1430 + }
+75
packages/website/src/utils/compile.ts
··· 1 + import { 2 + createTestHost, 3 + type TypeSpecTestLibrary, 4 + } from "@typespec/compiler/testing"; 5 + import { readFile } from "fs/promises"; 6 + import { fileURLToPath } from "url"; 7 + import { dirname, resolve } from "path"; 8 + 9 + const __filename = fileURLToPath(import.meta.url); 10 + const __dirname = dirname(__filename); 11 + 12 + // Get the emitter package root 13 + const emitterRoot = resolve(__dirname, "../../../emitter"); 14 + 15 + const TylexTestLibrary: TypeSpecTestLibrary = { 16 + name: "@tylex/emitter", 17 + packageRoot: emitterRoot, 18 + files: [ 19 + { 20 + realDir: "", 21 + pattern: "package.json", 22 + virtualPath: "./node_modules/@tylex/emitter", 23 + }, 24 + { 25 + realDir: "dist", 26 + pattern: "**/*.js", 27 + virtualPath: "./node_modules/@tylex/emitter/dist", 28 + }, 29 + { 30 + realDir: "lib/", 31 + pattern: "*.tsp", 32 + virtualPath: "./node_modules/@tylex/emitter/lib", 33 + }, 34 + ], 35 + }; 36 + 37 + export async function compileToJson(tspFilePath: string): Promise<string> { 38 + const baseOutputPath = "/tsp-output/"; 39 + 40 + // Create test host 41 + const host = await createTestHost({ 42 + libraries: [TylexTestLibrary], 43 + }); 44 + 45 + // Read the TypeSpec file 46 + const content = await readFile(tspFilePath, "utf-8"); 47 + const fileName = tspFilePath.split("/").pop() || "main.tsp"; 48 + 49 + // Add file to the virtual filesystem 50 + host.addTypeSpecFile(fileName, content); 51 + 52 + // Compile 53 + const [, diagnostics] = await host.compileAndDiagnose(fileName, { 54 + outputDir: baseOutputPath, 55 + noEmit: false, 56 + emit: ["@tylex/emitter"], 57 + }); 58 + 59 + // Check for errors 60 + const errors = diagnostics.filter(d => d.severity === "error"); 61 + if (errors.length > 0) { 62 + throw new Error(`TypeSpec compilation failed: ${errors.map(e => e.message).join(", ")}`); 63 + } 64 + 65 + // Extract the generated JSON from the virtual filesystem 66 + const outputEntries = [...host.fs.entries()] 67 + .filter(([name]) => name.startsWith(baseOutputPath) && name.endsWith('.json')); 68 + 69 + if (outputEntries.length === 0) { 70 + throw new Error("No JSON output found from TypeSpec compilation"); 71 + } 72 + 73 + // Return the first JSON file (there should only be one per input file) 74 + return outputEntries[0][1]; 75 + }
+71
packages/website/src/utils/shiki.ts
··· 1 + import { codeToHtml } from 'shiki'; 2 + import typespecGrammar from '../typespec-grammar.json'; 3 + 4 + const pastelTheme = { 5 + name: 'pastel-custom', 6 + type: 'dark', 7 + colors: { 8 + 'editor.background': '#1e1b29', 9 + 'editor.foreground': '#e2e8f0', 10 + }, 11 + tokenColors: [ 12 + { 13 + scope: ['keyword', 'storage.type', 'storage.modifier'], 14 + settings: { foreground: '#60a5fa' }, // blue for keywords 15 + }, 16 + { 17 + scope: ['entity.name.type', 'entity.name.class', 'support.type'], 18 + settings: { foreground: '#f9a8d4' }, // pink for types 19 + }, 20 + { 21 + scope: ['entity.name.function', 'variable.other.property'], 22 + settings: { foreground: '#5eead4' }, // teal for properties 23 + }, 24 + { 25 + scope: ['string', 'string.quoted'], 26 + settings: { foreground: '#86efac' }, // light green for strings 27 + }, 28 + { 29 + scope: ['constant.numeric', 'constant.language'], 30 + settings: { foreground: '#fbbf24' }, // amber for numbers 31 + }, 32 + { 33 + scope: ['meta.decorator', 'entity.name.tag'], 34 + settings: { foreground: '#a78bfa' }, // softer lavender for decorators 35 + }, 36 + { 37 + scope: ['comment'], 38 + settings: { foreground: '#64748b', fontStyle: 'italic' }, 39 + }, 40 + { 41 + scope: ['punctuation', 'meta.brace'], 42 + settings: { foreground: '#94a3b8' }, 43 + }, 44 + ], 45 + } as any; 46 + 47 + export async function highlightCode(code: string, lang: 'typespec' | 'json' | 'bash') { 48 + if (lang === 'typespec') { 49 + return await codeToHtml(code, { 50 + lang: 'typespec', 51 + theme: pastelTheme, 52 + langs: [ 53 + { 54 + ...typespecGrammar, 55 + name: 'typespec', 56 + scopeName: 'source.tsp', 57 + } as any, 58 + ], 59 + }); 60 + } else if (lang === 'bash') { 61 + return await codeToHtml(code, { 62 + lang: 'bash', 63 + theme: pastelTheme, 64 + }); 65 + } else { 66 + return await codeToHtml(code, { 67 + lang: 'json', 68 + theme: pastelTheme, 69 + }); 70 + } 71 + }
+9
packages/website/tsconfig.json
··· 1 + { 2 + "extends": "astro/tsconfigs/strict", 3 + "compilerOptions": { 4 + "jsx": "react-jsx", 5 + "jsxImportSource": "react" 6 + }, 7 + "include": [".astro/types.d.ts", "**/*"], 8 + "exclude": ["dist"] 9 + }