From ff67619d70783455ab504b08e2b2129da50033e4 Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Tue, 30 Dec 2025 09:33:51 +0300 Subject: [PATCH] Add graph follow/followers lexicons Add lexicon JSON and PKL defs for follow, getFollowers, getFollows, and graph defs. Generate corresponding TypeScript types and register entries in the lexicons index. Update lexicon schema (IntegerType maximum/default) and tweak a HandlerAuth import to use a type import. --- apps/api/lexicons/graph/defs.json | 45 +++++ apps/api/lexicons/graph/follow.json | 28 +++ apps/api/lexicons/graph/getFollowers.json | 58 ++++++ apps/api/lexicons/graph/getFollows.json | 58 ++++++ apps/api/pkl/defs/graph/defs.pkl | 41 ++++ apps/api/pkl/defs/graph/follow.pkl | 26 +++ apps/api/pkl/defs/graph/getFollowers.pkl | 54 ++++++ apps/api/pkl/defs/graph/getFollows.pkl | 54 ++++++ apps/api/pkl/schema/lexicon.pkl | 4 +- apps/api/src/lexicon/index.ts | 34 ++++ apps/api/src/lexicon/lexicons.ts | 182 ++++++++++++++++++ .../lexicon/types/app/rocksky/graph/defs.ts | 47 +++++ .../lexicon/types/app/rocksky/graph/follow.ts | 27 +++ .../types/app/rocksky/graph/getFollowers.ts | 52 +++++ .../types/app/rocksky/graph/getFollows.ts | 52 +++++ apps/api/src/xrpc/app/rocksky/feed/getFeed.ts | 2 +- 16 files changed, 762 insertions(+), 2 deletions(-) create mode 100644 apps/api/lexicons/graph/defs.json create mode 100644 apps/api/lexicons/graph/follow.json create mode 100644 apps/api/lexicons/graph/getFollowers.json create mode 100644 apps/api/lexicons/graph/getFollows.json create mode 100644 apps/api/pkl/defs/graph/defs.pkl create mode 100644 apps/api/pkl/defs/graph/follow.pkl create mode 100644 apps/api/pkl/defs/graph/getFollowers.pkl create mode 100644 apps/api/pkl/defs/graph/getFollows.pkl create mode 100644 apps/api/src/lexicon/types/app/rocksky/graph/defs.ts create mode 100644 apps/api/src/lexicon/types/app/rocksky/graph/follow.ts create mode 100644 apps/api/src/lexicon/types/app/rocksky/graph/getFollowers.ts create mode 100644 apps/api/src/lexicon/types/app/rocksky/graph/getFollows.ts diff --git a/apps/api/lexicons/graph/defs.json b/apps/api/lexicons/graph/defs.json new file mode 100644 index 00000000..059b923a --- /dev/null +++ b/apps/api/lexicons/graph/defs.json @@ -0,0 +1,45 @@ +{ + "lexicon": 1, + "id": "app.rocksky.graph.defs", + "defs": { + "notFoundActor": { + "type": "object", + "description": "indicates that a handle or DID could not be resolved", + "required": [ + "actor", + "notFound" + ], + "properties": { + "actor": { + "type": "string", + "format": "at-identifier" + }, + "notFound": { + "type": "boolean" + } + } + }, + "relationship": { + "type": "object", + "required": [ + "did" + ], + "properties": { + "did": { + "type": "string", + "format": "did" + }, + "following": { + "type": "string", + "description": "if the actor follows this DID, this is the AT-URI of the follow record", + "format": "at-uri" + }, + "followedBy": { + "type": "string", + "description": "if the actor is followed by this DID, contains the AT-URI of the follow record", + "format": "at-uri" + } + } + } + } +} diff --git a/apps/api/lexicons/graph/follow.json b/apps/api/lexicons/graph/follow.json new file mode 100644 index 00000000..d97078e3 --- /dev/null +++ b/apps/api/lexicons/graph/follow.json @@ -0,0 +1,28 @@ +{ + "lexicon": 1, + "id": "app.rocksky.graph.follow", + "defs": { + "main": { + "type": "record", + "description": "Record declaring a social 'follow' relationship of another account.", + "key": "tid", + "record": { + "type": "object", + "required": [ + "createdAt", + "subject" + ], + "properties": { + "createdAt": { + "type": "string", + "format": "datetime" + }, + "subject": { + "type": "ref", + "ref": "com.atproto.repo.strongRef" + } + } + } + } + } +} diff --git a/apps/api/lexicons/graph/getFollowers.json b/apps/api/lexicons/graph/getFollowers.json new file mode 100644 index 00000000..cad48fa9 --- /dev/null +++ b/apps/api/lexicons/graph/getFollowers.json @@ -0,0 +1,58 @@ +{ + "lexicon": 1, + "id": "app.rocksky.graph.getFollowers", + "defs": { + "main": { + "type": "query", + "description": "Enumerates accounts which follow a specified account (actor).", + "parameters": { + "type": "params", + "required": [ + "actor" + ], + "properties": { + "actor": { + "type": "string", + "format": "at-identifier" + }, + "limit": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "default": 50 + }, + "cursor": { + "type": "string" + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": [ + "subject", + "followers" + ], + "properties": { + "subject": { + "type": "ref", + "ref": "app.rocksky.actor.defs#profileViewBasic" + }, + "followers": { + "type": "array", + "items": { + "type": "ref", + "ref": "app.rocksky.actor.defs#profileViewBasic" + } + }, + "cursor": { + "type": "string", + "description": "A cursor value to pass to subsequent calls to get the next page of results." + } + } + } + } + } + } +} diff --git a/apps/api/lexicons/graph/getFollows.json b/apps/api/lexicons/graph/getFollows.json new file mode 100644 index 00000000..3fd6313b --- /dev/null +++ b/apps/api/lexicons/graph/getFollows.json @@ -0,0 +1,58 @@ +{ + "lexicon": 1, + "id": "app.rocksky.graph.getFollows", + "defs": { + "main": { + "type": "query", + "description": "Enumerates accounts which a specified account (actor) follows.", + "parameters": { + "type": "params", + "required": [ + "actor" + ], + "properties": { + "actor": { + "type": "string", + "format": "at-identifier" + }, + "limit": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "default": 50 + }, + "cursor": { + "type": "string" + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": [ + "subject", + "follows" + ], + "properties": { + "subject": { + "type": "ref", + "ref": "app.rocksky.actor.defs#profileViewBasic" + }, + "follows": { + "type": "array", + "items": { + "type": "ref", + "ref": "app.rocksky.actor.defs#profileViewBasic" + } + }, + "cursor": { + "type": "string", + "description": "A cursor value to pass to subsequent calls to get the next page of results." + } + } + } + } + } + } +} diff --git a/apps/api/pkl/defs/graph/defs.pkl b/apps/api/pkl/defs/graph/defs.pkl new file mode 100644 index 00000000..2bf5f6d9 --- /dev/null +++ b/apps/api/pkl/defs/graph/defs.pkl @@ -0,0 +1,41 @@ +amends "../../schema/lexicon.pkl" + +lexicon = 1 +id = "app.rocksky.graph.defs" +defs = new Mapping { + ["notFoundActor"] = new ObjectType { + type = "object" + description = "indicates that a handle or DID could not be resolved" + required = List("actor", "notFound") + properties { + ["actor"] = new StringType { + type = "string" + format = "at-identifier" + } + ["notFound"] = new BooleanType { + type = "boolean" + } + } + } + ["relationship"] { + type = "object" + required = List("did") + properties { + ["did"] = new StringType { + type = "string" + format = "did" + } + ["following"] = new StringType { + type = "string" + format = "at-uri" + description = "if the actor follows this DID, this is the AT-URI of the follow record" + } + ["followedBy"] = new StringType { + type = "string" + format = "at-uri" + description = + "if the actor is followed by this DID, contains the AT-URI of the follow record" + } + } + } +} diff --git a/apps/api/pkl/defs/graph/follow.pkl b/apps/api/pkl/defs/graph/follow.pkl new file mode 100644 index 00000000..5c83827a --- /dev/null +++ b/apps/api/pkl/defs/graph/follow.pkl @@ -0,0 +1,26 @@ +amends "../../schema/lexicon.pkl" + +lexicon = 1 +id = "app.rocksky.graph.follow" +defs = new Mapping { + ["main"] { + type = "record" + key = "tid" + description = "Record declaring a social 'follow' relationship of another account." + `record` { + type = "object" + required = List("createdAt", "subject") + properties { + ["createdAt"] = new StringType { + type = "string" + format = "datetime" + } + + ["subject"] = new Ref { + type = "ref" + ref = "com.atproto.repo.strongRef" + } + } + } + } +} diff --git a/apps/api/pkl/defs/graph/getFollowers.pkl b/apps/api/pkl/defs/graph/getFollowers.pkl new file mode 100644 index 00000000..75a5c1a9 --- /dev/null +++ b/apps/api/pkl/defs/graph/getFollowers.pkl @@ -0,0 +1,54 @@ +amends "../../schema/lexicon.pkl" + +lexicon = 1 +id = "app.rocksky.graph.getFollowers" +defs = new Mapping { + ["main"] { + type = "query" + description = "Enumerates accounts which follow a specified account (actor)." + parameters = new Params { + required = List("actor") + properties { + ["actor"] = new StringType { + type = "string" + format = "at-identifier" + } + ["limit"] = new IntegerType { + type = "integer" + maximum = 100 + minimum = 1 + default = 50 + } + ["cursor"] = new StringType { + type = "string" + } + } + } + + output { + encoding = "application/json" + schema = new ObjectType { + type = "object" + required = List("subject", "followers") + properties { + ["subject"] = new Ref { + type = "ref" + ref = "app.rocksky.actor.defs#profileViewBasic" + } + ["followers"] = new Array { + type = "array" + items = new Ref { + type = "ref" + ref = "app.rocksky.actor.defs#profileViewBasic" + } + } + ["cursor"] = new StringType { + type = "string" + description = + "A cursor value to pass to subsequent calls to get the next page of results." + } + } + } + } + } +} diff --git a/apps/api/pkl/defs/graph/getFollows.pkl b/apps/api/pkl/defs/graph/getFollows.pkl new file mode 100644 index 00000000..bfcef26c --- /dev/null +++ b/apps/api/pkl/defs/graph/getFollows.pkl @@ -0,0 +1,54 @@ +amends "../../schema/lexicon.pkl" + +lexicon = 1 +id = "app.rocksky.graph.getFollows" +defs = new Mapping { + ["main"] { + type = "query" + description = "Enumerates accounts which a specified account (actor) follows." + parameters = new Params { + required = List("actor") + properties { + ["actor"] = new StringType { + type = "string" + format = "at-identifier" + } + ["limit"] = new IntegerType { + type = "integer" + maximum = 100 + minimum = 1 + default = 50 + } + ["cursor"] = new StringType { + type = "string" + } + } + } + + output { + encoding = "application/json" + schema = new ObjectType { + type = "object" + required = List("subject", "follows") + properties { + ["subject"] = new Ref { + type = "ref" + ref = "app.rocksky.actor.defs#profileViewBasic" + } + ["follows"] = new Array { + type = "array" + items = new Ref { + type = "ref" + ref = "app.rocksky.actor.defs#profileViewBasic" + } + } + ["cursor"] = new StringType { + type = "string" + description = + "A cursor value to pass to subsequent calls to get the next page of results." + } + } + } + } + } +} diff --git a/apps/api/pkl/schema/lexicon.pkl b/apps/api/pkl/schema/lexicon.pkl index c8af9c51..17006236 100644 --- a/apps/api/pkl/schema/lexicon.pkl +++ b/apps/api/pkl/schema/lexicon.pkl @@ -13,7 +13,9 @@ class StringType extends BaseType { class IntegerType extends BaseType { type: "integer" + maximum: Int? minimum: Int? + default: Int? } class BooleanType extends BaseType { @@ -40,7 +42,7 @@ class Params { class ObjectType extends BaseType { type: "object" required: List? - properties: Mapping + properties: Mapping } class Union extends BaseType { diff --git a/apps/api/src/lexicon/index.ts b/apps/api/src/lexicon/index.ts index b54be268..64c4b23c 100644 --- a/apps/api/src/lexicon/index.ts +++ b/apps/api/src/lexicon/index.ts @@ -48,6 +48,8 @@ import type * as AppRockskyFeedSearch from "./types/app/rocksky/feed/search"; import type * as AppRockskyGoogledriveDownloadFile from "./types/app/rocksky/googledrive/downloadFile"; import type * as AppRockskyGoogledriveGetFile from "./types/app/rocksky/googledrive/getFile"; import type * as AppRockskyGoogledriveGetFiles from "./types/app/rocksky/googledrive/getFiles"; +import type * as AppRockskyGraphGetFollowers from "./types/app/rocksky/graph/getFollowers"; +import type * as AppRockskyGraphGetFollows from "./types/app/rocksky/graph/getFollows"; import type * as AppRockskyLikeDislikeShout from "./types/app/rocksky/like/dislikeShout"; import type * as AppRockskyLikeDislikeSong from "./types/app/rocksky/like/dislikeSong"; import type * as AppRockskyLikeLikeShout from "./types/app/rocksky/like/likeShout"; @@ -237,6 +239,7 @@ export class AppRockskyNS { dropbox: AppRockskyDropboxNS; feed: AppRockskyFeedNS; googledrive: AppRockskyGoogledriveNS; + graph: AppRockskyGraphNS; like: AppRockskyLikeNS; player: AppRockskyPlayerNS; playlist: AppRockskyPlaylistNS; @@ -256,6 +259,7 @@ export class AppRockskyNS { this.dropbox = new AppRockskyDropboxNS(server); this.feed = new AppRockskyFeedNS(server); this.googledrive = new AppRockskyGoogledriveNS(server); + this.graph = new AppRockskyGraphNS(server); this.like = new AppRockskyLikeNS(server); this.player = new AppRockskyPlayerNS(server); this.playlist = new AppRockskyPlaylistNS(server); @@ -705,6 +709,36 @@ export class AppRockskyGoogledriveNS { } } +export class AppRockskyGraphNS { + _server: Server; + + constructor(server: Server) { + this._server = server; + } + + getFollowers( + cfg: ConfigOf< + AV, + AppRockskyGraphGetFollowers.Handler>, + AppRockskyGraphGetFollowers.HandlerReqCtx> + >, + ) { + const nsid = "app.rocksky.graph.getFollowers"; // @ts-ignore + return this._server.xrpc.method(nsid, cfg); + } + + getFollows( + cfg: ConfigOf< + AV, + AppRockskyGraphGetFollows.Handler>, + AppRockskyGraphGetFollows.HandlerReqCtx> + >, + ) { + const nsid = "app.rocksky.graph.getFollows"; // @ts-ignore + return this._server.xrpc.method(nsid, cfg); + } +} + export class AppRockskyLikeNS { _server: Server; diff --git a/apps/api/src/lexicon/lexicons.ts b/apps/api/src/lexicon/lexicons.ts index 164169a4..607e603e 100644 --- a/apps/api/src/lexicon/lexicons.ts +++ b/apps/api/src/lexicon/lexicons.ts @@ -2735,6 +2735,184 @@ export const schemaDict = { }, }, }, + AppRockskyGraphDefs: { + lexicon: 1, + id: "app.rocksky.graph.defs", + defs: { + notFoundActor: { + type: "object", + description: "indicates that a handle or DID could not be resolved", + required: ["actor", "notFound"], + properties: { + actor: { + type: "string", + format: "at-identifier", + }, + notFound: { + type: "boolean", + }, + }, + }, + relationship: { + type: "object", + required: ["did"], + properties: { + did: { + type: "string", + format: "did", + }, + following: { + type: "string", + description: + "if the actor follows this DID, this is the AT-URI of the follow record", + format: "at-uri", + }, + followedBy: { + type: "string", + description: + "if the actor is followed by this DID, contains the AT-URI of the follow record", + format: "at-uri", + }, + }, + }, + }, + }, + AppRockskyGraphFollow: { + lexicon: 1, + id: "app.rocksky.graph.follow", + defs: { + main: { + type: "record", + description: + "Record declaring a social 'follow' relationship of another account.", + key: "tid", + record: { + type: "object", + required: ["createdAt", "subject"], + properties: { + createdAt: { + type: "string", + format: "datetime", + }, + subject: { + type: "ref", + ref: "lex:com.atproto.repo.strongRef", + }, + }, + }, + }, + }, + }, + AppRockskyGraphGetFollowers: { + lexicon: 1, + id: "app.rocksky.graph.getFollowers", + defs: { + main: { + type: "query", + description: + "Enumerates accounts which follow a specified account (actor).", + parameters: { + type: "params", + required: ["actor"], + properties: { + actor: { + type: "string", + format: "at-identifier", + }, + limit: { + type: "integer", + maximum: 100, + minimum: 1, + default: 50, + }, + cursor: { + type: "string", + }, + }, + }, + output: { + encoding: "application/json", + schema: { + type: "object", + required: ["subject", "followers"], + properties: { + subject: { + type: "ref", + ref: "lex:app.rocksky.actor.defs#profileViewBasic", + }, + followers: { + type: "array", + items: { + type: "ref", + ref: "lex:app.rocksky.actor.defs#profileViewBasic", + }, + }, + cursor: { + type: "string", + description: + "A cursor value to pass to subsequent calls to get the next page of results.", + }, + }, + }, + }, + }, + }, + }, + AppRockskyGraphGetFollows: { + lexicon: 1, + id: "app.rocksky.graph.getFollows", + defs: { + main: { + type: "query", + description: + "Enumerates accounts which a specified account (actor) follows.", + parameters: { + type: "params", + required: ["actor"], + properties: { + actor: { + type: "string", + format: "at-identifier", + }, + limit: { + type: "integer", + maximum: 100, + minimum: 1, + default: 50, + }, + cursor: { + type: "string", + }, + }, + }, + output: { + encoding: "application/json", + schema: { + type: "object", + required: ["subject", "follows"], + properties: { + subject: { + type: "ref", + ref: "lex:app.rocksky.actor.defs#profileViewBasic", + }, + follows: { + type: "array", + items: { + type: "ref", + ref: "lex:app.rocksky.actor.defs#profileViewBasic", + }, + }, + cursor: { + type: "string", + description: + "A cursor value to pass to subsequent calls to get the next page of results.", + }, + }, + }, + }, + }, + }, + }, AppRockskyLikeDislikeShout: { lexicon: 1, id: "app.rocksky.like.dislikeShout", @@ -5395,6 +5573,10 @@ export const ids = { AppRockskyGoogledriveDownloadFile: "app.rocksky.googledrive.downloadFile", AppRockskyGoogledriveGetFile: "app.rocksky.googledrive.getFile", AppRockskyGoogledriveGetFiles: "app.rocksky.googledrive.getFiles", + AppRockskyGraphDefs: "app.rocksky.graph.defs", + AppRockskyGraphFollow: "app.rocksky.graph.follow", + AppRockskyGraphGetFollowers: "app.rocksky.graph.getFollowers", + AppRockskyGraphGetFollows: "app.rocksky.graph.getFollows", AppRockskyLikeDislikeShout: "app.rocksky.like.dislikeShout", AppRockskyLikeDislikeSong: "app.rocksky.like.dislikeSong", AppRockskyLike: "app.rocksky.like", diff --git a/apps/api/src/lexicon/types/app/rocksky/graph/defs.ts b/apps/api/src/lexicon/types/app/rocksky/graph/defs.ts new file mode 100644 index 00000000..654ae397 --- /dev/null +++ b/apps/api/src/lexicon/types/app/rocksky/graph/defs.ts @@ -0,0 +1,47 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from "@atproto/lexicon"; +import { lexicons } from "../../../../lexicons"; +import { isObj, hasProp } from "../../../../util"; +import { CID } from "multiformats/cid"; + +/** indicates that a handle or DID could not be resolved */ +export interface NotFoundActor { + actor: string; + notFound: boolean; + [k: string]: unknown; +} + +export function isNotFoundActor(v: unknown): v is NotFoundActor { + return ( + isObj(v) && + hasProp(v, "$type") && + v.$type === "app.rocksky.graph.defs#notFoundActor" + ); +} + +export function validateNotFoundActor(v: unknown): ValidationResult { + return lexicons.validate("app.rocksky.graph.defs#notFoundActor", v); +} + +export interface Relationship { + did: string; + /** if the actor follows this DID, this is the AT-URI of the follow record */ + following?: string; + /** if the actor is followed by this DID, contains the AT-URI of the follow record */ + followedBy?: string; + [k: string]: unknown; +} + +export function isRelationship(v: unknown): v is Relationship { + return ( + isObj(v) && + hasProp(v, "$type") && + v.$type === "app.rocksky.graph.defs#relationship" + ); +} + +export function validateRelationship(v: unknown): ValidationResult { + return lexicons.validate("app.rocksky.graph.defs#relationship", v); +} diff --git a/apps/api/src/lexicon/types/app/rocksky/graph/follow.ts b/apps/api/src/lexicon/types/app/rocksky/graph/follow.ts new file mode 100644 index 00000000..eec9ecc0 --- /dev/null +++ b/apps/api/src/lexicon/types/app/rocksky/graph/follow.ts @@ -0,0 +1,27 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from "@atproto/lexicon"; +import { lexicons } from "../../../../lexicons"; +import { isObj, hasProp } from "../../../../util"; +import { CID } from "multiformats/cid"; +import type * as ComAtprotoRepoStrongRef from "../../../com/atproto/repo/strongRef"; + +export interface Record { + createdAt: string; + subject: ComAtprotoRepoStrongRef.Main; + [k: string]: unknown; +} + +export function isRecord(v: unknown): v is Record { + return ( + isObj(v) && + hasProp(v, "$type") && + (v.$type === "app.rocksky.graph.follow#main" || + v.$type === "app.rocksky.graph.follow") + ); +} + +export function validateRecord(v: unknown): ValidationResult { + return lexicons.validate("app.rocksky.graph.follow#main", v); +} diff --git a/apps/api/src/lexicon/types/app/rocksky/graph/getFollowers.ts b/apps/api/src/lexicon/types/app/rocksky/graph/getFollowers.ts new file mode 100644 index 00000000..181407b8 --- /dev/null +++ b/apps/api/src/lexicon/types/app/rocksky/graph/getFollowers.ts @@ -0,0 +1,52 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import type express from "express"; +import { ValidationResult, BlobRef } from "@atproto/lexicon"; +import { lexicons } from "../../../../lexicons"; +import { isObj, hasProp } from "../../../../util"; +import { CID } from "multiformats/cid"; +import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; +import type * as AppRockskyActorDefs from "../actor/defs"; + +export interface QueryParams { + actor: string; + limit: number; + cursor?: string; +} + +export type InputSchema = undefined; + +export interface OutputSchema { + subject: AppRockskyActorDefs.ProfileViewBasic; + followers: AppRockskyActorDefs.ProfileViewBasic[]; + /** A cursor value to pass to subsequent calls to get the next page of results. */ + cursor?: string; + [k: string]: unknown; +} + +export type HandlerInput = undefined; + +export interface HandlerSuccess { + encoding: "application/json"; + body: OutputSchema; + headers?: { [key: string]: string }; +} + +export interface HandlerError { + status: number; + message?: string; +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough; +export type HandlerReqCtx = { + auth: HA; + params: QueryParams; + input: HandlerInput; + req: express.Request; + res: express.Response; + resetRouteRateLimits: () => Promise; +}; +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput; diff --git a/apps/api/src/lexicon/types/app/rocksky/graph/getFollows.ts b/apps/api/src/lexicon/types/app/rocksky/graph/getFollows.ts new file mode 100644 index 00000000..e7c75bb0 --- /dev/null +++ b/apps/api/src/lexicon/types/app/rocksky/graph/getFollows.ts @@ -0,0 +1,52 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import type express from "express"; +import { ValidationResult, BlobRef } from "@atproto/lexicon"; +import { lexicons } from "../../../../lexicons"; +import { isObj, hasProp } from "../../../../util"; +import { CID } from "multiformats/cid"; +import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; +import type * as AppRockskyActorDefs from "../actor/defs"; + +export interface QueryParams { + actor: string; + limit: number; + cursor?: string; +} + +export type InputSchema = undefined; + +export interface OutputSchema { + subject: AppRockskyActorDefs.ProfileViewBasic; + follows: AppRockskyActorDefs.ProfileViewBasic[]; + /** A cursor value to pass to subsequent calls to get the next page of results. */ + cursor?: string; + [k: string]: unknown; +} + +export type HandlerInput = undefined; + +export interface HandlerSuccess { + encoding: "application/json"; + body: OutputSchema; + headers?: { [key: string]: string }; +} + +export interface HandlerError { + status: number; + message?: string; +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough; +export type HandlerReqCtx = { + auth: HA; + params: QueryParams; + input: HandlerInput; + req: express.Request; + res: express.Response; + resetRouteRateLimits: () => Promise; +}; +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput; diff --git a/apps/api/src/xrpc/app/rocksky/feed/getFeed.ts b/apps/api/src/xrpc/app/rocksky/feed/getFeed.ts index 506f1efa..88bfe071 100644 --- a/apps/api/src/xrpc/app/rocksky/feed/getFeed.ts +++ b/apps/api/src/xrpc/app/rocksky/feed/getFeed.ts @@ -10,7 +10,7 @@ import type { SelectScrobble } from "schema/scrobbles"; import type { SelectTrack } from "schema/tracks"; import type { SelectUser } from "schema/users"; import axios from "axios"; -import { HandlerAuth } from "@atproto/xrpc-server"; +import type { HandlerAuth } from "@atproto/xrpc-server"; import { env } from "lib/env"; export default function (server: Server, ctx: Context) { -- 2.51.2