@atproto/bsky 0.0.222 → 0.0.223

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js +1 -1
  3. package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js.map +1 -1
  4. package/dist/api/app/bsky/unspecced/getSuggestedUsersForDiscover.d.ts +4 -0
  5. package/dist/api/app/bsky/unspecced/getSuggestedUsersForDiscover.d.ts.map +1 -0
  6. package/dist/api/app/bsky/unspecced/getSuggestedUsersForDiscover.js +107 -0
  7. package/dist/api/app/bsky/unspecced/getSuggestedUsersForDiscover.js.map +1 -0
  8. package/dist/api/app/bsky/unspecced/getSuggestedUsersForExplore.d.ts +4 -0
  9. package/dist/api/app/bsky/unspecced/getSuggestedUsersForExplore.d.ts.map +1 -0
  10. package/dist/api/app/bsky/unspecced/getSuggestedUsersForExplore.js +109 -0
  11. package/dist/api/app/bsky/unspecced/getSuggestedUsersForExplore.js.map +1 -0
  12. package/dist/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.d.ts +4 -0
  13. package/dist/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.d.ts.map +1 -0
  14. package/dist/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.js +109 -0
  15. package/dist/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.js.map +1 -0
  16. package/dist/feature-gates/gates.d.ts +3 -0
  17. package/dist/feature-gates/gates.d.ts.map +1 -1
  18. package/dist/feature-gates/gates.js +3 -0
  19. package/dist/feature-gates/gates.js.map +1 -1
  20. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.d.ts +3 -0
  21. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.d.ts.map +1 -0
  22. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.d.ts +22 -0
  23. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.d.ts.map +1 -0
  24. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.js +53 -0
  25. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.js.map +1 -0
  26. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.js +45 -0
  27. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.js.map +1 -0
  28. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.d.ts +3 -0
  29. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.d.ts.map +1 -0
  30. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.d.ts +31 -0
  31. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.d.ts.map +1 -0
  32. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.js +20 -0
  33. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.js.map +1 -0
  34. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.js +45 -0
  35. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.js.map +1 -0
  36. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.d.ts +3 -0
  37. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.d.ts.map +1 -0
  38. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.d.ts +24 -0
  39. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.d.ts.map +1 -0
  40. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.js +54 -0
  41. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.js.map +1 -0
  42. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.js +45 -0
  43. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.js.map +1 -0
  44. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.d.ts +3 -0
  45. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.d.ts.map +1 -0
  46. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.d.ts +33 -0
  47. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.d.ts.map +1 -0
  48. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.js +21 -0
  49. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.js.map +1 -0
  50. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.js +45 -0
  51. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.js.map +1 -0
  52. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.d.ts +3 -0
  53. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.d.ts.map +1 -0
  54. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.d.ts +24 -0
  55. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.d.ts.map +1 -0
  56. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.js +54 -0
  57. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.js.map +1 -0
  58. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.js +45 -0
  59. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.js.map +1 -0
  60. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.d.ts +3 -0
  61. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.d.ts.map +1 -0
  62. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.d.ts +33 -0
  63. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.d.ts.map +1 -0
  64. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.js +21 -0
  65. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.js.map +1 -0
  66. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.js +45 -0
  67. package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.js.map +1 -0
  68. package/dist/lexicons/app/bsky/unspecced.d.ts +6 -0
  69. package/dist/lexicons/app/bsky/unspecced.d.ts.map +1 -1
  70. package/dist/lexicons/app/bsky/unspecced.js +7 -1
  71. package/dist/lexicons/app/bsky/unspecced.js.map +1 -1
  72. package/package.json +6 -6
  73. package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +2 -2
  74. package/src/api/app/bsky/unspecced/getSuggestedUsersForDiscover.ts +175 -0
  75. package/src/api/app/bsky/unspecced/getSuggestedUsersForExplore.ts +178 -0
  76. package/src/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.ts +178 -0
  77. package/src/feature-gates/gates.ts +3 -0
  78. package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atproto/bsky
2
2
 
3
+ ## 0.0.223
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4809](https://github.com/bluesky-social/atproto/pull/4809) [`2a5e2c2`](https://github.com/bluesky-social/atproto/commit/2a5e2c267f130df8eed87c9bdcb26e97841abc13) Thanks [@ds-boyce](https://github.com/ds-boyce)! - Create new endpoints for suggested users
8
+
9
+ - [#4810](https://github.com/bluesky-social/atproto/pull/4810) [`34f9ae1`](https://github.com/bluesky-social/atproto/commit/34f9ae1f6824bdd7f66c94c57e41cec757e267df) Thanks [@ds-boyce](https://github.com/ds-boyce)! - Show suggestions to logged out users
10
+
11
+ - Updated dependencies [[`2a5e2c2`](https://github.com/bluesky-social/atproto/commit/2a5e2c267f130df8eed87c9bdcb26e97841abc13), [`3711454`](https://github.com/bluesky-social/atproto/commit/371145432178b6c8c411f1289c266314cc7ec592)]:
12
+ - @atproto/api@0.19.6
13
+ - @atproto/syntax@0.5.3
14
+
3
15
  ## 0.0.222
4
16
 
5
17
  ### Patch Changes
@@ -9,7 +9,7 @@ const util_1 = require("../../../util");
9
9
  function default_1(server, ctx) {
10
10
  const getSuggestedFollowsByActor = (0, pipeline_1.createPipeline)(skeleton, hydration, noBlocksOrMutes, presentation);
11
11
  server.add(index_js_1.app.bsky.graph.getSuggestedFollowsByActor, {
12
- auth: ctx.authVerifier.standard,
12
+ auth: ctx.authVerifier.standardOptional,
13
13
  handler: async ({ auth, params, req }) => {
14
14
  const viewer = auth.credentials.iss;
15
15
  const labelers = ctx.reqLabelers(req);
@@ -1 +1 @@
1
- {"version":3,"file":"getSuggestedFollowsByActor.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/getSuggestedFollowsByActor.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined, noUndefinedVals } from '@atproto/common'\nimport { Client, DidString } from '@atproto/lex'\nimport {\n Headers as HeadersMap,\n InternalServerError,\n InvalidRequestError,\n Server,\n} from '@atproto/xrpc-server'\nimport { AppContext } from '../../../../context'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n RulesFnInput,\n SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\nexport default function (server: Server, ctx: AppContext) {\n const getSuggestedFollowsByActor = createPipeline(\n skeleton,\n hydration,\n noBlocksOrMutes,\n presentation,\n )\n server.add(app.bsky.graph.getSuggestedFollowsByActor, {\n auth: ctx.authVerifier.standard,\n handler: async ({ auth, params, 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\n if (!ctx.suggestionsClient) {\n return {\n encoding: 'application/json',\n body: { suggestions: [] },\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n }\n\n const headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n 'x-bsky-topics': Array.isArray(req.headers['x-bsky-topics'])\n ? req.headers['x-bsky-topics'].join(',')\n : req.headers['x-bsky-topics'],\n })\n\n const { contentLanguage, ...body } = await getSuggestedFollowsByActor(\n { ...params, hydrateCtx, headers },\n ctx,\n )\n\n return {\n encoding: 'application/json',\n body,\n headers: {\n ...(contentLanguage ? { 'content-language': contentLanguage } : null),\n ...resHeaders({ labelers: hydrateCtx.labelers }),\n },\n }\n },\n })\n}\n\nconst skeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n\n // handled above already, this branch should not be reached\n if (!ctx.suggestionsClient) {\n throw new InternalServerError('Suggestions service not configured')\n }\n\n const [relativeToDid] = await ctx.hydrator.actor.getDids([params.actor])\n if (!relativeToDid) {\n throw new InvalidRequestError('Actor not found')\n }\n\n const res = await ctx.suggestionsClient.xrpc(\n app.bsky.unspecced.getSuggestionsSkeleton,\n {\n params: {\n viewer: params.hydrateCtx.viewer ?? undefined,\n relativeToDid,\n },\n headers: params.headers,\n },\n )\n\n return {\n recIdStr: res.body.recIdStr,\n suggestedDids: res.body.actors.map((a) => a.did),\n contentLanguage: res.headers.get('content-language') ?? undefined,\n }\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const { suggestedDids } = skeleton\n if (\n params.hydrateCtx.features.checkGate(\n params.hydrateCtx.features.Gate.SuggestedUsersSocialProofEnable,\n )\n ) {\n return ctx.hydrator.hydrateProfilesDetailed(\n suggestedDids,\n params.hydrateCtx,\n )\n } else {\n return ctx.hydrator.hydrateProfiles(suggestedDids, params.hydrateCtx)\n }\n}\n\nconst noBlocksOrMutes = (\n input: RulesFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, hydration } = input\n skeleton.suggestedDids = skeleton.suggestedDids.filter(\n (did) =>\n !ctx.views.viewerBlockExists(did, hydration) &&\n !ctx.views.viewerMuteExists(did, hydration),\n )\n return skeleton\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, hydration, skeleton } = input\n const { suggestedDids, contentLanguage } = skeleton\n const suggestions = mapDefined(suggestedDids, (did) =>\n ctx.views.profileKnownFollowers(did, hydration),\n )\n return {\n recIdStr: skeleton.recIdStr,\n contentLanguage,\n suggestions,\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n suggestionsClient: Client | undefined\n}\n\ntype Params = app.bsky.graph.getSuggestedFollowsByActor.$Params & {\n hydrateCtx: HydrateCtx & { viewer: string }\n headers: HeadersMap\n}\n\ntype SkeletonState = {\n suggestedDids: DidString[]\n recIdStr?: string\n contentLanguage?: string\n}\n"]}
1
+ {"version":3,"file":"getSuggestedFollowsByActor.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/getSuggestedFollowsByActor.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined, noUndefinedVals } from '@atproto/common'\nimport { Client, DidString } from '@atproto/lex'\nimport {\n Headers as HeadersMap,\n InternalServerError,\n InvalidRequestError,\n Server,\n} from '@atproto/xrpc-server'\nimport { AppContext } from '../../../../context'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n RulesFnInput,\n SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\nexport default function (server: Server, ctx: AppContext) {\n const getSuggestedFollowsByActor = createPipeline(\n skeleton,\n hydration,\n noBlocksOrMutes,\n presentation,\n )\n server.add(app.bsky.graph.getSuggestedFollowsByActor, {\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 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\n if (!ctx.suggestionsClient) {\n return {\n encoding: 'application/json',\n body: { suggestions: [] },\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n }\n\n const headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n 'x-bsky-topics': Array.isArray(req.headers['x-bsky-topics'])\n ? req.headers['x-bsky-topics'].join(',')\n : req.headers['x-bsky-topics'],\n })\n\n const { contentLanguage, ...body } = await getSuggestedFollowsByActor(\n { ...params, hydrateCtx, headers },\n ctx,\n )\n\n return {\n encoding: 'application/json',\n body,\n headers: {\n ...(contentLanguage ? { 'content-language': contentLanguage } : null),\n ...resHeaders({ labelers: hydrateCtx.labelers }),\n },\n }\n },\n })\n}\n\nconst skeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n\n // handled above already, this branch should not be reached\n if (!ctx.suggestionsClient) {\n throw new InternalServerError('Suggestions service not configured')\n }\n\n const [relativeToDid] = await ctx.hydrator.actor.getDids([params.actor])\n if (!relativeToDid) {\n throw new InvalidRequestError('Actor not found')\n }\n\n const res = await ctx.suggestionsClient.xrpc(\n app.bsky.unspecced.getSuggestionsSkeleton,\n {\n params: {\n viewer: params.hydrateCtx.viewer ?? undefined,\n relativeToDid,\n },\n headers: params.headers,\n },\n )\n\n return {\n recIdStr: res.body.recIdStr,\n suggestedDids: res.body.actors.map((a) => a.did),\n contentLanguage: res.headers.get('content-language') ?? undefined,\n }\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const { suggestedDids } = skeleton\n if (\n params.hydrateCtx.features.checkGate(\n params.hydrateCtx.features.Gate.SuggestedUsersSocialProofEnable,\n )\n ) {\n return ctx.hydrator.hydrateProfilesDetailed(\n suggestedDids,\n params.hydrateCtx,\n )\n } else {\n return ctx.hydrator.hydrateProfiles(suggestedDids, params.hydrateCtx)\n }\n}\n\nconst noBlocksOrMutes = (\n input: RulesFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, hydration } = input\n skeleton.suggestedDids = skeleton.suggestedDids.filter(\n (did) =>\n !ctx.views.viewerBlockExists(did, hydration) &&\n !ctx.views.viewerMuteExists(did, hydration),\n )\n return skeleton\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, hydration, skeleton } = input\n const { suggestedDids, contentLanguage } = skeleton\n const suggestions = mapDefined(suggestedDids, (did) =>\n ctx.views.profileKnownFollowers(did, hydration),\n )\n return {\n recIdStr: skeleton.recIdStr,\n contentLanguage,\n suggestions,\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n suggestionsClient: Client | undefined\n}\n\ntype Params = app.bsky.graph.getSuggestedFollowsByActor.$Params & {\n hydrateCtx: HydrateCtx\n headers: HeadersMap\n}\n\ntype SkeletonState = {\n suggestedDids: DidString[]\n recIdStr?: string\n contentLanguage?: string\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { Server } from '@atproto/xrpc-server';
2
+ import { AppContext } from '../../../../context';
3
+ export default function (server: Server, ctx: AppContext): void;
4
+ //# sourceMappingURL=getSuggestedUsersForDiscover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForDiscover.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getSuggestedUsersForDiscover.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,MAAM,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAgBhD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAuCvD"}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = default_1;
4
+ const common_1 = require("@atproto/common");
5
+ const xrpc_server_1 = require("@atproto/xrpc-server");
6
+ const hydrator_1 = require("../../../../hydration/hydrator");
7
+ const index_js_1 = require("../../../../lexicons/index.js");
8
+ const pipeline_1 = require("../../../../pipeline");
9
+ function default_1(server, ctx) {
10
+ const getSuggestedUsersForDiscover = (0, pipeline_1.createPipeline)(skeleton, hydration, noBlocksOrFollows, presentation);
11
+ server.add(index_js_1.app.bsky.unspecced.getSuggestedUsersForDiscover, {
12
+ auth: ctx.authVerifier.standardOptional,
13
+ handler: async ({ auth, params, req }) => {
14
+ const viewer = auth.credentials.iss;
15
+ const labelers = ctx.reqLabelers(req);
16
+ const hydrateCtx = await ctx.hydrator.createContext({
17
+ labelers,
18
+ viewer,
19
+ features: ctx.featureGatesClient.scope(ctx.featureGatesClient.parseUserContextFromHandler({
20
+ viewer,
21
+ req,
22
+ })),
23
+ });
24
+ const headers = (0, common_1.noUndefinedVals)({
25
+ 'accept-language': req.headers['accept-language'],
26
+ });
27
+ const result = await getSuggestedUsersForDiscover({
28
+ ...params,
29
+ hydrateCtx,
30
+ headers,
31
+ }, ctx);
32
+ return {
33
+ encoding: 'application/json',
34
+ body: result,
35
+ };
36
+ },
37
+ });
38
+ }
39
+ const skeletonFromGetSuggestedUsersSkeleton = async (input) => {
40
+ const { params, ctx } = input;
41
+ if (!ctx.suggestionsClient) {
42
+ throw new xrpc_server_1.MethodNotImplementedError('Suggestions agent not available');
43
+ }
44
+ return ctx.suggestionsClient.call(index_js_1.app.bsky.unspecced.getSuggestedUsersSkeleton, {
45
+ limit: params.limit,
46
+ viewer: params.hydrateCtx.viewer ?? undefined,
47
+ }, {
48
+ headers: params.headers,
49
+ });
50
+ };
51
+ // TODO: rename to `skeleton` once we can fully migrate to the new endpoint
52
+ const skeletonFromGetSuggestedUsersForDiscoverSkeleton = async (input) => {
53
+ const { params, ctx } = input;
54
+ if (!ctx.suggestionsClient) {
55
+ throw new xrpc_server_1.MethodNotImplementedError('Suggestions agent not available');
56
+ }
57
+ return ctx.suggestionsClient.call(index_js_1.app.bsky.unspecced.getSuggestedUsersForDiscoverSkeleton, {
58
+ limit: params.limit,
59
+ viewer: params.hydrateCtx.viewer ?? undefined,
60
+ }, {
61
+ headers: params.headers,
62
+ });
63
+ };
64
+ const skeleton = async (input) => {
65
+ const useDiscover = input.params.hydrateCtx.features.checkGate(input.params.hydrateCtx.features.Gate.SuggestedUsersForDiscoverEnable);
66
+ const skeletonFn = useDiscover
67
+ ? skeletonFromGetSuggestedUsersForDiscoverSkeleton
68
+ : skeletonFromGetSuggestedUsersSkeleton;
69
+ return skeletonFn(input);
70
+ };
71
+ const hydration = async (input) => {
72
+ const { ctx, params, skeleton } = input;
73
+ const dids = (0, common_1.dedupeStrs)(skeleton.dids);
74
+ const pairs = new Map();
75
+ const viewer = params.hydrateCtx.viewer;
76
+ if (viewer) {
77
+ pairs.set(viewer, dids);
78
+ }
79
+ const [profilesState, bidirectionalBlocks] = await Promise.all([
80
+ ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx),
81
+ ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),
82
+ ]);
83
+ return (0, hydrator_1.mergeManyStates)(profilesState, { bidirectionalBlocks });
84
+ };
85
+ const noBlocksOrFollows = (input) => {
86
+ const { ctx, skeleton, params, hydration } = input;
87
+ const viewer = params.hydrateCtx.viewer;
88
+ if (!viewer) {
89
+ return skeleton;
90
+ }
91
+ const blocks = hydration.bidirectionalBlocks?.get(viewer);
92
+ return {
93
+ ...skeleton,
94
+ dids: skeleton.dids.filter((did) => {
95
+ const viewer = ctx.views.profileViewer(did, hydration);
96
+ return !blocks?.get(did) && !viewer?.following;
97
+ }),
98
+ };
99
+ };
100
+ const presentation = (input) => {
101
+ const { ctx, skeleton, hydration } = input;
102
+ return {
103
+ recIdStr: skeleton.recIdStr,
104
+ actors: (0, common_1.mapDefined)(skeleton.dids, (did) => ctx.views.profile(did, hydration)),
105
+ };
106
+ };
107
+ //# sourceMappingURL=getSuggestedUsersForDiscover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForDiscover.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getSuggestedUsersForDiscover.ts"],"names":[],"mappings":"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","sourcesContent":["import { dedupeStrs, mapDefined, noUndefinedVals } from '@atproto/common'\nimport { Client, DidString } from '@atproto/lex'\nimport { MethodNotImplementedError, Server } from '@atproto/xrpc-server'\nimport { AppContext } from '../../../../context'\nimport {\n HydrateCtx,\n Hydrator,\n mergeManyStates,\n} from '../../../../hydration/hydrator'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n RulesFnInput,\n SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline'\nimport { Views } from '../../../../views'\n\nexport default function (server: Server, ctx: AppContext) {\n const getSuggestedUsersForDiscover = createPipeline(\n skeleton,\n hydration,\n noBlocksOrFollows,\n presentation,\n )\n server.add(app.bsky.unspecced.getSuggestedUsersForDiscover, {\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 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 headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n })\n const result = await getSuggestedUsersForDiscover(\n {\n ...params,\n hydrateCtx,\n headers,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeletonFromGetSuggestedUsersSkeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n if (!ctx.suggestionsClient) {\n throw new MethodNotImplementedError('Suggestions agent not available')\n }\n\n return ctx.suggestionsClient.call(\n app.bsky.unspecced.getSuggestedUsersSkeleton,\n {\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\n// TODO: rename to `skeleton` once we can fully migrate to the new endpoint\nconst skeletonFromGetSuggestedUsersForDiscoverSkeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n\n if (!ctx.suggestionsClient) {\n throw new MethodNotImplementedError('Suggestions agent not available')\n }\n\n return ctx.suggestionsClient.call(\n app.bsky.unspecced.getSuggestedUsersForDiscoverSkeleton,\n {\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useDiscover = input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SuggestedUsersForDiscoverEnable,\n )\n const skeletonFn = useDiscover\n ? skeletonFromGetSuggestedUsersForDiscoverSkeleton\n : skeletonFromGetSuggestedUsersSkeleton\n return skeletonFn(input)\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const dids = dedupeStrs(skeleton.dids)\n const pairs: Map<DidString, DidString[]> = new Map()\n const viewer = params.hydrateCtx.viewer\n if (viewer) {\n pairs.set(viewer, dids)\n }\n const [profilesState, bidirectionalBlocks] = await Promise.all([\n ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx),\n ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),\n ])\n\n return mergeManyStates(profilesState, { bidirectionalBlocks })\n}\n\nconst noBlocksOrFollows = (\n input: RulesFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, params, hydration } = input\n const viewer = params.hydrateCtx.viewer\n if (!viewer) {\n return skeleton\n }\n const blocks = hydration.bidirectionalBlocks?.get(viewer)\n return {\n ...skeleton,\n dids: skeleton.dids.filter((did) => {\n const viewer = ctx.views.profileViewer(did, hydration)\n return !blocks?.get(did) && !viewer?.following\n }),\n }\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, hydration } = input\n return {\n recIdStr: skeleton.recIdStr,\n actors: mapDefined(skeleton.dids, (did) =>\n ctx.views.profile(did, hydration),\n ),\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n suggestionsClient: Client | undefined\n}\n\ntype Params = app.bsky.unspecced.getSuggestedUsersForDiscover.$Params & {\n hydrateCtx: HydrateCtx & { viewer: string | null }\n headers: Record<string, string>\n}\n\ntype SkeletonState = {\n dids: DidString[]\n recIdStr?: string\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { Server } from '@atproto/xrpc-server';
2
+ import { AppContext } from '../../../../context';
3
+ export default function (server: Server, ctx: AppContext): void;
4
+ //# sourceMappingURL=getSuggestedUsersForExplore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForExplore.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getSuggestedUsersForExplore.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,MAAM,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAgBhD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAuCvD"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = default_1;
4
+ const common_1 = require("@atproto/common");
5
+ const xrpc_server_1 = require("@atproto/xrpc-server");
6
+ const hydrator_1 = require("../../../../hydration/hydrator");
7
+ const index_js_1 = require("../../../../lexicons/index.js");
8
+ const pipeline_1 = require("../../../../pipeline");
9
+ function default_1(server, ctx) {
10
+ const getSuggestedUsersForExplore = (0, pipeline_1.createPipeline)(skeleton, hydration, noBlocksOrFollows, presentation);
11
+ server.add(index_js_1.app.bsky.unspecced.getSuggestedUsersForExplore, {
12
+ auth: ctx.authVerifier.standardOptional,
13
+ handler: async ({ auth, params, req }) => {
14
+ const viewer = auth.credentials.iss;
15
+ const labelers = ctx.reqLabelers(req);
16
+ const hydrateCtx = await ctx.hydrator.createContext({
17
+ labelers,
18
+ viewer,
19
+ features: ctx.featureGatesClient.scope(ctx.featureGatesClient.parseUserContextFromHandler({
20
+ viewer,
21
+ req,
22
+ })),
23
+ });
24
+ const headers = (0, common_1.noUndefinedVals)({
25
+ 'accept-language': req.headers['accept-language'],
26
+ });
27
+ const result = await getSuggestedUsersForExplore({
28
+ ...params,
29
+ hydrateCtx,
30
+ headers,
31
+ }, ctx);
32
+ return {
33
+ encoding: 'application/json',
34
+ body: result,
35
+ };
36
+ },
37
+ });
38
+ }
39
+ const skeletonFromGetSuggestedUsersSkeleton = async (input) => {
40
+ const { params, ctx } = input;
41
+ if (!ctx.suggestionsClient) {
42
+ throw new xrpc_server_1.MethodNotImplementedError('Suggestions agent not available');
43
+ }
44
+ return ctx.suggestionsClient.call(index_js_1.app.bsky.unspecced.getSuggestedUsersSkeleton, {
45
+ limit: params.limit,
46
+ category: params.category,
47
+ viewer: params.hydrateCtx.viewer ?? undefined,
48
+ }, {
49
+ headers: params.headers,
50
+ });
51
+ };
52
+ // TODO: rename to `skeleton` once we can fully migrate to the new endpoint
53
+ const skeletonFromGetSuggestedUsersForExploreSkeleton = async (input) => {
54
+ const { params, ctx } = input;
55
+ if (!ctx.suggestionsClient) {
56
+ throw new xrpc_server_1.MethodNotImplementedError('Suggestions agent not available');
57
+ }
58
+ return ctx.suggestionsClient.call(index_js_1.app.bsky.unspecced.getSuggestedUsersForExploreSkeleton, {
59
+ limit: params.limit,
60
+ category: params.category,
61
+ viewer: params.hydrateCtx.viewer ?? undefined,
62
+ }, {
63
+ headers: params.headers,
64
+ });
65
+ };
66
+ const skeleton = async (input) => {
67
+ const useExplore = input.params.hydrateCtx.features.checkGate(input.params.hydrateCtx.features.Gate.SuggestedUsersForExploreEnable);
68
+ const skeletonFn = useExplore
69
+ ? skeletonFromGetSuggestedUsersForExploreSkeleton
70
+ : skeletonFromGetSuggestedUsersSkeleton;
71
+ return skeletonFn(input);
72
+ };
73
+ const hydration = async (input) => {
74
+ const { ctx, params, skeleton } = input;
75
+ const dids = (0, common_1.dedupeStrs)(skeleton.dids);
76
+ const pairs = new Map();
77
+ const viewer = params.hydrateCtx.viewer;
78
+ if (viewer) {
79
+ pairs.set(viewer, dids);
80
+ }
81
+ const [profilesState, bidirectionalBlocks] = await Promise.all([
82
+ ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx),
83
+ ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),
84
+ ]);
85
+ return (0, hydrator_1.mergeManyStates)(profilesState, { bidirectionalBlocks });
86
+ };
87
+ const noBlocksOrFollows = (input) => {
88
+ const { ctx, skeleton, params, hydration } = input;
89
+ const viewer = params.hydrateCtx.viewer;
90
+ if (!viewer) {
91
+ return skeleton;
92
+ }
93
+ const blocks = hydration.bidirectionalBlocks?.get(viewer);
94
+ return {
95
+ ...skeleton,
96
+ dids: skeleton.dids.filter((did) => {
97
+ const viewer = ctx.views.profileViewer(did, hydration);
98
+ return !blocks?.get(did) && !viewer?.following;
99
+ }),
100
+ };
101
+ };
102
+ const presentation = (input) => {
103
+ const { ctx, skeleton, hydration } = input;
104
+ return {
105
+ recIdStr: skeleton.recIdStr,
106
+ actors: (0, common_1.mapDefined)(skeleton.dids, (did) => ctx.views.profile(did, hydration)),
107
+ };
108
+ };
109
+ //# sourceMappingURL=getSuggestedUsersForExplore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForExplore.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getSuggestedUsersForExplore.ts"],"names":[],"mappings":"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","sourcesContent":["import { dedupeStrs, mapDefined, noUndefinedVals } from '@atproto/common'\nimport { Client, DidString } from '@atproto/lex'\nimport { MethodNotImplementedError, Server } from '@atproto/xrpc-server'\nimport { AppContext } from '../../../../context'\nimport {\n HydrateCtx,\n Hydrator,\n mergeManyStates,\n} from '../../../../hydration/hydrator'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n RulesFnInput,\n SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline'\nimport { Views } from '../../../../views'\n\nexport default function (server: Server, ctx: AppContext) {\n const getSuggestedUsersForExplore = createPipeline(\n skeleton,\n hydration,\n noBlocksOrFollows,\n presentation,\n )\n server.add(app.bsky.unspecced.getSuggestedUsersForExplore, {\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 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 headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n })\n const result = await getSuggestedUsersForExplore(\n {\n ...params,\n hydrateCtx,\n headers,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeletonFromGetSuggestedUsersSkeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n if (!ctx.suggestionsClient) {\n throw new MethodNotImplementedError('Suggestions agent not available')\n }\n\n return ctx.suggestionsClient.call(\n app.bsky.unspecced.getSuggestedUsersSkeleton,\n {\n limit: params.limit,\n category: params.category,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\n// TODO: rename to `skeleton` once we can fully migrate to the new endpoint\nconst skeletonFromGetSuggestedUsersForExploreSkeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n\n if (!ctx.suggestionsClient) {\n throw new MethodNotImplementedError('Suggestions agent not available')\n }\n\n return ctx.suggestionsClient.call(\n app.bsky.unspecced.getSuggestedUsersForExploreSkeleton,\n {\n limit: params.limit,\n category: params.category,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useExplore = input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SuggestedUsersForExploreEnable,\n )\n const skeletonFn = useExplore\n ? skeletonFromGetSuggestedUsersForExploreSkeleton\n : skeletonFromGetSuggestedUsersSkeleton\n return skeletonFn(input)\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const dids = dedupeStrs(skeleton.dids)\n const pairs: Map<DidString, DidString[]> = new Map()\n const viewer = params.hydrateCtx.viewer\n if (viewer) {\n pairs.set(viewer, dids)\n }\n const [profilesState, bidirectionalBlocks] = await Promise.all([\n ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx),\n ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),\n ])\n\n return mergeManyStates(profilesState, { bidirectionalBlocks })\n}\n\nconst noBlocksOrFollows = (\n input: RulesFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, params, hydration } = input\n const viewer = params.hydrateCtx.viewer\n if (!viewer) {\n return skeleton\n }\n const blocks = hydration.bidirectionalBlocks?.get(viewer)\n return {\n ...skeleton,\n dids: skeleton.dids.filter((did) => {\n const viewer = ctx.views.profileViewer(did, hydration)\n return !blocks?.get(did) && !viewer?.following\n }),\n }\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, hydration } = input\n return {\n recIdStr: skeleton.recIdStr,\n actors: mapDefined(skeleton.dids, (did) =>\n ctx.views.profile(did, hydration),\n ),\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n suggestionsClient: Client | undefined\n}\n\ntype Params = app.bsky.unspecced.getSuggestedUsersForExplore.$Params & {\n hydrateCtx: HydrateCtx & { viewer: string | null }\n headers: Record<string, string>\n category?: string\n}\n\ntype SkeletonState = {\n dids: DidString[]\n recIdStr?: string\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { Server } from '@atproto/xrpc-server';
2
+ import { AppContext } from '../../../../context';
3
+ export default function (server: Server, ctx: AppContext): void;
4
+ //# sourceMappingURL=getSuggestedUsersForSeeMore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForSeeMore.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,MAAM,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAgBhD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAuCvD"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = default_1;
4
+ const common_1 = require("@atproto/common");
5
+ const xrpc_server_1 = require("@atproto/xrpc-server");
6
+ const hydrator_1 = require("../../../../hydration/hydrator");
7
+ const index_js_1 = require("../../../../lexicons/index.js");
8
+ const pipeline_1 = require("../../../../pipeline");
9
+ function default_1(server, ctx) {
10
+ const getSuggestedUsersForSeeMore = (0, pipeline_1.createPipeline)(skeleton, hydration, noBlocksOrFollows, presentation);
11
+ server.add(index_js_1.app.bsky.unspecced.getSuggestedUsersForSeeMore, {
12
+ auth: ctx.authVerifier.standardOptional,
13
+ handler: async ({ auth, params, req }) => {
14
+ const viewer = auth.credentials.iss;
15
+ const labelers = ctx.reqLabelers(req);
16
+ const hydrateCtx = await ctx.hydrator.createContext({
17
+ labelers,
18
+ viewer,
19
+ features: ctx.featureGatesClient.scope(ctx.featureGatesClient.parseUserContextFromHandler({
20
+ viewer,
21
+ req,
22
+ })),
23
+ });
24
+ const headers = (0, common_1.noUndefinedVals)({
25
+ 'accept-language': req.headers['accept-language'],
26
+ });
27
+ const result = await getSuggestedUsersForSeeMore({
28
+ ...params,
29
+ hydrateCtx,
30
+ headers,
31
+ }, ctx);
32
+ return {
33
+ encoding: 'application/json',
34
+ body: result,
35
+ };
36
+ },
37
+ });
38
+ }
39
+ const skeletonFromGetSuggestedUsersSkeleton = async (input) => {
40
+ const { params, ctx } = input;
41
+ if (!ctx.suggestionsClient) {
42
+ throw new xrpc_server_1.MethodNotImplementedError('Suggestions agent not available');
43
+ }
44
+ return ctx.suggestionsClient.call(index_js_1.app.bsky.unspecced.getSuggestedUsersSkeleton, {
45
+ limit: params.limit,
46
+ category: params.category,
47
+ viewer: params.hydrateCtx.viewer ?? undefined,
48
+ }, {
49
+ headers: params.headers,
50
+ });
51
+ };
52
+ // TODO: rename to `skeleton` once we can fully migrate to the new endpoint
53
+ const skeletonFromGetSuggestedUsersForSeeMoreSkeleton = async (input) => {
54
+ const { params, ctx } = input;
55
+ if (!ctx.suggestionsClient) {
56
+ throw new xrpc_server_1.MethodNotImplementedError('Suggestions agent not available');
57
+ }
58
+ return ctx.suggestionsClient.call(index_js_1.app.bsky.unspecced.getSuggestedUsersForSeeMoreSkeleton, {
59
+ limit: params.limit,
60
+ category: params.category,
61
+ viewer: params.hydrateCtx.viewer ?? undefined,
62
+ }, {
63
+ headers: params.headers,
64
+ });
65
+ };
66
+ const skeleton = async (input) => {
67
+ const useSeeMore = input.params.hydrateCtx.features.checkGate(input.params.hydrateCtx.features.Gate.SuggestedUsersForSeeMoreEnable);
68
+ const skeletonFn = useSeeMore
69
+ ? skeletonFromGetSuggestedUsersForSeeMoreSkeleton
70
+ : skeletonFromGetSuggestedUsersSkeleton;
71
+ return skeletonFn(input);
72
+ };
73
+ const hydration = async (input) => {
74
+ const { ctx, params, skeleton } = input;
75
+ const dids = (0, common_1.dedupeStrs)(skeleton.dids);
76
+ const pairs = new Map();
77
+ const viewer = params.hydrateCtx.viewer;
78
+ if (viewer) {
79
+ pairs.set(viewer, dids);
80
+ }
81
+ const [profilesState, bidirectionalBlocks] = await Promise.all([
82
+ ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx),
83
+ ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),
84
+ ]);
85
+ return (0, hydrator_1.mergeManyStates)(profilesState, { bidirectionalBlocks });
86
+ };
87
+ const noBlocksOrFollows = (input) => {
88
+ const { ctx, skeleton, params, hydration } = input;
89
+ const viewer = params.hydrateCtx.viewer;
90
+ if (!viewer) {
91
+ return skeleton;
92
+ }
93
+ const blocks = hydration.bidirectionalBlocks?.get(viewer);
94
+ return {
95
+ ...skeleton,
96
+ dids: skeleton.dids.filter((did) => {
97
+ const viewer = ctx.views.profileViewer(did, hydration);
98
+ return !blocks?.get(did) && !viewer?.following;
99
+ }),
100
+ };
101
+ };
102
+ const presentation = (input) => {
103
+ const { ctx, skeleton, hydration } = input;
104
+ return {
105
+ recIdStr: skeleton.recIdStr,
106
+ actors: (0, common_1.mapDefined)(skeleton.dids, (did) => ctx.views.profile(did, hydration)),
107
+ };
108
+ };
109
+ //# sourceMappingURL=getSuggestedUsersForSeeMore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForSeeMore.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.ts"],"names":[],"mappings":"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","sourcesContent":["import { dedupeStrs, mapDefined, noUndefinedVals } from '@atproto/common'\nimport { Client, DidString } from '@atproto/lex'\nimport { MethodNotImplementedError, Server } from '@atproto/xrpc-server'\nimport { AppContext } from '../../../../context'\nimport {\n HydrateCtx,\n Hydrator,\n mergeManyStates,\n} from '../../../../hydration/hydrator'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n RulesFnInput,\n SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline'\nimport { Views } from '../../../../views'\n\nexport default function (server: Server, ctx: AppContext) {\n const getSuggestedUsersForSeeMore = createPipeline(\n skeleton,\n hydration,\n noBlocksOrFollows,\n presentation,\n )\n server.add(app.bsky.unspecced.getSuggestedUsersForSeeMore, {\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 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 headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n })\n const result = await getSuggestedUsersForSeeMore(\n {\n ...params,\n hydrateCtx,\n headers,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeletonFromGetSuggestedUsersSkeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n if (!ctx.suggestionsClient) {\n throw new MethodNotImplementedError('Suggestions agent not available')\n }\n\n return ctx.suggestionsClient.call(\n app.bsky.unspecced.getSuggestedUsersSkeleton,\n {\n limit: params.limit,\n category: params.category,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\n// TODO: rename to `skeleton` once we can fully migrate to the new endpoint\nconst skeletonFromGetSuggestedUsersForSeeMoreSkeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n\n if (!ctx.suggestionsClient) {\n throw new MethodNotImplementedError('Suggestions agent not available')\n }\n\n return ctx.suggestionsClient.call(\n app.bsky.unspecced.getSuggestedUsersForSeeMoreSkeleton,\n {\n limit: params.limit,\n category: params.category,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useSeeMore = input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SuggestedUsersForSeeMoreEnable,\n )\n const skeletonFn = useSeeMore\n ? skeletonFromGetSuggestedUsersForSeeMoreSkeleton\n : skeletonFromGetSuggestedUsersSkeleton\n return skeletonFn(input)\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const dids = dedupeStrs(skeleton.dids)\n const pairs: Map<DidString, DidString[]> = new Map()\n const viewer = params.hydrateCtx.viewer\n if (viewer) {\n pairs.set(viewer, dids)\n }\n const [profilesState, bidirectionalBlocks] = await Promise.all([\n ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx),\n ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),\n ])\n\n return mergeManyStates(profilesState, { bidirectionalBlocks })\n}\n\nconst noBlocksOrFollows = (\n input: RulesFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, params, hydration } = input\n const viewer = params.hydrateCtx.viewer\n if (!viewer) {\n return skeleton\n }\n const blocks = hydration.bidirectionalBlocks?.get(viewer)\n return {\n ...skeleton,\n dids: skeleton.dids.filter((did) => {\n const viewer = ctx.views.profileViewer(did, hydration)\n return !blocks?.get(did) && !viewer?.following\n }),\n }\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, skeleton, hydration } = input\n return {\n recIdStr: skeleton.recIdStr,\n actors: mapDefined(skeleton.dids, (did) =>\n ctx.views.profile(did, hydration),\n ),\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n suggestionsClient: Client | undefined\n}\n\ntype Params = app.bsky.unspecced.getSuggestedUsersForSeeMore.$Params & {\n hydrateCtx: HydrateCtx & { viewer: string | null }\n headers: Record<string, string>\n category?: string\n}\n\ntype SkeletonState = {\n dids: DidString[]\n recIdStr?: string\n}\n"]}
@@ -8,6 +8,9 @@ export declare enum Gate {
8
8
  SuggestedUsersSocialProofEnable = "suggested_users:social_proof:enable",
9
9
  ThreadsReplyRankingExplorationEnable = "threads:reply_ranking_exploration:enable",
10
10
  SearchFilteringExplorationEnable = "search:filtering_exploration:enable",
11
+ SuggestedUsersForExploreEnable = "suggested_users:for_explore:enable",
12
+ SuggestedUsersForDiscoverEnable = "suggested_users:for_discover:enable",
13
+ SuggestedUsersForSeeMoreEnable = "suggested_users:for_see_more:enable",
11
14
  AATest = "aa-test-appview"
12
15
  }
13
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"gates.d.ts","sourceRoot":"","sources":["../../src/feature-gates/gates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,oBAAY,IAAI;IACd,4BAA4B,0CAA0C;IACtE,+BAA+B,wCAAwC;IACvE,oCAAoC,6CAA6C;IACjF,gCAAgC,wCAAwC;IAGxE,MAAM,oBAAoB;CAC3B;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,GAAG,CAAC,IAAI,CAAe,CAAA"}
1
+ {"version":3,"file":"gates.d.ts","sourceRoot":"","sources":["../../src/feature-gates/gates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,oBAAY,IAAI;IACd,4BAA4B,0CAA0C;IACtE,+BAA+B,wCAAwC;IACvE,oCAAoC,6CAA6C;IACjF,gCAAgC,wCAAwC;IACxE,8BAA8B,uCAAuC;IACrE,+BAA+B,wCAAwC;IACvE,8BAA8B,wCAAwC;IAGtE,MAAM,oBAAoB;CAC3B;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,GAAG,CAAC,IAAI,CAAe,CAAA"}
@@ -12,6 +12,9 @@ var Gate;
12
12
  Gate["SuggestedUsersSocialProofEnable"] = "suggested_users:social_proof:enable";
13
13
  Gate["ThreadsReplyRankingExplorationEnable"] = "threads:reply_ranking_exploration:enable";
14
14
  Gate["SearchFilteringExplorationEnable"] = "search:filtering_exploration:enable";
15
+ Gate["SuggestedUsersForExploreEnable"] = "suggested_users:for_explore:enable";
16
+ Gate["SuggestedUsersForDiscoverEnable"] = "suggested_users:for_discover:enable";
17
+ Gate["SuggestedUsersForSeeMoreEnable"] = "suggested_users:for_see_more:enable";
15
18
  // temp
16
19
  Gate["AATest"] = "aa-test-appview";
17
20
  })(Gate || (exports.Gate = Gate = {}));
@@ -1 +1 @@
1
- {"version":3,"file":"gates.js","sourceRoot":"","sources":["../../src/feature-gates/gates.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,IAAY,IAQX;AARD,WAAY,IAAI;IACd,8EAAsE,CAAA;IACtE,+EAAuE,CAAA;IACvE,yFAAiF,CAAA;IACjF,gFAAwE,CAAA;IAExE,OAAO;IACP,kCAA0B,CAAA;AAC5B,CAAC,EARW,IAAI,oBAAJ,IAAI,QAQf;AAED;;;;GAIG;AACU,QAAA,wBAAwB,GAAc,IAAI,GAAG,CAAC,EAAE,CAAC,CAAA","sourcesContent":["/**\n * Enum of all gates in the system. This should be the single source of truth\n * for all gates, and should be used in all places where gates are checked or\n * defined.\n */\nexport enum Gate {\n SuggestedUsersDiscoverEnable = 'suggested_users:discover_agent:enable',\n SuggestedUsersSocialProofEnable = 'suggested_users:social_proof:enable',\n ThreadsReplyRankingExplorationEnable = 'threads:reply_ranking_exploration:enable',\n SearchFilteringExplorationEnable = 'search:filtering_exploration:enable',\n\n // temp\n AATest = 'aa-test-appview',\n}\n\n/**\n * Set of gates that should be ignored when tracking gate evaluations for\n * analytics purposes. This is useful for gates that are not user-facing or are\n * overly noisy.\n */\nexport const IGNORE_METRICS_FOR_GATES: Set<Gate> = new Set([])\n"]}
1
+ {"version":3,"file":"gates.js","sourceRoot":"","sources":["../../src/feature-gates/gates.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,IAAY,IAWX;AAXD,WAAY,IAAI;IACd,8EAAsE,CAAA;IACtE,+EAAuE,CAAA;IACvE,yFAAiF,CAAA;IACjF,gFAAwE,CAAA;IACxE,6EAAqE,CAAA;IACrE,+EAAuE,CAAA;IACvE,8EAAsE,CAAA;IAEtE,OAAO;IACP,kCAA0B,CAAA;AAC5B,CAAC,EAXW,IAAI,oBAAJ,IAAI,QAWf;AAED;;;;GAIG;AACU,QAAA,wBAAwB,GAAc,IAAI,GAAG,CAAC,EAAE,CAAC,CAAA","sourcesContent":["/**\n * Enum of all gates in the system. This should be the single source of truth\n * for all gates, and should be used in all places where gates are checked or\n * defined.\n */\nexport enum Gate {\n SuggestedUsersDiscoverEnable = 'suggested_users:discover_agent:enable',\n SuggestedUsersSocialProofEnable = 'suggested_users:social_proof:enable',\n ThreadsReplyRankingExplorationEnable = 'threads:reply_ranking_exploration:enable',\n SearchFilteringExplorationEnable = 'search:filtering_exploration:enable',\n SuggestedUsersForExploreEnable = 'suggested_users:for_explore:enable',\n SuggestedUsersForDiscoverEnable = 'suggested_users:for_discover:enable',\n SuggestedUsersForSeeMoreEnable = 'suggested_users:for_see_more:enable',\n\n // temp\n AATest = 'aa-test-appview',\n}\n\n/**\n * Set of gates that should be ignored when tracking gate evaluations for\n * analytics purposes. This is useful for gates that are not user-facing or are\n * overly noisy.\n */\nexport const IGNORE_METRICS_FOR_GATES: Set<Gate> = new Set([])\n"]}
@@ -0,0 +1,3 @@
1
+ export * from './getSuggestedUsersForDiscover.defs.js';
2
+ export * as $defs from './getSuggestedUsersForDiscover.defs.js';
3
+ //# sourceMappingURL=getSuggestedUsersForDiscover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForDiscover.d.ts","sourceRoot":"","sources":["../../../../../src/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.ts"],"names":[],"mappings":"AAIA,cAAc,wCAAwC,CAAA;AACtD,OAAO,KAAK,KAAK,MAAM,wCAAwC,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { l } from '@atproto/lex';
2
+ import * as ActorDefs from '../actor/defs.defs.js';
3
+ declare const $nsid = "app.bsky.unspecced.getSuggestedUsersForDiscover";
4
+ export { $nsid };
5
+ /** Get a list of suggested users for the Discover page */
6
+ declare const main: l.Query<"app.bsky.unspecced.getSuggestedUsersForDiscover", l.ParamsSchema<{
7
+ readonly limit: l.OptionalSchema<l.WithDefaultSchema<l.IntegerSchema>>;
8
+ }>, l.Payload<"application/json", l.ObjectSchema<{
9
+ actors: l.ArraySchema<l.RefSchema<l.Validator<ActorDefs.ProfileView, ActorDefs.ProfileView>>>;
10
+ recIdStr: l.OptionalSchema<l.StringSchema<{}>>;
11
+ }>>, undefined>;
12
+ export { main };
13
+ export type $Params = l.InferMethodParams<typeof main>;
14
+ export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>;
15
+ export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<typeof main, B>;
16
+ export declare const $lxm: "app.bsky.unspecced.getSuggestedUsersForDiscover", $params: l.ParamsSchema<{
17
+ readonly limit: l.OptionalSchema<l.WithDefaultSchema<l.IntegerSchema>>;
18
+ }>, $output: l.Payload<"application/json", l.ObjectSchema<{
19
+ actors: l.ArraySchema<l.RefSchema<l.Validator<ActorDefs.ProfileView, ActorDefs.ProfileView>>>;
20
+ recIdStr: l.OptionalSchema<l.StringSchema<{}>>;
21
+ }>>;
22
+ //# sourceMappingURL=getSuggestedUsersForDiscover.defs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSuggestedUsersForDiscover.defs.d.ts","sourceRoot":"","sources":["../../../../../src/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAChC,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAElD,QAAA,MAAM,KAAK,oDAAoD,CAAA;AAE/D,OAAO,EAAE,KAAK,EAAE,CAAA;AAEhB,0DAA0D;AAC1D,QAAA,MAAM,IAAI;;;;;eAaT,CAAA;AACD,OAAO,EAAE,IAAI,EAAE,CAAA;AAEf,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,iBAAiB,CAAC,OAAO,IAAI,CAAC,CAAA;AACtD,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,iBAAiB,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAA;AAC3E,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,qBAAqB,CACjE,OAAO,IAAI,EACX,CAAC,CACF,CAAA;AAED,eAAO,MAAM,IAAI,mDAAY,EAC3B,OAAO;;EAAkB,EACzB,OAAO;;;GAAc,CAAA"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /*
3
+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.$output = exports.$params = exports.$lxm = exports.main = exports.$nsid = void 0;
40
+ const lex_1 = require("@atproto/lex");
41
+ const ActorDefs = __importStar(require("../actor/defs.defs.js"));
42
+ const $nsid = 'app.bsky.unspecced.getSuggestedUsersForDiscover';
43
+ exports.$nsid = $nsid;
44
+ /** Get a list of suggested users for the Discover page */
45
+ const main = lex_1.l.query($nsid, lex_1.l.params({
46
+ limit: lex_1.l.optional(lex_1.l.withDefault(lex_1.l.integer({ minimum: 1, maximum: 50 }), 25)),
47
+ }), lex_1.l.jsonPayload({
48
+ actors: lex_1.l.array(lex_1.l.ref((() => ActorDefs.profileView))),
49
+ recIdStr: lex_1.l.optional(lex_1.l.string()),
50
+ }));
51
+ exports.main = main;
52
+ exports.$lxm = main.nsid, exports.$params = main.parameters, exports.$output = main.output;
53
+ //# sourceMappingURL=getSuggestedUsersForDiscover.defs.js.map