@atproto/bsky 0.0.193 → 0.0.195

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 (77) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/api/app/bsky/feed/searchPosts.d.ts.map +1 -1
  3. package/dist/api/app/bsky/feed/searchPosts.js +43 -12
  4. package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
  5. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js +1 -2
  6. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -1
  7. package/dist/api/app/bsky/unspecced/getPostThreadV2.js +0 -1
  8. package/dist/api/app/bsky/unspecced/getPostThreadV2.js.map +1 -1
  9. package/dist/auth-verifier.d.ts +1 -0
  10. package/dist/auth-verifier.d.ts.map +1 -1
  11. package/dist/auth-verifier.js +4 -0
  12. package/dist/auth-verifier.js.map +1 -1
  13. package/dist/config.d.ts +2 -0
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +5 -0
  16. package/dist/config.js.map +1 -1
  17. package/dist/data-plane/server/routes/search.d.ts.map +1 -1
  18. package/dist/data-plane/server/routes/search.js +15 -1
  19. package/dist/data-plane/server/routes/search.js.map +1 -1
  20. package/dist/data-plane/server/util.d.ts +7 -0
  21. package/dist/data-plane/server/util.d.ts.map +1 -1
  22. package/dist/data-plane/server/util.js +38 -1
  23. package/dist/data-plane/server/util.js.map +1 -1
  24. package/dist/lexicon/index.d.ts +2 -0
  25. package/dist/lexicon/index.d.ts.map +1 -1
  26. package/dist/lexicon/index.js +4 -0
  27. package/dist/lexicon/index.js.map +1 -1
  28. package/dist/lexicon/lexicons.d.ts +106 -28
  29. package/dist/lexicon/lexicons.d.ts.map +1 -1
  30. package/dist/lexicon/lexicons.js +56 -14
  31. package/dist/lexicon/lexicons.js.map +1 -1
  32. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +0 -2
  33. package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
  34. package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
  35. package/dist/lexicon/types/app/bsky/graph/follow.d.ts +2 -0
  36. package/dist/lexicon/types/app/bsky/graph/follow.d.ts.map +1 -1
  37. package/dist/lexicon/types/app/bsky/graph/follow.js.map +1 -1
  38. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.d.ts +0 -2
  39. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.d.ts.map +1 -1
  40. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -1
  41. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts +0 -2
  42. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts.map +1 -1
  43. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.js.map +1 -1
  44. package/dist/lexicon/types/com/atproto/lexicon/resolveLexicon.d.ts +28 -0
  45. package/dist/lexicon/types/com/atproto/lexicon/resolveLexicon.d.ts.map +1 -0
  46. package/dist/lexicon/types/com/atproto/lexicon/resolveLexicon.js +7 -0
  47. package/dist/lexicon/types/com/atproto/lexicon/resolveLexicon.js.map +1 -0
  48. package/dist/views/index.d.ts +2 -4
  49. package/dist/views/index.d.ts.map +1 -1
  50. package/dist/views/index.js +8 -14
  51. package/dist/views/index.js.map +1 -1
  52. package/dist/views/threads-v2.d.ts +0 -1
  53. package/dist/views/threads-v2.d.ts.map +1 -1
  54. package/dist/views/threads-v2.js +2 -4
  55. package/dist/views/threads-v2.js.map +1 -1
  56. package/package.json +5 -5
  57. package/src/api/app/bsky/feed/searchPosts.ts +51 -10
  58. package/src/api/app/bsky/unspecced/getPostThreadOtherV2.ts +1 -2
  59. package/src/api/app/bsky/unspecced/getPostThreadV2.ts +0 -1
  60. package/src/auth-verifier.ts +5 -0
  61. package/src/config.ts +8 -0
  62. package/src/data-plane/server/routes/search.ts +18 -1
  63. package/src/data-plane/server/util.ts +51 -0
  64. package/src/lexicon/index.ts +13 -0
  65. package/src/lexicon/lexicons.ts +56 -16
  66. package/src/lexicon/types/app/bsky/actor/defs.ts +0 -2
  67. package/src/lexicon/types/app/bsky/graph/follow.ts +2 -0
  68. package/src/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.ts +0 -2
  69. package/src/lexicon/types/app/bsky/unspecced/getPostThreadV2.ts +0 -2
  70. package/src/lexicon/types/com/atproto/lexicon/resolveLexicon.ts +46 -0
  71. package/src/views/index.ts +3 -23
  72. package/src/views/threads-v2.ts +2 -12
  73. package/tests/utils.test.ts +45 -0
  74. package/tests/views/post-search.test.ts +221 -0
  75. package/tests/views/thread-v2.test.ts +2 -109
  76. package/tsconfig.build.tsbuildinfo +1 -1
  77. package/tsconfig.tests.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atproto/bsky
2
2
 
3
+ ## 0.0.195
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4269](https://github.com/bluesky-social/atproto/pull/4269) [`39b5c08e0`](https://github.com/bluesky-social/atproto/commit/39b5c08e0799468eba0c3bf50f4f5a8104c35f34) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Deprecate and remove `prioritizeFollowedUsers` setting from preferences response types and `getPostThreadV2` query params.
8
+
9
+ - Updated dependencies [[`94ddc8219`](https://github.com/bluesky-social/atproto/commit/94ddc8219c144475df622137ab88895255136eda), [`756ab5d87`](https://github.com/bluesky-social/atproto/commit/756ab5d87fea75e8648a6bdd545d8b441bfb2dd6), [`39b5c08e0`](https://github.com/bluesky-social/atproto/commit/39b5c08e0799468eba0c3bf50f4f5a8104c35f34)]:
10
+ - @atproto/api@0.18.0
11
+ - @atproto/sync@0.1.36
12
+
13
+ ## 0.0.194
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies [[`15fe80c39`](https://github.com/bluesky-social/atproto/commit/15fe80c39ff428652dfaa6b30c0bdb59a145aac6)]:
18
+ - @atproto/api@0.17.7
19
+
3
20
  ## 0.0.193
4
21
 
5
22
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"searchPosts.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPosts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAIhD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAa5C,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAqBvD"}
1
+ {"version":3,"file":"searchPosts.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/feed/searchPosts.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAQhD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAa5C,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAyBvD"}
@@ -2,29 +2,33 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = default_1;
4
4
  const common_1 = require("@atproto/common");
5
- const util_1 = require("../../../../hydration/util");
5
+ const util_1 = require("../../../../data-plane/server/util");
6
+ const util_2 = require("../../../../hydration/util");
6
7
  const pipeline_1 = require("../../../../pipeline");
7
8
  const uris_1 = require("../../../../util/uris");
8
- const util_2 = require("../../../util");
9
+ const util_3 = require("../../../util");
9
10
  function default_1(server, ctx) {
10
- const searchPosts = (0, pipeline_1.createPipeline)(skeleton, hydration, noBlocks, presentation);
11
+ const searchPosts = (0, pipeline_1.createPipeline)(skeleton, hydration, noBlocksOrTagged, presentation);
11
12
  server.app.bsky.feed.searchPosts({
12
13
  auth: ctx.authVerifier.standardOptional,
13
14
  handler: async ({ auth, params, req }) => {
14
- const viewer = auth.credentials.iss;
15
+ const { viewer, isModService } = ctx.authVerifier.parseCreds(auth);
15
16
  const labelers = ctx.reqLabelers(req);
16
17
  const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer });
17
- const results = await searchPosts({ ...params, hydrateCtx }, ctx);
18
+ const results = await searchPosts({ ...params, hydrateCtx, isModService }, ctx);
18
19
  return {
19
20
  encoding: 'application/json',
20
21
  body: results,
21
- headers: (0, util_2.resHeaders)({ labelers: hydrateCtx.labelers }),
22
+ headers: (0, util_3.resHeaders)({ labelers: hydrateCtx.labelers }),
22
23
  };
23
24
  },
24
25
  });
25
26
  }
26
27
  const skeleton = async (inputs) => {
27
28
  const { ctx, params } = inputs;
29
+ const parsedQuery = (0, util_1.parsePostSearchQuery)(params.q, {
30
+ author: params.author,
31
+ });
28
32
  if (ctx.searchAgent) {
29
33
  // @NOTE cursors won't change on appview swap
30
34
  const { data: res } = await ctx.searchAgent.api.app.bsky.unspecced.searchPostsSkeleton({
@@ -44,7 +48,8 @@ const skeleton = async (inputs) => {
44
48
  });
45
49
  return {
46
50
  posts: res.posts.map(({ uri }) => uri),
47
- cursor: (0, util_1.parseString)(res.cursor),
51
+ cursor: (0, util_2.parseString)(res.cursor),
52
+ parsedQuery,
48
53
  };
49
54
  }
50
55
  const res = await ctx.dataplane.searchPosts({
@@ -54,24 +59,50 @@ const skeleton = async (inputs) => {
54
59
  });
55
60
  return {
56
61
  posts: res.uris,
57
- cursor: (0, util_1.parseString)(res.cursor),
62
+ cursor: (0, util_2.parseString)(res.cursor),
63
+ parsedQuery,
58
64
  };
59
65
  };
60
66
  const hydration = async (inputs) => {
61
67
  const { ctx, params, skeleton } = inputs;
62
68
  return ctx.hydrator.hydratePosts(skeleton.posts.map((uri) => ({ uri })), params.hydrateCtx);
63
69
  };
64
- const noBlocks = (inputs) => {
65
- const { ctx, skeleton, hydration } = inputs;
70
+ const noBlocksOrTagged = (inputs) => {
71
+ const { ctx, params, skeleton, hydration } = inputs;
72
+ const { parsedQuery } = skeleton;
66
73
  skeleton.posts = skeleton.posts.filter((uri) => {
74
+ const post = hydration.posts?.get(uri);
75
+ if (!post)
76
+ return;
67
77
  const creator = (0, uris_1.uriToDid)(uri);
68
- return !ctx.views.viewerBlockExists(creator, hydration);
78
+ const isCuratedSearch = params.sort === 'top';
79
+ const isPostByViewer = creator === params.hydrateCtx.viewer;
80
+ // Cases to always show.
81
+ if (isPostByViewer)
82
+ return true;
83
+ if (params.isModService)
84
+ return true;
85
+ // Cases to never show.
86
+ if (ctx.views.viewerBlockExists(creator, hydration))
87
+ return false;
88
+ // Cases to conditionally show based on tagging.
89
+ const tagged = [...ctx.cfg.searchTagsHide].some((t) => post.tags.has(t));
90
+ if (isCuratedSearch && tagged)
91
+ return false;
92
+ if (!parsedQuery.author && tagged)
93
+ return false;
94
+ return true;
69
95
  });
70
96
  return skeleton;
71
97
  };
72
98
  const presentation = (inputs) => {
73
99
  const { ctx, skeleton, hydration } = inputs;
74
- const posts = (0, common_1.mapDefined)(skeleton.posts, (uri) => ctx.views.post(uri, hydration));
100
+ const posts = (0, common_1.mapDefined)(skeleton.posts, (uri) => {
101
+ const post = hydration.posts?.get(uri);
102
+ if (!post)
103
+ return;
104
+ return ctx.views.post(uri, hydration);
105
+ });
75
106
  return {
76
107
  posts,
77
108
  cursor: skeleton.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 { AtpAgent } from '@atproto/api'\nimport { mapDefined } from '@atproto/common'\nimport { AppContext } from '../../../../context'\nimport { DataPlaneClient } from '../../../../data-plane'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { parseString } from '../../../../hydration/util'\nimport { Server } from '../../../../lexicon'\nimport { QueryParams } from '../../../../lexicon/types/app/bsky/feed/searchPosts'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n RulesFnInput,\n SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchPosts = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.app.bsky.feed.searchPosts({\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({ labelers, viewer })\n const results = await searchPosts({ ...params, hydrateCtx }, ctx)\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {\n const { ctx, params } = inputs\n\n if (ctx.searchAgent) {\n // @NOTE cursors won't change on appview swap\n const { data: res } =\n await ctx.searchAgent.api.app.bsky.unspecced.searchPostsSkeleton({\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 return {\n posts: res.posts.map(({ uri }) => uri),\n cursor: parseString(res.cursor),\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,\n cursor: parseString(res.cursor),\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 noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration } = inputs\n skeleton.posts = skeleton.posts.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 posts = mapDefined(skeleton.posts, (uri) =>\n ctx.views.post(uri, hydration),\n )\n return {\n posts,\n cursor: skeleton.cursor,\n hitsTotal: skeleton.hitsTotal,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchAgent?: AtpAgent\n}\n\ntype Params = QueryParams & { hydrateCtx: HydrateCtx }\n\ntype Skeleton = {\n posts: string[]\n hitsTotal?: number\n cursor?: string\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 { AtpAgent } from '@atproto/api'\nimport { mapDefined } from '@atproto/common'\nimport { ServerConfig } from '../../../../config'\nimport { AppContext } from '../../../../context'\nimport { DataPlaneClient } from '../../../../data-plane'\nimport {\n PostSearchQuery,\n parsePostSearchQuery,\n} from '../../../../data-plane/server/util'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { parseString } from '../../../../hydration/util'\nimport { Server } from '../../../../lexicon'\nimport { QueryParams } from '../../../../lexicon/types/app/bsky/feed/searchPosts'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n RulesFnInput,\n SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchPosts = createPipeline(\n skeleton,\n hydration,\n noBlocksOrTagged,\n presentation,\n )\n server.app.bsky.feed.searchPosts({\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, isModService } = ctx.authVerifier.parseCreds(auth)\n\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer })\n const results = await searchPosts(\n { ...params, hydrateCtx, isModService },\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 (inputs: SkeletonFnInput<Context, Params>) => {\n const { ctx, params } = inputs\n const parsedQuery = parsePostSearchQuery(params.q, {\n author: params.author,\n })\n\n if (ctx.searchAgent) {\n // @NOTE cursors won't change on appview swap\n const { data: res } =\n await ctx.searchAgent.api.app.bsky.unspecced.searchPostsSkeleton({\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 return {\n posts: res.posts.map(({ uri }) => uri),\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,\n cursor: parseString(res.cursor),\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 // 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 // Cases to conditionally show based on tagging.\n const tagged = [...ctx.cfg.searchTagsHide].some((t) => post.tags.has(t))\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 searchAgent?: AtpAgent\n}\n\ntype Params = QueryParams & {\n hydrateCtx: HydrateCtx\n isModService: boolean\n}\n\ntype Skeleton = {\n posts: string[]\n hitsTotal?: number\n cursor?: string\n parsedQuery: PostSearchQuery\n}\n"]}
@@ -66,11 +66,10 @@ const hydration = async (inputs) => {
66
66
  return ctx.hydrator.hydrateThreadPosts(skeleton.uris.map((uri) => ({ uri })), params.hydrateCtx);
67
67
  };
68
68
  const presentation = (inputs) => {
69
- const { ctx, params, skeleton, hydration } = inputs;
69
+ const { ctx, skeleton, hydration } = inputs;
70
70
  const thread = ctx.views.threadOtherV2(skeleton, hydration, {
71
71
  below: BELOW,
72
72
  branchingFactor: BRANCHING_FACTOR,
73
- prioritizeFollowedUsers: params.prioritizeFollowedUsers,
74
73
  });
75
74
  return { thread };
76
75
  };
@@ -1 +1 @@
1
- {"version":3,"file":"getPostThreadOtherV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPostThreadOtherV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { ServerConfig } from '../../../../config'\nimport { AppContext } from '../../../../context'\nimport { Code, DataPlaneClient, isDataplaneError } from '../../../../data-plane'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { Server } from '../../../../lexicon'\nimport { QueryParams } from '../../../../lexicon/types/app/bsky/unspecced/getPostThreadOtherV2'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n SkeletonFnInput,\n createPipeline,\n noRules,\n} from '../../../../pipeline'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\n// No parents for hidden replies (it would be the anchor post).\nconst ABOVE = 0\n\n// For hidden replies we don't get more than the top-level replies.\n// To get nested replies, load the thread as one of the hidden replies as anchor.\nconst BELOW = 1\n\n// It doesn't really matter since BELOW is 1, so it will not be used.\nconst BRANCHING_FACTOR = 0\n\nexport default function (server: Server, ctx: AppContext) {\n const getPostThreadOther = createPipeline(\n skeleton,\n hydration,\n noRules, // handled in presentation: 3p block-violating replies are turned to #blockedPost, viewer blocks turned to #notFoundPost.\n presentation,\n )\n server.app.bsky.unspecced.getPostThreadOtherV2({\n auth: ctx.authVerifier.optionalStandardOrRole,\n handler: async ({ params, auth, req }) => {\n const { viewer, includeTakedowns, include3pBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n includeTakedowns,\n include3pBlocks,\n })\n\n return {\n encoding: 'application/json',\n body: await getPostThreadOther({ ...params, hydrateCtx }, ctx),\n headers: resHeaders({\n labelers: hydrateCtx.labelers,\n }),\n }\n },\n })\n}\n\nconst skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {\n const { ctx, params } = inputs\n const anchor = await ctx.hydrator.resolveUri(params.anchor)\n try {\n const res = await ctx.dataplane.getThread({\n postUri: anchor,\n above: ABOVE,\n below: BELOW,\n })\n return {\n anchor,\n uris: res.uris,\n }\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n return {\n anchor,\n uris: [],\n }\n } else {\n throw err\n }\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateThreadPosts(\n skeleton.uris.map((uri) => ({ uri })),\n params.hydrateCtx,\n )\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton, hydration } = inputs\n const thread = ctx.views.threadOtherV2(skeleton, hydration, {\n below: BELOW,\n branchingFactor: BRANCHING_FACTOR,\n prioritizeFollowedUsers: params.prioritizeFollowedUsers,\n })\n return { thread }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n cfg: ServerConfig\n}\n\ntype Params = QueryParams & { hydrateCtx: HydrateCtx }\n\ntype Skeleton = {\n anchor: string\n uris: string[]\n}\n"]}
1
+ {"version":3,"file":"getPostThreadOtherV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPostThreadOtherV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { ServerConfig } from '../../../../config'\nimport { AppContext } from '../../../../context'\nimport { Code, DataPlaneClient, isDataplaneError } from '../../../../data-plane'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { Server } from '../../../../lexicon'\nimport { QueryParams } from '../../../../lexicon/types/app/bsky/unspecced/getPostThreadOtherV2'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n SkeletonFnInput,\n createPipeline,\n noRules,\n} from '../../../../pipeline'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\n// No parents for hidden replies (it would be the anchor post).\nconst ABOVE = 0\n\n// For hidden replies we don't get more than the top-level replies.\n// To get nested replies, load the thread as one of the hidden replies as anchor.\nconst BELOW = 1\n\n// It doesn't really matter since BELOW is 1, so it will not be used.\nconst BRANCHING_FACTOR = 0\n\nexport default function (server: Server, ctx: AppContext) {\n const getPostThreadOther = createPipeline(\n skeleton,\n hydration,\n noRules, // handled in presentation: 3p block-violating replies are turned to #blockedPost, viewer blocks turned to #notFoundPost.\n presentation,\n )\n server.app.bsky.unspecced.getPostThreadOtherV2({\n auth: ctx.authVerifier.optionalStandardOrRole,\n handler: async ({ params, auth, req }) => {\n const { viewer, includeTakedowns, include3pBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n includeTakedowns,\n include3pBlocks,\n })\n\n return {\n encoding: 'application/json',\n body: await getPostThreadOther({ ...params, hydrateCtx }, ctx),\n headers: resHeaders({\n labelers: hydrateCtx.labelers,\n }),\n }\n },\n })\n}\n\nconst skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {\n const { ctx, params } = inputs\n const anchor = await ctx.hydrator.resolveUri(params.anchor)\n try {\n const res = await ctx.dataplane.getThread({\n postUri: anchor,\n above: ABOVE,\n below: BELOW,\n })\n return {\n anchor,\n uris: res.uris,\n }\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n return {\n anchor,\n uris: [],\n }\n } else {\n throw err\n }\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateThreadPosts(\n skeleton.uris.map((uri) => ({ uri })),\n params.hydrateCtx,\n )\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const thread = ctx.views.threadOtherV2(skeleton, hydration, {\n below: BELOW,\n branchingFactor: BRANCHING_FACTOR,\n })\n return { thread }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n cfg: ServerConfig\n}\n\ntype Params = QueryParams & { hydrateCtx: HydrateCtx }\n\ntype Skeleton = {\n anchor: string\n uris: string[]\n}\n"]}
@@ -65,7 +65,6 @@ const presentation = (inputs) => {
65
65
  above: calculateAbove(ctx, params),
66
66
  below: calculateBelow(ctx, skeleton.anchor, params),
67
67
  branchingFactor: params.branchingFactor,
68
- prioritizeFollowedUsers: params.prioritizeFollowedUsers,
69
68
  sort: params.sort,
70
69
  });
71
70
  const rootUri = hydration.posts?.get(skeleton.anchor)?.record.reply?.root.uri ??
@@ -1 +1 @@
1
- {"version":3,"file":"getPostThreadV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPostThreadV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { ServerConfig } from '../../../../config'\nimport { AppContext } from '../../../../context'\nimport { Code, DataPlaneClient, isDataplaneError } from '../../../../data-plane'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { Server } from '../../../../lexicon'\nimport { QueryParams } from '../../../../lexicon/types/app/bsky/unspecced/getPostThreadV2'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n SkeletonFnInput,\n createPipeline,\n noRules,\n} from '../../../../pipeline'\nimport { postUriToThreadgateUri } from '../../../../util/uris'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\nexport default function (server: Server, ctx: AppContext) {\n const getPostThread = createPipeline(\n skeleton,\n hydration,\n noRules, // handled in presentation: 3p block-violating replies are turned to #blockedPost, viewer blocks turned to #notFoundPost.\n presentation,\n )\n server.app.bsky.unspecced.getPostThreadV2({\n auth: ctx.authVerifier.optionalStandardOrRole,\n handler: async ({ params, auth, req }) => {\n const { viewer, includeTakedowns, include3pBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n includeTakedowns,\n include3pBlocks,\n })\n\n return {\n encoding: 'application/json',\n body: await getPostThread({ ...params, hydrateCtx }, ctx),\n headers: resHeaders({\n labelers: hydrateCtx.labelers,\n }),\n }\n },\n })\n}\n\nconst skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {\n const { ctx, params } = inputs\n const anchor = await ctx.hydrator.resolveUri(params.anchor)\n try {\n const res = await ctx.dataplane.getThread({\n postUri: anchor,\n above: calculateAbove(ctx, params),\n below: calculateBelow(ctx, anchor, params),\n })\n return {\n anchor,\n uris: res.uris,\n }\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n return {\n anchor,\n uris: [],\n }\n } else {\n throw err\n }\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateThreadPosts(\n skeleton.uris.map((uri) => ({ uri })),\n params.hydrateCtx,\n )\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton, hydration } = inputs\n const { hasOtherReplies, thread } = ctx.views.threadV2(skeleton, hydration, {\n above: calculateAbove(ctx, params),\n below: calculateBelow(ctx, skeleton.anchor, params),\n branchingFactor: params.branchingFactor,\n prioritizeFollowedUsers: params.prioritizeFollowedUsers,\n sort: params.sort,\n })\n\n const rootUri =\n hydration.posts?.get(skeleton.anchor)?.record.reply?.root.uri ??\n skeleton.anchor\n const threadgate = ctx.views.threadgate(\n postUriToThreadgateUri(rootUri),\n hydration,\n )\n return { hasOtherReplies, thread, threadgate }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n cfg: ServerConfig\n}\n\ntype Params = QueryParams & { hydrateCtx: HydrateCtx }\n\ntype Skeleton = {\n anchor: string\n uris: string[]\n}\n\nconst calculateAbove = (ctx: Context, params: Params) => {\n return params.above ? ctx.cfg.maxThreadParents : 0\n}\n\nconst calculateBelow = (ctx: Context, anchor: string, params: Params) => {\n let maxDepth = ctx.cfg.maxThreadDepth\n if (ctx.cfg.bigThreadUris.has(anchor) && ctx.cfg.bigThreadDepth) {\n maxDepth = ctx.cfg.bigThreadDepth\n }\n return maxDepth ? Math.min(maxDepth, params.below) : params.below\n}\n"]}
1
+ {"version":3,"file":"getPostThreadV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPostThreadV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { ServerConfig } from '../../../../config'\nimport { AppContext } from '../../../../context'\nimport { Code, DataPlaneClient, isDataplaneError } from '../../../../data-plane'\nimport { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'\nimport { Server } from '../../../../lexicon'\nimport { QueryParams } from '../../../../lexicon/types/app/bsky/unspecced/getPostThreadV2'\nimport {\n HydrationFnInput,\n PresentationFnInput,\n SkeletonFnInput,\n createPipeline,\n noRules,\n} from '../../../../pipeline'\nimport { postUriToThreadgateUri } from '../../../../util/uris'\nimport { Views } from '../../../../views'\nimport { resHeaders } from '../../../util'\n\nexport default function (server: Server, ctx: AppContext) {\n const getPostThread = createPipeline(\n skeleton,\n hydration,\n noRules, // handled in presentation: 3p block-violating replies are turned to #blockedPost, viewer blocks turned to #notFoundPost.\n presentation,\n )\n server.app.bsky.unspecced.getPostThreadV2({\n auth: ctx.authVerifier.optionalStandardOrRole,\n handler: async ({ params, auth, req }) => {\n const { viewer, includeTakedowns, include3pBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n includeTakedowns,\n include3pBlocks,\n })\n\n return {\n encoding: 'application/json',\n body: await getPostThread({ ...params, hydrateCtx }, ctx),\n headers: resHeaders({\n labelers: hydrateCtx.labelers,\n }),\n }\n },\n })\n}\n\nconst skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {\n const { ctx, params } = inputs\n const anchor = await ctx.hydrator.resolveUri(params.anchor)\n try {\n const res = await ctx.dataplane.getThread({\n postUri: anchor,\n above: calculateAbove(ctx, params),\n below: calculateBelow(ctx, anchor, params),\n })\n return {\n anchor,\n uris: res.uris,\n }\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n return {\n anchor,\n uris: [],\n }\n } else {\n throw err\n }\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateThreadPosts(\n skeleton.uris.map((uri) => ({ uri })),\n params.hydrateCtx,\n )\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton, hydration } = inputs\n const { hasOtherReplies, thread } = ctx.views.threadV2(skeleton, hydration, {\n above: calculateAbove(ctx, params),\n below: calculateBelow(ctx, skeleton.anchor, params),\n branchingFactor: params.branchingFactor,\n sort: params.sort,\n })\n\n const rootUri =\n hydration.posts?.get(skeleton.anchor)?.record.reply?.root.uri ??\n skeleton.anchor\n const threadgate = ctx.views.threadgate(\n postUriToThreadgateUri(rootUri),\n hydration,\n )\n return { hasOtherReplies, thread, threadgate }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n cfg: ServerConfig\n}\n\ntype Params = QueryParams & { hydrateCtx: HydrateCtx }\n\ntype Skeleton = {\n anchor: string\n uris: string[]\n}\n\nconst calculateAbove = (ctx: Context, params: Params) => {\n return params.above ? ctx.cfg.maxThreadParents : 0\n}\n\nconst calculateBelow = (ctx: Context, anchor: string, params: Params) => {\n let maxDepth = ctx.cfg.maxThreadDepth\n if (ctx.cfg.bigThreadUris.has(anchor) && ctx.cfg.bigThreadDepth) {\n maxDepth = ctx.cfg.bigThreadDepth\n }\n return maxDepth ? Math.min(maxDepth, params.below) : params.below\n}\n"]}
@@ -90,6 +90,7 @@ export declare class AuthVerifier {
90
90
  includeTakedowns: boolean;
91
91
  include3pBlocks: boolean;
92
92
  canPerformTakedown: boolean;
93
+ isModService: boolean;
93
94
  };
94
95
  }
95
96
  export declare const parseBasicAuth: (token: string) => {
@@ -1 +1 @@
1
- {"version":3,"file":"auth-verifier.d.ts","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-verifier.d.ts","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"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"}
@@ -380,11 +380,15 @@ class AuthVerifier {
380
380
  this.isModService(creds.credentials.iss));
381
381
  const canPerformTakedown = (creds.credentials.type === 'role' && creds.credentials.admin) ||
382
382
  creds.credentials.type === 'mod_service';
383
+ const isModService = creds.credentials.type === 'mod_service' ||
384
+ (creds.credentials.type === 'standard' &&
385
+ this.isModService(creds.credentials.iss));
383
386
  return {
384
387
  viewer,
385
388
  includeTakedowns: includeTakedownsAnd3pBlocks,
386
389
  include3pBlocks: includeTakedownsAnd3pBlocks,
387
390
  canPerformTakedown,
391
+ isModService,
388
392
  };
389
393
  }
390
394
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth-verifier.js","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto, { KeyObject } from 'node:crypto'\nimport express from 'express'\nimport * as jose from 'jose'\nimport KeyEncoder from 'key-encoder'\nimport * as ui8 from 'uint8arrays'\nimport { SECP256K1_JWT_ALG, parseDidKey } from '@atproto/crypto'\nimport {\n AuthRequiredError,\n VerifySignatureWithKeyFn,\n cryptoVerifySignatureWithKey,\n parseReqNsid,\n verifyJwt as verifyServiceJwt,\n} from '@atproto/xrpc-server'\nimport {\n Code,\n DataPlaneClient,\n getKeyAsDidKey,\n isDataplaneError,\n unpackIdentityKeys,\n} from './data-plane'\nimport { GetIdentityByDidResponse } from './proto/bsky_pb'\n\ntype ReqCtx = {\n req: express.Request\n}\n\ntype StandardAuthOpts = {\n skipAudCheck?: boolean\n lxmCheck?: (method?: string) => boolean\n}\n\nexport enum RoleStatus {\n Valid,\n Invalid,\n Missing,\n}\n\ntype NullOutput = {\n credentials: {\n type: 'none'\n iss: null\n }\n}\n\ntype StandardOutput = {\n credentials: {\n type: 'standard'\n aud: string\n iss: string\n }\n}\n\ntype RoleOutput = {\n credentials: {\n type: 'role'\n admin: boolean\n }\n}\n\ntype ModServiceOutput = {\n credentials: {\n type: 'mod_service'\n aud: string\n iss: string\n }\n}\n\nconst ALLOWED_AUTH_SCOPES = new Set([\n 'com.atproto.access',\n 'com.atproto.appPass',\n 'com.atproto.appPassPrivileged',\n])\n\nexport type AuthVerifierOpts = {\n ownDid: string\n alternateAudienceDids: string[]\n modServiceDid: string\n adminPasses: string[]\n entrywayJwtPublicKey?: KeyObject\n}\n\nexport class AuthVerifier {\n public ownDid: string\n public standardAudienceDids: Set<string>\n public modServiceDid: string\n private adminPasses: Set<string>\n private entrywayJwtPublicKey?: KeyObject\n\n constructor(\n public dataplane: DataPlaneClient,\n opts: AuthVerifierOpts,\n ) {\n this.ownDid = opts.ownDid\n this.standardAudienceDids = new Set([\n opts.ownDid,\n ...opts.alternateAudienceDids,\n ])\n this.modServiceDid = opts.modServiceDid\n this.adminPasses = new Set(opts.adminPasses)\n this.entrywayJwtPublicKey = opts.entrywayJwtPublicKey\n }\n\n // verifiers (arrow fns to preserve scope)\n standardOptionalParameterized =\n (opts: StandardAuthOpts) =>\n async (ctx: ReqCtx): Promise<StandardOutput | NullOutput> => {\n // @TODO remove! basic auth + did supported just for testing.\n if (isBasicToken(ctx.req)) {\n const aud = this.ownDid\n const iss = ctx.req.headers['appview-as-did']\n if (typeof iss !== 'string' || !iss.startsWith('did:')) {\n throw new AuthRequiredError('bad issuer')\n }\n if (!this.parseRoleCreds(ctx.req).admin) {\n throw new AuthRequiredError('bad credentials')\n }\n return {\n credentials: { type: 'standard', iss, aud },\n }\n } else if (isBearerToken(ctx.req)) {\n // @NOTE temporarily accept entryway session tokens to shed load from PDS instances\n const token = bearerTokenFromReq(ctx.req)\n const header = token ? jose.decodeProtectedHeader(token) : undefined\n if (header?.typ === 'at+jwt') {\n // we should never use entryway session tokens in the case of flexible auth audiences (namely in the case of getFeed)\n if (opts.skipAudCheck) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n return this.entrywaySession(ctx)\n }\n\n const { iss, aud } = await this.verifyServiceJwt(ctx, {\n lxmCheck: opts.lxmCheck,\n iss: null,\n aud: null,\n })\n if (!opts.skipAudCheck && !this.standardAudienceDids.has(aud)) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n return {\n credentials: {\n type: 'standard',\n iss,\n aud,\n },\n }\n } else {\n return this.nullCreds()\n }\n }\n\n standardOptional: (ctx: ReqCtx) => Promise<StandardOutput | NullOutput> =\n this.standardOptionalParameterized({})\n\n standard = async (ctx: ReqCtx): Promise<StandardOutput> => {\n const output = await this.standardOptional(ctx)\n if (output.credentials.type === 'none') {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n return output as StandardOutput\n }\n\n role = (ctx: ReqCtx): RoleOutput => {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status !== RoleStatus.Valid) {\n throw new AuthRequiredError()\n }\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n }\n\n standardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput> => {\n if (isBearerToken(ctx.req)) {\n return this.standard(ctx)\n } else {\n return this.role(ctx)\n }\n }\n\n optionalStandardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput | NullOutput> => {\n if (isBearerToken(ctx.req)) {\n return await this.standard(ctx)\n } else {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status === RoleStatus.Valid) {\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n } else if (creds.status === RoleStatus.Missing) {\n return this.nullCreds()\n } else {\n throw new AuthRequiredError()\n }\n }\n }\n\n // @NOTE this auth verifier method is not recommended to be implemented by most appviews\n // this is a short term fix to remove proxy load from Bluesky's PDS and in line with possible\n // future plans to have the client talk directly with the appview\n entrywaySession = async (reqCtx: ReqCtx): Promise<StandardOutput> => {\n const token = bearerTokenFromReq(reqCtx.req)\n if (!token) {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n\n // if entryway jwt key not configured then do not parsed these tokens\n if (!this.entrywayJwtPublicKey) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n\n const res = await jose\n .jwtVerify(token, this.entrywayJwtPublicKey)\n .catch((err) => {\n if (err?.['code'] === 'ERR_JWT_EXPIRED') {\n throw new AuthRequiredError('Token has expired', 'ExpiredToken')\n }\n throw new AuthRequiredError(\n 'Token could not be verified',\n 'InvalidToken',\n )\n })\n\n const { sub, aud, scope } = res.payload\n if (typeof sub !== 'string' || !sub.startsWith('did:')) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n } else if (\n typeof aud !== 'string' ||\n !aud.startsWith('did:web:') ||\n !aud.endsWith('.bsky.network')\n ) {\n throw new AuthRequiredError('Bad token aud', 'InvalidToken')\n } else if (typeof scope !== 'string' || !ALLOWED_AUTH_SCOPES.has(scope)) {\n throw new AuthRequiredError('Bad token scope', 'InvalidToken')\n }\n\n return {\n credentials: {\n type: 'standard',\n aud: this.ownDid,\n iss: sub,\n },\n }\n }\n\n modService = async (reqCtx: ReqCtx): Promise<ModServiceOutput> => {\n const { iss, aud } = await this.verifyServiceJwt(reqCtx, {\n aud: this.ownDid,\n iss: [this.modServiceDid, `${this.modServiceDid}#atproto_labeler`],\n })\n return { credentials: { type: 'mod_service', aud, iss } }\n }\n\n roleOrModService = async (\n reqCtx: ReqCtx,\n ): Promise<RoleOutput | ModServiceOutput> => {\n if (isBearerToken(reqCtx.req)) {\n return this.modService(reqCtx)\n } else {\n return this.role(reqCtx)\n }\n }\n\n parseRoleCreds(req: express.Request) {\n const parsed = parseBasicAuth(req.headers.authorization || '')\n const { Missing, Valid, Invalid } = RoleStatus\n if (!parsed) {\n return { status: Missing, admin: false, moderator: false, triage: false }\n }\n const { username, password } = parsed\n if (username === 'admin' && this.adminPasses.has(password)) {\n return { status: Valid, admin: true }\n }\n return { status: Invalid, admin: false }\n }\n\n async verifyServiceJwt(\n reqCtx: ReqCtx,\n opts: {\n iss: string[] | null\n aud: string | null\n lxmCheck?: (method?: string) => boolean\n },\n ) {\n const getSigningKey = async (\n iss: string,\n _forceRefresh: boolean, // @TODO consider propagating to dataplane\n ): Promise<string> => {\n if (opts.iss !== null && !opts.iss.includes(iss)) {\n throw new AuthRequiredError('Untrusted issuer', 'UntrustedIss')\n }\n const [did, serviceId] = iss.split('#')\n const keyId =\n serviceId === 'atproto_labeler' ? 'atproto_label' : 'atproto'\n let identity: GetIdentityByDidResponse\n try {\n identity = await this.dataplane.getIdentityByDid({ did })\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n throw new AuthRequiredError('identity unknown')\n }\n throw err\n }\n const keys = unpackIdentityKeys(identity.keys)\n const didKey = getKeyAsDidKey(keys, { id: keyId })\n if (!didKey) {\n throw new AuthRequiredError('missing or bad key')\n }\n return didKey\n }\n const assertLxmCheck = () => {\n const lxm = parseReqNsid(reqCtx.req)\n if (\n (opts.lxmCheck && !opts.lxmCheck(payload.lxm)) ||\n (!opts.lxmCheck && payload.lxm !== lxm)\n ) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n }\n\n const jwtStr = bearerTokenFromReq(reqCtx.req)\n if (!jwtStr) {\n throw new AuthRequiredError('missing jwt', 'MissingJwt')\n }\n // if validating additional scopes, skip scope check in initial validation & follow up afterwards\n const payload = await verifyServiceJwt(\n jwtStr,\n opts.aud,\n null,\n getSigningKey,\n verifySignatureWithKey,\n )\n if (\n !payload.iss.endsWith('#atproto_labeler') ||\n payload.lxm !== undefined\n ) {\n // @TODO currently permissive of labelers who dont set lxm yet.\n // we'll allow ozone self-hosters to upgrade before removing this condition.\n assertLxmCheck()\n }\n return { iss: payload.iss, aud: payload.aud }\n }\n\n isModService(iss: string): boolean {\n return [\n this.modServiceDid,\n `${this.modServiceDid}#atproto_labeler`,\n ].includes(iss)\n }\n\n nullCreds(): NullOutput {\n return {\n credentials: {\n type: 'none',\n iss: null,\n },\n }\n }\n\n parseCreds(\n creds: StandardOutput | RoleOutput | ModServiceOutput | NullOutput,\n ) {\n const viewer =\n creds.credentials.type === 'standard' ? creds.credentials.iss : null\n const includeTakedownsAnd3pBlocks =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service' ||\n (creds.credentials.type === 'standard' &&\n this.isModService(creds.credentials.iss))\n const canPerformTakedown =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service'\n\n return {\n viewer,\n includeTakedowns: includeTakedownsAnd3pBlocks,\n include3pBlocks: includeTakedownsAnd3pBlocks,\n canPerformTakedown,\n }\n }\n}\n\n// HELPERS\n// ---------\n\nconst BEARER = 'Bearer '\nconst BASIC = 'Basic '\n\nconst isBearerToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BEARER) ?? false\n}\n\nconst isBasicToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BASIC) ?? false\n}\n\nconst bearerTokenFromReq = (req: express.Request) => {\n const header = req.headers.authorization || ''\n if (!header.startsWith(BEARER)) return null\n return header.slice(BEARER.length).trim()\n}\n\nexport const parseBasicAuth = (\n token: string,\n): { username: string; password: string } | null => {\n if (!token.startsWith(BASIC)) return null\n const b64 = token.slice(BASIC.length)\n let parsed: string[]\n try {\n parsed = ui8.toString(ui8.fromString(b64, 'base64pad'), 'utf8').split(':')\n } catch (err) {\n return null\n }\n const [username, password] = parsed\n if (!username || !password) return null\n return { username, password }\n}\n\nexport const buildBasicAuth = (username: string, password: string): string => {\n return (\n BASIC +\n ui8.toString(ui8.fromString(`${username}:${password}`, 'utf8'), 'base64pad')\n )\n}\n\nconst keyEncoder = new KeyEncoder('secp256k1')\nexport const createPublicKeyObject = (publicKeyHex: string): KeyObject => {\n const key = keyEncoder.encodePublic(publicKeyHex, 'raw', 'pem')\n return crypto.createPublicKey({ format: 'pem', key })\n}\n\nconst verifySig = (\n publicKey: Uint8Array,\n data: Uint8Array,\n sig: Uint8Array,\n) => {\n const keyEncoder = new KeyEncoder('secp256k1')\n\n const pemKey = keyEncoder.encodePublic(\n ui8.toString(publicKey, 'hex'),\n 'raw',\n 'pem',\n )\n const key = crypto.createPublicKey({ format: 'pem', key: pemKey })\n\n return crypto.verify(\n 'sha256',\n data,\n {\n key,\n dsaEncoding: 'ieee-p1363',\n },\n sig,\n )\n}\n\nexport const verifySignatureWithKey: VerifySignatureWithKeyFn = async (\n didKey: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n if (alg === SECP256K1_JWT_ALG) {\n const parsed = parseDidKey(didKey)\n if (alg !== parsed.jwtAlg) {\n throw new Error(`Expected key alg ${alg}, got ${parsed.jwtAlg}`)\n }\n\n return verifySig(parsed.keyBytes, msgBytes, sigBytes)\n }\n\n return cryptoVerifySignatureWithKey(didKey, msgBytes, sigBytes, alg)\n}\n"]}
1
+ {"version":3,"file":"auth-verifier.js","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto, { KeyObject } from 'node:crypto'\nimport express from 'express'\nimport * as jose from 'jose'\nimport KeyEncoder from 'key-encoder'\nimport * as ui8 from 'uint8arrays'\nimport { SECP256K1_JWT_ALG, parseDidKey } from '@atproto/crypto'\nimport {\n AuthRequiredError,\n VerifySignatureWithKeyFn,\n cryptoVerifySignatureWithKey,\n parseReqNsid,\n verifyJwt as verifyServiceJwt,\n} from '@atproto/xrpc-server'\nimport {\n Code,\n DataPlaneClient,\n getKeyAsDidKey,\n isDataplaneError,\n unpackIdentityKeys,\n} from './data-plane'\nimport { GetIdentityByDidResponse } from './proto/bsky_pb'\n\ntype ReqCtx = {\n req: express.Request\n}\n\ntype StandardAuthOpts = {\n skipAudCheck?: boolean\n lxmCheck?: (method?: string) => boolean\n}\n\nexport enum RoleStatus {\n Valid,\n Invalid,\n Missing,\n}\n\ntype NullOutput = {\n credentials: {\n type: 'none'\n iss: null\n }\n}\n\ntype StandardOutput = {\n credentials: {\n type: 'standard'\n aud: string\n iss: string\n }\n}\n\ntype RoleOutput = {\n credentials: {\n type: 'role'\n admin: boolean\n }\n}\n\ntype ModServiceOutput = {\n credentials: {\n type: 'mod_service'\n aud: string\n iss: string\n }\n}\n\nconst ALLOWED_AUTH_SCOPES = new Set([\n 'com.atproto.access',\n 'com.atproto.appPass',\n 'com.atproto.appPassPrivileged',\n])\n\nexport type AuthVerifierOpts = {\n ownDid: string\n alternateAudienceDids: string[]\n modServiceDid: string\n adminPasses: string[]\n entrywayJwtPublicKey?: KeyObject\n}\n\nexport class AuthVerifier {\n public ownDid: string\n public standardAudienceDids: Set<string>\n public modServiceDid: string\n private adminPasses: Set<string>\n private entrywayJwtPublicKey?: KeyObject\n\n constructor(\n public dataplane: DataPlaneClient,\n opts: AuthVerifierOpts,\n ) {\n this.ownDid = opts.ownDid\n this.standardAudienceDids = new Set([\n opts.ownDid,\n ...opts.alternateAudienceDids,\n ])\n this.modServiceDid = opts.modServiceDid\n this.adminPasses = new Set(opts.adminPasses)\n this.entrywayJwtPublicKey = opts.entrywayJwtPublicKey\n }\n\n // verifiers (arrow fns to preserve scope)\n standardOptionalParameterized =\n (opts: StandardAuthOpts) =>\n async (ctx: ReqCtx): Promise<StandardOutput | NullOutput> => {\n // @TODO remove! basic auth + did supported just for testing.\n if (isBasicToken(ctx.req)) {\n const aud = this.ownDid\n const iss = ctx.req.headers['appview-as-did']\n if (typeof iss !== 'string' || !iss.startsWith('did:')) {\n throw new AuthRequiredError('bad issuer')\n }\n if (!this.parseRoleCreds(ctx.req).admin) {\n throw new AuthRequiredError('bad credentials')\n }\n return {\n credentials: { type: 'standard', iss, aud },\n }\n } else if (isBearerToken(ctx.req)) {\n // @NOTE temporarily accept entryway session tokens to shed load from PDS instances\n const token = bearerTokenFromReq(ctx.req)\n const header = token ? jose.decodeProtectedHeader(token) : undefined\n if (header?.typ === 'at+jwt') {\n // we should never use entryway session tokens in the case of flexible auth audiences (namely in the case of getFeed)\n if (opts.skipAudCheck) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n return this.entrywaySession(ctx)\n }\n\n const { iss, aud } = await this.verifyServiceJwt(ctx, {\n lxmCheck: opts.lxmCheck,\n iss: null,\n aud: null,\n })\n if (!opts.skipAudCheck && !this.standardAudienceDids.has(aud)) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n return {\n credentials: {\n type: 'standard',\n iss,\n aud,\n },\n }\n } else {\n return this.nullCreds()\n }\n }\n\n standardOptional: (ctx: ReqCtx) => Promise<StandardOutput | NullOutput> =\n this.standardOptionalParameterized({})\n\n standard = async (ctx: ReqCtx): Promise<StandardOutput> => {\n const output = await this.standardOptional(ctx)\n if (output.credentials.type === 'none') {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n return output as StandardOutput\n }\n\n role = (ctx: ReqCtx): RoleOutput => {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status !== RoleStatus.Valid) {\n throw new AuthRequiredError()\n }\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n }\n\n standardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput> => {\n if (isBearerToken(ctx.req)) {\n return this.standard(ctx)\n } else {\n return this.role(ctx)\n }\n }\n\n optionalStandardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput | NullOutput> => {\n if (isBearerToken(ctx.req)) {\n return await this.standard(ctx)\n } else {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status === RoleStatus.Valid) {\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n } else if (creds.status === RoleStatus.Missing) {\n return this.nullCreds()\n } else {\n throw new AuthRequiredError()\n }\n }\n }\n\n // @NOTE this auth verifier method is not recommended to be implemented by most appviews\n // this is a short term fix to remove proxy load from Bluesky's PDS and in line with possible\n // future plans to have the client talk directly with the appview\n entrywaySession = async (reqCtx: ReqCtx): Promise<StandardOutput> => {\n const token = bearerTokenFromReq(reqCtx.req)\n if (!token) {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n\n // if entryway jwt key not configured then do not parsed these tokens\n if (!this.entrywayJwtPublicKey) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n\n const res = await jose\n .jwtVerify(token, this.entrywayJwtPublicKey)\n .catch((err) => {\n if (err?.['code'] === 'ERR_JWT_EXPIRED') {\n throw new AuthRequiredError('Token has expired', 'ExpiredToken')\n }\n throw new AuthRequiredError(\n 'Token could not be verified',\n 'InvalidToken',\n )\n })\n\n const { sub, aud, scope } = res.payload\n if (typeof sub !== 'string' || !sub.startsWith('did:')) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n } else if (\n typeof aud !== 'string' ||\n !aud.startsWith('did:web:') ||\n !aud.endsWith('.bsky.network')\n ) {\n throw new AuthRequiredError('Bad token aud', 'InvalidToken')\n } else if (typeof scope !== 'string' || !ALLOWED_AUTH_SCOPES.has(scope)) {\n throw new AuthRequiredError('Bad token scope', 'InvalidToken')\n }\n\n return {\n credentials: {\n type: 'standard',\n aud: this.ownDid,\n iss: sub,\n },\n }\n }\n\n modService = async (reqCtx: ReqCtx): Promise<ModServiceOutput> => {\n const { iss, aud } = await this.verifyServiceJwt(reqCtx, {\n aud: this.ownDid,\n iss: [this.modServiceDid, `${this.modServiceDid}#atproto_labeler`],\n })\n return { credentials: { type: 'mod_service', aud, iss } }\n }\n\n roleOrModService = async (\n reqCtx: ReqCtx,\n ): Promise<RoleOutput | ModServiceOutput> => {\n if (isBearerToken(reqCtx.req)) {\n return this.modService(reqCtx)\n } else {\n return this.role(reqCtx)\n }\n }\n\n parseRoleCreds(req: express.Request) {\n const parsed = parseBasicAuth(req.headers.authorization || '')\n const { Missing, Valid, Invalid } = RoleStatus\n if (!parsed) {\n return { status: Missing, admin: false, moderator: false, triage: false }\n }\n const { username, password } = parsed\n if (username === 'admin' && this.adminPasses.has(password)) {\n return { status: Valid, admin: true }\n }\n return { status: Invalid, admin: false }\n }\n\n async verifyServiceJwt(\n reqCtx: ReqCtx,\n opts: {\n iss: string[] | null\n aud: string | null\n lxmCheck?: (method?: string) => boolean\n },\n ) {\n const getSigningKey = async (\n iss: string,\n _forceRefresh: boolean, // @TODO consider propagating to dataplane\n ): Promise<string> => {\n if (opts.iss !== null && !opts.iss.includes(iss)) {\n throw new AuthRequiredError('Untrusted issuer', 'UntrustedIss')\n }\n const [did, serviceId] = iss.split('#')\n const keyId =\n serviceId === 'atproto_labeler' ? 'atproto_label' : 'atproto'\n let identity: GetIdentityByDidResponse\n try {\n identity = await this.dataplane.getIdentityByDid({ did })\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n throw new AuthRequiredError('identity unknown')\n }\n throw err\n }\n const keys = unpackIdentityKeys(identity.keys)\n const didKey = getKeyAsDidKey(keys, { id: keyId })\n if (!didKey) {\n throw new AuthRequiredError('missing or bad key')\n }\n return didKey\n }\n const assertLxmCheck = () => {\n const lxm = parseReqNsid(reqCtx.req)\n if (\n (opts.lxmCheck && !opts.lxmCheck(payload.lxm)) ||\n (!opts.lxmCheck && payload.lxm !== lxm)\n ) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n }\n\n const jwtStr = bearerTokenFromReq(reqCtx.req)\n if (!jwtStr) {\n throw new AuthRequiredError('missing jwt', 'MissingJwt')\n }\n // if validating additional scopes, skip scope check in initial validation & follow up afterwards\n const payload = await verifyServiceJwt(\n jwtStr,\n opts.aud,\n null,\n getSigningKey,\n verifySignatureWithKey,\n )\n if (\n !payload.iss.endsWith('#atproto_labeler') ||\n payload.lxm !== undefined\n ) {\n // @TODO currently permissive of labelers who dont set lxm yet.\n // we'll allow ozone self-hosters to upgrade before removing this condition.\n assertLxmCheck()\n }\n return { iss: payload.iss, aud: payload.aud }\n }\n\n isModService(iss: string): boolean {\n return [\n this.modServiceDid,\n `${this.modServiceDid}#atproto_labeler`,\n ].includes(iss)\n }\n\n nullCreds(): NullOutput {\n return {\n credentials: {\n type: 'none',\n iss: null,\n },\n }\n }\n\n parseCreds(\n creds: StandardOutput | RoleOutput | ModServiceOutput | NullOutput,\n ) {\n const viewer =\n creds.credentials.type === 'standard' ? creds.credentials.iss : null\n const includeTakedownsAnd3pBlocks =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service' ||\n (creds.credentials.type === 'standard' &&\n this.isModService(creds.credentials.iss))\n const canPerformTakedown =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service'\n const isModService =\n creds.credentials.type === 'mod_service' ||\n (creds.credentials.type === 'standard' &&\n this.isModService(creds.credentials.iss))\n\n return {\n viewer,\n includeTakedowns: includeTakedownsAnd3pBlocks,\n include3pBlocks: includeTakedownsAnd3pBlocks,\n canPerformTakedown,\n isModService,\n }\n }\n}\n\n// HELPERS\n// ---------\n\nconst BEARER = 'Bearer '\nconst BASIC = 'Basic '\n\nconst isBearerToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BEARER) ?? false\n}\n\nconst isBasicToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BASIC) ?? false\n}\n\nconst bearerTokenFromReq = (req: express.Request) => {\n const header = req.headers.authorization || ''\n if (!header.startsWith(BEARER)) return null\n return header.slice(BEARER.length).trim()\n}\n\nexport const parseBasicAuth = (\n token: string,\n): { username: string; password: string } | null => {\n if (!token.startsWith(BASIC)) return null\n const b64 = token.slice(BASIC.length)\n let parsed: string[]\n try {\n parsed = ui8.toString(ui8.fromString(b64, 'base64pad'), 'utf8').split(':')\n } catch (err) {\n return null\n }\n const [username, password] = parsed\n if (!username || !password) return null\n return { username, password }\n}\n\nexport const buildBasicAuth = (username: string, password: string): string => {\n return (\n BASIC +\n ui8.toString(ui8.fromString(`${username}:${password}`, 'utf8'), 'base64pad')\n )\n}\n\nconst keyEncoder = new KeyEncoder('secp256k1')\nexport const createPublicKeyObject = (publicKeyHex: string): KeyObject => {\n const key = keyEncoder.encodePublic(publicKeyHex, 'raw', 'pem')\n return crypto.createPublicKey({ format: 'pem', key })\n}\n\nconst verifySig = (\n publicKey: Uint8Array,\n data: Uint8Array,\n sig: Uint8Array,\n) => {\n const keyEncoder = new KeyEncoder('secp256k1')\n\n const pemKey = keyEncoder.encodePublic(\n ui8.toString(publicKey, 'hex'),\n 'raw',\n 'pem',\n )\n const key = crypto.createPublicKey({ format: 'pem', key: pemKey })\n\n return crypto.verify(\n 'sha256',\n data,\n {\n key,\n dsaEncoding: 'ieee-p1363',\n },\n sig,\n )\n}\n\nexport const verifySignatureWithKey: VerifySignatureWithKeyFn = async (\n didKey: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n if (alg === SECP256K1_JWT_ALG) {\n const parsed = parseDidKey(didKey)\n if (alg !== parsed.jwtAlg) {\n throw new Error(`Expected key alg ${alg}, got ${parsed.jwtAlg}`)\n }\n\n return verifySig(parsed.keyBytes, msgBytes, sigBytes)\n }\n\n return cryptoVerifySignatureWithKey(didKey, msgBytes, sigBytes, alg)\n}\n"]}
package/dist/config.d.ts CHANGED
@@ -35,6 +35,7 @@ export interface ServerConfigValues {
35
35
  courierHttpVersion?: '1.1' | '2';
36
36
  courierIgnoreBadTls?: boolean;
37
37
  searchUrl?: string;
38
+ searchTagsHide: Set<string>;
38
39
  suggestionsUrl?: string;
39
40
  suggestionsApiKey?: string;
40
41
  topicsUrl?: string;
@@ -100,6 +101,7 @@ export declare class ServerConfig {
100
101
  get courierHttpVersion(): "2" | "1.1" | undefined;
101
102
  get courierIgnoreBadTls(): boolean | undefined;
102
103
  get searchUrl(): string | undefined;
104
+ get searchTagsHide(): Set<string>;
103
105
  get suggestionsUrl(): string | undefined;
104
106
  get suggestionsApiKey(): string | undefined;
105
107
  get topicsUrl(): string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -59,6 +59,7 @@ class ServerConfig {
59
59
  const searchUrl = process.env.BSKY_SEARCH_URL ||
60
60
  process.env.BSKY_SEARCH_ENDPOINT ||
61
61
  undefined;
62
+ const searchTagsHide = new Set(envList(process.env.BSKY_SEARCH_TAGS_HIDE));
62
63
  const suggestionsUrl = process.env.BSKY_SUGGESTIONS_URL || undefined;
63
64
  const suggestionsApiKey = process.env.BSKY_SUGGESTIONS_API_KEY || undefined;
64
65
  const topicsUrl = process.env.BSKY_TOPICS_URL || undefined;
@@ -177,6 +178,7 @@ class ServerConfig {
177
178
  dataplaneHttpVersion,
178
179
  dataplaneIgnoreBadTls,
179
180
  searchUrl,
181
+ searchTagsHide,
180
182
  suggestionsUrl,
181
183
  suggestionsApiKey,
182
184
  topicsUrl,
@@ -294,6 +296,9 @@ class ServerConfig {
294
296
  get searchUrl() {
295
297
  return this.cfg.searchUrl;
296
298
  }
299
+ get searchTagsHide() {
300
+ return this.cfg.searchTagsHide;
301
+ }
297
302
  get suggestionsUrl() {
298
303
  return this.cfg.suggestionsUrl;
299
304
  }