diff --git a/lexicons/app/bsky/actor/searchActors.json b/lexicons/app/bsky/actor/searchActors.json index dc76ad8fc39..f65e2fc953b 100644 --- a/lexicons/app/bsky/actor/searchActors.json +++ b/lexicons/app/bsky/actor/searchActors.json @@ -4,16 +4,23 @@ "defs": { "main": { "type": "query", - "description": "Find actors matching search criteria.", + "description": "Find actors (profiles) matching search criteria.", "parameters": { "type": "params", "properties": { - "term": { "type": "string" }, + "term": { + "type": "string", + "description": "DEPRECATED: use 'q' instead" + }, + "q": { + "type": "string", + "description": "search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended" + }, "limit": { "type": "integer", "minimum": 1, "maximum": 100, - "default": 50 + "default": 25 }, "cursor": { "type": "string" } } diff --git a/lexicons/app/bsky/actor/searchActorsTypeahead.json b/lexicons/app/bsky/actor/searchActorsTypeahead.json index 7065f3d7117..f94dd6c3f69 100644 --- a/lexicons/app/bsky/actor/searchActorsTypeahead.json +++ b/lexicons/app/bsky/actor/searchActorsTypeahead.json @@ -8,12 +8,19 @@ "parameters": { "type": "params", "properties": { - "term": { "type": "string" }, + "term": { + "type": "string", + "description": "DEPRECATED: use 'q' instead" + }, + "q": { + "type": "string", + "description": "search query prefix; not a full query string" + }, "limit": { "type": "integer", "minimum": 1, "maximum": 100, - "default": 50 + "default": 10 } } }, diff --git a/lexicons/app/bsky/feed/searchPosts.json b/lexicons/app/bsky/feed/searchPosts.json new file mode 100644 index 00000000000..34eb38f686e --- /dev/null +++ b/lexicons/app/bsky/feed/searchPosts.json @@ -0,0 +1,52 @@ +{ + "lexicon": 1, + "id": "app.bsky.feed.searchPosts", + "defs": { + "main": { + "type": "query", + "description": "Find posts matching search criteria", + "parameters": { + "type": "params", + "required": ["q"], + "properties": { + "q": { + "type": "string", + "description": "search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + }, + "cursor": { + "type": "string", + "description": "optional pagination mechanism; may not necessarily allow scrolling through entire result set" + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["posts"], + "properties": { + "cursor": { "type": "string" }, + "hitsTotal": { + "type": "integer", + "description": "count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits" + }, + "posts": { + "type": "array", + "items": { + "type": "ref", + "ref": "app.bsky.feed.defs#postView" + } + } + } + } + }, + "errors": [{ "name": "BadQueryString" }] + } + } +} diff --git a/lexicons/app/bsky/unspecced/defs.json b/lexicons/app/bsky/unspecced/defs.json new file mode 100644 index 00000000000..e9925922a3e --- /dev/null +++ b/lexicons/app/bsky/unspecced/defs.json @@ -0,0 +1,20 @@ +{ + "lexicon": 1, + "id": "app.bsky.unspecced.defs", + "defs": { + "skeletonSearchPost": { + "type": "object", + "required": ["uri"], + "properties": { + "uri": { "type": "string", "format": "at-uri" } + } + }, + "skeletonSearchActor": { + "type": "object", + "required": ["did"], + "properties": { + "did": { "type": "string", "format": "did" } + } + } + } +} diff --git a/lexicons/app/bsky/unspecced/searchActorsSkeleton.json b/lexicons/app/bsky/unspecced/searchActorsSkeleton.json new file mode 100644 index 00000000000..108dacf9b14 --- /dev/null +++ b/lexicons/app/bsky/unspecced/searchActorsSkeleton.json @@ -0,0 +1,56 @@ +{ + "lexicon": 1, + "id": "app.bsky.unspecced.searchActorsSkeleton", + "defs": { + "main": { + "type": "query", + "description": "Backend Actors (profile) search, returning only skeleton", + "parameters": { + "type": "params", + "required": ["q"], + "properties": { + "q": { + "type": "string", + "description": "search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax" + }, + "typeahead": { + "type": "boolean", + "description": "if true, acts as fast/simple 'typeahead' query" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + }, + "cursor": { + "type": "string", + "description": "optional pagination mechanism; may not necessarily allow scrolling through entire result set" + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["actors"], + "properties": { + "cursor": { "type": "string" }, + "hitsTotal": { + "type": "integer", + "description": "count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits" + }, + "actors": { + "type": "array", + "items": { + "type": "ref", + "ref": "app.bsky.unspecced.defs#skeletonSearchActor" + } + } + } + } + }, + "errors": [{ "name": "BadQueryString" }] + } + } +} diff --git a/lexicons/app/bsky/unspecced/searchPostsSkeleton.json b/lexicons/app/bsky/unspecced/searchPostsSkeleton.json new file mode 100644 index 00000000000..532bfea79f9 --- /dev/null +++ b/lexicons/app/bsky/unspecced/searchPostsSkeleton.json @@ -0,0 +1,52 @@ +{ + "lexicon": 1, + "id": "app.bsky.unspecced.searchPostsSkeleton", + "defs": { + "main": { + "type": "query", + "description": "Backend Posts search, returning only skeleton", + "parameters": { + "type": "params", + "required": ["q"], + "properties": { + "q": { + "type": "string", + "description": "search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + }, + "cursor": { + "type": "string", + "description": "optional pagination mechanism; may not necessarily allow scrolling through entire result set" + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["posts"], + "properties": { + "cursor": { "type": "string" }, + "hitsTotal": { + "type": "integer", + "description": "count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits" + }, + "posts": { + "type": "array", + "items": { + "type": "ref", + "ref": "app.bsky.unspecced.defs#skeletonSearchPost" + } + } + } + } + }, + "errors": [{ "name": "BadQueryString" }] + } + } +} diff --git a/lexicons/com/atproto/admin/searchRepos.json b/lexicons/com/atproto/admin/searchRepos.json index fb9c90f343c..85cc6fd482a 100644 --- a/lexicons/com/atproto/admin/searchRepos.json +++ b/lexicons/com/atproto/admin/searchRepos.json @@ -8,7 +8,11 @@ "parameters": { "type": "params", "properties": { - "term": { "type": "string" }, + "term": { + "type": "string", + "description": "DEPRECATED: use 'q' instead" + }, + "q": { "type": "string" }, "invitedBy": { "type": "string" }, "limit": { "type": "integer", diff --git a/packages/api/src/client/index.ts b/packages/api/src/client/index.ts index cc2e7268c8a..1aa1738e393 100644 --- a/packages/api/src/client/index.ts +++ b/packages/api/src/client/index.ts @@ -107,6 +107,7 @@ import * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline' import * as AppBskyFeedLike from './types/app/bsky/feed/like' import * as AppBskyFeedPost from './types/app/bsky/feed/post' import * as AppBskyFeedRepost from './types/app/bsky/feed/repost' +import * as AppBskyFeedSearchPosts from './types/app/bsky/feed/searchPosts' import * as AppBskyFeedThreadgate from './types/app/bsky/feed/threadgate' import * as AppBskyGraphBlock from './types/app/bsky/graph/block' import * as AppBskyGraphDefs from './types/app/bsky/graph/defs' @@ -133,9 +134,12 @@ import * as AppBskyNotificationRegisterPush from './types/app/bsky/notification/ import * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen' import * as AppBskyRichtextFacet from './types/app/bsky/richtext/facet' import * as AppBskyUnspeccedApplyLabels from './types/app/bsky/unspecced/applyLabels' +import * as AppBskyUnspeccedDefs from './types/app/bsky/unspecced/defs' import * as AppBskyUnspeccedGetPopular from './types/app/bsky/unspecced/getPopular' import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators' import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton' +import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton' +import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton' export * as ComAtprotoAdminDefs from './types/com/atproto/admin/defs' export * as ComAtprotoAdminDisableAccountInvites from './types/com/atproto/admin/disableAccountInvites' @@ -237,6 +241,7 @@ export * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline' export * as AppBskyFeedLike from './types/app/bsky/feed/like' export * as AppBskyFeedPost from './types/app/bsky/feed/post' export * as AppBskyFeedRepost from './types/app/bsky/feed/repost' +export * as AppBskyFeedSearchPosts from './types/app/bsky/feed/searchPosts' export * as AppBskyFeedThreadgate from './types/app/bsky/feed/threadgate' export * as AppBskyGraphBlock from './types/app/bsky/graph/block' export * as AppBskyGraphDefs from './types/app/bsky/graph/defs' @@ -263,9 +268,12 @@ export * as AppBskyNotificationRegisterPush from './types/app/bsky/notification/ export * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen' export * as AppBskyRichtextFacet from './types/app/bsky/richtext/facet' export * as AppBskyUnspeccedApplyLabels from './types/app/bsky/unspecced/applyLabels' +export * as AppBskyUnspeccedDefs from './types/app/bsky/unspecced/defs' export * as AppBskyUnspeccedGetPopular from './types/app/bsky/unspecced/getPopular' export * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators' export * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton' +export * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton' +export * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton' export const COM_ATPROTO_ADMIN = { DefsTakedown: 'com.atproto.admin.defs#takedown', @@ -1433,6 +1441,17 @@ export class FeedNS { throw AppBskyFeedGetTimeline.toKnownErr(e) }) } + + searchPosts( + params?: AppBskyFeedSearchPosts.QueryParams, + opts?: AppBskyFeedSearchPosts.CallOptions, + ): Promise { + return this._service.xrpc + .call('app.bsky.feed.searchPosts', params, undefined, opts) + .catch((e) => { + throw AppBskyFeedSearchPosts.toKnownErr(e) + }) + } } export class GeneratorRecord { @@ -2334,4 +2353,26 @@ export class UnspeccedNS { throw AppBskyUnspeccedGetTimelineSkeleton.toKnownErr(e) }) } + + searchActorsSkeleton( + params?: AppBskyUnspeccedSearchActorsSkeleton.QueryParams, + opts?: AppBskyUnspeccedSearchActorsSkeleton.CallOptions, + ): Promise { + return this._service.xrpc + .call('app.bsky.unspecced.searchActorsSkeleton', params, undefined, opts) + .catch((e) => { + throw AppBskyUnspeccedSearchActorsSkeleton.toKnownErr(e) + }) + } + + searchPostsSkeleton( + params?: AppBskyUnspeccedSearchPostsSkeleton.QueryParams, + opts?: AppBskyUnspeccedSearchPostsSkeleton.CallOptions, + ): Promise { + return this._service.xrpc + .call('app.bsky.unspecced.searchPostsSkeleton', params, undefined, opts) + .catch((e) => { + throw AppBskyUnspeccedSearchPostsSkeleton.toKnownErr(e) + }) + } } diff --git a/packages/api/src/client/lexicons.ts b/packages/api/src/client/lexicons.ts index fcc72aaed20..822eab72e74 100644 --- a/packages/api/src/client/lexicons.ts +++ b/packages/api/src/client/lexicons.ts @@ -1113,6 +1113,10 @@ export const schemaDict = { properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', }, invitedBy: { type: 'string', @@ -4115,18 +4119,24 @@ export const schemaDict = { defs: { main: { type: 'query', - description: 'Find actors matching search criteria.', + description: 'Find actors (profiles) matching search criteria.', parameters: { type: 'params', properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', }, limit: { type: 'integer', minimum: 1, maximum: 100, - default: 50, + default: 25, }, cursor: { type: 'string', @@ -4167,12 +4177,17 @@ export const schemaDict = { properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + description: 'search query prefix; not a full query string', }, limit: { type: 'integer', minimum: 1, maximum: 100, - default: 50, + default: 10, }, }, }, @@ -5830,6 +5845,67 @@ export const schemaDict = { }, }, }, + AppBskyFeedSearchPosts: { + lexicon: 1, + id: 'app.bsky.feed.searchPosts', + defs: { + main: { + type: 'query', + description: 'Find posts matching search criteria', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['posts'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + posts: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.feed.defs#postView', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, AppBskyFeedThreadgate: { lexicon: 1, id: 'app.bsky.feed.threadgate', @@ -6972,6 +7048,32 @@ export const schemaDict = { }, }, }, + AppBskyUnspeccedDefs: { + lexicon: 1, + id: 'app.bsky.unspecced.defs', + defs: { + skeletonSearchPost: { + type: 'object', + required: ['uri'], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + }, + }, + skeletonSearchActor: { + type: 'object', + required: ['did'], + properties: { + did: { + type: 'string', + format: 'did', + }, + }, + }, + }, + }, AppBskyUnspeccedGetPopular: { lexicon: 1, id: 'app.bsky.unspecced.getPopular', @@ -7114,6 +7216,132 @@ export const schemaDict = { }, }, }, + AppBskyUnspeccedSearchActorsSkeleton: { + lexicon: 1, + id: 'app.bsky.unspecced.searchActorsSkeleton', + defs: { + main: { + type: 'query', + description: 'Backend Actors (profile) search, returning only skeleton', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax', + }, + typeahead: { + type: 'boolean', + description: "if true, acts as fast/simple 'typeahead' query", + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['actors'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + actors: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.unspecced.defs#skeletonSearchActor', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, + AppBskyUnspeccedSearchPostsSkeleton: { + lexicon: 1, + id: 'app.bsky.unspecced.searchPostsSkeleton', + defs: { + main: { + type: 'query', + description: 'Backend Posts search, returning only skeleton', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['posts'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + posts: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.unspecced.defs#skeletonSearchPost', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, } export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[] export const lexicons: Lexicons = new Lexicons(schemas) @@ -7225,6 +7453,7 @@ export const ids = { AppBskyFeedLike: 'app.bsky.feed.like', AppBskyFeedPost: 'app.bsky.feed.post', AppBskyFeedRepost: 'app.bsky.feed.repost', + AppBskyFeedSearchPosts: 'app.bsky.feed.searchPosts', AppBskyFeedThreadgate: 'app.bsky.feed.threadgate', AppBskyGraphBlock: 'app.bsky.graph.block', AppBskyGraphDefs: 'app.bsky.graph.defs', @@ -7253,8 +7482,12 @@ export const ids = { AppBskyNotificationUpdateSeen: 'app.bsky.notification.updateSeen', AppBskyRichtextFacet: 'app.bsky.richtext.facet', AppBskyUnspeccedApplyLabels: 'app.bsky.unspecced.applyLabels', + AppBskyUnspeccedDefs: 'app.bsky.unspecced.defs', AppBskyUnspeccedGetPopular: 'app.bsky.unspecced.getPopular', AppBskyUnspeccedGetPopularFeedGenerators: 'app.bsky.unspecced.getPopularFeedGenerators', AppBskyUnspeccedGetTimelineSkeleton: 'app.bsky.unspecced.getTimelineSkeleton', + AppBskyUnspeccedSearchActorsSkeleton: + 'app.bsky.unspecced.searchActorsSkeleton', + AppBskyUnspeccedSearchPostsSkeleton: 'app.bsky.unspecced.searchPostsSkeleton', } diff --git a/packages/api/src/client/types/app/bsky/actor/searchActors.ts b/packages/api/src/client/types/app/bsky/actor/searchActors.ts index 526e012910f..5e6527606d8 100644 --- a/packages/api/src/client/types/app/bsky/actor/searchActors.ts +++ b/packages/api/src/client/types/app/bsky/actor/searchActors.ts @@ -9,7 +9,10 @@ import { CID } from 'multiformats/cid' import * as AppBskyActorDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q?: string limit?: number cursor?: string } diff --git a/packages/api/src/client/types/app/bsky/actor/searchActorsTypeahead.ts b/packages/api/src/client/types/app/bsky/actor/searchActorsTypeahead.ts index 5bb1557b406..5818d6f64ad 100644 --- a/packages/api/src/client/types/app/bsky/actor/searchActorsTypeahead.ts +++ b/packages/api/src/client/types/app/bsky/actor/searchActorsTypeahead.ts @@ -9,7 +9,10 @@ import { CID } from 'multiformats/cid' import * as AppBskyActorDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + /** search query prefix; not a full query string */ + q?: string limit?: number } diff --git a/packages/api/src/client/types/app/bsky/feed/searchPosts.ts b/packages/api/src/client/types/app/bsky/feed/searchPosts.ts new file mode 100644 index 00000000000..6b8613a2e1f --- /dev/null +++ b/packages/api/src/client/types/app/bsky/feed/searchPosts.ts @@ -0,0 +1,50 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as AppBskyFeedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q: string + limit?: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + posts: AppBskyFeedDefs.PostView[] + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export class BadQueryStringError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'BadQueryString') return new BadQueryStringError(e) + } + return e +} diff --git a/packages/api/src/client/types/app/bsky/unspecced/defs.ts b/packages/api/src/client/types/app/bsky/unspecced/defs.ts new file mode 100644 index 00000000000..ecee03578af --- /dev/null +++ b/packages/api/src/client/types/app/bsky/unspecced/defs.ts @@ -0,0 +1,41 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' + +export interface SkeletonSearchPost { + uri: string + [k: string]: unknown +} + +export function isSkeletonSearchPost(v: unknown): v is SkeletonSearchPost { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'app.bsky.unspecced.defs#skeletonSearchPost' + ) +} + +export function validateSkeletonSearchPost(v: unknown): ValidationResult { + return lexicons.validate('app.bsky.unspecced.defs#skeletonSearchPost', v) +} + +export interface SkeletonSearchActor { + did: string + [k: string]: unknown +} + +export function isSkeletonSearchActor(v: unknown): v is SkeletonSearchActor { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'app.bsky.unspecced.defs#skeletonSearchActor' + ) +} + +export function validateSkeletonSearchActor(v: unknown): ValidationResult { + return lexicons.validate('app.bsky.unspecced.defs#skeletonSearchActor', v) +} diff --git a/packages/api/src/client/types/app/bsky/unspecced/searchActorsSkeleton.ts b/packages/api/src/client/types/app/bsky/unspecced/searchActorsSkeleton.ts new file mode 100644 index 00000000000..7cc2729620e --- /dev/null +++ b/packages/api/src/client/types/app/bsky/unspecced/searchActorsSkeleton.ts @@ -0,0 +1,52 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as AppBskyUnspeccedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax */ + q: string + /** if true, acts as fast/simple 'typeahead' query */ + typeahead?: boolean + limit?: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + actors: AppBskyUnspeccedDefs.SkeletonSearchActor[] + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export class BadQueryStringError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'BadQueryString') return new BadQueryStringError(e) + } + return e +} diff --git a/packages/api/src/client/types/app/bsky/unspecced/searchPostsSkeleton.ts b/packages/api/src/client/types/app/bsky/unspecced/searchPostsSkeleton.ts new file mode 100644 index 00000000000..07391886f8f --- /dev/null +++ b/packages/api/src/client/types/app/bsky/unspecced/searchPostsSkeleton.ts @@ -0,0 +1,50 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as AppBskyUnspeccedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q: string + limit?: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + posts: AppBskyUnspeccedDefs.SkeletonSearchPost[] + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export class BadQueryStringError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'BadQueryString') return new BadQueryStringError(e) + } + return e +} diff --git a/packages/api/src/client/types/com/atproto/admin/searchRepos.ts b/packages/api/src/client/types/com/atproto/admin/searchRepos.ts index a43e0ee7322..372cc98ff13 100644 --- a/packages/api/src/client/types/com/atproto/admin/searchRepos.ts +++ b/packages/api/src/client/types/com/atproto/admin/searchRepos.ts @@ -9,7 +9,9 @@ import { CID } from 'multiformats/cid' import * as ComAtprotoAdminDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + q?: string invitedBy?: string limit?: number cursor?: string diff --git a/packages/bsky/src/api/app/bsky/actor/searchActors.ts b/packages/bsky/src/api/app/bsky/actor/searchActors.ts index df5821a03f9..d4ae0a8d264 100644 --- a/packages/bsky/src/api/app/bsky/actor/searchActors.ts +++ b/packages/bsky/src/api/app/bsky/actor/searchActors.ts @@ -11,8 +11,14 @@ export default function (server: Server, ctx: AppContext) { server.app.bsky.actor.searchActors({ auth: ctx.authOptionalVerifier, handler: async ({ auth, params }) => { - const { cursor, limit, term: rawTerm } = params + let { cursor, limit, term: rawTerm, q: rawQ } = params const requester = auth.credentials.did + + // prefer new 'q' query param over deprecated 'term' + if (rawQ) { + rawTerm = rawQ + } + const term = cleanTerm(rawTerm || '') const db = ctx.db.getReplica('search') diff --git a/packages/bsky/src/api/app/bsky/actor/searchActorsTypeahead.ts b/packages/bsky/src/api/app/bsky/actor/searchActorsTypeahead.ts index 64bcd811d02..c438c4d2324 100644 --- a/packages/bsky/src/api/app/bsky/actor/searchActorsTypeahead.ts +++ b/packages/bsky/src/api/app/bsky/actor/searchActorsTypeahead.ts @@ -9,8 +9,14 @@ export default function (server: Server, ctx: AppContext) { server.app.bsky.actor.searchActorsTypeahead({ auth: ctx.authOptionalVerifier, handler: async ({ params, auth }) => { - const { limit, term: rawTerm } = params + let { limit, term: rawTerm, q: rawQ } = params const requester = auth.credentials.did + + // prefer new 'q' query param over deprecated 'term' + if (rawQ) { + rawTerm = rawQ + } + const term = cleanTerm(rawTerm || '') const db = ctx.db.getReplica('search') diff --git a/packages/bsky/src/api/com/atproto/admin/searchRepos.ts b/packages/bsky/src/api/com/atproto/admin/searchRepos.ts index 9945b27fcb4..a17421e90cd 100644 --- a/packages/bsky/src/api/com/atproto/admin/searchRepos.ts +++ b/packages/bsky/src/api/com/atproto/admin/searchRepos.ts @@ -12,6 +12,11 @@ export default function (server: Server, ctx: AppContext) { if (invitedBy) { throw new InvalidRequestError('The invitedBy parameter is unsupported') } + // prefer new 'q' query param over deprecated 'term' + const { q } = params + if (q) { + params.term = q + } const { results, cursor } = await ctx.services .actor(db) diff --git a/packages/bsky/src/lexicon/index.ts b/packages/bsky/src/lexicon/index.ts index 96721b37ff6..99a1f8e78db 100644 --- a/packages/bsky/src/lexicon/index.ts +++ b/packages/bsky/src/lexicon/index.ts @@ -93,6 +93,7 @@ import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts' import * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy' import * as AppBskyFeedGetSuggestedFeeds from './types/app/bsky/feed/getSuggestedFeeds' import * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline' +import * as AppBskyFeedSearchPosts from './types/app/bsky/feed/searchPosts' import * as AppBskyGraphGetBlocks from './types/app/bsky/graph/getBlocks' import * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers' import * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows' @@ -114,6 +115,8 @@ import * as AppBskyUnspeccedApplyLabels from './types/app/bsky/unspecced/applyLa import * as AppBskyUnspeccedGetPopular from './types/app/bsky/unspecced/getPopular' import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators' import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton' +import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton' +import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton' export const COM_ATPROTO_ADMIN = { DefsTakedown: 'com.atproto.admin.defs#takedown', @@ -1216,6 +1219,17 @@ export class FeedNS { const nsid = 'app.bsky.feed.getTimeline' // @ts-ignore return this._server.xrpc.method(nsid, cfg) } + + searchPosts( + cfg: ConfigOf< + AV, + AppBskyFeedSearchPosts.Handler>, + AppBskyFeedSearchPosts.HandlerReqCtx> + >, + ) { + const nsid = 'app.bsky.feed.searchPosts' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } } export class GraphNS { @@ -1479,6 +1493,28 @@ export class UnspeccedNS { const nsid = 'app.bsky.unspecced.getTimelineSkeleton' // @ts-ignore return this._server.xrpc.method(nsid, cfg) } + + searchActorsSkeleton( + cfg: ConfigOf< + AV, + AppBskyUnspeccedSearchActorsSkeleton.Handler>, + AppBskyUnspeccedSearchActorsSkeleton.HandlerReqCtx> + >, + ) { + const nsid = 'app.bsky.unspecced.searchActorsSkeleton' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + searchPostsSkeleton( + cfg: ConfigOf< + AV, + AppBskyUnspeccedSearchPostsSkeleton.Handler>, + AppBskyUnspeccedSearchPostsSkeleton.HandlerReqCtx> + >, + ) { + const nsid = 'app.bsky.unspecced.searchPostsSkeleton' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } } type SharedRateLimitOpts = { diff --git a/packages/bsky/src/lexicon/lexicons.ts b/packages/bsky/src/lexicon/lexicons.ts index fcc72aaed20..822eab72e74 100644 --- a/packages/bsky/src/lexicon/lexicons.ts +++ b/packages/bsky/src/lexicon/lexicons.ts @@ -1113,6 +1113,10 @@ export const schemaDict = { properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', }, invitedBy: { type: 'string', @@ -4115,18 +4119,24 @@ export const schemaDict = { defs: { main: { type: 'query', - description: 'Find actors matching search criteria.', + description: 'Find actors (profiles) matching search criteria.', parameters: { type: 'params', properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', }, limit: { type: 'integer', minimum: 1, maximum: 100, - default: 50, + default: 25, }, cursor: { type: 'string', @@ -4167,12 +4177,17 @@ export const schemaDict = { properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + description: 'search query prefix; not a full query string', }, limit: { type: 'integer', minimum: 1, maximum: 100, - default: 50, + default: 10, }, }, }, @@ -5830,6 +5845,67 @@ export const schemaDict = { }, }, }, + AppBskyFeedSearchPosts: { + lexicon: 1, + id: 'app.bsky.feed.searchPosts', + defs: { + main: { + type: 'query', + description: 'Find posts matching search criteria', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['posts'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + posts: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.feed.defs#postView', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, AppBskyFeedThreadgate: { lexicon: 1, id: 'app.bsky.feed.threadgate', @@ -6972,6 +7048,32 @@ export const schemaDict = { }, }, }, + AppBskyUnspeccedDefs: { + lexicon: 1, + id: 'app.bsky.unspecced.defs', + defs: { + skeletonSearchPost: { + type: 'object', + required: ['uri'], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + }, + }, + skeletonSearchActor: { + type: 'object', + required: ['did'], + properties: { + did: { + type: 'string', + format: 'did', + }, + }, + }, + }, + }, AppBskyUnspeccedGetPopular: { lexicon: 1, id: 'app.bsky.unspecced.getPopular', @@ -7114,6 +7216,132 @@ export const schemaDict = { }, }, }, + AppBskyUnspeccedSearchActorsSkeleton: { + lexicon: 1, + id: 'app.bsky.unspecced.searchActorsSkeleton', + defs: { + main: { + type: 'query', + description: 'Backend Actors (profile) search, returning only skeleton', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax', + }, + typeahead: { + type: 'boolean', + description: "if true, acts as fast/simple 'typeahead' query", + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['actors'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + actors: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.unspecced.defs#skeletonSearchActor', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, + AppBskyUnspeccedSearchPostsSkeleton: { + lexicon: 1, + id: 'app.bsky.unspecced.searchPostsSkeleton', + defs: { + main: { + type: 'query', + description: 'Backend Posts search, returning only skeleton', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['posts'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + posts: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.unspecced.defs#skeletonSearchPost', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, } export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[] export const lexicons: Lexicons = new Lexicons(schemas) @@ -7225,6 +7453,7 @@ export const ids = { AppBskyFeedLike: 'app.bsky.feed.like', AppBskyFeedPost: 'app.bsky.feed.post', AppBskyFeedRepost: 'app.bsky.feed.repost', + AppBskyFeedSearchPosts: 'app.bsky.feed.searchPosts', AppBskyFeedThreadgate: 'app.bsky.feed.threadgate', AppBskyGraphBlock: 'app.bsky.graph.block', AppBskyGraphDefs: 'app.bsky.graph.defs', @@ -7253,8 +7482,12 @@ export const ids = { AppBskyNotificationUpdateSeen: 'app.bsky.notification.updateSeen', AppBskyRichtextFacet: 'app.bsky.richtext.facet', AppBskyUnspeccedApplyLabels: 'app.bsky.unspecced.applyLabels', + AppBskyUnspeccedDefs: 'app.bsky.unspecced.defs', AppBskyUnspeccedGetPopular: 'app.bsky.unspecced.getPopular', AppBskyUnspeccedGetPopularFeedGenerators: 'app.bsky.unspecced.getPopularFeedGenerators', AppBskyUnspeccedGetTimelineSkeleton: 'app.bsky.unspecced.getTimelineSkeleton', + AppBskyUnspeccedSearchActorsSkeleton: + 'app.bsky.unspecced.searchActorsSkeleton', + AppBskyUnspeccedSearchPostsSkeleton: 'app.bsky.unspecced.searchPostsSkeleton', } diff --git a/packages/bsky/src/lexicon/types/app/bsky/actor/searchActors.ts b/packages/bsky/src/lexicon/types/app/bsky/actor/searchActors.ts index f620a463cff..0222f3658da 100644 --- a/packages/bsky/src/lexicon/types/app/bsky/actor/searchActors.ts +++ b/packages/bsky/src/lexicon/types/app/bsky/actor/searchActors.ts @@ -10,7 +10,10 @@ import { HandlerAuth } from '@atproto/xrpc-server' import * as AppBskyActorDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q?: string limit: number cursor?: string } diff --git a/packages/bsky/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts b/packages/bsky/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts index 4f5bbb7c23c..ba0d62444ce 100644 --- a/packages/bsky/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts +++ b/packages/bsky/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts @@ -10,7 +10,10 @@ import { HandlerAuth } from '@atproto/xrpc-server' import * as AppBskyActorDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + /** search query prefix; not a full query string */ + q?: string limit: number } diff --git a/packages/bsky/src/lexicon/types/app/bsky/feed/searchPosts.ts b/packages/bsky/src/lexicon/types/app/bsky/feed/searchPosts.ts new file mode 100644 index 00000000000..6b5fe08e467 --- /dev/null +++ b/packages/bsky/src/lexicon/types/app/bsky/feed/searchPosts.ts @@ -0,0 +1,54 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth } from '@atproto/xrpc-server' +import * as AppBskyFeedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q: string + limit: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + posts: AppBskyFeedDefs.PostView[] + [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 + error?: 'BadQueryString' +} + +export type HandlerOutput = HandlerError | HandlerSuccess +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/bsky/src/lexicon/types/app/bsky/unspecced/defs.ts b/packages/bsky/src/lexicon/types/app/bsky/unspecced/defs.ts new file mode 100644 index 00000000000..59a6b38064c --- /dev/null +++ b/packages/bsky/src/lexicon/types/app/bsky/unspecced/defs.ts @@ -0,0 +1,41 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' + +export interface SkeletonSearchPost { + uri: string + [k: string]: unknown +} + +export function isSkeletonSearchPost(v: unknown): v is SkeletonSearchPost { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'app.bsky.unspecced.defs#skeletonSearchPost' + ) +} + +export function validateSkeletonSearchPost(v: unknown): ValidationResult { + return lexicons.validate('app.bsky.unspecced.defs#skeletonSearchPost', v) +} + +export interface SkeletonSearchActor { + did: string + [k: string]: unknown +} + +export function isSkeletonSearchActor(v: unknown): v is SkeletonSearchActor { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'app.bsky.unspecced.defs#skeletonSearchActor' + ) +} + +export function validateSkeletonSearchActor(v: unknown): ValidationResult { + return lexicons.validate('app.bsky.unspecced.defs#skeletonSearchActor', v) +} diff --git a/packages/bsky/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts b/packages/bsky/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts new file mode 100644 index 00000000000..2cf59bf86a9 --- /dev/null +++ b/packages/bsky/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts @@ -0,0 +1,56 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth } from '@atproto/xrpc-server' +import * as AppBskyUnspeccedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax */ + q: string + /** if true, acts as fast/simple 'typeahead' query */ + typeahead?: boolean + limit: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + actors: AppBskyUnspeccedDefs.SkeletonSearchActor[] + [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 + error?: 'BadQueryString' +} + +export type HandlerOutput = HandlerError | HandlerSuccess +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/bsky/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts b/packages/bsky/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts new file mode 100644 index 00000000000..df990d2c5c6 --- /dev/null +++ b/packages/bsky/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts @@ -0,0 +1,54 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth } from '@atproto/xrpc-server' +import * as AppBskyUnspeccedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q: string + limit: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + posts: AppBskyUnspeccedDefs.SkeletonSearchPost[] + [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 + error?: 'BadQueryString' +} + +export type HandlerOutput = HandlerError | HandlerSuccess +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/bsky/src/lexicon/types/com/atproto/admin/searchRepos.ts b/packages/bsky/src/lexicon/types/com/atproto/admin/searchRepos.ts index c79cd046ca0..32266fd66fd 100644 --- a/packages/bsky/src/lexicon/types/com/atproto/admin/searchRepos.ts +++ b/packages/bsky/src/lexicon/types/com/atproto/admin/searchRepos.ts @@ -10,7 +10,9 @@ import { HandlerAuth } from '@atproto/xrpc-server' import * as ComAtprotoAdminDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + q?: string invitedBy?: string limit: number cursor?: string diff --git a/packages/pds/src/lexicon/index.ts b/packages/pds/src/lexicon/index.ts index 96721b37ff6..99a1f8e78db 100644 --- a/packages/pds/src/lexicon/index.ts +++ b/packages/pds/src/lexicon/index.ts @@ -93,6 +93,7 @@ import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts' import * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy' import * as AppBskyFeedGetSuggestedFeeds from './types/app/bsky/feed/getSuggestedFeeds' import * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline' +import * as AppBskyFeedSearchPosts from './types/app/bsky/feed/searchPosts' import * as AppBskyGraphGetBlocks from './types/app/bsky/graph/getBlocks' import * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers' import * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows' @@ -114,6 +115,8 @@ import * as AppBskyUnspeccedApplyLabels from './types/app/bsky/unspecced/applyLa import * as AppBskyUnspeccedGetPopular from './types/app/bsky/unspecced/getPopular' import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators' import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton' +import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton' +import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton' export const COM_ATPROTO_ADMIN = { DefsTakedown: 'com.atproto.admin.defs#takedown', @@ -1216,6 +1219,17 @@ export class FeedNS { const nsid = 'app.bsky.feed.getTimeline' // @ts-ignore return this._server.xrpc.method(nsid, cfg) } + + searchPosts( + cfg: ConfigOf< + AV, + AppBskyFeedSearchPosts.Handler>, + AppBskyFeedSearchPosts.HandlerReqCtx> + >, + ) { + const nsid = 'app.bsky.feed.searchPosts' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } } export class GraphNS { @@ -1479,6 +1493,28 @@ export class UnspeccedNS { const nsid = 'app.bsky.unspecced.getTimelineSkeleton' // @ts-ignore return this._server.xrpc.method(nsid, cfg) } + + searchActorsSkeleton( + cfg: ConfigOf< + AV, + AppBskyUnspeccedSearchActorsSkeleton.Handler>, + AppBskyUnspeccedSearchActorsSkeleton.HandlerReqCtx> + >, + ) { + const nsid = 'app.bsky.unspecced.searchActorsSkeleton' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + searchPostsSkeleton( + cfg: ConfigOf< + AV, + AppBskyUnspeccedSearchPostsSkeleton.Handler>, + AppBskyUnspeccedSearchPostsSkeleton.HandlerReqCtx> + >, + ) { + const nsid = 'app.bsky.unspecced.searchPostsSkeleton' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } } type SharedRateLimitOpts = { diff --git a/packages/pds/src/lexicon/lexicons.ts b/packages/pds/src/lexicon/lexicons.ts index fcc72aaed20..822eab72e74 100644 --- a/packages/pds/src/lexicon/lexicons.ts +++ b/packages/pds/src/lexicon/lexicons.ts @@ -1113,6 +1113,10 @@ export const schemaDict = { properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', }, invitedBy: { type: 'string', @@ -4115,18 +4119,24 @@ export const schemaDict = { defs: { main: { type: 'query', - description: 'Find actors matching search criteria.', + description: 'Find actors (profiles) matching search criteria.', parameters: { type: 'params', properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', }, limit: { type: 'integer', minimum: 1, maximum: 100, - default: 50, + default: 25, }, cursor: { type: 'string', @@ -4167,12 +4177,17 @@ export const schemaDict = { properties: { term: { type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + description: 'search query prefix; not a full query string', }, limit: { type: 'integer', minimum: 1, maximum: 100, - default: 50, + default: 10, }, }, }, @@ -5830,6 +5845,67 @@ export const schemaDict = { }, }, }, + AppBskyFeedSearchPosts: { + lexicon: 1, + id: 'app.bsky.feed.searchPosts', + defs: { + main: { + type: 'query', + description: 'Find posts matching search criteria', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['posts'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + posts: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.feed.defs#postView', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, AppBskyFeedThreadgate: { lexicon: 1, id: 'app.bsky.feed.threadgate', @@ -6972,6 +7048,32 @@ export const schemaDict = { }, }, }, + AppBskyUnspeccedDefs: { + lexicon: 1, + id: 'app.bsky.unspecced.defs', + defs: { + skeletonSearchPost: { + type: 'object', + required: ['uri'], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + }, + }, + skeletonSearchActor: { + type: 'object', + required: ['did'], + properties: { + did: { + type: 'string', + format: 'did', + }, + }, + }, + }, + }, AppBskyUnspeccedGetPopular: { lexicon: 1, id: 'app.bsky.unspecced.getPopular', @@ -7114,6 +7216,132 @@ export const schemaDict = { }, }, }, + AppBskyUnspeccedSearchActorsSkeleton: { + lexicon: 1, + id: 'app.bsky.unspecced.searchActorsSkeleton', + defs: { + main: { + type: 'query', + description: 'Backend Actors (profile) search, returning only skeleton', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax', + }, + typeahead: { + type: 'boolean', + description: "if true, acts as fast/simple 'typeahead' query", + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['actors'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + actors: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.unspecced.defs#skeletonSearchActor', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, + AppBskyUnspeccedSearchPostsSkeleton: { + lexicon: 1, + id: 'app.bsky.unspecced.searchPostsSkeleton', + defs: { + main: { + type: 'query', + description: 'Backend Posts search, returning only skeleton', + parameters: { + type: 'params', + required: ['q'], + properties: { + q: { + type: 'string', + description: + 'search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 25, + }, + cursor: { + type: 'string', + description: + 'optional pagination mechanism; may not necessarily allow scrolling through entire result set', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['posts'], + properties: { + cursor: { + type: 'string', + }, + hitsTotal: { + type: 'integer', + description: + 'count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits', + }, + posts: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:app.bsky.unspecced.defs#skeletonSearchPost', + }, + }, + }, + }, + }, + errors: [ + { + name: 'BadQueryString', + }, + ], + }, + }, + }, } export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[] export const lexicons: Lexicons = new Lexicons(schemas) @@ -7225,6 +7453,7 @@ export const ids = { AppBskyFeedLike: 'app.bsky.feed.like', AppBskyFeedPost: 'app.bsky.feed.post', AppBskyFeedRepost: 'app.bsky.feed.repost', + AppBskyFeedSearchPosts: 'app.bsky.feed.searchPosts', AppBskyFeedThreadgate: 'app.bsky.feed.threadgate', AppBskyGraphBlock: 'app.bsky.graph.block', AppBskyGraphDefs: 'app.bsky.graph.defs', @@ -7253,8 +7482,12 @@ export const ids = { AppBskyNotificationUpdateSeen: 'app.bsky.notification.updateSeen', AppBskyRichtextFacet: 'app.bsky.richtext.facet', AppBskyUnspeccedApplyLabels: 'app.bsky.unspecced.applyLabels', + AppBskyUnspeccedDefs: 'app.bsky.unspecced.defs', AppBskyUnspeccedGetPopular: 'app.bsky.unspecced.getPopular', AppBskyUnspeccedGetPopularFeedGenerators: 'app.bsky.unspecced.getPopularFeedGenerators', AppBskyUnspeccedGetTimelineSkeleton: 'app.bsky.unspecced.getTimelineSkeleton', + AppBskyUnspeccedSearchActorsSkeleton: + 'app.bsky.unspecced.searchActorsSkeleton', + AppBskyUnspeccedSearchPostsSkeleton: 'app.bsky.unspecced.searchPostsSkeleton', } diff --git a/packages/pds/src/lexicon/types/app/bsky/actor/searchActors.ts b/packages/pds/src/lexicon/types/app/bsky/actor/searchActors.ts index f620a463cff..0222f3658da 100644 --- a/packages/pds/src/lexicon/types/app/bsky/actor/searchActors.ts +++ b/packages/pds/src/lexicon/types/app/bsky/actor/searchActors.ts @@ -10,7 +10,10 @@ import { HandlerAuth } from '@atproto/xrpc-server' import * as AppBskyActorDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q?: string limit: number cursor?: string } diff --git a/packages/pds/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts b/packages/pds/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts index 4f5bbb7c23c..ba0d62444ce 100644 --- a/packages/pds/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts +++ b/packages/pds/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts @@ -10,7 +10,10 @@ import { HandlerAuth } from '@atproto/xrpc-server' import * as AppBskyActorDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + /** search query prefix; not a full query string */ + q?: string limit: number } diff --git a/packages/pds/src/lexicon/types/app/bsky/feed/searchPosts.ts b/packages/pds/src/lexicon/types/app/bsky/feed/searchPosts.ts new file mode 100644 index 00000000000..6b5fe08e467 --- /dev/null +++ b/packages/pds/src/lexicon/types/app/bsky/feed/searchPosts.ts @@ -0,0 +1,54 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth } from '@atproto/xrpc-server' +import * as AppBskyFeedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q: string + limit: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + posts: AppBskyFeedDefs.PostView[] + [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 + error?: 'BadQueryString' +} + +export type HandlerOutput = HandlerError | HandlerSuccess +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/app/bsky/unspecced/defs.ts b/packages/pds/src/lexicon/types/app/bsky/unspecced/defs.ts new file mode 100644 index 00000000000..59a6b38064c --- /dev/null +++ b/packages/pds/src/lexicon/types/app/bsky/unspecced/defs.ts @@ -0,0 +1,41 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' + +export interface SkeletonSearchPost { + uri: string + [k: string]: unknown +} + +export function isSkeletonSearchPost(v: unknown): v is SkeletonSearchPost { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'app.bsky.unspecced.defs#skeletonSearchPost' + ) +} + +export function validateSkeletonSearchPost(v: unknown): ValidationResult { + return lexicons.validate('app.bsky.unspecced.defs#skeletonSearchPost', v) +} + +export interface SkeletonSearchActor { + did: string + [k: string]: unknown +} + +export function isSkeletonSearchActor(v: unknown): v is SkeletonSearchActor { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'app.bsky.unspecced.defs#skeletonSearchActor' + ) +} + +export function validateSkeletonSearchActor(v: unknown): ValidationResult { + return lexicons.validate('app.bsky.unspecced.defs#skeletonSearchActor', v) +} diff --git a/packages/pds/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts b/packages/pds/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts new file mode 100644 index 00000000000..2cf59bf86a9 --- /dev/null +++ b/packages/pds/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts @@ -0,0 +1,56 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth } from '@atproto/xrpc-server' +import * as AppBskyUnspeccedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax */ + q: string + /** if true, acts as fast/simple 'typeahead' query */ + typeahead?: boolean + limit: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + actors: AppBskyUnspeccedDefs.SkeletonSearchActor[] + [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 + error?: 'BadQueryString' +} + +export type HandlerOutput = HandlerError | HandlerSuccess +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts b/packages/pds/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts new file mode 100644 index 00000000000..df990d2c5c6 --- /dev/null +++ b/packages/pds/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts @@ -0,0 +1,54 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth } from '@atproto/xrpc-server' +import * as AppBskyUnspeccedDefs from './defs' + +export interface QueryParams { + /** search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended */ + q: string + limit: number + /** optional pagination mechanism; may not necessarily allow scrolling through entire result set */ + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + /** count of search hits. optional, may be rounded/truncated, and may not be possible to paginate through all hits */ + hitsTotal?: number + posts: AppBskyUnspeccedDefs.SkeletonSearchPost[] + [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 + error?: 'BadQueryString' +} + +export type HandlerOutput = HandlerError | HandlerSuccess +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/com/atproto/admin/searchRepos.ts b/packages/pds/src/lexicon/types/com/atproto/admin/searchRepos.ts index c79cd046ca0..32266fd66fd 100644 --- a/packages/pds/src/lexicon/types/com/atproto/admin/searchRepos.ts +++ b/packages/pds/src/lexicon/types/com/atproto/admin/searchRepos.ts @@ -10,7 +10,9 @@ import { HandlerAuth } from '@atproto/xrpc-server' import * as ComAtprotoAdminDefs from './defs' export interface QueryParams { + /** DEPRECATED: use 'q' instead */ term?: string + q?: string invitedBy?: string limit: number cursor?: string