···7474 }
7575 }
7676 },
7777+ "songViewBasic": {
7878+ "type": "object",
7979+ "properties": {
8080+ "uri": {
8181+ "type": "string",
8282+ "description": "The URI of the song.",
8383+ "format": "at-uri"
8484+ },
8585+ "title": {
8686+ "type": "string",
8787+ "description": "The title of the song."
8888+ },
8989+ "playCount": {
9090+ "type": "integer",
9191+ "description": "The number of times the song has been played.",
9292+ "minimum": 0
9393+ }
9494+ }
9595+ },
7796 "listenerViewBasic": {
7897 "type": "object",
7998 "properties": {
···100119 },
101120 "mostListenedSong": {
102121 "type": "ref",
103103- "ref": "app.rocksky.song.defs#songViewBasic"
122122+ "ref": "app.rocksky.artist.defs#songViewBasic"
123123+ },
124124+ "totalPlays": {
125125+ "type": "integer",
126126+ "description": "The total number of plays by the listener.",
127127+ "minimum": 0
128128+ },
129129+ "rank": {
130130+ "type": "integer",
131131+ "description": "The rank of the listener among all listeners of the artist.",
132132+ "minimum": 1
104133 }
105134 }
106135 }
+36-1
apps/api/pkl/defs/artist/defs.pkl
···9191 }
9292 }
93939494+ ["songViewBasic"] {
9595+ type = "object"
9696+ properties {
9797+ ["uri"] = new StringType {
9898+ type = "string"
9999+ format = "at-uri"
100100+ description = "The URI of the song."
101101+ }
102102+103103+ ["title"] = new StringType {
104104+ type = "string"
105105+ description = "The title of the song."
106106+ }
107107+108108+ ["playCount"] = new IntegerType {
109109+ type = "integer"
110110+ description = "The number of times the song has been played."
111111+ minimum = 0
112112+ }
113113+114114+ }
115115+ }
116116+94117 ["listenerViewBasic"] {
95118 type = "object"
96119 properties {
···121144 }
122145123146 ["mostListenedSong"] = new Ref {
124124- ref = "app.rocksky.song.defs#songViewBasic"
147147+ ref = "app.rocksky.artist.defs#songViewBasic"
148148+ }
149149+150150+ ["totalPlays"] = new IntegerType {
151151+ type = "integer"
152152+ description = "The total number of plays by the listener."
153153+ minimum = 0
154154+ }
155155+156156+ ["rank"] = new IntegerType {
157157+ type = "integer"
158158+ description = "The rank of the listener among all listeners of the artist."
159159+ minimum = 1
125160 }
126161127162 }
+31-1
apps/api/src/lexicon/lexicons.ts
···10661066 },
10671067 },
10681068 },
10691069+ songViewBasic: {
10701070+ type: 'object',
10711071+ properties: {
10721072+ uri: {
10731073+ type: 'string',
10741074+ description: 'The URI of the song.',
10751075+ format: 'at-uri',
10761076+ },
10771077+ title: {
10781078+ type: 'string',
10791079+ description: 'The title of the song.',
10801080+ },
10811081+ playCount: {
10821082+ type: 'integer',
10831083+ description: 'The number of times the song has been played.',
10841084+ minimum: 0,
10851085+ },
10861086+ },
10871087+ },
10691088 listenerViewBasic: {
10701089 type: 'object',
10711090 properties: {
···10921111 },
10931112 mostListenedSong: {
10941113 type: 'ref',
10951095- ref: 'lex:app.rocksky.song.defs#songViewBasic',
11141114+ ref: 'lex:app.rocksky.artist.defs#songViewBasic',
11151115+ },
11161116+ totalPlays: {
11171117+ type: 'integer',
11181118+ description: 'The total number of plays by the listener.',
11191119+ minimum: 0,
11201120+ },
11211121+ rank: {
11221122+ type: 'integer',
11231123+ description:
11241124+ 'The rank of the listener among all listeners of the artist.',
11251125+ minimum: 1,
10961126 },
10971127 },
10981128 },
···55import { lexicons } from '../../../../lexicons'
66import { isObj, hasProp } from '../../../../util'
77import { CID } from 'multiformats/cid'
88-import type * as AppRockskySongDefs from '../song/defs'
98109export interface ArtistViewBasic {
1110 /** The unique identifier of the artist. */
···6766 return lexicons.validate('app.rocksky.artist.defs#artistViewDetailed', v)
6867}
69686969+export interface SongViewBasic {
7070+ /** The URI of the song. */
7171+ uri?: string
7272+ /** The title of the song. */
7373+ title?: string
7474+ /** The number of times the song has been played. */
7575+ playCount?: number
7676+ [k: string]: unknown
7777+}
7878+7979+export function isSongViewBasic(v: unknown): v is SongViewBasic {
8080+ return (
8181+ isObj(v) &&
8282+ hasProp(v, '$type') &&
8383+ v.$type === 'app.rocksky.artist.defs#songViewBasic'
8484+ )
8585+}
8686+8787+export function validateSongViewBasic(v: unknown): ValidationResult {
8888+ return lexicons.validate('app.rocksky.artist.defs#songViewBasic', v)
8989+}
9090+7091export interface ListenerViewBasic {
7192 /** The unique identifier of the actor. */
7293 id?: string
···7899 displayName?: string
79100 /** The URL of the listener's avatar image. */
80101 avatar?: string
8181- mostListenedSong?: AppRockskySongDefs.SongViewBasic
102102+ mostListenedSong?: SongViewBasic
103103+ /** The total number of plays by the listener. */
104104+ totalPlays?: number
105105+ /** The rank of the listener among all listeners of the artist. */
106106+ rank?: number
82107 [k: string]: unknown
83108}
84109