···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.actor.getTopAlbums",
44+ "description": "This lexicon is in a not officially released state. It is subject to change. | Retrieves a list of the top albums from a given user.",
55+ "defs": {
66+ "main": {
77+ "type": "query",
88+ "parameters": {
99+ "type": "params",
1010+ "required": ["actor"],
1111+ "properties": {
1212+ "actor": {
1313+ "type": "string",
1414+ "format": "at-identifier",
1515+ "description": "The author's DID"
1616+ },
1717+ "limit": {
1818+ "type": "integer",
1919+ "description": "The maximum number of albums to return",
2020+ "default": 10
2121+ }
2222+ }
2323+ },
2424+ "output": {
2525+ "encoding": "application/json",
2626+ "schema": {
2727+ "type": "object",
2828+ "required": ["actor", "albums"],
2929+ "properties": {
3030+ "actor": {
3131+ "type": "ref",
3232+ "ref": "fm.teal.alpha.actor.defs#profileView"
3333+ },
3434+ "albums": {
3535+ "type": "array",
3636+ "items": {
3737+ "type": "ref",
3838+ "ref": "fm.teal.alpha.actor.defs#albumView"
3939+ }
4040+ }
4141+ }
4242+ }
4343+ }
4444+ }
4545+ }
4646+}
+21-9
packages/lexicons/src/index.ts
···44import {
55 createServer as createXrpcServer,
66 Server as XrpcServer,
77- Options as XrpcOptions,
88- AuthVerifier,
99- StreamAuthVerifier,
77+ type Options as XrpcOptions,
88+ type AuthVerifier,
99+ type StreamAuthVerifier,
1010} from '@atproto/xrpc-server'
1111-import { schemas } from './lexicons'
1212-import * as FmTealAlphaActorGetProfile from './types/fm/teal/alpha/actor/getProfile'
1313-import * as FmTealAlphaActorGetProfiles from './types/fm/teal/alpha/actor/getProfiles'
1414-import * as FmTealAlphaActorSearchActors from './types/fm/teal/alpha/actor/searchActors'
1515-import * as FmTealAlphaFeedGetActorFeed from './types/fm/teal/alpha/feed/getActorFeed'
1616-import * as FmTealAlphaFeedGetPlay from './types/fm/teal/alpha/feed/getPlay'
1111+import { schemas } from './lexicons.js'
1212+import * as FmTealAlphaActorGetProfile from './types/fm/teal/alpha/actor/getProfile.js'
1313+import * as FmTealAlphaActorGetProfiles from './types/fm/teal/alpha/actor/getProfiles.js'
1414+import * as FmTealAlphaActorGetTopAlbums from './types/fm/teal/alpha/actor/getTopAlbums.js'
1515+import * as FmTealAlphaActorSearchActors from './types/fm/teal/alpha/actor/searchActors.js'
1616+import * as FmTealAlphaFeedGetActorFeed from './types/fm/teal/alpha/feed/getActorFeed.js'
1717+import * as FmTealAlphaFeedGetPlay from './types/fm/teal/alpha/feed/getPlay.js'
17181819export function createServer(options?: XrpcOptions): Server {
1920 return new Server(options)
···129130 >,
130131 ) {
131132 const nsid = 'fm.teal.alpha.actor.getProfiles' // @ts-ignore
133133+ return this._server.xrpc.method(nsid, cfg)
134134+ }
135135+136136+ getTopAlbums<AV extends AuthVerifier>(
137137+ cfg: ConfigOf<
138138+ AV,
139139+ FmTealAlphaActorGetTopAlbums.Handler<ExtractAuth<AV>>,
140140+ FmTealAlphaActorGetTopAlbums.HandlerReqCtx<ExtractAuth<AV>>
141141+ >,
142142+ ) {
143143+ const nsid = 'fm.teal.alpha.actor.getTopAlbums' // @ts-ignore
132144 return this._server.xrpc.method(nsid, cfg)
133145 }
134146
+114-4
packages/lexicons/src/lexicons.ts
···11/**
22 * GENERATED CODE - DO NOT MODIFY
33 */
44-import { LexiconDoc, Lexicons } from '@atproto/lexicon'
44+import {
55+ type LexiconDoc,
66+ Lexicons,
77+ ValidationError,
88+ type ValidationResult,
99+} from '@atproto/lexicon'
1010+import { type $Typed, is$typed, maybe$typed } from './util.js'
511612export const schemaDict = {
713 AppBskyActorProfile: {
···206212 },
207213 },
208214 },
215215+ albumView: {
216216+ type: 'object',
217217+ required: ['albumName', 'albumArtist'],
218218+ properties: {
219219+ albumName: {
220220+ type: 'string',
221221+ description: 'The name of the album',
222222+ },
223223+ albumArtist: {
224224+ type: 'string',
225225+ description: 'The artist of the album',
226226+ },
227227+ albumArt: {
228228+ type: 'string',
229229+ description: 'The URL of the album art',
230230+ },
231231+ albumReleaseMBID: {
232232+ type: 'string',
233233+ description: 'The MusicBrainz ID of the album',
234234+ },
235235+ },
236236+ },
209237 },
210238 },
211239 FmTealAlphaActorGetProfile: {
···284312 },
285313 },
286314 },
315315+ FmTealAlphaActorGetTopAlbums: {
316316+ lexicon: 1,
317317+ id: 'fm.teal.alpha.actor.getTopAlbums',
318318+ description:
319319+ 'This lexicon is in a not officially released state. It is subject to change. | Retrieves a list of the top albums from a given user.',
320320+ defs: {
321321+ main: {
322322+ type: 'query',
323323+ parameters: {
324324+ type: 'params',
325325+ required: ['actor'],
326326+ properties: {
327327+ actor: {
328328+ type: 'string',
329329+ format: 'at-identifier',
330330+ description: "The author's DID",
331331+ },
332332+ limit: {
333333+ type: 'integer',
334334+ description: 'The maximum number of albums to return',
335335+ default: 10,
336336+ },
337337+ },
338338+ },
339339+ output: {
340340+ encoding: 'application/json',
341341+ schema: {
342342+ type: 'object',
343343+ required: ['actor', 'albums'],
344344+ properties: {
345345+ actor: {
346346+ type: 'ref',
347347+ ref: 'lex:fm.teal.alpha.actor.defs#profileView',
348348+ },
349349+ albums: {
350350+ type: 'array',
351351+ items: {
352352+ type: 'ref',
353353+ ref: 'lex:fm.teal.alpha.actor.defs#albumView',
354354+ },
355355+ },
356356+ },
357357+ },
358358+ },
359359+ },
360360+ },
361361+ },
287362 FmTealAlphaActorProfile: {
288363 lexicon: 1,
289364 id: 'fm.teal.alpha.actor.profile',
···430505 type: 'string',
431506 format: 'datetime',
432507 description: 'The unix timestamp of when the item was recorded',
508508+ },
509509+ expiry: {
510510+ type: 'string',
511511+ format: 'datetime',
512512+ description:
513513+ 'The unix timestamp of the expiry time of the item. If unavailable, default to 10 minutes past the start time.',
433514 },
434515 item: {
435516 type: 'ref',
···729810 },
730811 },
731812} as const satisfies Record<string, LexiconDoc>
813813+export const schemas = Object.values(schemaDict) satisfies LexiconDoc[]
814814+export const lexicons: Lexicons = new Lexicons(schemas)
732815733733-export const schemas = Object.values(schemaDict)
734734-export const lexicons: Lexicons = new Lexicons(schemas)
816816+export function validate<T extends { $type: string }>(
817817+ v: unknown,
818818+ id: string,
819819+ hash: string,
820820+ requiredType: true,
821821+): ValidationResult<T>
822822+export function validate<T extends { $type?: string }>(
823823+ v: unknown,
824824+ id: string,
825825+ hash: string,
826826+ requiredType?: false,
827827+): ValidationResult<T>
828828+export function validate(
829829+ v: unknown,
830830+ id: string,
831831+ hash: string,
832832+ requiredType?: boolean,
833833+): ValidationResult {
834834+ return (requiredType ? is$typed : maybe$typed)(v, id, hash)
835835+ ? lexicons.validate(`${id}#${hash}`, v)
836836+ : {
837837+ success: false,
838838+ error: new ValidationError(
839839+ `Must be an object with "${hash === 'main' ? id : `${id}#${hash}`}" $type property`,
840840+ ),
841841+ }
842842+}
843843+735844export const ids = {
736845 AppBskyActorProfile: 'app.bsky.actor.profile',
737846 AppBskyRichtextFacet: 'app.bsky.richtext.facet',
738847 FmTealAlphaActorDefs: 'fm.teal.alpha.actor.defs',
739848 FmTealAlphaActorGetProfile: 'fm.teal.alpha.actor.getProfile',
740849 FmTealAlphaActorGetProfiles: 'fm.teal.alpha.actor.getProfiles',
850850+ FmTealAlphaActorGetTopAlbums: 'fm.teal.alpha.actor.getTopAlbums',
741851 FmTealAlphaActorProfile: 'fm.teal.alpha.actor.profile',
742852 FmTealAlphaActorSearchActors: 'fm.teal.alpha.actor.searchActors',
743853 FmTealAlphaActorStatus: 'fm.teal.alpha.actor.status',
···746856 FmTealAlphaFeedGetPlay: 'fm.teal.alpha.feed.getPlay',
747857 FmTealAlphaFeedPlay: 'fm.teal.alpha.feed.play',
748858 XyzStatusphereStatus: 'xyz.statusphere.status',
749749-}
859859+} as const
···11/**
22 * GENERATED CODE - DO NOT MODIFY
33 */
44-import { ValidationResult, BlobRef } from '@atproto/lexicon'
55-import { lexicons } from '../../../../../lexicons'
66-import { isObj, hasProp } from '../../../../../util'
44+import { type ValidationResult, BlobRef } from '@atproto/lexicon'
75import { CID } from 'multiformats/cid'
88-import * as FmTealAlphaFeedDefs from '../feed/defs'
66+import { validate as _validate } from '../../../../../lexicons'
77+import {
88+ type $Typed,
99+ is$typed as _is$typed,
1010+ type OmitKey,
1111+} from '../../../../../util'
1212+import type * as FmTealAlphaFeedDefs from '../feed/defs.js'
1313+1414+const is$typed = _is$typed,
1515+ validate = _validate
1616+const id = 'fm.teal.alpha.actor.status'
9171018export interface Record {
1919+ $type: 'fm.teal.alpha.actor.status'
1120 /** The unix timestamp of when the item was recorded */
1221 time: string
2222+ /** The unix timestamp of the expiry time of the item. If unavailable, default to 10 minutes past the start time. */
2323+ expiry?: string
1324 item: FmTealAlphaFeedDefs.PlayView
1425 [k: string]: unknown
1526}
16271717-export function isRecord(v: unknown): v is Record {
1818- return (
1919- isObj(v) &&
2020- hasProp(v, '$type') &&
2121- (v.$type === 'fm.teal.alpha.actor.status#main' ||
2222- v.$type === 'fm.teal.alpha.actor.status')
2323- )
2828+const hashRecord = 'main'
2929+3030+export function isRecord<V>(v: V) {
3131+ return is$typed(v, id, hashRecord)
2432}
25332626-export function validateRecord(v: unknown): ValidationResult {
2727- return lexicons.validate('fm.teal.alpha.actor.status#main', v)
3434+export function validateRecord<V>(v: V) {
3535+ return validate<Record & V>(v, id, hashRecord, true)
2836}
···22 * GENERATED CODE - DO NOT MODIFY
33 */
44import express from 'express'
55-import { ValidationResult, BlobRef } from '@atproto/lexicon'
66-import { lexicons } from '../../../../../lexicons'
77-import { isObj, hasProp } from '../../../../../util'
55+import { type ValidationResult, BlobRef } from '@atproto/lexicon'
86import { CID } from 'multiformats/cid'
77+import { validate as _validate } from '../../../../../lexicons'
88+import {
99+ type $Typed,
1010+ is$typed as _is$typed,
1111+ type OmitKey,
1212+} from '../../../../../util'
913import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
1010-import * as FmTealAlphaFeedDefs from './defs'
1414+import type * as FmTealAlphaFeedDefs from './defs.js'
1515+1616+const is$typed = _is$typed,
1717+ validate = _validate
1818+const id = 'fm.teal.alpha.feed.getActorFeed'
11191220export interface QueryParams {
1321 /** The author's DID for the play */
···22302331export interface OutputSchema {
2432 plays: FmTealAlphaFeedDefs.PlayView[]
2525- [k: string]: unknown
2633}
27342835export type HandlerInput = undefined
···22 * GENERATED CODE - DO NOT MODIFY
33 */
44import express from 'express'
55-import { ValidationResult, BlobRef } from '@atproto/lexicon'
66-import { lexicons } from '../../../../../lexicons'
77-import { isObj, hasProp } from '../../../../../util'
55+import { type ValidationResult, BlobRef } from '@atproto/lexicon'
86import { CID } from 'multiformats/cid'
77+import { validate as _validate } from '../../../../../lexicons'
88+import {
99+ type $Typed,
1010+ is$typed as _is$typed,
1111+ type OmitKey,
1212+} from '../../../../../util'
913import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
1010-import * as FmTealAlphaFeedDefs from './defs'
1414+import type * as FmTealAlphaFeedDefs from './defs.js'
1515+1616+const is$typed = _is$typed,
1717+ validate = _validate
1818+const id = 'fm.teal.alpha.feed.getPlay'
11191220export interface QueryParams {
1321 /** The author's DID for the play */
···20282129export interface OutputSchema {
2230 play: FmTealAlphaFeedDefs.PlayView
2323- [k: string]: unknown
2431}
25322633export type HandlerInput = undefined