@atproto/api 0.1.3 → 0.2.1

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 (208) hide show
  1. package/README.md +179 -25
  2. package/build.js +2 -1
  3. package/dist/agent.d.ts +11 -6
  4. package/dist/bsky-agent.d.ts +43 -0
  5. package/dist/client/index.d.ts +117 -215
  6. package/dist/client/lexicons.d.ts +1447 -1401
  7. package/dist/client/types/app/bsky/actor/defs.d.ts +47 -0
  8. package/dist/client/types/app/bsky/actor/getProfile.d.ts +2 -2
  9. package/dist/client/types/app/bsky/actor/getProfiles.d.ts +2 -2
  10. package/dist/client/types/app/bsky/actor/getSuggestions.d.ts +2 -2
  11. package/dist/client/types/app/bsky/actor/profile.d.ts +4 -60
  12. package/dist/client/types/app/bsky/actor/searchActors.d.ts +22 -0
  13. package/dist/client/types/app/bsky/actor/searchActorsTypeahead.d.ts +20 -0
  14. package/dist/client/types/app/bsky/embed/complexRecord.d.ts +24 -0
  15. package/dist/client/types/app/bsky/embed/external.d.ts +9 -13
  16. package/dist/client/types/app/bsky/embed/images.d.ts +9 -13
  17. package/dist/client/types/app/bsky/embed/post.d.ts +33 -0
  18. package/dist/client/types/app/bsky/embed/record.d.ts +21 -13
  19. package/dist/client/types/app/bsky/embed/recordWithMedia.d.ts +24 -0
  20. package/dist/client/types/app/bsky/feed/defs.d.ts +77 -0
  21. package/dist/client/types/app/bsky/feed/getAuthorFeed.d.ts +4 -4
  22. package/dist/client/types/app/bsky/{graph/getMembers.d.ts → feed/getLikes.d.ts} +12 -14
  23. package/dist/client/types/app/bsky/feed/getPostThread.d.ts +2 -24
  24. package/dist/client/types/app/bsky/feed/getRepostedBy.d.ts +3 -3
  25. package/dist/client/types/app/bsky/feed/getTimeline.d.ts +3 -3
  26. package/dist/client/types/app/bsky/feed/post.d.ts +4 -29
  27. package/dist/client/types/app/bsky/graph/follow.d.ts +1 -2
  28. package/dist/client/types/app/bsky/graph/getFollowers.d.ts +5 -5
  29. package/dist/client/types/app/bsky/graph/getFollows.d.ts +5 -5
  30. package/dist/client/types/app/bsky/graph/getMutes.d.ts +3 -3
  31. package/dist/client/types/app/bsky/{notification/updateSeen.d.ts → graph/muteActor.d.ts} +1 -1
  32. package/dist/client/types/app/bsky/graph/unmuteActor.d.ts +17 -0
  33. package/dist/client/types/app/bsky/notification/getUnreadCount.d.ts +17 -0
  34. package/dist/client/types/app/bsky/{graph/getMemberships.d.ts → notification/listNotifications.d.ts} +13 -14
  35. package/dist/client/types/app/bsky/richtext/facet.d.ts +30 -0
  36. package/dist/client/types/app/bsky/unspecced/getPopular.d.ts +21 -0
  37. package/dist/client/types/com/atproto/admin/defs.d.ts +181 -0
  38. package/dist/client/types/com/atproto/admin/getModerationAction.d.ts +2 -2
  39. package/dist/client/types/com/atproto/admin/getModerationActions.d.ts +3 -3
  40. package/dist/client/types/com/atproto/admin/getModerationReport.d.ts +2 -2
  41. package/dist/client/types/com/atproto/admin/getModerationReports.d.ts +3 -3
  42. package/dist/client/types/com/atproto/admin/getRecord.d.ts +2 -2
  43. package/dist/client/types/com/atproto/admin/getRepo.d.ts +2 -2
  44. package/dist/client/types/com/atproto/admin/resolveModerationReports.d.ts +2 -2
  45. package/dist/client/types/com/atproto/admin/reverseModerationAction.d.ts +2 -2
  46. package/dist/client/types/com/atproto/admin/searchRepos.d.ts +3 -3
  47. package/dist/client/types/com/atproto/admin/takeModerationAction.d.ts +5 -6
  48. package/dist/client/types/com/atproto/{sync/getHead.d.ts → identity/resolveHandle.d.ts} +2 -2
  49. package/dist/client/types/com/atproto/identity/updateHandle.d.ts +17 -0
  50. package/dist/client/types/com/atproto/moderation/createReport.d.ts +38 -0
  51. package/dist/client/types/com/atproto/moderation/defs.d.ts +3 -0
  52. package/dist/client/types/com/atproto/repo/applyWrites.d.ts +47 -0
  53. package/dist/client/types/com/atproto/repo/createRecord.d.ts +7 -2
  54. package/dist/client/types/com/atproto/repo/deleteRecord.d.ts +7 -2
  55. package/dist/client/types/com/atproto/repo/describeRepo.d.ts +22 -0
  56. package/dist/client/types/com/atproto/repo/getRecord.d.ts +1 -1
  57. package/dist/client/types/com/atproto/repo/listRecords.d.ts +3 -3
  58. package/dist/client/types/com/atproto/repo/putRecord.d.ts +7 -2
  59. package/dist/client/types/com/atproto/repo/uploadBlob.d.ts +20 -0
  60. package/dist/client/types/{app/bsky/actor/createScene.d.ts → com/atproto/server/createAccount.d.ts} +14 -2
  61. package/dist/client/types/com/atproto/server/createInviteCode.d.ts +22 -0
  62. package/dist/client/types/com/atproto/server/createSession.d.ts +29 -0
  63. package/dist/client/types/com/atproto/server/deleteAccount.d.ts +25 -0
  64. package/dist/client/types/com/atproto/{sync/getRecord.d.ts → server/deleteSession.d.ts} +1 -5
  65. package/dist/client/types/com/atproto/server/describeServer.d.ts +27 -0
  66. package/dist/client/types/com/atproto/{sync/getRoot.d.ts → server/getSession.d.ts} +2 -2
  67. package/dist/client/types/com/atproto/server/refreshSession.d.ts +24 -0
  68. package/dist/client/types/com/atproto/{sync/updateRepo.d.ts → server/requestAccountDelete.d.ts} +1 -3
  69. package/dist/client/types/com/atproto/server/requestPasswordReset.d.ts +17 -0
  70. package/dist/client/types/com/atproto/server/resetPassword.d.ts +24 -0
  71. package/dist/client/types/com/atproto/sync/{getCheckout.d.ts → getBlob.d.ts} +1 -1
  72. package/dist/client/types/com/atproto/sync/{getCommitPath.d.ts → listBlobs.d.ts} +1 -1
  73. package/dist/client/types/com/atproto/sync/notifyOfUpdate.d.ts +1 -0
  74. package/dist/client/types/com/atproto/sync/requestCrawl.d.ts +1 -1
  75. package/dist/client/types/com/atproto/sync/subscribeAllRepos.d.ts +9 -1
  76. package/dist/client/types/com/atproto/sync/subscribeRepos.d.ts +58 -0
  77. package/dist/index.d.ts +6 -0
  78. package/dist/index.js +8055 -3651
  79. package/dist/index.js.map +4 -4
  80. package/dist/rich-text/detection.d.ts +4 -0
  81. package/dist/rich-text/rich-text.d.ts +39 -0
  82. package/dist/rich-text/sanitization.d.ts +4 -0
  83. package/dist/rich-text/unicode.d.ts +11 -0
  84. package/dist/types.d.ts +2 -2
  85. package/docs/rn-fetch-handler.ts +88 -0
  86. package/package.json +4 -1
  87. package/src/agent.ts +51 -15
  88. package/src/bsky-agent.ts +228 -0
  89. package/src/client/index.ts +330 -581
  90. package/src/client/lexicons.ts +1833 -1779
  91. package/src/client/types/app/bsky/actor/defs.ts +97 -0
  92. package/src/client/types/app/bsky/actor/getProfile.ts +4 -3
  93. package/src/client/types/app/bsky/actor/getProfiles.ts +4 -3
  94. package/src/client/types/app/bsky/actor/getSuggestions.ts +4 -3
  95. package/src/client/types/app/bsky/actor/profile.ts +5 -95
  96. package/src/client/types/app/bsky/actor/{searchTypeahead.ts → searchActors.ts} +6 -3
  97. package/src/client/types/app/bsky/actor/{search.ts → searchActorsTypeahead.ts} +4 -5
  98. package/src/client/types/app/bsky/embed/external.ts +14 -13
  99. package/src/client/types/app/bsky/embed/images.ts +14 -15
  100. package/src/client/types/app/bsky/embed/record.ts +32 -25
  101. package/src/client/types/app/bsky/embed/recordWithMedia.ts +53 -0
  102. package/src/client/types/app/bsky/feed/defs.ts +156 -0
  103. package/src/client/types/app/bsky/feed/getAuthorFeed.ts +6 -5
  104. package/src/client/types/app/bsky/feed/{getVotes.ts → getLikes.ts} +11 -12
  105. package/src/client/types/app/bsky/feed/getPostThread.ts +5 -48
  106. package/src/client/types/app/bsky/feed/getRepostedBy.ts +5 -4
  107. package/src/client/types/app/bsky/feed/getTimeline.ts +5 -4
  108. package/src/client/types/app/bsky/feed/{vote.ts → like.ts} +4 -4
  109. package/src/client/types/app/bsky/feed/post.ts +10 -52
  110. package/src/client/types/app/bsky/feed/repost.ts +2 -1
  111. package/src/client/types/app/bsky/graph/follow.ts +3 -3
  112. package/src/client/types/app/bsky/graph/getFollowers.ts +7 -6
  113. package/src/client/types/app/bsky/graph/getFollows.ts +7 -6
  114. package/src/client/types/app/bsky/graph/getMutes.ts +5 -4
  115. package/src/client/types/app/bsky/graph/{mute.ts → muteActor.ts} +3 -2
  116. package/src/client/types/app/bsky/graph/{unmute.ts → unmuteActor.ts} +3 -2
  117. package/src/client/types/app/bsky/notification/{getCount.ts → getUnreadCount.ts} +2 -1
  118. package/src/client/types/app/bsky/notification/{list.ts → listNotifications.ts} +13 -9
  119. package/src/client/types/app/bsky/notification/updateSeen.ts +2 -1
  120. package/src/client/types/app/bsky/richtext/facet.ts +81 -0
  121. package/src/client/types/app/bsky/unspecced/getPopular.ts +38 -0
  122. package/src/client/types/com/atproto/admin/defs.ts +366 -0
  123. package/src/client/types/com/atproto/admin/getModerationAction.ts +4 -3
  124. package/src/client/types/com/atproto/admin/getModerationActions.ts +5 -4
  125. package/src/client/types/com/atproto/admin/getModerationReport.ts +4 -3
  126. package/src/client/types/com/atproto/admin/getModerationReports.ts +5 -4
  127. package/src/client/types/com/atproto/admin/getRecord.ts +4 -3
  128. package/src/client/types/com/atproto/admin/getRepo.ts +4 -3
  129. package/src/client/types/com/atproto/admin/resolveModerationReports.ts +4 -3
  130. package/src/client/types/com/atproto/admin/reverseModerationAction.ts +4 -3
  131. package/src/client/types/com/atproto/admin/searchRepos.ts +5 -4
  132. package/src/client/types/com/atproto/admin/takeModerationAction.ts +10 -10
  133. package/src/client/types/com/atproto/{handle/resolve.ts → identity/resolveHandle.ts} +2 -1
  134. package/src/client/types/com/atproto/{handle/update.ts → identity/updateHandle.ts} +2 -1
  135. package/src/client/types/com/atproto/{report/create.ts → moderation/createReport.ts} +10 -10
  136. package/src/client/types/com/atproto/moderation/defs.ts +17 -0
  137. package/src/client/types/com/atproto/repo/{batchWrite.ts → applyWrites.ts} +21 -12
  138. package/src/client/types/com/atproto/repo/createRecord.ts +15 -3
  139. package/src/client/types/com/atproto/repo/deleteRecord.ts +15 -3
  140. package/src/client/types/com/atproto/repo/{describe.ts → describeRepo.ts} +3 -2
  141. package/src/client/types/com/atproto/repo/getRecord.ts +4 -3
  142. package/src/client/types/com/atproto/repo/listRecords.ts +7 -6
  143. package/src/client/types/com/atproto/repo/putRecord.ts +18 -6
  144. package/src/client/types/com/atproto/repo/strongRef.ts +2 -1
  145. package/src/client/types/com/atproto/{blob/upload.ts → repo/uploadBlob.ts} +3 -2
  146. package/src/client/types/com/atproto/{account/create.ts → server/createAccount.ts} +9 -1
  147. package/src/client/types/com/atproto/{account → server}/createInviteCode.ts +2 -1
  148. package/src/client/types/com/atproto/{session/create.ts → server/createSession.ts} +2 -1
  149. package/src/client/types/com/atproto/{account/delete.ts → server/deleteAccount.ts} +2 -1
  150. package/src/client/types/com/atproto/{account/requestDelete.ts → server/deleteSession.ts} +2 -1
  151. package/src/client/types/com/atproto/server/{getAccountsConfig.ts → describeServer.ts} +4 -3
  152. package/src/client/types/com/atproto/{session/get.ts → server/getSession.ts} +2 -1
  153. package/src/client/types/com/atproto/{session/refresh.ts → server/refreshSession.ts} +2 -1
  154. package/src/client/types/com/atproto/{session/delete.ts → server/requestAccountDelete.ts} +2 -1
  155. package/src/client/types/com/atproto/{account → server}/requestPasswordReset.ts +2 -1
  156. package/src/client/types/com/atproto/{account → server}/resetPassword.ts +2 -1
  157. package/src/client/types/com/atproto/sync/getBlob.ts +33 -0
  158. package/src/client/types/com/atproto/sync/getBlocks.ts +2 -1
  159. package/src/client/types/com/atproto/sync/getCheckout.ts +2 -1
  160. package/src/client/types/com/atproto/sync/getCommitPath.ts +2 -1
  161. package/src/client/types/com/atproto/sync/getHead.ts +2 -1
  162. package/src/client/types/com/atproto/sync/getRecord.ts +2 -1
  163. package/src/client/types/com/atproto/sync/getRepo.ts +2 -1
  164. package/src/client/types/com/atproto/sync/listBlobs.ts +40 -0
  165. package/src/client/types/com/atproto/sync/notifyOfUpdate.ts +6 -2
  166. package/src/client/types/com/atproto/sync/requestCrawl.ts +3 -2
  167. package/src/client/types/com/atproto/sync/subscribeRepos.ts +131 -0
  168. package/src/index.ts +12 -0
  169. package/src/rich-text/detection.ts +83 -0
  170. package/src/rich-text/rich-text.ts +401 -0
  171. package/src/rich-text/sanitization.ts +40 -0
  172. package/src/rich-text/unicode.ts +47 -0
  173. package/src/types.ts +2 -2
  174. package/tests/agent.test.ts +10 -6
  175. package/tests/bsky-agent.test.ts +140 -0
  176. package/tests/errors.test.ts +4 -4
  177. package/tests/rich-text-detection.test.ts +229 -0
  178. package/tests/rich-text-sanitization.test.ts +211 -0
  179. package/tests/rich-text.test.ts +661 -0
  180. package/tsconfig.build.tsbuildinfo +1 -1
  181. package/dist/client/types/app/bsky/feed/trend.d.ts +0 -9
  182. package/dist/client/types/app/bsky/graph/getAssertions.d.ts +0 -48
  183. package/dist/client/types/app/bsky/system/actorScene.d.ts +0 -1
  184. package/dist/client/types/com/atproto/repo/strongRef.d.ts +0 -8
  185. package/dist/client/util.d.ts +0 -2
  186. package/src/client/types/app/bsky/actor/ref.ts +0 -64
  187. package/src/client/types/app/bsky/actor/updateProfile.ts +0 -71
  188. package/src/client/types/app/bsky/feed/feedViewPost.ts +0 -64
  189. package/src/client/types/app/bsky/feed/setVote.ts +0 -40
  190. package/src/client/types/app/bsky/graph/assertCreator.ts +0 -9
  191. package/src/client/types/app/bsky/graph/assertMember.ts +0 -9
  192. package/src/client/types/app/bsky/graph/assertion.ts +0 -27
  193. package/src/client/types/app/bsky/graph/confirmation.ts +0 -28
  194. package/src/client/types/app/bsky/system/actorUser.ts +0 -9
  195. package/src/client/types/app/bsky/system/declRef.ts +0 -26
  196. package/src/client/types/app/bsky/system/declaration.ts +0 -24
  197. package/src/client/types/com/atproto/account/get.ts +0 -26
  198. package/src/client/types/com/atproto/admin/blob.ts +0 -84
  199. package/src/client/types/com/atproto/admin/moderationAction.ts +0 -118
  200. package/src/client/types/com/atproto/admin/moderationReport.ts +0 -64
  201. package/src/client/types/com/atproto/admin/record.ts +0 -92
  202. package/src/client/types/com/atproto/admin/repo.ts +0 -103
  203. package/src/client/types/com/atproto/repo/recordRef.ts +0 -25
  204. package/src/client/types/com/atproto/repo/repoRef.ts +0 -24
  205. package/src/client/types/com/atproto/report/reasonType.ts +0 -16
  206. package/src/client/types/com/atproto/report/subject.ts +0 -66
  207. package/src/client/types/com/atproto/sync/subscribeAllRepos.ts +0 -7
  208. /package/dist/client/types/app/bsky/feed/{repost.d.ts → like.d.ts} +0 -0
@@ -0,0 +1,4 @@
1
+ import { AppBskyRichtextFacet } from '../client';
2
+ import { UnicodeString } from './unicode';
3
+ export declare type Facet = AppBskyRichtextFacet.Main;
4
+ export declare function detectFacets(text: UnicodeString): Facet[] | undefined;
@@ -0,0 +1,39 @@
1
+ import { AtpAgent } from '../agent';
2
+ import { AppBskyFeedPost, AppBskyRichtextFacet } from '../client';
3
+ import { UnicodeString } from './unicode';
4
+ export declare type Facet = AppBskyRichtextFacet.Main;
5
+ export declare type FacetLink = AppBskyRichtextFacet.Link;
6
+ export declare type FacetMention = AppBskyRichtextFacet.Mention;
7
+ export declare type Entity = AppBskyFeedPost.Entity;
8
+ export interface RichTextProps {
9
+ text: string;
10
+ facets?: Facet[];
11
+ entities?: Entity[];
12
+ }
13
+ export interface RichTextOpts {
14
+ cleanNewlines?: boolean;
15
+ }
16
+ export declare class RichTextSegment {
17
+ text: string;
18
+ facet?: AppBskyRichtextFacet.Main | undefined;
19
+ constructor(text: string, facet?: AppBskyRichtextFacet.Main | undefined);
20
+ get link(): FacetLink | undefined;
21
+ isLink(): boolean;
22
+ get mention(): FacetMention | undefined;
23
+ isMention(): boolean;
24
+ }
25
+ export declare class RichText {
26
+ unicodeText: UnicodeString;
27
+ facets?: Facet[];
28
+ constructor(props: RichTextProps, opts?: RichTextOpts);
29
+ get text(): string;
30
+ get length(): number;
31
+ get graphemeLength(): number;
32
+ clone(): RichText;
33
+ copyInto(target: RichText): void;
34
+ segments(): Generator<RichTextSegment, void, void>;
35
+ insert(insertIndex: number, insertText: string): this;
36
+ delete(removeStartIndex: number, removeEndIndex: number): this;
37
+ detectFacets(agent: AtpAgent): Promise<void>;
38
+ detectFacetsWithoutResolution(): void;
39
+ }
@@ -0,0 +1,4 @@
1
+ import { RichText } from './rich-text';
2
+ export declare function sanitizeRichText(richText: RichText, opts: {
3
+ cleanNewlines?: boolean;
4
+ }): RichText;
@@ -0,0 +1,11 @@
1
+ export declare class UnicodeString {
2
+ utf16: string;
3
+ utf8: Uint8Array;
4
+ private _graphemeLen?;
5
+ constructor(utf16: string);
6
+ get length(): number;
7
+ get graphemeLength(): number;
8
+ slice(start?: number, end?: number): string;
9
+ utf16IndexToUtf8Index(i: number): number;
10
+ toString(): string;
11
+ }
package/dist/types.d.ts CHANGED
@@ -26,8 +26,8 @@ export interface AtpAgentFetchHandlerResponse {
26
26
  headers: Record<string, string>;
27
27
  body: any;
28
28
  }
29
- export declare type AptAgentFetchHandler = (httpUri: string, httpMethod: string, httpHeaders: AtpAgentFetchHeaders, httpReqBody: any) => Promise<AtpAgentFetchHandlerResponse>;
29
+ export declare type AtpAgentFetchHandler = (httpUri: string, httpMethod: string, httpHeaders: AtpAgentFetchHeaders, httpReqBody: any) => Promise<AtpAgentFetchHandlerResponse>;
30
30
  export interface AtpAgentGlobalOpts {
31
- fetch: AptAgentFetchHandler;
31
+ fetch: AtpAgentFetchHandler;
32
32
  }
33
33
  export {};
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The following is the react-native fetch handler used currently in the bluesky app
3
+ * It's not our prettiest work, but it gets the job done
4
+ */
5
+
6
+ import { BskyAgent, stringifyLex, jsonToLex } from '@atproto/api'
7
+ import RNFS from 'react-native-fs'
8
+
9
+ const GET_TIMEOUT = 15e3 // 15s
10
+ const POST_TIMEOUT = 60e3 // 60s
11
+
12
+ export function doPolyfill() {
13
+ BskyAgent.configure({ fetch: fetchHandler })
14
+ }
15
+
16
+ interface FetchHandlerResponse {
17
+ status: number
18
+ headers: Record<string, string>
19
+ body: ArrayBuffer | undefined
20
+ }
21
+
22
+ async function fetchHandler(
23
+ reqUri: string,
24
+ reqMethod: string,
25
+ reqHeaders: Record<string, string>,
26
+ reqBody: any,
27
+ ): Promise<FetchHandlerResponse> {
28
+ const reqMimeType = reqHeaders['Content-Type'] || reqHeaders['content-type']
29
+ if (reqMimeType && reqMimeType.startsWith('application/json')) {
30
+ reqBody = stringifyLex(reqBody)
31
+ } else if (
32
+ typeof reqBody === 'string' &&
33
+ (reqBody.startsWith('/') || reqBody.startsWith('file:'))
34
+ ) {
35
+ if (reqBody.endsWith('.jpeg') || reqBody.endsWith('.jpg')) {
36
+ // HACK
37
+ // React native has a bug that inflates the size of jpegs on upload
38
+ // we get around that by renaming the file ext to .bin
39
+ // see https://github.com/facebook/react-native/issues/27099
40
+ // -prf
41
+ const newPath = reqBody.replace(/\.jpe?g$/, '.bin')
42
+ await RNFS.moveFile(reqBody, newPath)
43
+ reqBody = newPath
44
+ }
45
+ // NOTE
46
+ // React native treats bodies with {uri: string} as file uploads to pull from cache
47
+ // -prf
48
+ reqBody = { uri: reqBody }
49
+ }
50
+
51
+ const controller = new AbortController()
52
+ const to = setTimeout(
53
+ () => controller.abort(),
54
+ reqMethod === 'post' ? POST_TIMEOUT : GET_TIMEOUT,
55
+ )
56
+
57
+ const res = await fetch(reqUri, {
58
+ method: reqMethod,
59
+ headers: reqHeaders,
60
+ body: reqBody,
61
+ signal: controller.signal,
62
+ })
63
+
64
+ const resStatus = res.status
65
+ const resHeaders: Record<string, string> = {}
66
+ res.headers.forEach((value: string, key: string) => {
67
+ resHeaders[key] = value
68
+ })
69
+ const resMimeType = resHeaders['Content-Type'] || resHeaders['content-type']
70
+ let resBody
71
+ if (resMimeType) {
72
+ if (resMimeType.startsWith('application/json')) {
73
+ resBody = jsonToLex(await res.json())
74
+ } else if (resMimeType.startsWith('text/')) {
75
+ resBody = await res.text()
76
+ } else {
77
+ throw new Error('TODO: non-textual response body')
78
+ }
79
+ }
80
+
81
+ clearTimeout(to)
82
+
83
+ return {
84
+ status: resStatus,
85
+ headers: resHeaders,
86
+ body: resBody,
87
+ }
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/api",
3
- "version": "0.1.3",
3
+ "version": "0.2.1",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "codegen": "lex gen-api ./src/client ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*",
@@ -14,7 +14,10 @@
14
14
  },
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
+ "@atproto/common-web": "*",
18
+ "@atproto/uri": "*",
17
19
  "@atproto/xrpc": "*",
20
+ "tlds": "^1.234.0",
18
21
  "typed-emitter": "^2.1.0"
19
22
  },
20
23
  "devDependencies": {
package/src/agent.ts CHANGED
@@ -3,23 +3,24 @@ import { defaultFetchHandler } from '@atproto/xrpc'
3
3
  import {
4
4
  AtpBaseClient,
5
5
  AtpServiceClient,
6
- ComAtprotoAccountCreate,
7
- ComAtprotoSessionCreate,
8
- ComAtprotoSessionGet,
9
- ComAtprotoSessionRefresh,
6
+ ComAtprotoServerCreateAccount,
7
+ ComAtprotoServerCreateSession,
8
+ ComAtprotoServerGetSession,
9
+ ComAtprotoServerRefreshSession,
10
+ ComAtprotoRepoUploadBlob,
10
11
  } from './client'
11
12
  import {
12
13
  AtpSessionData,
13
14
  AtpAgentCreateAccountOpts,
14
15
  AtpAgentLoginOpts,
15
- AptAgentFetchHandler,
16
+ AtpAgentFetchHandler,
16
17
  AtpAgentFetchHandlerResponse,
17
18
  AtpAgentGlobalOpts,
18
19
  AtpPersistSessionHandler,
19
20
  AtpAgentOpts,
20
21
  } from './types'
21
22
 
22
- const REFRESH_SESSION = 'com.atproto.session.refresh'
23
+ const REFRESH_SESSION = 'com.atproto.server.refreshSession'
23
24
 
24
25
  /**
25
26
  * An ATP "Agent"
@@ -34,10 +35,14 @@ export class AtpAgent {
34
35
  private _persistSession?: AtpPersistSessionHandler
35
36
  private _refreshSessionPromise: Promise<void> | undefined
36
37
 
38
+ get com() {
39
+ return this.api.com
40
+ }
41
+
37
42
  /**
38
43
  * The `fetch` implementation; must be implemented for your platform.
39
44
  */
40
- static fetch: AptAgentFetchHandler | undefined = defaultFetchHandler
45
+ static fetch: AtpAgentFetchHandler | undefined = defaultFetchHandler
41
46
 
42
47
  /**
43
48
  * Configures the API globally.
@@ -77,9 +82,9 @@ export class AtpAgent {
77
82
  */
78
83
  async createAccount(
79
84
  opts: AtpAgentCreateAccountOpts,
80
- ): Promise<ComAtprotoAccountCreate.Response> {
85
+ ): Promise<ComAtprotoServerCreateAccount.Response> {
81
86
  try {
82
- const res = await this.api.com.atproto.account.create({
87
+ const res = await this.api.com.atproto.server.createAccount({
83
88
  handle: opts.handle,
84
89
  password: opts.password,
85
90
  email: opts.email,
@@ -109,9 +114,9 @@ export class AtpAgent {
109
114
  */
110
115
  async login(
111
116
  opts: AtpAgentLoginOpts,
112
- ): Promise<ComAtprotoSessionCreate.Response> {
117
+ ): Promise<ComAtprotoServerCreateSession.Response> {
113
118
  try {
114
- const res = await this.api.com.atproto.session.create({
119
+ const res = await this.api.com.atproto.server.createSession({
115
120
  identifier: opts.identifier,
116
121
  password: opts.password,
117
122
  })
@@ -139,10 +144,10 @@ export class AtpAgent {
139
144
  */
140
145
  async resumeSession(
141
146
  session: AtpSessionData,
142
- ): Promise<ComAtprotoSessionGet.Response> {
147
+ ): Promise<ComAtprotoServerGetSession.Response> {
143
148
  try {
144
149
  this.session = session
145
- const res = await this.api.com.atproto.session.get()
150
+ const res = await this.api.com.atproto.server.getSession()
146
151
  if (!res.success || res.data.did !== this.session.did) {
147
152
  throw new Error('Invalid session')
148
153
  }
@@ -271,6 +276,34 @@ export class AtpAgent {
271
276
  // propagate in the _fetch() handler's second attempt to run
272
277
  // the request
273
278
  }
279
+
280
+ /**
281
+ * Upload a binary blob to the server
282
+ */
283
+ uploadBlob: typeof this.api.com.atproto.repo.uploadBlob = (data, opts) =>
284
+ this.api.com.atproto.repo.uploadBlob(data, opts)
285
+
286
+ /**
287
+ * Resolve a handle to a DID
288
+ */
289
+ resolveHandle: typeof this.api.com.atproto.identity.resolveHandle = (
290
+ params,
291
+ opts,
292
+ ) => this.api.com.atproto.identity.resolveHandle(params, opts)
293
+
294
+ /**
295
+ * Change the user's handle
296
+ */
297
+ updateHandle: typeof this.api.com.atproto.identity.updateHandle = (
298
+ data,
299
+ opts,
300
+ ) => this.api.com.atproto.identity.updateHandle(data, opts)
301
+
302
+ /**
303
+ * Create a moderation report
304
+ */
305
+ createModerationReport: typeof this.api.com.atproto.moderation.createReport =
306
+ (data, opts) => this.api.com.atproto.moderation.createReport(data, opts)
274
307
  }
275
308
 
276
309
  function isErrorObject(v: unknown): v is ErrorResponseBody {
@@ -295,9 +328,12 @@ function isErrorResponse(
295
328
  function isNewSessionObject(
296
329
  client: AtpBaseClient,
297
330
  v: unknown,
298
- ): v is ComAtprotoSessionRefresh.OutputSchema {
331
+ ): v is ComAtprotoServerRefreshSession.OutputSchema {
299
332
  try {
300
- client.xrpc.lex.assertValidXrpcOutput('com.atproto.session.refresh', v)
333
+ client.xrpc.lex.assertValidXrpcOutput(
334
+ 'com.atproto.server.refreshSession',
335
+ v,
336
+ )
301
337
  return true
302
338
  } catch {
303
339
  return false
@@ -0,0 +1,228 @@
1
+ import { AtUri } from '@atproto/uri'
2
+ import { AtpAgent } from './agent'
3
+ import {
4
+ AppBskyFeedPost,
5
+ AppBskyActorProfile,
6
+ ComAtprotoRepoPutRecord,
7
+ } from './client'
8
+
9
+ export class BskyAgent extends AtpAgent {
10
+ get app() {
11
+ return this.api.app
12
+ }
13
+
14
+ getTimeline: typeof this.api.app.bsky.feed.getTimeline = (params, opts) =>
15
+ this.api.app.bsky.feed.getTimeline(params, opts)
16
+
17
+ getAuthorFeed: typeof this.api.app.bsky.feed.getAuthorFeed = (params, opts) =>
18
+ this.api.app.bsky.feed.getAuthorFeed(params, opts)
19
+
20
+ getPostThread: typeof this.api.app.bsky.feed.getPostThread = (params, opts) =>
21
+ this.api.app.bsky.feed.getPostThread(params, opts)
22
+
23
+ getPost: typeof this.api.app.bsky.feed.post.get = (params) =>
24
+ this.api.app.bsky.feed.post.get(params)
25
+
26
+ getLikes: typeof this.api.app.bsky.feed.getLikes = (params, opts) =>
27
+ this.api.app.bsky.feed.getLikes(params, opts)
28
+
29
+ getRepostedBy: typeof this.api.app.bsky.feed.getRepostedBy = (params, opts) =>
30
+ this.api.app.bsky.feed.getRepostedBy(params, opts)
31
+
32
+ getFollows: typeof this.api.app.bsky.graph.getFollows = (params, opts) =>
33
+ this.api.app.bsky.graph.getFollows(params, opts)
34
+
35
+ getFollowers: typeof this.api.app.bsky.graph.getFollowers = (params, opts) =>
36
+ this.api.app.bsky.graph.getFollowers(params, opts)
37
+
38
+ getProfile: typeof this.api.app.bsky.actor.getProfile = (params, opts) =>
39
+ this.api.app.bsky.actor.getProfile(params, opts)
40
+
41
+ getProfiles: typeof this.api.app.bsky.actor.getProfiles = (params, opts) =>
42
+ this.api.app.bsky.actor.getProfiles(params, opts)
43
+
44
+ searchActors: typeof this.api.app.bsky.actor.searchActors = (params, opts) =>
45
+ this.api.app.bsky.actor.searchActors(params, opts)
46
+
47
+ searchActorsTypeahead: typeof this.api.app.bsky.actor.searchActorsTypeahead =
48
+ (params, opts) =>
49
+ this.api.app.bsky.actor.searchActorsTypeahead(params, opts)
50
+
51
+ listNotifications: typeof this.api.app.bsky.notification.listNotifications = (
52
+ params,
53
+ opts,
54
+ ) => this.api.app.bsky.notification.listNotifications(params, opts)
55
+
56
+ countUnreadNotifications: typeof this.api.app.bsky.notification.getUnreadCount =
57
+ (params, opts) =>
58
+ this.api.app.bsky.notification.getUnreadCount(params, opts)
59
+
60
+ async post(
61
+ record: Partial<AppBskyFeedPost.Record> &
62
+ Omit<AppBskyFeedPost.Record, 'createdAt'>,
63
+ ) {
64
+ if (!this.session) {
65
+ throw new Error('Not logged in')
66
+ }
67
+ record.createdAt = record.createdAt || new Date().toISOString()
68
+ return this.api.app.bsky.feed.post.create(
69
+ { repo: this.session.did },
70
+ record as AppBskyFeedPost.Record,
71
+ )
72
+ }
73
+
74
+ async deletePost(postUri: string) {
75
+ if (!this.session) {
76
+ throw new Error('Not logged in')
77
+ }
78
+ const postUrip = new AtUri(postUri)
79
+ return await this.api.app.bsky.feed.post.delete({
80
+ repo: postUrip.hostname,
81
+ rkey: postUrip.rkey,
82
+ })
83
+ }
84
+
85
+ async like(uri: string, cid: string) {
86
+ if (!this.session) {
87
+ throw new Error('Not logged in')
88
+ }
89
+ return await this.api.app.bsky.feed.like.create(
90
+ { repo: this.session.did },
91
+ {
92
+ subject: { uri, cid },
93
+ createdAt: new Date().toISOString(),
94
+ },
95
+ )
96
+ }
97
+
98
+ async deleteLike(likeUri: string) {
99
+ if (!this.session) {
100
+ throw new Error('Not logged in')
101
+ }
102
+ const likeUrip = new AtUri(likeUri)
103
+ return await this.api.app.bsky.feed.like.delete({
104
+ repo: likeUrip.hostname,
105
+ rkey: likeUrip.rkey,
106
+ })
107
+ }
108
+
109
+ async repost(uri: string, cid: string) {
110
+ if (!this.session) {
111
+ throw new Error('Not logged in')
112
+ }
113
+ return await this.api.app.bsky.feed.repost.create(
114
+ { repo: this.session.did },
115
+ {
116
+ subject: { uri, cid },
117
+ createdAt: new Date().toISOString(),
118
+ },
119
+ )
120
+ }
121
+
122
+ async deleteRepost(repostUri: string) {
123
+ if (!this.session) {
124
+ throw new Error('Not logged in')
125
+ }
126
+ const repostUrip = new AtUri(repostUri)
127
+ return await this.api.app.bsky.feed.repost.delete({
128
+ repo: repostUrip.hostname,
129
+ rkey: repostUrip.rkey,
130
+ })
131
+ }
132
+
133
+ async follow(subjectDid: string) {
134
+ if (!this.session) {
135
+ throw new Error('Not logged in')
136
+ }
137
+ return await this.api.app.bsky.graph.follow.create(
138
+ { repo: this.session.did },
139
+ {
140
+ subject: subjectDid,
141
+ createdAt: new Date().toISOString(),
142
+ },
143
+ )
144
+ }
145
+
146
+ async deleteFollow(followUri: string) {
147
+ if (!this.session) {
148
+ throw new Error('Not logged in')
149
+ }
150
+ const followUrip = new AtUri(followUri)
151
+ return await this.api.app.bsky.graph.follow.delete({
152
+ repo: followUrip.hostname,
153
+ rkey: followUrip.rkey,
154
+ })
155
+ }
156
+
157
+ async upsertProfile(
158
+ updateFn: (
159
+ existing: AppBskyActorProfile.Record | undefined,
160
+ ) => AppBskyActorProfile.Record | Promise<AppBskyActorProfile.Record>,
161
+ ) {
162
+ if (!this.session) {
163
+ throw new Error('Not logged in')
164
+ }
165
+
166
+ let retriesRemaining = 5
167
+ while (retriesRemaining >= 0) {
168
+ // fetch existing
169
+ const existing = await this.com.atproto.repo
170
+ .getRecord({
171
+ repo: this.session.did,
172
+ collection: 'app.bsky.actor.profile',
173
+ rkey: 'self',
174
+ })
175
+ .catch((_) => undefined)
176
+
177
+ // run the update
178
+ const updated = await updateFn(existing?.data.value)
179
+ if (updated) {
180
+ updated.$type = 'app.bsky.actor.profile'
181
+ }
182
+
183
+ // validate the record
184
+ const validation = AppBskyActorProfile.validateRecord(updated)
185
+ if (!validation.success) {
186
+ throw validation.error
187
+ }
188
+
189
+ try {
190
+ // attempt the put
191
+ await this.com.atproto.repo.putRecord({
192
+ repo: this.session.did,
193
+ collection: 'app.bsky.actor.profile',
194
+ rkey: 'self',
195
+ record: updated,
196
+ swapRecord: existing?.data.cid || null,
197
+ })
198
+ } catch (e: unknown) {
199
+ if (
200
+ retriesRemaining > 0 &&
201
+ e instanceof ComAtprotoRepoPutRecord.InvalidSwapError
202
+ ) {
203
+ // try again
204
+ retriesRemaining--
205
+ continue
206
+ } else {
207
+ throw e
208
+ }
209
+ }
210
+ break
211
+ }
212
+ }
213
+
214
+ async mute(actor: string) {
215
+ return this.api.app.bsky.graph.muteActor({ actor })
216
+ }
217
+
218
+ async unmute(actor: string) {
219
+ return this.api.app.bsky.graph.unmuteActor({ actor })
220
+ }
221
+
222
+ async updateSeenNotifications(seenAt?: string) {
223
+ seenAt = seenAt || new Date().toISOString()
224
+ return this.api.app.bsky.notification.updateSeen({
225
+ seenAt,
226
+ })
227
+ }
228
+ }