@colibri-social/space 0.1.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 +78 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/credentials.d.ts +43 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +120 -0
- package/dist/credentials.js.map +1 -0
- package/dist/dpop.d.ts +15 -0
- package/dist/dpop.d.ts.map +1 -0
- package/dist/dpop.js +32 -0
- package/dist/dpop.js.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/host.d.ts +21 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +48 -0
- package/dist/host.js.map +1 -0
- package/dist/http.d.ts +40 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +103 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/pds.d.ts +125 -0
- package/dist/pds.d.ts.map +1 -0
- package/dist/pds.js +131 -0
- package/dist/pds.js.map +1 -0
- package/dist/repo.d.ts +30 -0
- package/dist/repo.d.ts.map +1 -0
- package/dist/repo.js +33 -0
- package/dist/repo.js.map +1 -0
- package/dist/session.d.ts +26 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +57 -0
- package/dist/session.js.map +1 -0
- package/dist/space-client.d.ts +92 -0
- package/dist/space-client.d.ts.map +1 -0
- package/dist/space-client.js +137 -0
- package/dist/space-client.js.map +1 -0
- package/dist/space-ref.d.ts +20 -0
- package/dist/space-ref.d.ts.map +1 -0
- package/dist/space-ref.js +55 -0
- package/dist/space-ref.js.map +1 -0
- package/dist/tid.d.ts +3 -0
- package/dist/tid.d.ts.map +1 -0
- package/dist/tid.js +4 -0
- package/dist/tid.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { parseSpaceToken } from "@atproto/space";
|
|
2
|
+
import { DpopKey } from "./dpop.js";
|
|
3
|
+
import { SpaceCredentialError, XrpcError } from "./errors.js";
|
|
4
|
+
import { XrpcClient } from "./http.js";
|
|
5
|
+
import { parseSpaceRef } from "./space-ref.js";
|
|
6
|
+
export const inMemoryCredentialStorage = () => {
|
|
7
|
+
const held = new Map();
|
|
8
|
+
return {
|
|
9
|
+
load: async (space) => held.get(space) ?? null,
|
|
10
|
+
save: async (space, credential) => void held.set(space, credential),
|
|
11
|
+
forget: async (space) => void held.delete(space),
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
const GET_SPACE_CREDENTIAL = "com.atproto.space.getSpaceCredential";
|
|
15
|
+
export class SpaceCredentials {
|
|
16
|
+
options;
|
|
17
|
+
storage;
|
|
18
|
+
renewBeforeMs;
|
|
19
|
+
inFlight = new Map();
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.options = options;
|
|
22
|
+
this.storage = options.storage ?? inMemoryCredentialStorage();
|
|
23
|
+
this.renewBeforeMs = (options.renewBeforeSeconds ?? 300) * 1000;
|
|
24
|
+
}
|
|
25
|
+
async acquire(space) {
|
|
26
|
+
const existing = this.inFlight.get(space);
|
|
27
|
+
if (existing)
|
|
28
|
+
return existing;
|
|
29
|
+
const pending = this.resolve(space).finally(() => this.inFlight.delete(space));
|
|
30
|
+
this.inFlight.set(space, pending);
|
|
31
|
+
return pending;
|
|
32
|
+
}
|
|
33
|
+
async acquireWith(space, delegationToken) {
|
|
34
|
+
return this.mint(space, delegationToken);
|
|
35
|
+
}
|
|
36
|
+
async invalidate(space) {
|
|
37
|
+
await this.storage.forget(space);
|
|
38
|
+
}
|
|
39
|
+
async resolve(space) {
|
|
40
|
+
const stored = await this.storage.load(space);
|
|
41
|
+
if (stored && stored.expiresAt.getTime() - Date.now() > this.renewBeforeMs) {
|
|
42
|
+
return {
|
|
43
|
+
credential: stored.credential,
|
|
44
|
+
key: await DpopKey.fromJwk(stored.privateJwk),
|
|
45
|
+
expiresAt: stored.expiresAt,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return this.mint(space);
|
|
49
|
+
}
|
|
50
|
+
async mint(space, delegationToken) {
|
|
51
|
+
try {
|
|
52
|
+
return await this.exchange(space, delegationToken);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const replayable = delegationToken === undefined &&
|
|
56
|
+
error instanceof SpaceCredentialError &&
|
|
57
|
+
error.reason === "invalidDelegationToken";
|
|
58
|
+
if (!replayable)
|
|
59
|
+
throw error;
|
|
60
|
+
return this.exchange(space);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async exchange(space, delegationToken) {
|
|
64
|
+
const token = delegationToken ?? (await this.options.delegation(space));
|
|
65
|
+
if (!token) {
|
|
66
|
+
throw new SpaceCredentialError(space, "noDelegationToken", `no session can mint a delegation token for ${space}`);
|
|
67
|
+
}
|
|
68
|
+
const { authority } = parseSpaceRef(space);
|
|
69
|
+
const host = await this.options.hosts.hostFor(authority);
|
|
70
|
+
const key = await DpopKey.generate();
|
|
71
|
+
const client = new XrpcClient({ service: host, fetch: this.options.fetch });
|
|
72
|
+
const clientAttestation = await this.options.clientAttestation?.(space);
|
|
73
|
+
const response = await client
|
|
74
|
+
.procedure(GET_SPACE_CREDENTIAL, clientAttestation ? { space, clientAttestation } : { space }, { kind: "dpopGrant", token, key })
|
|
75
|
+
.catch((cause) => {
|
|
76
|
+
throw toCredentialError(space, cause);
|
|
77
|
+
});
|
|
78
|
+
const expiresAt = expiryOf(space, response.credential);
|
|
79
|
+
await this.storage.save(space, {
|
|
80
|
+
credential: response.credential,
|
|
81
|
+
privateJwk: key.exportJwk(),
|
|
82
|
+
thumbprint: key.thumbprint,
|
|
83
|
+
expiresAt,
|
|
84
|
+
});
|
|
85
|
+
return { credential: response.credential, key, expiresAt };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const expiryOf = (space, credential) => {
|
|
89
|
+
try {
|
|
90
|
+
return new Date(parseSpaceToken("credential", credential).payload.exp * 1000);
|
|
91
|
+
}
|
|
92
|
+
catch (cause) {
|
|
93
|
+
throw new SpaceCredentialError(space, "upstream", "space host returned an unreadable credential", {
|
|
94
|
+
cause,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const toCredentialError = (space, cause) => {
|
|
99
|
+
if (cause instanceof XrpcError) {
|
|
100
|
+
if (cause.isSpaceDeleted) {
|
|
101
|
+
return new SpaceCredentialError(space, "spaceDeleted", `${space} has been deleted`, {
|
|
102
|
+
cause,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (cause.code === "InvalidDelegationToken") {
|
|
106
|
+
return new SpaceCredentialError(space, "invalidDelegationToken", `the authority rejected the delegation token for ${space}`, { cause });
|
|
107
|
+
}
|
|
108
|
+
if (cause.code === "UserNotAuthorized" ||
|
|
109
|
+
cause.code === "AppNotAuthorized" ||
|
|
110
|
+
cause.code === "NotAuthorized") {
|
|
111
|
+
return new SpaceCredentialError(space, "refused", `the authority refused access to ${space}`, {
|
|
112
|
+
cause,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return new SpaceCredentialError(space, "upstream", `could not obtain a credential for ${space}`, {
|
|
117
|
+
cause,
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
|
package/dist/dpop.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DpopProofRequest = {
|
|
2
|
+
method: string;
|
|
3
|
+
url: string;
|
|
4
|
+
credential?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare class DpopKey {
|
|
7
|
+
private readonly key;
|
|
8
|
+
readonly thumbprint: string;
|
|
9
|
+
private constructor();
|
|
10
|
+
static generate(): Promise<DpopKey>;
|
|
11
|
+
static fromJwk(jwk: string): Promise<DpopKey>;
|
|
12
|
+
exportJwk(): string;
|
|
13
|
+
proof({ method, url, credential }: DpopProofRequest): Promise<string>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=dpop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpop.d.ts","sourceRoot":"","sources":["../src/dpop.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,gBAAgB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,OAAO;IAElB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM;IAF5B,OAAO,eAGH;IAEJ,OAAa,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxC;IAED,OAAa,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGlD;IAED,SAAS,IAAI,MAAM,CAElB;IAED,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpE;CACD"}
|
package/dist/dpop.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { JoseKey } from "@atproto/jwk-jose";
|
|
2
|
+
import { createDpopProof, dpopJktForKey } from "@atproto/space";
|
|
3
|
+
export class DpopKey {
|
|
4
|
+
key;
|
|
5
|
+
thumbprint;
|
|
6
|
+
constructor(key, thumbprint) {
|
|
7
|
+
this.key = key;
|
|
8
|
+
this.thumbprint = thumbprint;
|
|
9
|
+
}
|
|
10
|
+
static async generate() {
|
|
11
|
+
const key = await JoseKey.generate(["ES256"]);
|
|
12
|
+
return new DpopKey(key, await dpopJktForKey(key));
|
|
13
|
+
}
|
|
14
|
+
static async fromJwk(jwk) {
|
|
15
|
+
const key = await JoseKey.fromImportable(JSON.parse(jwk));
|
|
16
|
+
return new DpopKey(key, await dpopJktForKey(key));
|
|
17
|
+
}
|
|
18
|
+
exportJwk() {
|
|
19
|
+
return JSON.stringify(this.key.privateJwk);
|
|
20
|
+
}
|
|
21
|
+
proof({ method, url, credential }) {
|
|
22
|
+
const htu = canonicalHtu(url);
|
|
23
|
+
return createDpopProof(this.key, credential ? { htm: method, htu, credential } : { htm: method, htu });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const canonicalHtu = (url) => {
|
|
27
|
+
const parsed = new URL(url);
|
|
28
|
+
parsed.search = "";
|
|
29
|
+
parsed.hash = "";
|
|
30
|
+
return parsed.toString();
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=dpop.js.map
|
package/dist/dpop.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpop.js","sourceRoot":"","sources":["../src/dpop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQhE,MAAM,OAAO,OAAO;IAED,GAAG;IACX,UAAU;IAFpB,YACkB,GAAY,EACpB,UAAkB;mBADV,GAAG;0BACX,UAAU;IACjB,CAAC;IAEJ,MAAM,CAAC,KAAK,CAAC,QAAQ;QACpB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9C,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAW;QAC/B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,SAAS;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAoB;QAClD,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,eAAe,CACrB,IAAI,CAAC,GAAG,EACR,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CACpE,CAAC;IACH,CAAC;CACD;AAED,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;IACjB,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class XrpcError extends Error {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly code: string;
|
|
4
|
+
readonly method: string;
|
|
5
|
+
constructor(status: number, code: string, message: string, method: string);
|
|
6
|
+
get isAuthFailure(): boolean;
|
|
7
|
+
get isExpiredToken(): boolean;
|
|
8
|
+
get isSpaceDeleted(): boolean;
|
|
9
|
+
get isNotFound(): boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class SpaceCredentialError extends Error {
|
|
12
|
+
readonly space: string;
|
|
13
|
+
readonly reason: "noDelegationToken" | "invalidDelegationToken" | "hostUnresolvable" | "refused" | "spaceDeleted" | "upstream";
|
|
14
|
+
constructor(space: string, reason: "noDelegationToken" | "invalidDelegationToken" | "hostUnresolvable" | "refused" | "spaceDeleted" | "upstream", message: string, options?: {
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export declare class SpaceRefError extends Error {
|
|
19
|
+
constructor(value: string);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;IAElC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAJxB,YACU,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,EAIvB;IAED,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;CACD;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAE7C,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,MAAM,EACZ,mBAAmB,GACnB,wBAAwB,GACxB,kBAAkB,GAClB,SAAS,GACT,cAAc,GACd,UAAU;IARd,YACU,KAAK,EAAE,MAAM,EACb,MAAM,EACZ,mBAAmB,GACnB,wBAAwB,GACxB,kBAAkB,GAClB,SAAS,GACT,cAAc,GACd,UAAU,EACb,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAI7B;CACD;AAED,qBAAa,aAAc,SAAQ,KAAK;IACvC,YAAY,KAAK,EAAE,MAAM,EAGxB;CACD"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class XrpcError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
code;
|
|
4
|
+
method;
|
|
5
|
+
constructor(status, code, message, method) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.method = method;
|
|
10
|
+
this.name = "XrpcError";
|
|
11
|
+
}
|
|
12
|
+
get isAuthFailure() {
|
|
13
|
+
return this.status === 401 || this.status === 403;
|
|
14
|
+
}
|
|
15
|
+
get isExpiredToken() {
|
|
16
|
+
return this.code === "ExpiredToken";
|
|
17
|
+
}
|
|
18
|
+
get isSpaceDeleted() {
|
|
19
|
+
return this.code === "SpaceDeleted";
|
|
20
|
+
}
|
|
21
|
+
get isNotFound() {
|
|
22
|
+
return this.status === 404 || this.code.endsWith("NotFound");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class SpaceCredentialError extends Error {
|
|
26
|
+
space;
|
|
27
|
+
reason;
|
|
28
|
+
constructor(space, reason, message, options) {
|
|
29
|
+
super(message, options);
|
|
30
|
+
this.space = space;
|
|
31
|
+
this.reason = reason;
|
|
32
|
+
this.name = "SpaceCredentialError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class SpaceRefError extends Error {
|
|
36
|
+
constructor(value) {
|
|
37
|
+
super(`not a space reference: ${value}`);
|
|
38
|
+
this.name = "SpaceRefError";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAU,SAAQ,KAAK;IAEzB,MAAM;IACN,IAAI;IAEJ,MAAM;IAJhB,YACU,MAAc,EACd,IAAY,EACrB,OAAe,EACN,MAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;sBALN,MAAM;oBACN,IAAI;sBAEJ,MAAM;QAGf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IACzB,CAAC;IAED,IAAI,aAAa;QAChB,OAAO,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC;IACnD,CAAC;IAED,IAAI,cAAc;QACjB,OAAO,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC;IACrC,CAAC;IAED,IAAI,cAAc;QACjB,OAAO,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC;IACrC,CAAC;IAED,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC;CACD;AAED,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAEpC,KAAK;IACL,MAAM;IAFhB,YACU,KAAa,EACb,MAMI,EACb,OAAe,EACf,OAA6B;QAE7B,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;qBAXf,KAAK;sBACL,MAAM;QAWf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACpC,CAAC;CACD;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACvC,YAAY,KAAa;QACxB,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC7B,CAAC;CACD"}
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DidResolver } from "@atproto/identity";
|
|
2
|
+
export declare const SPACE_HOST_SERVICE_ID = "#atproto_space_host";
|
|
3
|
+
export declare const PDS_SERVICE_ID = "#atproto_pds";
|
|
4
|
+
export type SpaceHostResolver = {
|
|
5
|
+
hostFor(authority: string): Promise<string>;
|
|
6
|
+
};
|
|
7
|
+
export type DidDocumentHostResolverOptions = {
|
|
8
|
+
plcUrl?: string;
|
|
9
|
+
resolver?: DidResolver;
|
|
10
|
+
};
|
|
11
|
+
export declare class DidDocumentSpaceHostResolver implements SpaceHostResolver {
|
|
12
|
+
private readonly resolver;
|
|
13
|
+
constructor(options?: DidDocumentHostResolverOptions);
|
|
14
|
+
hostFor(authority: string): Promise<string>;
|
|
15
|
+
}
|
|
16
|
+
export declare class StaticSpaceHostResolver implements SpaceHostResolver {
|
|
17
|
+
private readonly hosts;
|
|
18
|
+
constructor(hosts: Map<string, string>);
|
|
19
|
+
hostFor(authority: string): Promise<string>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,mBAAmB,CAAC;AAG7D,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAC3D,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAE7C,MAAM,MAAM,iBAAiB,GAAG;IAC/B,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5C,CAAC;AAUF,MAAM,MAAM,8BAA8B,GAAG;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF,qBAAa,4BAA6B,YAAW,iBAAiB;IACrE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IAEvC,YAAY,OAAO,GAAE,8BAAmC,EAOvD;IAEK,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBhD;CACD;AAED,qBAAa,uBAAwB,YAAW,iBAAiB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAlC,YAA6B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAI;IAErD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUhD;CACD"}
|
package/dist/host.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DidResolver, MemoryCache } from "@atproto/identity";
|
|
2
|
+
import { SpaceCredentialError } from "./errors.js";
|
|
3
|
+
export const SPACE_HOST_SERVICE_ID = "#atproto_space_host";
|
|
4
|
+
export const PDS_SERVICE_ID = "#atproto_pds";
|
|
5
|
+
const endpointOf = (services, id) => {
|
|
6
|
+
const match = services.find((service) => service.id === id || service.id.endsWith(id));
|
|
7
|
+
if (!match || typeof match.serviceEndpoint !== "string")
|
|
8
|
+
return null;
|
|
9
|
+
return match.serviceEndpoint.replace(/\/$/, "");
|
|
10
|
+
};
|
|
11
|
+
export class DidDocumentSpaceHostResolver {
|
|
12
|
+
resolver;
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.resolver =
|
|
15
|
+
options.resolver ??
|
|
16
|
+
new DidResolver({
|
|
17
|
+
plcUrl: options.plcUrl ?? "https://plc.directory",
|
|
18
|
+
didCache: new MemoryCache(60 * 60 * 1000, 24 * 60 * 60 * 1000),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async hostFor(authority) {
|
|
22
|
+
const document = await this.resolver.resolve(authority).catch((cause) => {
|
|
23
|
+
throw new SpaceCredentialError(authority, "hostUnresolvable", `cannot resolve ${authority}`, {
|
|
24
|
+
cause,
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
const services = (document?.service ?? []);
|
|
28
|
+
const endpoint = endpointOf(services, SPACE_HOST_SERVICE_ID) ?? endpointOf(services, PDS_SERVICE_ID);
|
|
29
|
+
if (!endpoint) {
|
|
30
|
+
throw new SpaceCredentialError(authority, "hostUnresolvable", `${authority} publishes neither ${SPACE_HOST_SERVICE_ID} nor ${PDS_SERVICE_ID}`);
|
|
31
|
+
}
|
|
32
|
+
return endpoint;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class StaticSpaceHostResolver {
|
|
36
|
+
hosts;
|
|
37
|
+
constructor(hosts) {
|
|
38
|
+
this.hosts = hosts;
|
|
39
|
+
}
|
|
40
|
+
async hostFor(authority) {
|
|
41
|
+
const host = this.hosts.get(authority);
|
|
42
|
+
if (!host) {
|
|
43
|
+
throw new SpaceCredentialError(authority, "hostUnresolvable", `no host configured for ${authority}`);
|
|
44
|
+
}
|
|
45
|
+
return host;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=host.js.map
|
package/dist/host.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,CAAC,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAC3D,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAQ7C,MAAM,UAAU,GAAG,CAAC,QAAsB,EAAE,EAAU,EAAiB,EAAE;IACxE,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACvF,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,eAAe,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACrE,OAAO,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACjD,CAAC,CAAC;AAOF,MAAM,OAAO,4BAA4B;IACvB,QAAQ,CAAc;IAEvC,YAAY,OAAO,GAAmC,EAAE;QACvD,IAAI,CAAC,QAAQ;YACZ,OAAO,CAAC,QAAQ;gBAChB,IAAI,WAAW,CAAC;oBACf,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,uBAAuB;oBACjD,QAAQ,EAAE,IAAI,WAAW,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;iBAC9D,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAiB;QAC9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACvE,MAAM,IAAI,oBAAoB,CAAC,SAAS,EAAE,kBAAkB,EAAE,kBAAkB,SAAS,EAAE,EAAE;gBAC5F,KAAK;aACL,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAiB,CAAC;QAC3D,MAAM,QAAQ,GACb,UAAU,CAAC,QAAQ,EAAE,qBAAqB,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACrF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,oBAAoB,CAC7B,SAAS,EACT,kBAAkB,EAClB,GAAG,SAAS,sBAAsB,qBAAqB,QAAQ,cAAc,EAAE,CAC/E,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC;CACD;AAED,MAAM,OAAO,uBAAuB;IACN,KAAK;IAAlC,YAA6B,KAA0B;qBAA1B,KAAK;IAAwB,CAAC;IAE3D,KAAK,CAAC,OAAO,CAAC,SAAiB;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,MAAM,IAAI,oBAAoB,CAC7B,SAAS,EACT,kBAAkB,EAClB,0BAA0B,SAAS,EAAE,CACrC,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;CACD"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { DpopKey } from "./dpop.js";
|
|
2
|
+
export type Auth = {
|
|
3
|
+
kind: "none";
|
|
4
|
+
} | {
|
|
5
|
+
kind: "bearer";
|
|
6
|
+
token: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "basic";
|
|
9
|
+
user: string;
|
|
10
|
+
password: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "dpopGrant";
|
|
13
|
+
token: string;
|
|
14
|
+
key: DpopKey;
|
|
15
|
+
} | {
|
|
16
|
+
kind: "dpopCredential";
|
|
17
|
+
credential: string;
|
|
18
|
+
key: DpopKey;
|
|
19
|
+
};
|
|
20
|
+
export type QueryParams = Record<string, string | number | boolean | undefined | null | Array<string | number>>;
|
|
21
|
+
export type XrpcClientOptions = {
|
|
22
|
+
service: string;
|
|
23
|
+
fetch?: typeof globalThis.fetch;
|
|
24
|
+
timeoutMs?: number;
|
|
25
|
+
userAgent?: string;
|
|
26
|
+
};
|
|
27
|
+
export declare class XrpcClient {
|
|
28
|
+
private readonly options;
|
|
29
|
+
private readonly fetchImpl;
|
|
30
|
+
private readonly timeoutMs;
|
|
31
|
+
constructor(options: XrpcClientOptions);
|
|
32
|
+
get service(): string;
|
|
33
|
+
query<T>(nsid: string, params?: QueryParams, auth?: Auth): Promise<T>;
|
|
34
|
+
procedure<T>(nsid: string, body?: unknown, auth?: Auth): Promise<T>;
|
|
35
|
+
stream(nsid: string, params?: QueryParams, auth?: Auth): Promise<Response>;
|
|
36
|
+
private urlFor;
|
|
37
|
+
private headersFor;
|
|
38
|
+
private send;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,MAAM,MAAM,IAAI,GACb;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhE,MAAM,MAAM,WAAW,GAAG,MAAM,CAC/B,MAAM,EACN,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CACrE,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AA2BF,qBAAa,UAAU;IAIV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YAA6B,OAAO,EAAE,iBAAiB,EAGtD;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAEK,KAAK,CAAC,CAAC,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,WAAgB,EACxB,IAAI,GAAE,IAAuB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAGZ;IAEK,SAAS,CAAC,CAAC,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,OAAmB,EACzB,IAAI,GAAE,IAAuB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAKZ;IAEK,MAAM,CACX,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,WAAgB,EACxB,IAAI,GAAE,IAAuB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CAEnB;IAED,OAAO,CAAC,MAAM;YAKA,UAAU;YA4BV,IAAI;CAuBlB"}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { XrpcError } from "./errors.js";
|
|
2
|
+
const encodeParams = (params) => {
|
|
3
|
+
const search = new URLSearchParams();
|
|
4
|
+
for (const [key, value] of Object.entries(params)) {
|
|
5
|
+
if (value === undefined || value === null)
|
|
6
|
+
continue;
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
for (const entry of value)
|
|
9
|
+
search.append(key, String(entry));
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
search.append(key, String(value));
|
|
13
|
+
}
|
|
14
|
+
return search.toString();
|
|
15
|
+
};
|
|
16
|
+
const parseFailure = async (response, method) => {
|
|
17
|
+
const body = await response.text().catch(() => "");
|
|
18
|
+
let code = response.status === 401 ? "AuthRequired" : "UpstreamFailure";
|
|
19
|
+
let message = body || response.statusText;
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(body);
|
|
22
|
+
if (parsed.error)
|
|
23
|
+
code = parsed.error;
|
|
24
|
+
if (parsed.message)
|
|
25
|
+
message = parsed.message;
|
|
26
|
+
}
|
|
27
|
+
catch { }
|
|
28
|
+
return new XrpcError(response.status, code, message, method);
|
|
29
|
+
};
|
|
30
|
+
export class XrpcClient {
|
|
31
|
+
options;
|
|
32
|
+
fetchImpl;
|
|
33
|
+
timeoutMs;
|
|
34
|
+
constructor(options) {
|
|
35
|
+
this.options = options;
|
|
36
|
+
this.fetchImpl = options.fetch ?? globalThis.fetch;
|
|
37
|
+
this.timeoutMs = options.timeoutMs ?? 30_000;
|
|
38
|
+
}
|
|
39
|
+
get service() {
|
|
40
|
+
return this.options.service;
|
|
41
|
+
}
|
|
42
|
+
async query(nsid, params = {}, auth = { kind: "none" }) {
|
|
43
|
+
const response = await this.send(nsid, "GET", params, undefined, auth);
|
|
44
|
+
return (await response.json());
|
|
45
|
+
}
|
|
46
|
+
async procedure(nsid, body = undefined, auth = { kind: "none" }) {
|
|
47
|
+
const response = await this.send(nsid, "POST", {}, body, auth);
|
|
48
|
+
if (response.status === 204)
|
|
49
|
+
return undefined;
|
|
50
|
+
const text = await response.text();
|
|
51
|
+
return (text ? JSON.parse(text) : undefined);
|
|
52
|
+
}
|
|
53
|
+
async stream(nsid, params = {}, auth = { kind: "none" }) {
|
|
54
|
+
return this.send(nsid, "GET", params, undefined, auth);
|
|
55
|
+
}
|
|
56
|
+
urlFor(nsid, params) {
|
|
57
|
+
const query = encodeParams(params);
|
|
58
|
+
return `${this.options.service.replace(/\/$/, "")}/xrpc/${nsid}${query ? `?${query}` : ""}`;
|
|
59
|
+
}
|
|
60
|
+
async headersFor(auth, method, url) {
|
|
61
|
+
const headers = new Headers({ accept: "application/json" });
|
|
62
|
+
if (this.options.userAgent)
|
|
63
|
+
headers.set("user-agent", this.options.userAgent);
|
|
64
|
+
switch (auth.kind) {
|
|
65
|
+
case "none":
|
|
66
|
+
break;
|
|
67
|
+
case "bearer":
|
|
68
|
+
headers.set("authorization", `Bearer ${auth.token}`);
|
|
69
|
+
break;
|
|
70
|
+
case "basic":
|
|
71
|
+
headers.set("authorization", `Basic ${Buffer.from(`${auth.user}:${auth.password}`).toString("base64")}`);
|
|
72
|
+
break;
|
|
73
|
+
case "dpopGrant":
|
|
74
|
+
headers.set("authorization", `Bearer ${auth.token}`);
|
|
75
|
+
headers.set("dpop", await auth.key.proof({ method, url }));
|
|
76
|
+
break;
|
|
77
|
+
case "dpopCredential":
|
|
78
|
+
headers.set("authorization", `DPoP ${auth.credential}`);
|
|
79
|
+
headers.set("dpop", await auth.key.proof({ method, url, credential: auth.credential }));
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
return headers;
|
|
83
|
+
}
|
|
84
|
+
async send(nsid, method, params, body, auth) {
|
|
85
|
+
const url = this.urlFor(nsid, params);
|
|
86
|
+
const attempt = async () => {
|
|
87
|
+
const headers = await this.headersFor(auth, method, url);
|
|
88
|
+
if (body !== undefined)
|
|
89
|
+
headers.set("content-type", "application/json");
|
|
90
|
+
return this.fetchImpl(url, {
|
|
91
|
+
method,
|
|
92
|
+
headers,
|
|
93
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
94
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
const response = await attempt();
|
|
98
|
+
if (!response.ok)
|
|
99
|
+
throw await parseFailure(response, nsid);
|
|
100
|
+
return response;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./credentials.js";
|
|
2
|
+
export * from "./dpop.js";
|
|
3
|
+
export * from "./errors.js";
|
|
4
|
+
export * from "./host.js";
|
|
5
|
+
export * from "./http.js";
|
|
6
|
+
export * from "./pds.js";
|
|
7
|
+
export * from "./repo.js";
|
|
8
|
+
export * from "./session.js";
|
|
9
|
+
export * from "./space-client.js";
|
|
10
|
+
export * from "./space-ref.js";
|
|
11
|
+
export * from "./tid.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./credentials.js";
|
|
2
|
+
export * from "./dpop.js";
|
|
3
|
+
export * from "./errors.js";
|
|
4
|
+
export * from "./host.js";
|
|
5
|
+
export * from "./http.js";
|
|
6
|
+
export * from "./pds.js";
|
|
7
|
+
export * from "./repo.js";
|
|
8
|
+
export * from "./session.js";
|
|
9
|
+
export * from "./space-client.js";
|
|
10
|
+
export * from "./space-ref.js";
|
|
11
|
+
export * from "./tid.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC"}
|