@atproto/bsky 0.0.257 → 0.0.258
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/api/app/bsky/actor/searchActors.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/searchActors.js +6 -2
- package/dist/api/app/bsky/actor/searchActors.js.map +1 -1
- package/dist/api/app/bsky/actor/searchActorsTypeahead.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/searchActorsTypeahead.js +6 -2
- package/dist/api/app/bsky/actor/searchActorsTypeahead.js.map +1 -1
- package/dist/api/app/bsky/feed/searchPosts.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/searchPosts.js +6 -2
- package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
- package/dist/api/app/bsky/feed/searchPostsV2.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/searchPostsV2.js +6 -2
- package/dist/api/app/bsky/feed/searchPostsV2.js.map +1 -1
- package/dist/api/app/bsky/graph/searchStarterPacks.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/searchStarterPacks.js +6 -2
- package/dist/api/app/bsky/graph/searchStarterPacks.js.map +1 -1
- package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.d.ts.map +1 -1
- package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js +10 -4
- package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js.map +1 -1
- package/dist/data-plane/client/util.d.ts +2 -1
- package/dist/data-plane/client/util.d.ts.map +1 -1
- package/dist/data-plane/client/util.js +12 -1
- package/dist/data-plane/client/util.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @atproto/bsky
|
|
2
2
|
|
|
3
|
+
## 0.0.258
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5213](https://github.com/bluesky-social/atproto/pull/5213) [`bd2b7b6`](https://github.com/bluesky-social/atproto/commit/bd2b7b6b5b56585b763a8dc505ba6d27369454c3) Thanks [@treethought](https://github.com/treethought)! - return 400 for dataplane InvalidArgument in search
|
|
8
|
+
|
|
3
9
|
## 0.0.257
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchActors.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchActors.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAkBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAwCvD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mapDefined } from '@atproto/common';
|
|
2
|
+
import { asInvalidRequest, } from '../../../../data-plane/index.js';
|
|
2
3
|
import { parseString } from '../../../../hydration/util.js';
|
|
3
4
|
import { app } from '../../../../lexicons/index.js';
|
|
4
5
|
import { createPipeline, } from '../../../../pipeline.js';
|
|
@@ -64,14 +65,17 @@ const skeletonV1 = async (inputs) => {
|
|
|
64
65
|
const skeletonV2 = async (inputs) => {
|
|
65
66
|
const { ctx, params } = inputs;
|
|
66
67
|
const term = params.q ?? params.term ?? '';
|
|
67
|
-
|
|
68
|
+
// Surface dataplane InvalidArgument errors as a 400 rather than a 500.
|
|
69
|
+
const res = await ctx.dataplane
|
|
70
|
+
.searchActorsV2({
|
|
68
71
|
params: {
|
|
69
72
|
query: term,
|
|
70
73
|
viewer: params.hydrateCtx.viewer ?? undefined,
|
|
71
74
|
limit: params.limit,
|
|
72
75
|
cursor: params.cursor,
|
|
73
76
|
},
|
|
74
|
-
})
|
|
77
|
+
})
|
|
78
|
+
.catch(asInvalidRequest());
|
|
75
79
|
return {
|
|
76
80
|
dids: res.actors.map(({ did }) => did),
|
|
77
81
|
cursor: parseString(res.pageInfo?.cursor),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchActors.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchActors.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActors.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { Client, DidString } from '@atproto/lex'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchActors = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.actor.searchActors, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, includeTakedowns, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n includeTakedowns,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const results = await searchActors(\n {\n ...params,\n hydrateCtx,\n isV2Override: resolveSearchV2Override(req, ctx.cfg),\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeletonV1 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const term = params.q ?? params.term ?? ''\n\n // @TODO\n // add hits total\n\n if (ctx.searchClient) {\n // @NOTE cursors won't change on appview swap\n const res = await ctx.searchClient.call(\n app.bsky.unspecced.searchActorsSkeleton,\n {\n q: term,\n cursor: params.cursor,\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n )\n return {\n dids: res.actors.map(({ did }) => did as DidString),\n cursor: parseString(res.cursor),\n }\n }\n\n const res = await ctx.dataplane.searchActors({\n term,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n dids: res.dids as DidString[],\n cursor: parseString(res.cursor),\n }\n}\n\nconst skeletonV2 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const term = params.q ?? params.term ?? ''\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchActorsV2({\n params: {\n query: term,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n })\n .catch(asInvalidRequest())\n return {\n dids: res.actors.map(({ did }) => did as DidString),\n cursor: parseString(res.pageInfo?.cursor),\n }\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useV2 =\n input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SearchV2Enable,\n ) || input.params.isV2Override\n const skeletonFn = useV2 ? skeletonV2 : skeletonV1\n return skeletonFn(input)\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateProfiles(skeleton.dids, params.hydrateCtx)\n}\n\nconst noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration } = inputs\n skeleton.dids = skeleton.dids.filter(\n (did) => !ctx.views.viewerBlockExists(did, hydration),\n )\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const actors = mapDefined(skeleton.dids, (did) =>\n ctx.views.profile(did, hydration),\n )\n return {\n actors,\n cursor: skeleton.cursor,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchClient?: Client\n}\n\ntype Params = app.bsky.actor.searchActors.$Params & {\n hydrateCtx: HydrateCtx\n isV2Override: boolean\n}\n\ntype Skeleton = {\n dids: DidString[]\n hitsTotal?: number\n cursor?: string\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchActorsTypeahead.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActorsTypeahead.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchActorsTypeahead.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActorsTypeahead.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAiBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAqCvD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mapDefined } from '@atproto/common';
|
|
2
|
+
import { asInvalidRequest, } from '../../../../data-plane/index.js';
|
|
2
3
|
import { app } from '../../../../lexicons/index.js';
|
|
3
4
|
import { createPipeline, } from '../../../../pipeline.js';
|
|
4
5
|
import { resHeaders, resolveSearchV2Override } from '../../../util.js';
|
|
@@ -58,13 +59,16 @@ const skeletonV1 = async (inputs) => {
|
|
|
58
59
|
const skeletonV2 = async (inputs) => {
|
|
59
60
|
const { ctx, params } = inputs;
|
|
60
61
|
const term = params.q ?? params.term ?? '';
|
|
61
|
-
|
|
62
|
+
// Surface dataplane InvalidArgument errors as a 400 rather than a 500.
|
|
63
|
+
const res = await ctx.dataplane
|
|
64
|
+
.searchActorsTypeahead({
|
|
62
65
|
params: {
|
|
63
66
|
query: term,
|
|
64
67
|
viewer: params.hydrateCtx.viewer ?? undefined,
|
|
65
68
|
limit: params.limit,
|
|
66
69
|
},
|
|
67
|
-
})
|
|
70
|
+
})
|
|
71
|
+
.catch(asInvalidRequest());
|
|
68
72
|
return {
|
|
69
73
|
dids: res.actors.map(({ did }) => did),
|
|
70
74
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchActorsTypeahead.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActorsTypeahead.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchActorsTypeahead.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/searchActorsTypeahead.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { Client, DidString } from '@atproto/lex'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchActorsTypeahead = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.actor.searchActorsTypeahead, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ params, auth, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const results = await searchActorsTypeahead(\n {\n ...params,\n hydrateCtx,\n isV2Override: resolveSearchV2Override(req, ctx.cfg),\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeletonV1 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const term = params.q ?? params.term ?? ''\n\n // @TODO\n // add typeahead option\n // add hits total\n\n if (ctx.searchClient) {\n const { actors } = await ctx.searchClient.call(\n app.bsky.unspecced.searchActorsSkeleton,\n {\n typeahead: true,\n q: term,\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n )\n return {\n dids: actors.map(({ did }) => did),\n }\n }\n\n const res = await ctx.dataplane.searchActors({\n term,\n limit: params.limit,\n })\n return {\n dids: res.dids as DidString[],\n }\n}\n\nconst skeletonV2 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const term = params.q ?? params.term ?? ''\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchActorsTypeahead({\n params: {\n query: term,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n },\n })\n .catch(asInvalidRequest())\n return {\n dids: res.actors.map(({ did }) => did as DidString),\n }\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useV2 =\n input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SearchV2Enable,\n ) || input.params.isV2Override\n const skeletonFn = useV2 ? skeletonV2 : skeletonV1\n return skeletonFn(input)\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateProfilesBasic(skeleton.dids, params.hydrateCtx)\n}\n\nconst noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration, params } = inputs\n skeleton.dids = skeleton.dids.filter((did) => {\n const actor = hydration.actors?.get(did)\n if (!actor) return false\n // Always display exact matches so that users can find profiles that they have blocked\n const term = (params.q ?? params.term ?? '').toLowerCase()\n const isExactMatch = actor.handle?.toLowerCase() === term\n return isExactMatch || !ctx.views.viewerBlockExists(did, hydration)\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const actors = mapDefined(skeleton.dids, (did) =>\n ctx.views.profileBasic(did, hydration),\n )\n return {\n actors,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchClient?: Client\n}\n\ntype Params = app.bsky.actor.searchActorsTypeahead.$Params & {\n hydrateCtx: HydrateCtx\n isV2Override: boolean\n}\n\ntype Skeleton = {\n dids: DidString[]\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchPosts.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPosts.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchPosts.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPosts.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAwBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAyCvD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Timestamp } from '@bufbuild/protobuf';
|
|
2
2
|
import { mapDefined } from '@atproto/common';
|
|
3
3
|
import { InvalidRequestError } from '@atproto/xrpc-server';
|
|
4
|
+
import { asInvalidRequest, } from '../../../../data-plane/index.js';
|
|
4
5
|
import { parsePostSearchQuery, } from '../../../../data-plane/server/util.js';
|
|
5
6
|
import { parseString } from '../../../../hydration/util.js';
|
|
6
7
|
import { app } from '../../../../lexicons/index.js';
|
|
@@ -82,7 +83,9 @@ const skeletonV2 = async (inputs) => {
|
|
|
82
83
|
const parsedQuery = parsePostSearchQuery(params.q, {
|
|
83
84
|
author: params.author,
|
|
84
85
|
});
|
|
85
|
-
|
|
86
|
+
// Surface dataplane InvalidArgument errors as a 400 rather than a 500.
|
|
87
|
+
const res = await ctx.dataplane
|
|
88
|
+
.searchPostsV2({
|
|
86
89
|
allTime: true, // match v1 behavior, v2 defaults to false
|
|
87
90
|
params: {
|
|
88
91
|
query: params.q,
|
|
@@ -101,7 +104,8 @@ const skeletonV2 = async (inputs) => {
|
|
|
101
104
|
},
|
|
102
105
|
since: parseTimestamp(params.since),
|
|
103
106
|
until: parseTimestamp(params.until),
|
|
104
|
-
})
|
|
107
|
+
})
|
|
108
|
+
.catch(asInvalidRequest());
|
|
105
109
|
return {
|
|
106
110
|
posts: res.posts.map(({ uri }) => uri),
|
|
107
111
|
cursor: parseString(res.pageInfo?.cursor),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchPosts.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPosts.ts"],"names":[],"mappings":"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","sourcesContent":["import { Timestamp } from '@bufbuild/protobuf'\nimport { mapDefined } from '@atproto/common'\nimport type { AtUriString, Client } from '@atproto/lex'\nimport { InvalidRequestError, type Server } from '@atproto/xrpc-server'\nimport type { ServerConfig } from '../../../../config.js'\nimport type { AppContext } from '../../../../context.js'\nimport type { DataPlaneClient } from '../../../../data-plane/index.js'\nimport {\n type PostSearchQuery,\n parsePostSearchQuery,\n} from '../../../../data-plane/server/util.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport { SearchSortOrder } from '../../../../proto/bsky_pb.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchPosts = createPipeline(\n skeleton,\n hydration,\n noBlocksOrTagged,\n presentation,\n )\n server.add(app.bsky.feed.searchPosts, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, isModService, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const results = await searchPosts(\n {\n ...params,\n hydrateCtx,\n isModService,\n isV2Override: resolveSearchV2Override(req, ctx.cfg),\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeletonV1 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const parsedQuery = parsePostSearchQuery(params.q, {\n author: params.author,\n })\n\n if (ctx.searchClient) {\n // @NOTE cursors won't change on appview swap\n const res = await ctx.searchClient.call(\n app.bsky.unspecced.searchPostsSkeleton,\n {\n q: params.q,\n cursor: params.cursor,\n limit: params.limit,\n author: params.author,\n domain: params.domain,\n lang: params.lang,\n mentions: params.mentions,\n since: params.since,\n sort: params.sort,\n tag: params.tag,\n until: params.until,\n url: params.url,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n )\n return {\n posts: res.posts.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.cursor),\n parsedQuery,\n }\n }\n\n const res = await ctx.dataplane.searchPosts({\n term: params.q,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n posts: res.uris as AtUriString[],\n cursor: parseString(res.cursor),\n parsedQuery,\n }\n}\n\nconst skeletonV2 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const parsedQuery = parsePostSearchQuery(params.q, {\n author: params.author,\n })\n const res = await ctx.dataplane.searchPostsV2({\n allTime: true, // match v1 behavior, v2 defaults to false\n params: {\n query: params.q,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: sanitizeCursor(params.cursor),\n },\n sort: postSortToV2(params.sort),\n filters: {\n authors: params.author ? [params.author] : [],\n mentions: params.mentions ? [params.mentions] : [],\n domains: params.domain ? [params.domain] : [],\n urls: params.url ? [params.url] : [],\n hashtags: params.tag ?? [],\n languages: params.lang ? [params.lang] : [],\n },\n since: parseTimestamp(params.since),\n until: parseTimestamp(params.until),\n })\n return {\n posts: res.posts.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n hitsTotal: res.pageInfo?.hitsTotal\n ? Number(res.pageInfo.hitsTotal)\n : undefined,\n parsedQuery,\n }\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useV2 =\n input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SearchV2Enable,\n ) || input.params.isV2Override\n const skeletonFn = useV2 ? skeletonV2 : skeletonV1\n return skeletonFn(input)\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydratePosts(\n skeleton.posts.map((uri) => ({ uri })),\n params.hydrateCtx,\n undefined,\n {\n processDynamicTagsForView: params.hydrateCtx.features?.checkGate(\n params.hydrateCtx.features.Gate.SearchFilteringExplorationEnable,\n )\n ? 'search'\n : undefined,\n },\n )\n}\n\nconst noBlocksOrTagged = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, params, skeleton, hydration } = inputs\n const { parsedQuery } = skeleton\n\n skeleton.posts = skeleton.posts.filter((uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n const creator = creatorFromUri(uri)\n const isCuratedSearch = params.sort === 'top'\n const isPostByViewer = creator === params.hydrateCtx.viewer\n\n // Cases to always show.\n if (isPostByViewer) return true\n if (params.isModService) return true\n\n // Cases to never show.\n if (ctx.views.viewerBlockExists(creator, hydration)) return false\n\n // Roll the post's own tags together with moderation tags on its author,\n // so author-level tags are filtered the same way as post-level tags.\n const author = hydration.actors?.get(creator)\n const tags = new Set([\n ...post.tags,\n ...(author?.accountModerationTags ?? []),\n ...(author?.profileModerationTags ?? []),\n ])\n\n // Tags that are hidden from all search surfaces (Top and Latest),\n // regardless of curation or author filtering.\n const alwaysHidden = [...ctx.cfg.searchTagsHideAll].some((t) => tags.has(t))\n if (alwaysHidden) return false\n\n let tagged = false\n if (\n params.hydrateCtx.features?.checkGate(\n params.hydrateCtx.features.Gate.SearchFilteringExplorationEnable,\n )\n ) {\n tagged = tags.has(ctx.cfg.visibilityTagHide)\n } else {\n tagged = [...ctx.cfg.searchTagsHide].some((t) => tags.has(t))\n }\n\n // Cases to conditionally show based on tagging.\n if (isCuratedSearch && tagged) return false\n if (!parsedQuery.author && tagged) return false\n return true\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const posts = mapDefined(skeleton.posts, (uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n return ctx.views.post(uri, hydration)\n })\n return {\n posts,\n cursor: skeleton.cursor,\n hitsTotal: skeleton.hitsTotal,\n }\n}\n\ntype Context = {\n cfg: ServerConfig\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchClient?: Client\n}\n\ntype Params = app.bsky.feed.searchPosts.$Params & {\n hydrateCtx: HydrateCtx\n isModService: boolean\n isV2Override: boolean\n}\n\ntype Skeleton = {\n posts: AtUriString[]\n hitsTotal?: number\n cursor?: string\n parsedQuery: PostSearchQuery\n}\n\nconst postSortToV2 = (sort: string | undefined): SearchSortOrder => {\n if (sort === 'top') return SearchSortOrder.TOP\n if (sort === 'latest') return SearchSortOrder.RECENT\n return SearchSortOrder.UNSPECIFIED\n}\n\nconst parseTimestamp = (value: string | undefined): Timestamp | undefined => {\n if (!value) return undefined\n const date = new Date(value)\n if (isNaN(date.getTime())) return undefined\n return Timestamp.fromDate(date)\n}\n\nconst sanitizeCursor = (cursor: string | undefined): string | undefined => {\n if (!cursor) return undefined\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8')\n const parsed = JSON.parse(decoded)\n if (typeof parsed === 'object' && parsed !== null) {\n return cursor\n }\n } catch {\n // fall through to throw below\n }\n throw new InvalidRequestError('Invalid cursor format')\n}\n"]}
|
|
1
|
+
{"version":3,"file":"searchPosts.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPosts.ts"],"names":[],"mappings":"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","sourcesContent":["import { Timestamp } from '@bufbuild/protobuf'\nimport { mapDefined } from '@atproto/common'\nimport type { AtUriString, Client } from '@atproto/lex'\nimport { InvalidRequestError, type Server } from '@atproto/xrpc-server'\nimport type { ServerConfig } from '../../../../config.js'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport {\n type PostSearchQuery,\n parsePostSearchQuery,\n} from '../../../../data-plane/server/util.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport { SearchSortOrder } from '../../../../proto/bsky_pb.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchPosts = createPipeline(\n skeleton,\n hydration,\n noBlocksOrTagged,\n presentation,\n )\n server.add(app.bsky.feed.searchPosts, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, isModService, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const results = await searchPosts(\n {\n ...params,\n hydrateCtx,\n isModService,\n isV2Override: resolveSearchV2Override(req, ctx.cfg),\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeletonV1 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const parsedQuery = parsePostSearchQuery(params.q, {\n author: params.author,\n })\n\n if (ctx.searchClient) {\n // @NOTE cursors won't change on appview swap\n const res = await ctx.searchClient.call(\n app.bsky.unspecced.searchPostsSkeleton,\n {\n q: params.q,\n cursor: params.cursor,\n limit: params.limit,\n author: params.author,\n domain: params.domain,\n lang: params.lang,\n mentions: params.mentions,\n since: params.since,\n sort: params.sort,\n tag: params.tag,\n until: params.until,\n url: params.url,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n )\n return {\n posts: res.posts.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.cursor),\n parsedQuery,\n }\n }\n\n const res = await ctx.dataplane.searchPosts({\n term: params.q,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n posts: res.uris as AtUriString[],\n cursor: parseString(res.cursor),\n parsedQuery,\n }\n}\n\nconst skeletonV2 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const parsedQuery = parsePostSearchQuery(params.q, {\n author: params.author,\n })\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchPostsV2({\n allTime: true, // match v1 behavior, v2 defaults to false\n params: {\n query: params.q,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: sanitizeCursor(params.cursor),\n },\n sort: postSortToV2(params.sort),\n filters: {\n authors: params.author ? [params.author] : [],\n mentions: params.mentions ? [params.mentions] : [],\n domains: params.domain ? [params.domain] : [],\n urls: params.url ? [params.url] : [],\n hashtags: params.tag ?? [],\n languages: params.lang ? [params.lang] : [],\n },\n since: parseTimestamp(params.since),\n until: parseTimestamp(params.until),\n })\n .catch(asInvalidRequest())\n return {\n posts: res.posts.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n hitsTotal: res.pageInfo?.hitsTotal\n ? Number(res.pageInfo.hitsTotal)\n : undefined,\n parsedQuery,\n }\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useV2 =\n input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SearchV2Enable,\n ) || input.params.isV2Override\n const skeletonFn = useV2 ? skeletonV2 : skeletonV1\n return skeletonFn(input)\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydratePosts(\n skeleton.posts.map((uri) => ({ uri })),\n params.hydrateCtx,\n undefined,\n {\n processDynamicTagsForView: params.hydrateCtx.features?.checkGate(\n params.hydrateCtx.features.Gate.SearchFilteringExplorationEnable,\n )\n ? 'search'\n : undefined,\n },\n )\n}\n\nconst noBlocksOrTagged = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, params, skeleton, hydration } = inputs\n const { parsedQuery } = skeleton\n\n skeleton.posts = skeleton.posts.filter((uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n const creator = creatorFromUri(uri)\n const isCuratedSearch = params.sort === 'top'\n const isPostByViewer = creator === params.hydrateCtx.viewer\n\n // Cases to always show.\n if (isPostByViewer) return true\n if (params.isModService) return true\n\n // Cases to never show.\n if (ctx.views.viewerBlockExists(creator, hydration)) return false\n\n // Roll the post's own tags together with moderation tags on its author,\n // so author-level tags are filtered the same way as post-level tags.\n const author = hydration.actors?.get(creator)\n const tags = new Set([\n ...post.tags,\n ...(author?.accountModerationTags ?? []),\n ...(author?.profileModerationTags ?? []),\n ])\n\n // Tags that are hidden from all search surfaces (Top and Latest),\n // regardless of curation or author filtering.\n const alwaysHidden = [...ctx.cfg.searchTagsHideAll].some((t) => tags.has(t))\n if (alwaysHidden) return false\n\n let tagged = false\n if (\n params.hydrateCtx.features?.checkGate(\n params.hydrateCtx.features.Gate.SearchFilteringExplorationEnable,\n )\n ) {\n tagged = tags.has(ctx.cfg.visibilityTagHide)\n } else {\n tagged = [...ctx.cfg.searchTagsHide].some((t) => tags.has(t))\n }\n\n // Cases to conditionally show based on tagging.\n if (isCuratedSearch && tagged) return false\n if (!parsedQuery.author && tagged) return false\n return true\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const posts = mapDefined(skeleton.posts, (uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n return ctx.views.post(uri, hydration)\n })\n return {\n posts,\n cursor: skeleton.cursor,\n hitsTotal: skeleton.hitsTotal,\n }\n}\n\ntype Context = {\n cfg: ServerConfig\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchClient?: Client\n}\n\ntype Params = app.bsky.feed.searchPosts.$Params & {\n hydrateCtx: HydrateCtx\n isModService: boolean\n isV2Override: boolean\n}\n\ntype Skeleton = {\n posts: AtUriString[]\n hitsTotal?: number\n cursor?: string\n parsedQuery: PostSearchQuery\n}\n\nconst postSortToV2 = (sort: string | undefined): SearchSortOrder => {\n if (sort === 'top') return SearchSortOrder.TOP\n if (sort === 'latest') return SearchSortOrder.RECENT\n return SearchSortOrder.UNSPECIFIED\n}\n\nconst parseTimestamp = (value: string | undefined): Timestamp | undefined => {\n if (!value) return undefined\n const date = new Date(value)\n if (isNaN(date.getTime())) return undefined\n return Timestamp.fromDate(date)\n}\n\nconst sanitizeCursor = (cursor: string | undefined): string | undefined => {\n if (!cursor) return undefined\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8')\n const parsed = JSON.parse(decoded)\n if (typeof parsed === 'object' && parsed !== null) {\n return cursor\n }\n } catch {\n // fall through to throw below\n }\n throw new InvalidRequestError('Invalid cursor format')\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchPostsV2.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPostsV2.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,MAAM,EACZ,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchPostsV2.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPostsV2.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,MAAM,EACZ,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AA2BxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QA4DvD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Timestamp } from '@bufbuild/protobuf';
|
|
2
2
|
import { mapDefined } from '@atproto/common';
|
|
3
3
|
import { ForbiddenError, InvalidRequestError, } from '@atproto/xrpc-server';
|
|
4
|
+
import { asInvalidRequest, } from '../../../../data-plane/index.js';
|
|
4
5
|
import { parsePostSearchQuery, } from '../../../../data-plane/server/util.js';
|
|
5
6
|
import { parseString } from '../../../../hydration/util.js';
|
|
6
7
|
import { app } from '../../../../lexicons/index.js';
|
|
@@ -58,7 +59,9 @@ const skeleton = async (inputs) => {
|
|
|
58
59
|
const parsedQuery = parsePostSearchQuery(query, {
|
|
59
60
|
author: params.authors?.[0],
|
|
60
61
|
});
|
|
61
|
-
|
|
62
|
+
// Surface dataplane InvalidArgument errors as a 400 rather than a 500.
|
|
63
|
+
const res = await ctx.dataplane
|
|
64
|
+
.searchPostsV2({
|
|
62
65
|
params: {
|
|
63
66
|
query,
|
|
64
67
|
viewer: params.hydrateCtx.viewer ?? undefined,
|
|
@@ -95,7 +98,8 @@ const skeleton = async (inputs) => {
|
|
|
95
98
|
repliesOnly: params.repliesOnly,
|
|
96
99
|
following: params.following,
|
|
97
100
|
queryLanguage: queryLanguageToV2(params.queryLanguage),
|
|
98
|
-
})
|
|
101
|
+
})
|
|
102
|
+
.catch(asInvalidRequest());
|
|
99
103
|
return {
|
|
100
104
|
posts: res.posts.map(({ uri }) => uri),
|
|
101
105
|
cursor: parseString(res.pageInfo?.cursor),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchPostsV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPostsV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { Timestamp } from '@bufbuild/protobuf'\nimport { mapDefined } from '@atproto/common'\nimport type { AtUriString } from '@atproto/lex'\nimport {\n ForbiddenError,\n InvalidRequestError,\n type Server,\n} from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport type { DataPlaneClient } from '../../../../data-plane/index.js'\nimport {\n type PostSearchQuery,\n parsePostSearchQuery,\n} from '../../../../data-plane/server/util.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport {\n SearchQueryLanguage,\n SearchSortOrder,\n} from '../../../../proto/bsky_pb.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchPostsV2 = createPipeline(\n skeleton,\n hydration,\n noBlocksOrTagged,\n presentation,\n )\n server.add(app.bsky.feed.searchPostsV2, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, isModService, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const isV2Enabled =\n hydrateCtx.features.checkGate(\n hydrateCtx.features.Gate.SearchV2Enable,\n ) || resolveSearchV2Override(req, ctx.cfg)\n if (!isV2Enabled) {\n throw new InvalidRequestError('Search v2 is not enabled')\n }\n\n /*\n * Matches v1 handling: allow one page of results for unauthenticated\n * users, but block further pages. This is a temporary measure until\n * we finalize moderation rules for search v2.\n */\n if (!viewer && params.cursor) {\n throw new ForbiddenError('Request forbidden by administrative rules.')\n }\n\n const results = await searchPostsV2(\n {\n ...params,\n // Default to curated 'top' ranking when unset; the backend rejects an\n // unspecified sort order.\n sort: params.sort ?? 'top',\n hydrateCtx,\n isModService,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const query = params.query ?? ''\n const parsedQuery = parsePostSearchQuery(query, {\n author: params.authors?.[0],\n })\n\n const res = await ctx.dataplane.searchPostsV2({\n params: {\n query,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n sort: postSortToV2(params.sort),\n filters: {\n authors: params.authors ?? [],\n mentions: params.mentions ?? [],\n domains: params.domains ?? [],\n urls: params.urls ?? [],\n embeddedAtUris: params.embeddedAtUris ?? [],\n hashtags: params.hashtags ?? [],\n languages: params.languages ?? [],\n },\n exclude: {\n authors: params.excludeAuthors ?? [],\n mentions: params.excludeMentions ?? [],\n domains: params.excludeDomains ?? [],\n urls: params.excludeUrls ?? [],\n embeddedAtUris: params.excludeEmbeddedAtUris ?? [],\n hashtags: params.excludeHashtags ?? [],\n languages: params.excludeLanguages ?? [],\n },\n since: parseTimestamp(params.since),\n until: parseTimestamp(params.until),\n allTime: params.allTime,\n hasMedia: params.hasMedia,\n hasVideo: params.hasVideo,\n replyParentUri: params.replyParentUri,\n threadRootUri: params.threadRootUri,\n excludeReplies: params.excludeReplies,\n repliesOnly: params.repliesOnly,\n following: params.following,\n queryLanguage: queryLanguageToV2(params.queryLanguage),\n })\n return {\n posts: res.posts.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n hitsTotal: res.pageInfo?.hitsTotal\n ? Number(res.pageInfo.hitsTotal)\n : undefined,\n detectedQueryLanguages: res.detectedQueryLanguages,\n parsedQuery,\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydratePosts(\n skeleton.posts.map((uri) => ({ uri })),\n params.hydrateCtx,\n )\n}\n\nconst noBlocksOrTagged = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, params, skeleton, hydration } = inputs\n const { parsedQuery } = skeleton\n\n skeleton.posts = skeleton.posts.filter((uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n const creator = creatorFromUri(uri)\n const isCuratedSearch = params.sort === 'top'\n const isPostByViewer = creator === params.hydrateCtx.viewer\n\n if (isPostByViewer) return true\n if (params.isModService) return true\n\n if (ctx.views.viewerBlockExists(creator, hydration)) return false\n\n // Roll the post's own tags together with moderation tags on its author,\n // so author-level tags are filtered the same way as post-level tags.\n const author = hydration.actors?.get(creator)\n const tags = new Set([\n ...post.tags,\n ...(author?.accountModerationTags ?? []),\n ...(author?.profileModerationTags ?? []),\n ])\n\n // Tags that are hidden from all search surfaces (Top and Latest),\n // regardless of curation or author filtering.\n const alwaysHidden = [...ctx.cfg.searchTagsHideAll].some((t) => tags.has(t))\n if (alwaysHidden) return false\n\n const tagged = [...ctx.cfg.searchTagsHide].some((t) => tags.has(t))\n\n if (isCuratedSearch && tagged) return false\n if (!(parsedQuery.author || params.authors?.length) && tagged) return false\n return true\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const posts = mapDefined(skeleton.posts, (uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n return ctx.views.post(uri, hydration)\n })\n return {\n posts,\n cursor: skeleton.cursor,\n hitsTotal: skeleton.hitsTotal,\n detectedQueryLanguages: skeleton.detectedQueryLanguages,\n }\n}\n\ntype Context = {\n cfg: AppContext['cfg']\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = app.bsky.feed.searchPostsV2.$Params & {\n hydrateCtx: HydrateCtx\n isModService: boolean\n}\n\ntype Skeleton = {\n posts: AtUriString[]\n hitsTotal?: number\n cursor?: string\n detectedQueryLanguages?: string[]\n parsedQuery: PostSearchQuery\n}\n\nconst postSortToV2 = (sort?: string): SearchSortOrder => {\n if (sort === 'top') return SearchSortOrder.TOP\n if (sort === 'recent') return SearchSortOrder.RECENT\n return SearchSortOrder.UNSPECIFIED\n}\n\nconst queryLanguageToV2 = (\n lang: string | undefined,\n): SearchQueryLanguage | undefined => {\n if (lang === 'ja') return SearchQueryLanguage.JA\n if (lang === 'zh') return SearchQueryLanguage.ZH\n if (lang === 'ko') return SearchQueryLanguage.KO\n if (lang === 'th') return SearchQueryLanguage.TH\n if (lang === 'ar') return SearchQueryLanguage.AR\n return undefined\n}\n\nconst parseTimestamp = (value: string | undefined): Timestamp | undefined => {\n if (!value) return undefined\n const date = new Date(value)\n if (isNaN(date.getTime())) return undefined\n return Timestamp.fromDate(date)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"searchPostsV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPostsV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { Timestamp } from '@bufbuild/protobuf'\nimport { mapDefined } from '@atproto/common'\nimport type { AtUriString } from '@atproto/lex'\nimport {\n ForbiddenError,\n InvalidRequestError,\n type Server,\n} from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport {\n type PostSearchQuery,\n parsePostSearchQuery,\n} from '../../../../data-plane/server/util.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport {\n SearchQueryLanguage,\n SearchSortOrder,\n} from '../../../../proto/bsky_pb.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchPostsV2 = createPipeline(\n skeleton,\n hydration,\n noBlocksOrTagged,\n presentation,\n )\n server.add(app.bsky.feed.searchPostsV2, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, isModService, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const isV2Enabled =\n hydrateCtx.features.checkGate(\n hydrateCtx.features.Gate.SearchV2Enable,\n ) || resolveSearchV2Override(req, ctx.cfg)\n if (!isV2Enabled) {\n throw new InvalidRequestError('Search v2 is not enabled')\n }\n\n /*\n * Matches v1 handling: allow one page of results for unauthenticated\n * users, but block further pages. This is a temporary measure until\n * we finalize moderation rules for search v2.\n */\n if (!viewer && params.cursor) {\n throw new ForbiddenError('Request forbidden by administrative rules.')\n }\n\n const results = await searchPostsV2(\n {\n ...params,\n // Default to curated 'top' ranking when unset; the backend rejects an\n // unspecified sort order.\n sort: params.sort ?? 'top',\n hydrateCtx,\n isModService,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const query = params.query ?? ''\n const parsedQuery = parsePostSearchQuery(query, {\n author: params.authors?.[0],\n })\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchPostsV2({\n params: {\n query,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n sort: postSortToV2(params.sort),\n filters: {\n authors: params.authors ?? [],\n mentions: params.mentions ?? [],\n domains: params.domains ?? [],\n urls: params.urls ?? [],\n embeddedAtUris: params.embeddedAtUris ?? [],\n hashtags: params.hashtags ?? [],\n languages: params.languages ?? [],\n },\n exclude: {\n authors: params.excludeAuthors ?? [],\n mentions: params.excludeMentions ?? [],\n domains: params.excludeDomains ?? [],\n urls: params.excludeUrls ?? [],\n embeddedAtUris: params.excludeEmbeddedAtUris ?? [],\n hashtags: params.excludeHashtags ?? [],\n languages: params.excludeLanguages ?? [],\n },\n since: parseTimestamp(params.since),\n until: parseTimestamp(params.until),\n allTime: params.allTime,\n hasMedia: params.hasMedia,\n hasVideo: params.hasVideo,\n replyParentUri: params.replyParentUri,\n threadRootUri: params.threadRootUri,\n excludeReplies: params.excludeReplies,\n repliesOnly: params.repliesOnly,\n following: params.following,\n queryLanguage: queryLanguageToV2(params.queryLanguage),\n })\n .catch(asInvalidRequest())\n return {\n posts: res.posts.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n hitsTotal: res.pageInfo?.hitsTotal\n ? Number(res.pageInfo.hitsTotal)\n : undefined,\n detectedQueryLanguages: res.detectedQueryLanguages,\n parsedQuery,\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydratePosts(\n skeleton.posts.map((uri) => ({ uri })),\n params.hydrateCtx,\n )\n}\n\nconst noBlocksOrTagged = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, params, skeleton, hydration } = inputs\n const { parsedQuery } = skeleton\n\n skeleton.posts = skeleton.posts.filter((uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n const creator = creatorFromUri(uri)\n const isCuratedSearch = params.sort === 'top'\n const isPostByViewer = creator === params.hydrateCtx.viewer\n\n if (isPostByViewer) return true\n if (params.isModService) return true\n\n if (ctx.views.viewerBlockExists(creator, hydration)) return false\n\n // Roll the post's own tags together with moderation tags on its author,\n // so author-level tags are filtered the same way as post-level tags.\n const author = hydration.actors?.get(creator)\n const tags = new Set([\n ...post.tags,\n ...(author?.accountModerationTags ?? []),\n ...(author?.profileModerationTags ?? []),\n ])\n\n // Tags that are hidden from all search surfaces (Top and Latest),\n // regardless of curation or author filtering.\n const alwaysHidden = [...ctx.cfg.searchTagsHideAll].some((t) => tags.has(t))\n if (alwaysHidden) return false\n\n const tagged = [...ctx.cfg.searchTagsHide].some((t) => tags.has(t))\n\n if (isCuratedSearch && tagged) return false\n if (!(parsedQuery.author || params.authors?.length) && tagged) return false\n return true\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const posts = mapDefined(skeleton.posts, (uri) => {\n const post = hydration.posts?.get(uri)\n if (!post) return\n\n return ctx.views.post(uri, hydration)\n })\n return {\n posts,\n cursor: skeleton.cursor,\n hitsTotal: skeleton.hitsTotal,\n detectedQueryLanguages: skeleton.detectedQueryLanguages,\n }\n}\n\ntype Context = {\n cfg: AppContext['cfg']\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = app.bsky.feed.searchPostsV2.$Params & {\n hydrateCtx: HydrateCtx\n isModService: boolean\n}\n\ntype Skeleton = {\n posts: AtUriString[]\n hitsTotal?: number\n cursor?: string\n detectedQueryLanguages?: string[]\n parsedQuery: PostSearchQuery\n}\n\nconst postSortToV2 = (sort?: string): SearchSortOrder => {\n if (sort === 'top') return SearchSortOrder.TOP\n if (sort === 'recent') return SearchSortOrder.RECENT\n return SearchSortOrder.UNSPECIFIED\n}\n\nconst queryLanguageToV2 = (\n lang: string | undefined,\n): SearchQueryLanguage | undefined => {\n if (lang === 'ja') return SearchQueryLanguage.JA\n if (lang === 'zh') return SearchQueryLanguage.ZH\n if (lang === 'ko') return SearchQueryLanguage.KO\n if (lang === 'th') return SearchQueryLanguage.TH\n if (lang === 'ar') return SearchQueryLanguage.AR\n return undefined\n}\n\nconst parseTimestamp = (value: string | undefined): Timestamp | undefined => {\n if (!value) return undefined\n const date = new Date(value)\n if (isNaN(date.getTime())) return undefined\n return Timestamp.fromDate(date)\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchStarterPacks.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchStarterPacks.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAmBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAwCvD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mapDefined } from '@atproto/common';
|
|
2
|
+
import { asInvalidRequest, } from '../../../../data-plane/index.js';
|
|
2
3
|
import { parseString } from '../../../../hydration/util.js';
|
|
3
4
|
import { app } from '../../../../lexicons/index.js';
|
|
4
5
|
import { createPipeline, } from '../../../../pipeline.js';
|
|
@@ -63,14 +64,17 @@ const skeletonV1 = async (inputs) => {
|
|
|
63
64
|
const skeletonV2 = async (inputs) => {
|
|
64
65
|
const { ctx, params } = inputs;
|
|
65
66
|
const { q } = params;
|
|
66
|
-
|
|
67
|
+
// Surface dataplane InvalidArgument errors as a 400 rather than a 500.
|
|
68
|
+
const res = await ctx.dataplane
|
|
69
|
+
.searchStarterPacksV2({
|
|
67
70
|
params: {
|
|
68
71
|
query: q,
|
|
69
72
|
viewer: params.hydrateCtx.viewer ?? undefined,
|
|
70
73
|
limit: params.limit,
|
|
71
74
|
cursor: params.cursor,
|
|
72
75
|
},
|
|
73
|
-
})
|
|
76
|
+
})
|
|
77
|
+
.catch(asInvalidRequest());
|
|
74
78
|
return {
|
|
75
79
|
uris: res.starterPacks.map(({ uri }) => uri),
|
|
76
80
|
cursor: parseString(res.pageInfo?.cursor),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchStarterPacks.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"searchStarterPacks.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacks.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString, Client } from '@atproto/lex'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchStarterPacks = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.graph.searchStarterPacks, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, includeTakedowns, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n includeTakedowns,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const results = await searchStarterPacks(\n {\n ...params,\n hydrateCtx,\n isV2Override: resolveSearchV2Override(req, ctx.cfg),\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeletonV1 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n if (ctx.searchClient) {\n // @NOTE cursors won't change on appview swap\n const res = await ctx.searchClient.call(\n app.bsky.unspecced.searchStarterPacksSkeleton,\n {\n q,\n cursor: params.cursor,\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n )\n return {\n uris: res.starterPacks.map(({ uri }) => uri),\n cursor: parseString(res.cursor),\n }\n }\n\n const res = await ctx.dataplane.searchStarterPacks({\n term: q,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n uris: res.uris as AtUriString[],\n cursor: parseString(res.cursor),\n }\n}\n\nconst skeletonV2 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchStarterPacksV2({\n params: {\n query: q,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n })\n .catch(asInvalidRequest())\n return {\n uris: res.starterPacks.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n }\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useV2 =\n input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SearchV2Enable,\n ) || input.params.isV2Override\n const skeletonFn = useV2 ? skeletonV2 : skeletonV1\n return skeletonFn(input)\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateStarterPacksBasic(skeleton.uris, params.hydrateCtx)\n}\n\nconst noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration } = inputs\n skeleton.uris = skeleton.uris.filter((uri) => {\n const creator = creatorFromUri(uri)\n return !ctx.views.viewerBlockExists(creator, hydration)\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const starterPacks = mapDefined(skeleton.uris, (uri) =>\n ctx.views.starterPackBasic(uri, hydration),\n )\n return {\n starterPacks: starterPacks,\n cursor: skeleton.cursor,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchClient?: Client\n}\n\ntype Params = app.bsky.graph.searchStarterPacks.$Params & {\n hydrateCtx: HydrateCtx\n isV2Override: boolean\n}\n\ntype Skeleton = {\n uris: AtUriString[]\n cursor?: string\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPopularFeedGenerators.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"getPopularFeedGenerators.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAaxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAgFvD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mapDefined } from '@atproto/common';
|
|
2
|
+
import { asInvalidRequest } from '../../../../data-plane/index.js';
|
|
2
3
|
import { parseString } from '../../../../hydration/util.js';
|
|
3
4
|
import { app } from '../../../../lexicons/index.js';
|
|
4
5
|
import { clearlyBadCursor, resHeaders, resolveSearchV2Override, } from '../../../util.js';
|
|
@@ -32,21 +33,26 @@ export default function (server, ctx) {
|
|
|
32
33
|
const query = params.query?.trim() ?? '';
|
|
33
34
|
if (query) {
|
|
34
35
|
const useV2 = features.checkGate(features.Gate.SearchV2Enable) || isV2Override;
|
|
36
|
+
// Surface dataplane InvalidArgument errors as a 400 rather than a 500.
|
|
35
37
|
if (useV2) {
|
|
36
|
-
const res = await ctx.dataplane
|
|
38
|
+
const res = await ctx.dataplane
|
|
39
|
+
.searchFeedGeneratorsV2({
|
|
37
40
|
params: {
|
|
38
41
|
query,
|
|
39
42
|
viewer: viewer ?? undefined,
|
|
40
43
|
limit: params.limit,
|
|
41
44
|
},
|
|
42
|
-
})
|
|
45
|
+
})
|
|
46
|
+
.catch(asInvalidRequest());
|
|
43
47
|
uris = res.feedGenerators.map(({ uri }) => uri);
|
|
44
48
|
}
|
|
45
49
|
else {
|
|
46
|
-
const res = await ctx.dataplane
|
|
50
|
+
const res = await ctx.dataplane
|
|
51
|
+
.searchFeedGenerators({
|
|
47
52
|
query,
|
|
48
53
|
limit: params.limit,
|
|
49
|
-
})
|
|
54
|
+
})
|
|
55
|
+
.catch(asInvalidRequest());
|
|
50
56
|
uris = res.uris;
|
|
51
57
|
}
|
|
52
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPopularFeedGenerators.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAI5C,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,uBAAuB,GACxB,MAAM,kBAAkB,CAAA;AAEzB,sCAAsC;AACtC,2EAA2E;AAC3E,gGAAgG;AAChG,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,wBAAwB,EAAE;QACtD,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,gBAAgB;QACvC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAA;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,kBAAkB,CAAC,KAAK,CAC3C,GAAG,CAAC,kBAAkB,CAAC,2BAA2B,CAAC;gBACjD,MAAM;gBACN,GAAG;aACJ,CAAC,CACH,CAAA;YACD,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAClD,MAAM;gBACN,QAAQ;gBACR,QAAQ;aACT,CAAC,CAAA;YAEF,IAAI,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBACpC,OAAO;oBACL,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;iBACpB,CAAA;YACH,CAAC;YAED,IAAI,IAAmB,CAAA;YACvB,IAAI,MAA0B,CAAA;YAE9B,MAAM,YAAY,GAAG,uBAAuB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;YAE1D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;YACxC,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,KAAK,GACT,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,YAAY,CAAA;gBAClE,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"getPopularFeedGenerators.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString } from '@atproto/syntax'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport { asInvalidRequest } from '../../../../data-plane/index.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n clearlyBadCursor,\n resHeaders,\n resolveSearchV2Override,\n} from '../../../util.js'\n\n// THIS IS A TEMPORARY UNSPECCED ROUTE\n// @TODO currently mirrors getSuggestedFeeds and ignores the \"query\" param.\n// In the future may take into consideration popularity via likes w/ its own dataplane endpoint.\nexport default function (server: Server, ctx: AppContext) {\n server.add(app.bsky.unspecced.getPopularFeedGenerators, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const features = ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n )\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n features,\n })\n\n if (clearlyBadCursor(params.cursor)) {\n return {\n encoding: 'application/json',\n body: { feeds: [] },\n }\n }\n\n let uris: AtUriString[]\n let cursor: string | undefined\n\n const isV2Override = resolveSearchV2Override(req, ctx.cfg)\n\n const query = params.query?.trim() ?? ''\n if (query) {\n const useV2 =\n features.checkGate(features.Gate.SearchV2Enable) || isV2Override\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n if (useV2) {\n const res = await ctx.dataplane\n .searchFeedGeneratorsV2({\n params: {\n query,\n viewer: viewer ?? undefined,\n limit: params.limit,\n },\n })\n .catch(asInvalidRequest())\n uris = res.feedGenerators.map(({ uri }) => uri) as AtUriString[]\n } else {\n const res = await ctx.dataplane\n .searchFeedGenerators({\n query,\n limit: params.limit,\n })\n .catch(asInvalidRequest())\n uris = res.uris as AtUriString[]\n }\n } else {\n const res = await ctx.dataplane.getSuggestedFeeds({\n actorDid: viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n })\n uris = res.uris as AtUriString[]\n cursor = parseString(res.cursor)\n }\n\n const hydration = await ctx.hydrator.hydrateFeedGens(uris, hydrateCtx)\n const feedViews = mapDefined(uris, (uri) =>\n ctx.views.feedGenerator(uri, hydration),\n )\n\n return {\n encoding: 'application/json',\n body: {\n feeds: feedViews,\n cursor,\n },\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Code, ConnectError, type Interceptor } from '@connectrpc/connect';
|
|
2
2
|
export declare const callerInterceptor: (caller: string) => Interceptor;
|
|
3
3
|
export declare const isDataplaneError: (err: unknown, code?: Code) => err is ConnectError;
|
|
4
|
+
export declare const asInvalidRequest: (message?: string) => (err: unknown) => never;
|
|
4
5
|
export declare const unpackIdentityServices: (servicesBytes: Uint8Array) => UnpackedServices;
|
|
5
6
|
export declare const unpackIdentityKeys: (keysBytes: Uint8Array) => UnpackedKeys;
|
|
6
7
|
export declare const getServiceEndpoint: (services: UnpackedServices, opts: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/data-plane/client/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/data-plane/client/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAK1E,eAAO,MAAM,iBAAiB,WACnB,MAAM,KAAG,WAKjB,CAAA;AAEH,eAAO,MAAM,gBAAgB,QACtB,OAAO,SACL,IAAI,KACV,GAAG,IAAI,YAKT,CAAA;AAMD,eAAO,MAAM,gBAAgB,8BAErB,OAAO,KAAG,KAKf,CAAA;AAEH,eAAO,MAAM,sBAAsB,kBAAmB,UAAU,qBAI/D,CAAA;AAED,eAAO,MAAM,kBAAkB,cAAe,UAAU,iBAIvD,CAAA;AAED,eAAO,MAAM,kBAAkB,aACnB,gBAAgB,QACpB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,uBAOnC,CAAA;AAED,eAAO,MAAM,cAAc,SAAU,YAAY,QAAQ;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,uBAQtE,CAAA;AAED,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAErE,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ConnectError } from '@connectrpc/connect';
|
|
1
|
+
import { Code, ConnectError } from '@connectrpc/connect';
|
|
2
2
|
import * as ui8 from 'uint8arrays';
|
|
3
3
|
import { getDidKeyFromMultibase } from '@atproto/identity';
|
|
4
|
+
import { InvalidRequestError } from '@atproto/xrpc-server';
|
|
4
5
|
export const callerInterceptor = (caller) => (next) => (req) => {
|
|
5
6
|
req.header.set('x-atlantis-caller', caller);
|
|
6
7
|
return next(req);
|
|
@@ -11,6 +12,16 @@ export const isDataplaneError = (err, code) => {
|
|
|
11
12
|
}
|
|
12
13
|
return false;
|
|
13
14
|
};
|
|
15
|
+
// Rethrows a dataplane InvalidArgument error as a client-facing 400, with an
|
|
16
|
+
// optional message. Use as a `.catch()` handler on a dataplane call whose args
|
|
17
|
+
// come from user input. Returns `never`, so the awaited result keeps its type.
|
|
18
|
+
// Any other error passes through unchanged.
|
|
19
|
+
export const asInvalidRequest = (message = 'Invalid request') => (err) => {
|
|
20
|
+
if (isDataplaneError(err, Code.InvalidArgument)) {
|
|
21
|
+
throw new InvalidRequestError(message);
|
|
22
|
+
}
|
|
23
|
+
throw err;
|
|
24
|
+
};
|
|
14
25
|
export const unpackIdentityServices = (servicesBytes) => {
|
|
15
26
|
const servicesStr = ui8.toString(servicesBytes, 'utf8');
|
|
16
27
|
if (!servicesStr)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/data-plane/client/util.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/data-plane/client/util.ts"],"names":[],"mappings":"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","sourcesContent":["import { Code, ConnectError, type Interceptor } from '@connectrpc/connect'\nimport * as ui8 from 'uint8arrays'\nimport { getDidKeyFromMultibase } from '@atproto/identity'\nimport { InvalidRequestError } from '@atproto/xrpc-server'\n\nexport const callerInterceptor =\n (caller: string): Interceptor =>\n (next) =>\n (req) => {\n req.header.set('x-atlantis-caller', caller)\n return next(req)\n }\n\nexport const isDataplaneError = (\n err: unknown,\n code?: Code,\n): err is ConnectError => {\n if (err instanceof ConnectError) {\n return !code || err.code === code\n }\n return false\n}\n\n// Rethrows a dataplane InvalidArgument error as a client-facing 400, with an\n// optional message. Use as a `.catch()` handler on a dataplane call whose args\n// come from user input. Returns `never`, so the awaited result keeps its type.\n// Any other error passes through unchanged.\nexport const asInvalidRequest =\n (message = 'Invalid request') =>\n (err: unknown): never => {\n if (isDataplaneError(err, Code.InvalidArgument)) {\n throw new InvalidRequestError(message)\n }\n throw err\n }\n\nexport const unpackIdentityServices = (servicesBytes: Uint8Array) => {\n const servicesStr = ui8.toString(servicesBytes, 'utf8')\n if (!servicesStr) return {}\n return JSON.parse(servicesStr) as UnpackedServices\n}\n\nexport const unpackIdentityKeys = (keysBytes: Uint8Array) => {\n const keysStr = ui8.toString(keysBytes, 'utf8')\n if (!keysStr) return {}\n return JSON.parse(keysStr) as UnpackedKeys\n}\n\nexport const getServiceEndpoint = (\n services: UnpackedServices,\n opts: { id: string; type: string },\n) => {\n const endpoint =\n services[opts.id] &&\n services[opts.id].Type === opts.type &&\n validateUrl(services[opts.id].URL)\n return endpoint || undefined\n}\n\nexport const getKeyAsDidKey = (keys: UnpackedKeys, opts: { id: string }) => {\n const key =\n keys[opts.id] &&\n getDidKeyFromMultibase({\n type: keys[opts.id].Type,\n publicKeyMultibase: keys[opts.id].PublicKeyMultibase,\n })\n return key || undefined\n}\n\ntype UnpackedServices = Record<string, { Type: string; URL: string }>\n\ntype UnpackedKeys = Record<string, { Type: string; PublicKeyMultibase: string }>\n\nconst validateUrl = (urlStr: string): string | undefined => {\n let url\n try {\n url = new URL(urlStr)\n } catch {\n return undefined\n }\n if (!['http:', 'https:'].includes(url.protocol)) {\n return undefined\n } else if (!url.hostname) {\n return undefined\n } else {\n return urlStr\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/bsky",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.258",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Reference implementation of app.bsky App View (Bluesky API)",
|
|
6
6
|
"keywords": [
|
|
@@ -60,18 +60,18 @@
|
|
|
60
60
|
"uint8arrays": "^5.0.0",
|
|
61
61
|
"undici": "^8.5.0",
|
|
62
62
|
"zod": "3.23.8",
|
|
63
|
-
"@atproto-labs/xrpc-utils": "^0.1.7",
|
|
64
63
|
"@atproto-labs/fetch-node": "^0.3.5",
|
|
65
|
-
"@atproto/api": "^0.20.27",
|
|
66
64
|
"@atproto/common": "^0.7.1",
|
|
65
|
+
"@atproto/crypto": "^0.5.4",
|
|
67
66
|
"@atproto/did": "^0.5.4",
|
|
68
67
|
"@atproto/identity": "^0.5.5",
|
|
69
|
-
"@atproto/
|
|
68
|
+
"@atproto-labs/xrpc-utils": "^0.1.7",
|
|
70
69
|
"@atproto/lex": "^0.2.1",
|
|
70
|
+
"@atproto/api": "^0.20.27",
|
|
71
71
|
"@atproto/repo": "^0.10.5",
|
|
72
|
-
"@atproto/sync": "^0.3.9",
|
|
73
72
|
"@atproto/xrpc-server": "^0.11.8",
|
|
74
|
-
"@atproto/syntax": "^0.7.1"
|
|
73
|
+
"@atproto/syntax": "^0.7.1",
|
|
74
|
+
"@atproto/sync": "^0.3.9"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@bufbuild/buf": "^1.28.1",
|