diff --git a/packages/lexicons/defs/sh/comet/v0/actor/getProfiles.json b/packages/lexicons/defs/sh/comet/v0/actor/getProfiles.json new file mode 100644 index 0000000..b22dd9e --- /dev/null +++ b/packages/lexicons/defs/sh/comet/v0/actor/getProfiles.json @@ -0,0 +1,37 @@ +{ + "lexicon": 1, + "id": "sh.comet.v0.actor.getProfiles", + "defs": { + "main": { + "type": "query", + "description": "Get the profile views of multiple actors.", + "parameters": { + "type": "params", + "required": ["actors"], + "properties": { + "actors": { + "type": "array", + "maxLength": 25, + "items": { "type": "string", "format": "at-identifier" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["profiles"], + "properties": { + "profiles": { + "type": "array", + "items": { + "type": "ref", + "ref": "sh.comet.v0.actor.profile#view" + } + } + } + } + } + } + } +} diff --git a/packages/lexicons/defs/sh/comet/v0/actor/profile.json b/packages/lexicons/defs/sh/comet/v0/actor/profile.json index b9e32c2..e6b8640 100644 --- a/packages/lexicons/defs/sh/comet/v0/actor/profile.json +++ b/packages/lexicons/defs/sh/comet/v0/actor/profile.json @@ -58,19 +58,10 @@ "maxGraphemes": 64, "maxLength": 640 }, - "description": { - "type": "string", - "maxGraphemes": 256, - "maxLength": 2560 - }, - "descriptionFacets": { - "type": "ref", - "ref": "sh.comet.v0.richtext.facet" - }, "avatar": { "type": "string", "format": "uri" }, "indexedAt": { "type": "string", "format": "datetime" }, "createdAt": { "type": "string", "format": "datetime" }, - "viewer": { "type": "unknown", "description": "TODO" } + "viewer": { "type": "ref", "ref": "#viewerState" } } }, "viewFull": { @@ -106,8 +97,13 @@ "maxLength": 5, "items": { "type": "string", "format": "at-uri" } }, - "viewer": { "type": "unknown", "description": "TODO" } + "viewer": { "type": "ref", "ref": "#viewerState" } } + }, + "viewerState": { + "type": "object", + "description": "Metadata about the requesting account's relationship with the user. TODO: determine if we create our own graph or inherit bsky's.", + "properties": {} } } } diff --git a/packages/lexicons/defs/sh/comet/v0/feed/defs.json b/packages/lexicons/defs/sh/comet/v0/feed/defs.json index 2189ed5..d90c314 100644 --- a/packages/lexicons/defs/sh/comet/v0/feed/defs.json +++ b/packages/lexicons/defs/sh/comet/v0/feed/defs.json @@ -30,7 +30,8 @@ "description": "Metadata about the requesting account's relationship with the subject content. Only has meaningful content for authed requests.", "properties": { "like": { "type": "string", "format": "at-uri" }, - "repost": { "type": "string", "format": "at-uri" } + "repost": { "type": "string", "format": "at-uri" }, + "featured": { "type": "boolean" } } } } diff --git a/packages/lexicons/defs/sh/comet/v0/feed/getActorPlaylists.json b/packages/lexicons/defs/sh/comet/v0/feed/getActorPlaylists.json new file mode 100644 index 0000000..52c1744 --- /dev/null +++ b/packages/lexicons/defs/sh/comet/v0/feed/getActorPlaylists.json @@ -0,0 +1,44 @@ +{ + "lexicon": 1, + "id": "sh.comet.v0.feed.getActorPlaylists", + "defs": { + "main": { + "type": "query", + "description": "Get a list of an actor's playlists.", + "parameters": { + "type": "params", + "required": ["actor"], + "properties": { + "actor": { + "type": "string", + "format": "at-identifier" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["playlists"], + "properties": { + "cursor": { "type": "string" }, + "playlists": { + "type": "array", + "items": { + "type": "ref", + "ref": "sh.comet.v0.feed.playlist#view" + } + } + } + } + } + } + } +} diff --git a/packages/lexicons/defs/sh/comet/v0/feed/getActorTracks.json b/packages/lexicons/defs/sh/comet/v0/feed/getActorTracks.json new file mode 100644 index 0000000..9c07111 --- /dev/null +++ b/packages/lexicons/defs/sh/comet/v0/feed/getActorTracks.json @@ -0,0 +1,44 @@ +{ + "lexicon": 1, + "id": "sh.comet.v0.feed.getActorTracks", + "defs": { + "main": { + "type": "query", + "description": "Get a list of an actor's tracks.", + "parameters": { + "type": "params", + "required": ["actor"], + "properties": { + "actor": { + "type": "string", + "format": "at-identifier" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["tracks"], + "properties": { + "cursor": { "type": "string" }, + "tracks": { + "type": "array", + "items": { + "type": "ref", + "ref": "sh.comet.v0.feed.track#view" + } + } + } + } + } + } + } +} diff --git a/packages/lexicons/defs/sh/comet/v0/feed/playlist.json b/packages/lexicons/defs/sh/comet/v0/feed/playlist.json index d2b448a..5a8037d 100644 --- a/packages/lexicons/defs/sh/comet/v0/feed/playlist.json +++ b/packages/lexicons/defs/sh/comet/v0/feed/playlist.json @@ -12,7 +12,6 @@ "properties": { "tracks": { "type": "array", - "minLength": 1, "items": { "type": "string", "format": "at-uri" } }, "image": { @@ -82,6 +81,38 @@ "podcast": { "type": "token", "description": "Indicates the playlist is a podcast or radio show split into several individual tracks." + }, + "view": { + "type": "object", + "required": ["uri", "cid", "author", "tracks", "record"], + "properties": { + "uri": { "type": "string", "format": "at-uri" }, + "cid": { "type": "string", "format": "cid" }, + "author": { + "type": "ref", + "ref": "sh.comet.v0.actor.profile#viewFull" + }, + "tracks": { + "type": "array", + "items": { "type": "ref", "ref": "sh.comet.v0.feed.track#view" }, + "description": "TODO: include cursor for pagination if too many?" + }, + "image": { + "type": "string", + "format": "uri", + "description": "URL pointing to where the image for the playlist can be fetched." + }, + "record": { + "type": "ref", + "ref": "#main" + }, + "repostCount": { "type": "integer" }, + "likeCount": { "type": "integer" }, + "commentCount": { "type": "integer" }, + "trackCount": { "type": "integer" }, + "indexedAt": { "type": "string", "format": "datetime" }, + "viewer": { "type": "ref", "ref": "sh.comet.v0.feed.defs#viewerState" } + } } } } diff --git a/packages/lexicons/defs/sh/comet/v0/feed/track.json b/packages/lexicons/defs/sh/comet/v0/feed/track.json index 7b90a22..e25a230 100644 --- a/packages/lexicons/defs/sh/comet/v0/feed/track.json +++ b/packages/lexicons/defs/sh/comet/v0/feed/track.json @@ -4,7 +4,7 @@ "defs": { "main": { "type": "record", - "description": "A Comet audio track.", + "description": "A Comet audio track. TODO: should probably have some sort of pre-calculated waveform, or have a query to get one from a blob?", "key": "tid", "record": { "type": "object", @@ -64,7 +64,10 @@ "properties": { "uri": { "type": "string", "format": "at-uri" }, "cid": { "type": "string", "format": "cid" }, - "author": { "type": "unknown", "description": "TODO" }, + "author": { + "type": "ref", + "ref": "sh.comet.v0.actor.profile#viewFull" + }, "audio": { "type": "string", "format": "uri", @@ -82,6 +85,7 @@ "repostCount": { "type": "integer" }, "likeCount": { "type": "integer" }, "playCount": { "type": "integer" }, + "commentCount": { "type": "integer" }, "indexedAt": { "type": "string", "format": "datetime" }, "viewer": { "type": "ref", "ref": "sh.comet.v0.feed.defs#viewerState" } } diff --git a/packages/lexicons/package.json b/packages/lexicons/package.json index 0372efc..dbfd257 100644 --- a/packages/lexicons/package.json +++ b/packages/lexicons/package.json @@ -1,6 +1,6 @@ { "name": "@comet/lexicons", - "module": "index.ts", + "main": "src/index.ts", "devDependencies": { "@atcute/lex-cli": "^2.0.2", "@types/bun": "latest" diff --git a/packages/lexicons/src/index.ts b/packages/lexicons/src/index.ts index a63091e..b0d207c 100644 --- a/packages/lexicons/src/index.ts +++ b/packages/lexicons/src/index.ts @@ -1,7 +1,10 @@ export * as ShCometV0ActorGetProfile from "./types/sh/comet/v0/actor/getProfile.js"; +export * as ShCometV0ActorGetProfiles from "./types/sh/comet/v0/actor/getProfiles.js"; export * as ShCometV0ActorProfile from "./types/sh/comet/v0/actor/profile.js"; export * as ShCometV0FeedComment from "./types/sh/comet/v0/feed/comment.js"; export * as ShCometV0FeedDefs from "./types/sh/comet/v0/feed/defs.js"; +export * as ShCometV0FeedGetActorPlaylists from "./types/sh/comet/v0/feed/getActorPlaylists.js"; +export * as ShCometV0FeedGetActorTracks from "./types/sh/comet/v0/feed/getActorTracks.js"; export * as ShCometV0FeedLike from "./types/sh/comet/v0/feed/like.js"; export * as ShCometV0FeedPlay from "./types/sh/comet/v0/feed/play.js"; export * as ShCometV0FeedPlaylist from "./types/sh/comet/v0/feed/playlist.js"; diff --git a/packages/lexicons/src/types/sh/comet/v0/actor/getProfiles.ts b/packages/lexicons/src/types/sh/comet/v0/actor/getProfiles.ts new file mode 100644 index 0000000..03f19ac --- /dev/null +++ b/packages/lexicons/src/types/sh/comet/v0/actor/getProfiles.ts @@ -0,0 +1,33 @@ +import type {} from "@atcute/lexicons"; +import * as v from "@atcute/lexicons/validations"; +import type {} from "@atcute/lexicons/ambient"; +import * as ShCometV0ActorProfile from "./profile.js"; + +const _mainSchema = /*#__PURE__*/ v.query("sh.comet.v0.actor.getProfiles", { + params: /*#__PURE__*/ v.object({ + actors: /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.array(/*#__PURE__*/ v.actorIdentifierString()), + [/*#__PURE__*/ v.arrayLength(0, 25)], + ), + }), + output: { + type: "lex", + schema: /*#__PURE__*/ v.object({ + get profiles() { + return /*#__PURE__*/ v.array(ShCometV0ActorProfile.viewSchema); + }, + }), + }, +}); + +type main$schematype = typeof _mainSchema; + +export interface mainSchema extends main$schematype {} + +export const mainSchema = _mainSchema as mainSchema; + +declare module "@atcute/lexicons/ambient" { + interface XRPCQueries { + "sh.comet.v0.actor.getProfiles": mainSchema; + } +} diff --git a/packages/lexicons/src/types/sh/comet/v0/actor/profile.ts b/packages/lexicons/src/types/sh/comet/v0/actor/profile.ts index 7ccce19..7a1db4e 100644 --- a/packages/lexicons/src/types/sh/comet/v0/actor/profile.ts +++ b/packages/lexicons/src/types/sh/comet/v0/actor/profile.ts @@ -39,15 +39,6 @@ const _viewSchema = /*#__PURE__*/ v.object({ ), avatar: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), createdAt: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), - description: /*#__PURE__*/ v.optional( - /*#__PURE__*/ v.constrain(/*#__PURE__*/ v.string(), [ - /*#__PURE__*/ v.stringLength(0, 2560), - /*#__PURE__*/ v.stringGraphemes(0, 256), - ]), - ), - get descriptionFacets() { - return /*#__PURE__*/ v.optional(ShCometV0RichtextFacet.mainSchema); - }, did: /*#__PURE__*/ v.didString(), displayName: /*#__PURE__*/ v.optional( /*#__PURE__*/ v.constrain(/*#__PURE__*/ v.string(), [ @@ -57,7 +48,9 @@ const _viewSchema = /*#__PURE__*/ v.object({ ), handle: /*#__PURE__*/ v.handleString(), indexedAt: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), - viewer: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), + get viewer() { + return /*#__PURE__*/ v.optional(viewerStateSchema); + }, }); const _viewFullSchema = /*#__PURE__*/ v.object({ $type: /*#__PURE__*/ v.optional( @@ -94,24 +87,35 @@ const _viewFullSchema = /*#__PURE__*/ v.object({ indexedAt: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), playlistsCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), tracksCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), - viewer: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), + get viewer() { + return /*#__PURE__*/ v.optional(viewerStateSchema); + }, +}); +const _viewerStateSchema = /*#__PURE__*/ v.object({ + $type: /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.literal("sh.comet.v0.actor.profile#viewerState"), + ), }); type main$schematype = typeof _mainSchema; type view$schematype = typeof _viewSchema; type viewFull$schematype = typeof _viewFullSchema; +type viewerState$schematype = typeof _viewerStateSchema; export interface mainSchema extends main$schematype {} export interface viewSchema extends view$schematype {} export interface viewFullSchema extends viewFull$schematype {} +export interface viewerStateSchema extends viewerState$schematype {} export const mainSchema = _mainSchema as mainSchema; export const viewSchema = _viewSchema as viewSchema; export const viewFullSchema = _viewFullSchema as viewFullSchema; +export const viewerStateSchema = _viewerStateSchema as viewerStateSchema; export interface Main extends v.InferInput {} export interface View extends v.InferInput {} export interface ViewFull extends v.InferInput {} +export interface ViewerState extends v.InferInput {} declare module "@atcute/lexicons/ambient" { interface Records { diff --git a/packages/lexicons/src/types/sh/comet/v0/feed/defs.ts b/packages/lexicons/src/types/sh/comet/v0/feed/defs.ts index 8560df7..34c0a1a 100644 --- a/packages/lexicons/src/types/sh/comet/v0/feed/defs.ts +++ b/packages/lexicons/src/types/sh/comet/v0/feed/defs.ts @@ -20,6 +20,7 @@ const _viewerStateSchema = /*#__PURE__*/ v.object({ $type: /*#__PURE__*/ v.optional( /*#__PURE__*/ v.literal("sh.comet.v0.feed.defs#viewerState"), ), + featured: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), like: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), repost: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), }); diff --git a/packages/lexicons/src/types/sh/comet/v0/feed/getActorPlaylists.ts b/packages/lexicons/src/types/sh/comet/v0/feed/getActorPlaylists.ts new file mode 100644 index 0000000..10da347 --- /dev/null +++ b/packages/lexicons/src/types/sh/comet/v0/feed/getActorPlaylists.ts @@ -0,0 +1,41 @@ +import type {} from "@atcute/lexicons"; +import * as v from "@atcute/lexicons/validations"; +import type {} from "@atcute/lexicons/ambient"; +import * as ShCometV0FeedPlaylist from "./playlist.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "sh.comet.v0.feed.getActorPlaylists", + { + params: /*#__PURE__*/ v.object({ + actor: /*#__PURE__*/ v.actorIdentifierString(), + cursor: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + limit: /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain(/*#__PURE__*/ v.integer(), [ + /*#__PURE__*/ v.integerRange(1, 100), + ]), + 50, + ), + }), + output: { + type: "lex", + schema: /*#__PURE__*/ v.object({ + cursor: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get playlists() { + return /*#__PURE__*/ v.array(ShCometV0FeedPlaylist.viewSchema); + }, + }), + }, + }, +); + +type main$schematype = typeof _mainSchema; + +export interface mainSchema extends main$schematype {} + +export const mainSchema = _mainSchema as mainSchema; + +declare module "@atcute/lexicons/ambient" { + interface XRPCQueries { + "sh.comet.v0.feed.getActorPlaylists": mainSchema; + } +} diff --git a/packages/lexicons/src/types/sh/comet/v0/feed/getActorTracks.ts b/packages/lexicons/src/types/sh/comet/v0/feed/getActorTracks.ts new file mode 100644 index 0000000..a9f3452 --- /dev/null +++ b/packages/lexicons/src/types/sh/comet/v0/feed/getActorTracks.ts @@ -0,0 +1,38 @@ +import type {} from "@atcute/lexicons"; +import * as v from "@atcute/lexicons/validations"; +import type {} from "@atcute/lexicons/ambient"; +import * as ShCometV0FeedTrack from "./track.js"; + +const _mainSchema = /*#__PURE__*/ v.query("sh.comet.v0.feed.getActorTracks", { + params: /*#__PURE__*/ v.object({ + actor: /*#__PURE__*/ v.actorIdentifierString(), + cursor: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + limit: /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain(/*#__PURE__*/ v.integer(), [ + /*#__PURE__*/ v.integerRange(1, 100), + ]), + 50, + ), + }), + output: { + type: "lex", + schema: /*#__PURE__*/ v.object({ + cursor: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get tracks() { + return /*#__PURE__*/ v.array(ShCometV0FeedTrack.viewSchema); + }, + }), + }, +}); + +type main$schematype = typeof _mainSchema; + +export interface mainSchema extends main$schematype {} + +export const mainSchema = _mainSchema as mainSchema; + +declare module "@atcute/lexicons/ambient" { + interface XRPCQueries { + "sh.comet.v0.feed.getActorTracks": mainSchema; + } +} diff --git a/packages/lexicons/src/types/sh/comet/v0/feed/playlist.ts b/packages/lexicons/src/types/sh/comet/v0/feed/playlist.ts index 4dfd553..2e27289 100644 --- a/packages/lexicons/src/types/sh/comet/v0/feed/playlist.ts +++ b/packages/lexicons/src/types/sh/comet/v0/feed/playlist.ts @@ -1,7 +1,9 @@ import type {} from "@atcute/lexicons"; import * as v from "@atcute/lexicons/validations"; import type {} from "@atcute/lexicons/ambient"; +import * as ShCometV0ActorProfile from "../actor/profile.js"; import * as ShCometV0FeedDefs from "./defs.js"; +import * as ShCometV0FeedTrack from "./track.js"; import * as ShCometV0RichtextFacet from "../richtext/facet.js"; const _albumSchema = /*#__PURE__*/ v.literal("sh.comet.v0.feed.playlist#album"); @@ -41,10 +43,7 @@ const _mainSchema = /*#__PURE__*/ v.record( /*#__PURE__*/ v.stringLength(1, 2560), /*#__PURE__*/ v.stringGraphemes(0, 256), ]), - tracks: /*#__PURE__*/ v.constrain( - /*#__PURE__*/ v.array(/*#__PURE__*/ v.resourceUriString()), - [/*#__PURE__*/ v.arrayLength(1)], - ), + tracks: /*#__PURE__*/ v.array(/*#__PURE__*/ v.resourceUriString()), type: /*#__PURE__*/ v.string< | "sh.comet.v0.feed.playlist#album" | "sh.comet.v0.feed.playlist#compilation" @@ -60,30 +59,59 @@ const _playlistSchema = /*#__PURE__*/ v.literal( const _podcastSchema = /*#__PURE__*/ v.literal( "sh.comet.v0.feed.playlist#podcast", ); +const _viewSchema = /*#__PURE__*/ v.object({ + $type: /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.literal("sh.comet.v0.feed.playlist#view"), + ), + get author() { + return ShCometV0ActorProfile.viewFullSchema; + }, + cid: /*#__PURE__*/ v.cidString(), + commentCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + image: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + indexedAt: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), + likeCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + get record() { + return mainSchema; + }, + repostCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + trackCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + get tracks() { + return /*#__PURE__*/ v.array(ShCometV0FeedTrack.viewSchema); + }, + uri: /*#__PURE__*/ v.resourceUriString(), + get viewer() { + return /*#__PURE__*/ v.optional(ShCometV0FeedDefs.viewerStateSchema); + }, +}); type album$schematype = typeof _albumSchema; type compilation$schematype = typeof _compilationSchema; type main$schematype = typeof _mainSchema; type playlist$schematype = typeof _playlistSchema; type podcast$schematype = typeof _podcastSchema; +type view$schematype = typeof _viewSchema; export interface albumSchema extends album$schematype {} export interface compilationSchema extends compilation$schematype {} export interface mainSchema extends main$schematype {} export interface playlistSchema extends playlist$schematype {} export interface podcastSchema extends podcast$schematype {} +export interface viewSchema extends view$schematype {} export const albumSchema = _albumSchema as albumSchema; export const compilationSchema = _compilationSchema as compilationSchema; export const mainSchema = _mainSchema as mainSchema; export const playlistSchema = _playlistSchema as playlistSchema; export const podcastSchema = _podcastSchema as podcastSchema; +export const viewSchema = _viewSchema as viewSchema; export type Album = v.InferInput; export type Compilation = v.InferInput; export interface Main extends v.InferInput {} export type Playlist = v.InferInput; export type Podcast = v.InferInput; +export interface View extends v.InferInput {} declare module "@atcute/lexicons/ambient" { interface Records { diff --git a/packages/lexicons/src/types/sh/comet/v0/feed/track.ts b/packages/lexicons/src/types/sh/comet/v0/feed/track.ts index e0e75c2..22b3258 100644 --- a/packages/lexicons/src/types/sh/comet/v0/feed/track.ts +++ b/packages/lexicons/src/types/sh/comet/v0/feed/track.ts @@ -1,6 +1,7 @@ import type {} from "@atcute/lexicons"; import * as v from "@atcute/lexicons/validations"; import type {} from "@atcute/lexicons/ambient"; +import * as ShCometV0ActorProfile from "../actor/profile.js"; import * as ShCometV0FeedDefs from "./defs.js"; import * as ShCometV0RichtextFacet from "../richtext/facet.js"; @@ -45,8 +46,11 @@ const _viewSchema = /*#__PURE__*/ v.object({ /*#__PURE__*/ v.literal("sh.comet.v0.feed.track#view"), ), audio: /*#__PURE__*/ v.genericUriString(), - author: /*#__PURE__*/ v.unknown(), + get author() { + return ShCometV0ActorProfile.viewFullSchema; + }, cid: /*#__PURE__*/ v.cidString(), + commentCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), image: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), indexedAt: /*#__PURE__*/ v.datetimeString(), likeCount: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()),