@atproto/api 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -25
- package/build.js +10 -1
- package/dist/agent.d.ts +11 -6
- package/dist/bsky-agent.d.ts +43 -0
- package/dist/client/index.d.ts +127 -215
- package/dist/client/lexicons.d.ts +1496 -1347
- package/dist/client/types/app/bsky/actor/defs.d.ts +47 -0
- package/dist/client/types/app/bsky/actor/getProfile.d.ts +2 -2
- package/dist/client/types/app/bsky/actor/getProfiles.d.ts +2 -2
- package/dist/client/types/app/bsky/actor/getSuggestions.d.ts +2 -2
- package/dist/client/types/app/bsky/actor/profile.d.ts +4 -60
- package/dist/client/types/app/bsky/actor/searchActors.d.ts +22 -0
- package/dist/client/types/app/bsky/actor/searchActorsTypeahead.d.ts +20 -0
- package/dist/client/types/app/bsky/actor/updateProfile.d.ts +4 -11
- package/dist/client/types/app/bsky/embed/external.d.ts +9 -13
- package/dist/client/types/app/bsky/embed/images.d.ts +9 -13
- package/dist/client/types/app/bsky/embed/record.d.ts +41 -0
- package/dist/client/types/app/bsky/embed/recordWithMedia.d.ts +24 -0
- package/dist/client/types/app/bsky/feed/defs.d.ts +77 -0
- package/dist/client/types/app/bsky/feed/getAuthorFeed.d.ts +4 -4
- package/dist/client/types/app/bsky/feed/getLikes.d.ts +34 -0
- package/dist/client/types/app/bsky/feed/getPostThread.d.ts +2 -24
- package/dist/client/types/app/bsky/feed/getRepostedBy.d.ts +3 -3
- package/dist/client/types/app/bsky/feed/getTimeline.d.ts +3 -3
- package/dist/client/types/app/bsky/feed/like.d.ts +9 -0
- package/dist/client/types/app/bsky/feed/post.d.ts +5 -29
- package/dist/client/types/app/bsky/graph/follow.d.ts +1 -2
- package/dist/client/types/app/bsky/graph/getFollowers.d.ts +5 -5
- package/dist/client/types/app/bsky/graph/getFollows.d.ts +5 -5
- package/dist/client/types/app/bsky/graph/getMutes.d.ts +3 -3
- package/dist/client/types/app/bsky/graph/muteActor.d.ts +17 -0
- package/dist/client/types/app/bsky/graph/unmuteActor.d.ts +17 -0
- package/dist/client/types/app/bsky/notification/getUnreadCount.d.ts +17 -0
- package/dist/client/types/app/bsky/notification/listNotifications.d.ts +35 -0
- package/dist/client/types/app/bsky/richtext/facet.d.ts +30 -0
- package/dist/client/types/app/bsky/unspecced/getPopular.d.ts +21 -0
- package/dist/client/types/com/atproto/admin/defs.d.ts +181 -0
- package/dist/client/types/com/atproto/admin/getModerationAction.d.ts +2 -2
- package/dist/client/types/com/atproto/admin/getModerationActions.d.ts +3 -3
- package/dist/client/types/com/atproto/admin/getModerationReport.d.ts +2 -2
- package/dist/client/types/com/atproto/admin/getModerationReports.d.ts +3 -3
- package/dist/client/types/com/atproto/admin/getRecord.d.ts +2 -2
- package/dist/client/types/com/atproto/admin/getRepo.d.ts +2 -2
- package/dist/client/types/com/atproto/admin/resolveModerationReports.d.ts +2 -2
- package/dist/client/types/com/atproto/admin/reverseModerationAction.d.ts +2 -2
- package/dist/client/types/com/atproto/admin/searchRepos.d.ts +3 -3
- package/dist/client/types/com/atproto/admin/takeModerationAction.d.ts +5 -6
- package/dist/client/types/com/atproto/identity/resolveHandle.d.ts +18 -0
- package/dist/client/types/com/atproto/identity/updateHandle.d.ts +17 -0
- package/dist/client/types/com/atproto/moderation/createReport.d.ts +38 -0
- package/dist/client/types/com/atproto/moderation/defs.d.ts +3 -0
- package/dist/client/types/com/atproto/repo/applyWrites.d.ts +47 -0
- package/dist/client/types/com/atproto/repo/createRecord.d.ts +7 -2
- package/dist/client/types/com/atproto/repo/deleteRecord.d.ts +7 -2
- package/dist/client/types/com/atproto/repo/describeRepo.d.ts +22 -0
- package/dist/client/types/com/atproto/repo/getRecord.d.ts +1 -1
- package/dist/client/types/com/atproto/repo/listRecords.d.ts +3 -3
- package/dist/client/types/com/atproto/repo/putRecord.d.ts +7 -2
- package/dist/client/types/com/atproto/repo/uploadBlob.d.ts +20 -0
- package/dist/client/types/com/atproto/server/createAccount.d.ts +44 -0
- package/dist/client/types/com/atproto/server/createInviteCode.d.ts +22 -0
- package/dist/client/types/com/atproto/server/createSession.d.ts +29 -0
- package/dist/client/types/com/atproto/server/deleteAccount.d.ts +25 -0
- package/dist/client/types/com/atproto/server/deleteSession.d.ts +13 -0
- package/dist/client/types/com/atproto/server/describeServer.d.ts +27 -0
- package/dist/client/types/com/atproto/server/getSession.d.ts +18 -0
- package/dist/client/types/com/atproto/server/refreshSession.d.ts +24 -0
- package/dist/client/types/com/atproto/server/requestAccountDelete.d.ts +13 -0
- package/dist/client/types/com/atproto/server/requestPasswordReset.d.ts +17 -0
- package/dist/client/types/com/atproto/server/resetPassword.d.ts +24 -0
- package/dist/client/types/com/atproto/sync/getBlob.d.ts +15 -0
- package/dist/client/types/com/atproto/sync/getBlocks.d.ts +15 -0
- package/dist/client/types/com/atproto/sync/listBlobs.d.ts +20 -0
- package/dist/client/types/com/atproto/sync/notifyOfUpdate.d.ts +13 -0
- package/dist/client/types/com/atproto/sync/requestCrawl.d.ts +13 -0
- package/dist/client/types/com/atproto/sync/subscribeAllRepos.d.ts +6 -17
- package/dist/client/types/com/atproto/sync/subscribeRepos.d.ts +58 -0
- package/dist/helpers/bsky.d.ts +20 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8222 -3608
- package/dist/index.js.map +4 -4
- package/dist/mixins/bsky.d.ts +23 -0
- package/dist/rich-text/detection.d.ts +4 -0
- package/dist/rich-text/rich-text.d.ts +39 -0
- package/dist/rich-text/sanitization.d.ts +4 -0
- package/dist/rich-text/sanitize.d.ts +4 -0
- package/dist/rich-text/unicode.d.ts +11 -0
- package/dist/types.d.ts +2 -2
- package/docs/rn-fetch-handler.ts +88 -0
- package/package.json +4 -1
- package/src/agent.ts +51 -15
- package/src/bsky-agent.ts +228 -0
- package/src/client/index.ts +371 -581
- package/src/client/lexicons.ts +1920 -1746
- package/src/client/types/app/bsky/actor/defs.ts +97 -0
- package/src/client/types/app/bsky/actor/getProfile.ts +4 -3
- package/src/client/types/app/bsky/actor/getProfiles.ts +4 -3
- package/src/client/types/app/bsky/actor/getSuggestions.ts +4 -3
- package/src/client/types/app/bsky/actor/profile.ts +5 -95
- package/src/client/types/app/bsky/actor/{searchTypeahead.ts → searchActors.ts} +6 -3
- package/src/client/types/app/bsky/actor/{search.ts → searchActorsTypeahead.ts} +4 -5
- package/src/client/types/app/bsky/embed/external.ts +14 -13
- package/src/client/types/app/bsky/embed/images.ts +14 -15
- package/src/client/types/app/bsky/embed/record.ts +90 -0
- package/src/client/types/app/bsky/embed/recordWithMedia.ts +53 -0
- package/src/client/types/app/bsky/feed/defs.ts +156 -0
- package/src/client/types/app/bsky/feed/getAuthorFeed.ts +6 -5
- package/src/client/types/app/bsky/feed/{getVotes.ts → getLikes.ts} +11 -12
- package/src/client/types/app/bsky/feed/getPostThread.ts +5 -48
- package/src/client/types/app/bsky/feed/getRepostedBy.ts +5 -4
- package/src/client/types/app/bsky/feed/getTimeline.ts +5 -4
- package/src/client/types/app/bsky/feed/{vote.ts → like.ts} +4 -4
- package/src/client/types/app/bsky/feed/post.ts +12 -51
- package/src/client/types/app/bsky/feed/repost.ts +2 -1
- package/src/client/types/app/bsky/graph/follow.ts +3 -3
- package/src/client/types/app/bsky/graph/getFollowers.ts +7 -6
- package/src/client/types/app/bsky/graph/getFollows.ts +7 -6
- package/src/client/types/app/bsky/graph/getMutes.ts +5 -4
- package/src/client/types/app/bsky/graph/{mute.ts → muteActor.ts} +3 -2
- package/src/client/types/app/bsky/graph/{unmute.ts → unmuteActor.ts} +3 -2
- package/src/client/types/app/bsky/notification/{getCount.ts → getUnreadCount.ts} +2 -1
- package/src/client/types/app/bsky/notification/{list.ts → listNotifications.ts} +13 -9
- package/src/client/types/app/bsky/notification/updateSeen.ts +2 -1
- package/src/client/types/app/bsky/richtext/facet.ts +81 -0
- package/src/client/types/app/bsky/unspecced/getPopular.ts +38 -0
- package/src/client/types/com/atproto/admin/defs.ts +366 -0
- package/src/client/types/com/atproto/admin/getModerationAction.ts +4 -3
- package/src/client/types/com/atproto/admin/getModerationActions.ts +5 -4
- package/src/client/types/com/atproto/admin/getModerationReport.ts +4 -3
- package/src/client/types/com/atproto/admin/getModerationReports.ts +5 -4
- package/src/client/types/com/atproto/admin/getRecord.ts +4 -3
- package/src/client/types/com/atproto/admin/getRepo.ts +4 -3
- package/src/client/types/com/atproto/admin/resolveModerationReports.ts +4 -3
- package/src/client/types/com/atproto/admin/reverseModerationAction.ts +4 -3
- package/src/client/types/com/atproto/admin/searchRepos.ts +5 -4
- package/src/client/types/com/atproto/admin/takeModerationAction.ts +10 -10
- package/src/client/types/com/atproto/{handle/resolve.ts → identity/resolveHandle.ts} +2 -1
- package/src/client/types/com/atproto/{handle/update.ts → identity/updateHandle.ts} +2 -1
- package/src/client/types/com/atproto/{report/create.ts → moderation/createReport.ts} +10 -10
- package/src/client/types/com/atproto/moderation/defs.ts +17 -0
- package/src/client/types/com/atproto/repo/{batchWrite.ts → applyWrites.ts} +21 -12
- package/src/client/types/com/atproto/repo/createRecord.ts +15 -3
- package/src/client/types/com/atproto/repo/deleteRecord.ts +15 -3
- package/src/client/types/com/atproto/repo/{describe.ts → describeRepo.ts} +3 -2
- package/src/client/types/com/atproto/repo/getRecord.ts +4 -3
- package/src/client/types/com/atproto/repo/listRecords.ts +7 -6
- package/src/client/types/com/atproto/repo/putRecord.ts +18 -6
- package/src/client/types/com/atproto/repo/strongRef.ts +2 -1
- package/src/client/types/com/atproto/{blob/upload.ts → repo/uploadBlob.ts} +3 -2
- package/src/client/types/com/atproto/{account/create.ts → server/createAccount.ts} +9 -1
- package/src/client/types/com/atproto/{account → server}/createInviteCode.ts +2 -1
- package/src/client/types/com/atproto/{session/create.ts → server/createSession.ts} +2 -1
- package/src/client/types/com/atproto/{account/delete.ts → server/deleteAccount.ts} +2 -1
- package/src/client/types/com/atproto/{account/requestDelete.ts → server/deleteSession.ts} +2 -1
- package/src/client/types/com/atproto/server/{getAccountsConfig.ts → describeServer.ts} +4 -3
- package/src/client/types/com/atproto/{session/get.ts → server/getSession.ts} +2 -1
- package/src/client/types/com/atproto/{session/refresh.ts → server/refreshSession.ts} +2 -1
- package/src/client/types/com/atproto/{session/delete.ts → server/requestAccountDelete.ts} +2 -1
- package/src/client/types/com/atproto/{account → server}/requestPasswordReset.ts +2 -1
- package/src/client/types/com/atproto/{account → server}/resetPassword.ts +2 -1
- package/src/client/types/com/atproto/sync/getBlob.ts +33 -0
- package/src/client/types/com/atproto/sync/getBlocks.ts +32 -0
- package/src/client/types/com/atproto/sync/getCheckout.ts +2 -1
- package/src/client/types/com/atproto/sync/getCommitPath.ts +2 -1
- package/src/client/types/com/atproto/sync/getHead.ts +2 -1
- package/src/client/types/com/atproto/sync/getRecord.ts +2 -1
- package/src/client/types/com/atproto/sync/getRepo.ts +2 -1
- package/src/client/types/com/atproto/sync/listBlobs.ts +40 -0
- package/src/client/types/com/atproto/sync/notifyOfUpdate.ts +30 -0
- package/src/client/types/com/atproto/{account/get.ts → sync/requestCrawl.ts} +6 -2
- package/src/client/types/com/atproto/sync/subscribeRepos.ts +131 -0
- package/src/index.ts +12 -0
- package/src/rich-text/detection.ts +83 -0
- package/src/rich-text/rich-text.ts +401 -0
- package/src/rich-text/sanitization.ts +40 -0
- package/src/rich-text/unicode.ts +47 -0
- package/src/types.ts +2 -2
- package/tests/agent.test.ts +10 -6
- package/tests/bsky-agent.test.ts +140 -0
- package/tests/errors.test.ts +4 -4
- package/tests/rich-text-detection.test.ts +229 -0
- package/tests/rich-text-sanitization.test.ts +211 -0
- package/tests/rich-text.test.ts +661 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/src/client/types/app/bsky/actor/ref.ts +0 -64
- package/src/client/types/app/bsky/actor/updateProfile.ts +0 -71
- package/src/client/types/app/bsky/feed/feedViewPost.ts +0 -64
- package/src/client/types/app/bsky/feed/setVote.ts +0 -40
- package/src/client/types/app/bsky/graph/assertCreator.ts +0 -9
- package/src/client/types/app/bsky/graph/assertMember.ts +0 -9
- package/src/client/types/app/bsky/graph/assertion.ts +0 -27
- package/src/client/types/app/bsky/graph/confirmation.ts +0 -28
- package/src/client/types/app/bsky/system/actorUser.ts +0 -9
- package/src/client/types/app/bsky/system/declRef.ts +0 -26
- package/src/client/types/app/bsky/system/declaration.ts +0 -24
- package/src/client/types/com/atproto/admin/blob.ts +0 -84
- package/src/client/types/com/atproto/admin/moderationAction.ts +0 -118
- package/src/client/types/com/atproto/admin/moderationReport.ts +0 -64
- package/src/client/types/com/atproto/admin/record.ts +0 -92
- package/src/client/types/com/atproto/admin/repo.ts +0 -103
- package/src/client/types/com/atproto/repo/recordRef.ts +0 -25
- package/src/client/types/com/atproto/repo/repoRef.ts +0 -24
- package/src/client/types/com/atproto/report/reasonType.ts +0 -16
- package/src/client/types/com/atproto/report/subject.ts +0 -66
- package/src/client/types/com/atproto/sync/subscribeAllRepos.ts +0 -48
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AtpAgentType } from '../types';
|
|
2
|
+
export declare function addBsky<TBase extends AtpAgentType>(Base: TBase): {
|
|
3
|
+
new (...args: any[]): {
|
|
4
|
+
like(uri: string, cid: string): Promise<{
|
|
5
|
+
uri: string;
|
|
6
|
+
cid: string;
|
|
7
|
+
}>;
|
|
8
|
+
unlike(likeUri: string): Promise<void>;
|
|
9
|
+
repost(uri: string, cid: string): Promise<{
|
|
10
|
+
uri: string;
|
|
11
|
+
cid: string;
|
|
12
|
+
}>;
|
|
13
|
+
unrepost(repostUri: string): Promise<void>;
|
|
14
|
+
follow(subjectDid: string): Promise<{
|
|
15
|
+
uri: string;
|
|
16
|
+
cid: string;
|
|
17
|
+
}>;
|
|
18
|
+
unfollow(followUri: string): Promise<void>;
|
|
19
|
+
service: URL;
|
|
20
|
+
api: import("..").AtpServiceClient;
|
|
21
|
+
session?: import("../types").AtpSessionData | undefined;
|
|
22
|
+
};
|
|
23
|
+
} & TBase;
|
|
@@ -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,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
|
|
29
|
+
export declare type AtpAgentFetchHandler = (httpUri: string, httpMethod: string, httpHeaders: AtpAgentFetchHeaders, httpReqBody: any) => Promise<AtpAgentFetchHandlerResponse>;
|
|
30
30
|
export interface AtpAgentGlobalOpts {
|
|
31
|
-
fetch:
|
|
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.
|
|
3
|
+
"version": "0.2.0",
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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<
|
|
85
|
+
): Promise<ComAtprotoServerCreateAccount.Response> {
|
|
81
86
|
try {
|
|
82
|
-
const res = await this.api.com.atproto.
|
|
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<
|
|
117
|
+
): Promise<ComAtprotoServerCreateSession.Response> {
|
|
113
118
|
try {
|
|
114
|
-
const res = await this.api.com.atproto.
|
|
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<
|
|
147
|
+
): Promise<ComAtprotoServerGetSession.Response> {
|
|
143
148
|
try {
|
|
144
149
|
this.session = session
|
|
145
|
-
const res = await this.api.com.atproto.
|
|
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
|
|
331
|
+
): v is ComAtprotoServerRefreshSession.OutputSchema {
|
|
299
332
|
try {
|
|
300
|
-
client.xrpc.lex.assertValidXrpcOutput(
|
|
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
|
+
}
|