@synonymdev/pubky 0.6.0 → 0.8.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.
Files changed (6) hide show
  1. package/README.md +1 -1
  2. package/index.cjs +2323 -1989
  3. package/index.js +2305 -2117
  4. package/package.json +1 -1
  5. package/pubky.d.ts +1176 -840
  6. package/pubky_bg.wasm +0 -0
package/pubky.d.ts CHANGED
@@ -1,64 +1,17 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
- /**
4
- * Set the global logging verbosity for the WASM Pubky SDK. Routes Rust `log` output to the browser console.
5
- *
6
- * Accepted values (case-sensitive): "error" | "warn" | "info" | "debug" | "trace".
7
- * Effects:
8
- * - Initializes the logger once; subsequent calls may throw if the logger is already set.
9
- * - Emits a single info log: `Log level set to: <level>`.
10
- * - Messages at or above `level` are forwarded to the appropriate `console.*` method.
11
- *
12
- * @param {Level} level
13
- * Minimum log level to enable. One of: "error" | "warn" | "info" | "debug" | "trace".
14
- *
15
- * @returns {void}
16
- *
17
- * @throws {Error}
18
- * If `level` is invalid ("Invalid log level") or the logger cannot be initialized
19
- * (e.g., already initialized).
20
- *
21
- * Usage:
22
- * Call once at application startup, before invoking other SDK APIs.
23
- */
24
- export function setLogLevel(level: Level): void;
25
- /**
26
- * Resolve a `pubky://` or `pubky<pk>/…` identifier into the homeserver transport URL.
27
- *
28
- * @param {string} identifier Either `pubky<pk>/...` (preferred) or `pubky://<pk>/...`.
29
- * @returns {string} HTTPS URL in the form `https://_pubky.<pk>/...`.
30
- */
31
- export function resolvePubky(identifier: string): string;
32
- /**
33
- * Validate and normalize a capabilities string.
34
- *
35
- * - Normalizes action order (`wr` -> `rw`)
36
- * - Throws `InvalidInput` listing malformed entries.
37
- *
38
- * @param {string} input
39
- * @returns {string} Normalized string (same shape as input).
40
- * @throws {PubkyError} `{ name: "InvalidInput" }` with a helpful message.
41
- * The error's `data` field is `{ invalidEntries: string[] }` listing malformed tokens.
42
- */
43
- export function validateCapabilities(input: string): string;
44
3
  /**
45
4
  * An enum representing the available verbosity levels of the logger.
46
5
  */
6
+
47
7
  type Level = "error" | "warn" | "info" | "debug" | "trace";
48
8
  /**
49
9
  * The `ReadableStreamType` enum.
50
10
  *
51
11
  * *This API requires the following crate features to be activated: `ReadableStreamType`*
52
12
  */
53
- type ReadableStreamType = "bytes";
54
- export type Path = `/pub/${string}`;
55
-
56
- export type CapabilityAction = "r" | "w" | "rw";
57
- export type CapabilityScope = `/${string}`;
58
- export type CapabilityEntry = `${CapabilityScope}:${CapabilityAction}`;
59
- type CapabilitiesTail = `,${CapabilityEntry}${string}`;
60
- export type Capabilities = "" | CapabilityEntry | `${CapabilityEntry}${CapabilitiesTail}`;
61
13
 
14
+ type ReadableStreamType = "bytes";
62
15
  /**
63
16
  * A union type of all possible machine-readable codes for the `name` property
64
17
  * of a {@link PubkyError}.
@@ -68,6 +21,31 @@ export type Capabilities = "" | CapabilityEntry | `${CapabilityEntry}${Capabilit
68
21
  */
69
22
  export type PubkyErrorName = "RequestError" | "InvalidInput" | "AuthenticationError" | "PkarrError" | "ClientStateError" | "InternalError";
70
23
 
24
+ /**
25
+ * Pkarr Config
26
+ */
27
+ export interface PkarrConfig {
28
+ /**
29
+ * The list of relays to access the DHT with.
30
+ */
31
+ relays?: string[];
32
+ /**
33
+ * The timeout for DHT requests in milliseconds.
34
+ * Default is 2000ms.
35
+ */
36
+ requestTimeout?: number;
37
+ }
38
+
39
+ /**
40
+ * Pubky Client Config
41
+ */
42
+ export interface PubkyClientConfig {
43
+ /**
44
+ * Configuration on how to access pkarr packets on the mainline DHT.
45
+ */
46
+ pkarr?: PkarrConfig;
47
+ }
48
+
71
49
  /**
72
50
  * Represents the standard error structure for all exceptions thrown by the Pubky
73
51
  * WASM client.
@@ -83,10 +61,10 @@ export type PubkyErrorName = "RequestError" | "InvalidInput" | "AuthenticationEr
83
61
  * } catch (e) {
84
62
  * const error = e as PubkyError;
85
63
  * if (
86
- * error.name === \'RequestError\' &&
87
- * typeof error.data === \'object\' &&
64
+ * error.name === "RequestError" &&
65
+ * typeof error.data === "object" &&
88
66
  * error.data !== null &&
89
- * \'statusCode\' in error.data &&
67
+ * "statusCode" in error.data &&
90
68
  * (error.data as { statusCode?: number }).statusCode === 404
91
69
  * ) {
92
70
  * // Handle not found...
@@ -94,12 +72,9 @@ export type PubkyErrorName = "RequestError" | "InvalidInput" | "AuthenticationEr
94
72
  * }
95
73
  * ```
96
74
  */
97
- export interface PubkyError {
75
+ export interface PubkyError extends Error {
98
76
  name: PubkyErrorName;
99
77
  message: string;
100
- /**
101
- * Optional structured context associated with the error.
102
- */
103
78
  data?: unknown;
104
79
  }
105
80
 
@@ -118,10 +93,10 @@ export interface PubkyError {
118
93
  * } catch (e) {
119
94
  * const error = e as PubkyError;
120
95
  * if (
121
- * error.name === "RequestError" &&
122
- * typeof error.data === "object" &&
96
+ * error.name === \'RequestError\' &&
97
+ * typeof error.data === \'object\' &&
123
98
  * error.data !== null &&
124
- * "statusCode" in error.data &&
99
+ * \'statusCode\' in error.data &&
125
100
  * (error.data as { statusCode?: number }).statusCode === 404
126
101
  * ) {
127
102
  * // Handle not found...
@@ -129,37 +104,13 @@ export interface PubkyError {
129
104
  * }
130
105
  * ```
131
106
  */
132
- export interface PubkyError extends Error {
133
- name: PubkyErrorName;
134
- message: string;
135
- data?: unknown;
136
- }
137
-
138
- export type Address = `pubky${string}/pub/${string}` | `pubky://${string}/pub/${string}`;
139
-
140
- /**
141
- * Pkarr Config
142
- */
143
- export interface PkarrConfig {
144
- /**
145
- * The list of relays to access the DHT with.
146
- */
147
- relays?: string[];
148
- /**
149
- * The timeout for DHT requests in milliseconds.
150
- * Default is 2000ms.
151
- */
152
- requestTimeout?: number;
153
- }
154
-
155
- /**
156
- * Pubky Client Config
157
- */
158
- export interface PubkyClientConfig {
107
+ export interface PubkyError {
108
+ name: PubkyErrorName;
109
+ message: string;
159
110
  /**
160
- * Configuration on how to access pkarr packets on the mainline DHT.
111
+ * Optional structured context associated with the error.
161
112
  */
162
- pkarr?: PkarrConfig;
113
+ data?: unknown;
163
114
  }
164
115
 
165
116
  /**
@@ -201,6 +152,17 @@ export interface ResourceStats {
201
152
  etag?: string;
202
153
  }
203
154
 
155
+ export type Address = `pubky${string}/pub/${string}` | `pubky://${string}/pub/${string}`;
156
+
157
+ export type CapabilityAction = "r" | "w" | "rw";
158
+ export type CapabilityScope = `/${string}`;
159
+ export type CapabilityEntry = `${CapabilityScope}:${CapabilityAction}`;
160
+ type CapabilitiesTail = `,${CapabilityEntry}${string}`;
161
+ export type Capabilities = "" | CapabilityEntry | `${CapabilityEntry}${CapabilitiesTail}`;
162
+
163
+ export type Path = `/pub/${string}`;
164
+
165
+
204
166
  /**
205
167
  * Start and control a pubkyauth authorization flow.
206
168
  *
@@ -210,107 +172,129 @@ export interface ResourceStats {
210
172
  * 3) `awaitApproval()` to receive a ready `Session`
211
173
  */
212
174
  export class AuthFlow {
213
- private constructor();
214
- free(): void;
215
- [Symbol.dispose](): void;
216
- /**
217
- * Start a flow (standalone).
218
- * Prefer `pubky.startAuthFlow()` to reuse a facade client.
219
- *
220
- * @param {string} capabilities
221
- * Comma-separated capabilities, e.g. `"/pub/app/:rw,/priv/foo.txt:r"`.
222
- * Each entry must be `"<scope>:<actions>"`, where:
223
- * - `scope` starts with `/` (e.g. `/pub/example.com/`)
224
- * - `actions` is any combo of `r` and/or `w` (order is normalized; `wr` -> `rw`)
225
- * Empty string is allowed (no scopes).
226
- *
227
- * @param {AuthFlowKind} kind
228
- * The kind of authentication flow to perform.
229
- * This can either be a sign in or a sign up flow.
230
- * Examples:
231
- * - `AuthFlowKind.signin()` - Sign in to an existing account.
232
- * - `AuthFlowKind.signup(homeserverPublicKey, signupToken)` - Sign up for a new account.
233
- *
234
- * @param {string} [relay]
235
- * Optional HTTP relay base, e.g. `"https://demo.httprelay.io/link/"`.
236
- * Defaults to the default Synonym-hosted relay when omitted.
237
- *
238
- * @returns {AuthFlow}
239
- * A running auth flow. Call `authorizationUrl()` to show the deep link,
240
- * then `awaitApproval()` to receive a `Session`.
241
- * @throws {PubkyError}
242
- * - `{ name: "InvalidInput", message: string }` if any capability entry is invalid
243
- * or for an invalid relay URL.
244
- * @example
245
- * const flow = AuthFlow.start("/pub/my-cool-app/:rw,/pub/pubky.app/:w");
246
- * renderQRCode(flow.authorizationUrl());
247
- * const session = await flow.awaitApproval();
248
- */
249
- static start(capabilities: Capabilities, kind: AuthFlowKind, relay?: string | null): AuthFlow;
250
- /**
251
- * Block until the user approves on their signer device; returns a `Session`.
252
- *
253
- * @returns {Promise<Session>}
254
- * Resolves when approved; rejects on timeout/cancel/network errors.
255
- *
256
- * @throws {PubkyError}
257
- * - `RequestError` if relay/network fails
258
- * - `AuthenticationError` if approval is denied/invalid
259
- */
260
- awaitApproval(): Promise<Session>;
261
- /**
262
- * Block until the user approves on their signer device; returns an `AuthToken`.
263
- *
264
- * @returns {Promise<AuthToken>}
265
- * Resolves when approved; rejects on timeout/cancel/network errors.
266
- *
267
- * @throws {PubkyError}
268
- * - `RequestError` if relay/network fails
269
- */
270
- awaitToken(): Promise<AuthToken>;
271
- /**
272
- * Non-blocking single poll step (advanced UIs).
273
- *
274
- * @returns {Promise<Session|undefined>} A session if the approval arrived, otherwise `undefined`.
275
- */
276
- tryPollOnce(): Promise<Session | undefined>;
277
- /**
278
- * Return the authorization deep link (URL) to show as QR or open on the signer device.
279
- *
280
- * @returns {string} A `pubkyauth://…` or `https://…` URL with channel info.
281
- *
282
- * @example
283
- * renderQr(flow.authorizationUrl());
284
- */
285
- readonly authorizationUrl: string;
175
+ private constructor();
176
+ free(): void;
177
+ [Symbol.dispose](): void;
178
+ /**
179
+ * Block until the user approves on their signer device; returns a `Session`.
180
+ *
181
+ * @returns {Promise<Session>}
182
+ * Resolves when approved; rejects on timeout/cancel/network errors.
183
+ *
184
+ * @throws {PubkyError}
185
+ * - `RequestError` if relay/network fails
186
+ * - `AuthenticationError` if approval is denied/invalid
187
+ */
188
+ awaitApproval(): Promise<Session>;
189
+ /**
190
+ * Block until the user approves on their signer device; returns an `AuthToken`.
191
+ *
192
+ * @returns {Promise<AuthToken>}
193
+ * Resolves when approved; rejects on timeout/cancel/network errors.
194
+ *
195
+ * @throws {PubkyError}
196
+ * - `RequestError` if relay/network fails
197
+ */
198
+ awaitToken(): Promise<AuthToken>;
199
+ /**
200
+ * Resume a previously started auth flow from its saved `authorizationUrl` (standalone).
201
+ * Prefer `pubky.resumeAuthFlow()` to reuse a facade client; this creates a default (mainnet) client.
202
+ *
203
+ * Relay messages expire after ~5 minutes; resume is only viable in that window.
204
+ * See `Pubky.resumeAuthFlow()` / `Pubky.startAuthFlow()` for full guidance.
205
+ *
206
+ * **Security:** `authorizationUrl` contains the `client_secret`.
207
+ * Delete it from storage as soon as resume completes or is abandoned.
208
+ *
209
+ * @param {string} authorizationUrl The `pubkyauth://…` URL from a previous flow.
210
+ * @returns {AuthFlow} A flow reconnected to the original relay channel.
211
+ * @throws {PubkyError}
212
+ * - `{ name: "AuthenticationError" }` if the URL is invalid or not a signin/signup link
213
+ */
214
+ static resume(authorization_url: string): AuthFlow;
215
+ /**
216
+ * Start a flow (standalone).
217
+ * Prefer `pubky.startAuthFlow()` to reuse a facade client.
218
+ *
219
+ * @param {string} capabilities
220
+ * Comma-separated capabilities, e.g. `"/pub/app/:rw,/priv/foo.txt:r"`.
221
+ * Each entry must be `"<scope>:<actions>"`, where:
222
+ * - `scope` starts with `/` (e.g. `/pub/example.com/`)
223
+ * - `actions` is any combo of `r` and/or `w` (order is normalized; `wr` -> `rw`)
224
+ * Empty string is allowed (no scopes).
225
+ *
226
+ * @param {AuthFlowKind} kind
227
+ * The kind of authentication flow to perform.
228
+ * This can either be a sign in or a sign up flow.
229
+ * Examples:
230
+ * - `AuthFlowKind.signin()` - Sign in to an existing account.
231
+ * - `AuthFlowKind.signup(homeserverPublicKey, signupToken)` - Sign up for a new account.
232
+ *
233
+ * @param {string} [relay]
234
+ * Optional HTTP relay base, e.g. `"https://demo.httprelay.io/inbox/"`.
235
+ * Defaults to the default Synonym-hosted relay when omitted.
236
+ *
237
+ * @returns {AuthFlow}
238
+ * A running auth flow. Call `authorizationUrl()` to show the deep link,
239
+ * then `awaitApproval()` to receive a `Session`.
240
+ * @throws {PubkyError}
241
+ * - `{ name: "InvalidInput", message: string }` if any capability entry is invalid
242
+ * or for an invalid relay URL.
243
+ * @example
244
+ * const flow = AuthFlow.start("/pub/my-cool-app/:rw,/pub/pubky.app/:w");
245
+ * renderQRCode(flow.authorizationUrl());
246
+ * const session = await flow.awaitApproval();
247
+ */
248
+ static start(capabilities: Capabilities, kind: AuthFlowKind, relay?: string | null): AuthFlow;
249
+ /**
250
+ * Non-blocking single poll step (advanced UIs).
251
+ *
252
+ * @returns {Promise<Session|undefined>} A session if the approval arrived, otherwise `undefined`.
253
+ */
254
+ tryPollOnce(): Promise<Session | undefined>;
255
+ /**
256
+ * Return the authorization deep link (URL) to show as QR or open on the signer device.
257
+ *
258
+ * **Security:** This URL contains the `client_secret` in plaintext.
259
+ * Treat it as a short-lived secret and delete it after the flow completes.
260
+ * See `Pubky.startAuthFlow()` docs for storage guidance.
261
+ *
262
+ * @returns {string} A `pubkyauth://…` or `https://…` URL with channel info.
263
+ *
264
+ * @example
265
+ * renderQr(flow.authorizationUrl);
266
+ */
267
+ readonly authorizationUrl: string;
286
268
  }
269
+
287
270
  /**
288
271
  * The kind of authentication flow to perform.
289
272
  * This can either be a sign in or a sign up flow.
290
273
  */
291
274
  export class AuthFlowKind {
292
- private constructor();
293
- free(): void;
294
- [Symbol.dispose](): void;
295
- /**
296
- * Create a sign in flow.
297
- */
298
- static signin(): AuthFlowKind;
299
- /**
300
- * Create a sign up flow.
301
- * # Arguments
302
- * * `homeserver_public_key` - The public key of the homeserver to sign up on.
303
- * * `signup_token` - The signup token to use for the signup flow. This is optional.
304
- */
305
- static signup(homeserver_public_key: PublicKey, signup_token?: string | null): AuthFlowKind;
306
- /**
307
- * Get the intent of the authentication flow.
308
- * # Returns
309
- * * `"signin"` - If the authentication flow is a sign in flow.
310
- * * `"signup"` - If the authentication flow is a sign up flow.
311
- */
312
- readonly intent: string;
275
+ private constructor();
276
+ free(): void;
277
+ [Symbol.dispose](): void;
278
+ /**
279
+ * Create a sign in flow.
280
+ */
281
+ static signin(): AuthFlowKind;
282
+ /**
283
+ * Create a sign up flow.
284
+ * # Arguments
285
+ * * `homeserver_public_key` - The public key of the homeserver to sign up on.
286
+ * * `signup_token` - The signup token to use for the signup flow. This is optional.
287
+ */
288
+ static signup(homeserver_public_key: PublicKey, signup_token?: string | null): AuthFlowKind;
289
+ /**
290
+ * Get the intent of the authentication flow.
291
+ * # Returns
292
+ * * `"signin"` - If the authentication flow is a sign in flow.
293
+ * * `"signup"` - If the authentication flow is a sign up flow.
294
+ */
295
+ readonly intent: string;
313
296
  }
297
+
314
298
  /**
315
299
  * AuthToken: signed, time-bound proof of key ownership.
316
300
  *
@@ -338,70 +322,71 @@ export class AuthFlowKind {
338
322
  * `Uint8Array`, and [`AuthToken.verify()`] to parse + verify on the server.
339
323
  */
340
324
  export class AuthToken {
341
- private constructor();
342
- free(): void;
343
- [Symbol.dispose](): void;
344
- /**
345
- * Parse and verify an `AuthToken` from its canonical bytes.
346
- *
347
- * - Verifies version, timestamp freshness window, and signature.
348
- * - Throws on invalid/expired/unknown version.
349
- *
350
- * Use this on your server after receiving `Uint8Array` from the client.
351
- *
352
- * ```js
353
- * import { AuthToken } from "@synonymdev/pubky";
354
- *
355
- * export async function POST(req) {
356
- * const bytes = new Uint8Array(await req.arrayBuffer());
357
- * const token = AuthToken.verify(bytes); // throws on failure
358
- * return new Response(token.publicKey().toString(), { status: 200 });
359
- * }
360
- * ```
361
- */
362
- static verify(bytes: Uint8Array): AuthToken;
363
- /**
364
- * Deserialize an `AuthToken` **without** verification.
365
- *
366
- * Most apps should call [`AuthToken.verify()`]. This is provided for tooling or diagnostics
367
- * where you want to inspect the structure first.
368
- *
369
- * Throws if the bytes cannot be parsed as a valid serialized token.
370
- */
371
- static fromBytes(bytes: Uint8Array): AuthToken;
372
- /**
373
- * Serialize the token to a `Uint8Array` in its **canonical** (postcard) binary format.
374
- *
375
- * Use this to send the token to a backend for verification.
376
- *
377
- * ```js
378
- * const bytes = token.toBytes();
379
- * await fetch("/api/verify", { method: "POST", body: bytes });
380
- * ```
381
- */
382
- toBytes(): Uint8Array;
383
- /**
384
- * Returns the **public key** that authenticated with this token.
385
- *
386
- * Use `.toString()` on the returned `PublicKey` to get the `pubky<z32>` identifier.
387
- * Call `.z32()` when you specifically need the raw z-base32 value (e.g. hostnames).
388
- *
389
- * @example
390
- * const who = token.publicKey.toString();
391
- */
392
- readonly publicKey: PublicKey;
393
- /**
394
- * Returns the **capabilities** requested by the flow at the time this token was signed.
395
- *
396
- * Most auth-only flows pass an empty string to `startAuthFlow("", relay)`, so this will
397
- * commonly be an empty array.
398
- *
399
- * Returns: `string[]`, where each item is the canonical entry `"<scope>:<actions>"`.
400
- *
401
- * Example entry: `"/pub/my-cool-app/:rw"`
402
- */
403
- readonly capabilities: string[];
325
+ private constructor();
326
+ free(): void;
327
+ [Symbol.dispose](): void;
328
+ /**
329
+ * Deserialize an `AuthToken` **without** verification.
330
+ *
331
+ * Most apps should call [`AuthToken.verify()`]. This is provided for tooling or diagnostics
332
+ * where you want to inspect the structure first.
333
+ *
334
+ * Throws if the bytes cannot be parsed as a valid serialized token.
335
+ */
336
+ static fromBytes(bytes: Uint8Array): AuthToken;
337
+ /**
338
+ * Serialize the token to a `Uint8Array` in its **canonical** (postcard) binary format.
339
+ *
340
+ * Use this to send the token to a backend for verification.
341
+ *
342
+ * ```js
343
+ * const bytes = token.toBytes();
344
+ * await fetch("/api/verify", { method: "POST", body: bytes });
345
+ * ```
346
+ */
347
+ toBytes(): Uint8Array;
348
+ /**
349
+ * Parse and verify an `AuthToken` from its canonical bytes.
350
+ *
351
+ * - Verifies version, timestamp freshness window, and signature.
352
+ * - Throws on invalid/expired/unknown version.
353
+ *
354
+ * Use this on your server after receiving `Uint8Array` from the client.
355
+ *
356
+ * ```js
357
+ * import { AuthToken } from "@synonymdev/pubky";
358
+ *
359
+ * export async function POST(req) {
360
+ * const bytes = new Uint8Array(await req.arrayBuffer());
361
+ * const token = AuthToken.verify(bytes); // throws on failure
362
+ * return new Response(token.publicKey().toString(), { status: 200 });
363
+ * }
364
+ * ```
365
+ */
366
+ static verify(bytes: Uint8Array): AuthToken;
367
+ /**
368
+ * Returns the **capabilities** requested by the flow at the time this token was signed.
369
+ *
370
+ * Most auth-only flows pass an empty string to `startAuthFlow("", relay)`, so this will
371
+ * commonly be an empty array.
372
+ *
373
+ * Returns: `string[]`, where each item is the canonical entry `"<scope>:<actions>"`.
374
+ *
375
+ * Example entry: `"/pub/my-cool-app/:rw"`
376
+ */
377
+ readonly capabilities: string[];
378
+ /**
379
+ * Returns the **public key** that authenticated with this token.
380
+ *
381
+ * Use `.toString()` on the returned `PublicKey` to get the `pubky<z32>` identifier.
382
+ * Call `.z32()` when you specifically need the raw z-base32 value (e.g. hostnames).
383
+ *
384
+ * @example
385
+ * const who = token.publicKey.toString();
386
+ */
387
+ readonly publicKey: PublicKey;
404
388
  }
389
+
405
390
  /**
406
391
  * Low-level HTTP bridge used by the Pubky facade and actors.
407
392
  *
@@ -409,567 +394,872 @@ export class AuthToken {
409
394
  * - In browsers/undici, passes `credentials: "include"` to send cookies.
410
395
  */
411
396
  export class Client {
412
- free(): void;
413
- [Symbol.dispose](): void;
414
- /**
415
- * Perform a raw fetch. Works with `http(s)://` URLs.
416
- *
417
- * @param {string} url
418
- * @param {RequestInit} init Standard fetch options; `credentials: "include"` recommended for session I/O.
419
- * @returns {Promise<Response>}
420
- *
421
- * @example
422
- * const client = pubky.client;
423
- * const res = await client.fetch(`https://_pubky.${user}/pub/app/file.txt`, { method: "PUT", body: "hi", credentials: "include" });
424
- */
425
- fetch(url: string, init?: RequestInit | null): Promise<Response>;
426
- /**
427
- * Create a Pubky HTTP client.
428
- *
429
- * @param {PubkyClientConfig} [config]
430
- * Optional transport overrides:
431
- * `{ pkarr?: { relays?: string[], request_timeout?: number } }`.
432
- *
433
- * @returns {Client}
434
- * A configured low-level client. Prefer `new Pubky().client` unless you
435
- * need custom relays/timeouts.
436
- *
437
- * @throws {InvalidInput}
438
- * If any PKARR relay URL is invalid.
439
- *
440
- * @example
441
- * const client = new Client({
442
- * pkarr: { relays: ["https://relay1/","https://relay2/"], request_timeout: 8000 }
443
- * });
444
- * const pubky = Pubky.withClient(client);
445
- */
446
- constructor(config_opt?: PubkyClientConfig | null);
447
- /**
448
- * Create a client wired for **local testnet**.
449
- *
450
- * Configures PKARR relays for the testnet and remembers the hostname for WASM `_pubky` mapping.
451
- *
452
- * @param {string} [host="localhost"]
453
- * Testnet hostname or IP.
454
- *
455
- * @returns {Client}
456
- * A client ready to talk to your local testnet.
457
- *
458
- * @example
459
- * const client = Client.testnet(); // localhost
460
- * const pubky = Pubky.withClient(client);
461
- *
462
- * @example
463
- * const client = Client.testnet("docker0"); // custom host
464
- */
465
- static testnet(host?: string | null): Client;
397
+ free(): void;
398
+ [Symbol.dispose](): void;
399
+ /**
400
+ * Perform a raw fetch. Works with `http(s)://` URLs.
401
+ *
402
+ * @param {string} url
403
+ * @param {RequestInit} init Standard fetch options; `credentials: "include"` recommended for session I/O.
404
+ * @returns {Promise<Response>}
405
+ *
406
+ * @example
407
+ * const client = pubky.client;
408
+ * const res = await client.fetch(`https://_pubky.${user}/pub/app/file.txt`, { method: "PUT", body: "hi", credentials: "include" });
409
+ */
410
+ fetch(url: string, init?: RequestInit | null): Promise<Response>;
411
+ /**
412
+ * Create a Pubky HTTP client.
413
+ *
414
+ * @param {PubkyClientConfig} [config]
415
+ * Optional transport overrides:
416
+ * `{ pkarr?: { relays?: string[], request_timeout?: number } }`.
417
+ *
418
+ * @returns {Client}
419
+ * A configured low-level client. Prefer `new Pubky().client` unless you
420
+ * need custom relays/timeouts.
421
+ *
422
+ * @throws {InvalidInput}
423
+ * If any PKARR relay URL is invalid.
424
+ *
425
+ * @example
426
+ * const client = new Client({
427
+ * pkarr: { relays: ["https://relay1/","https://relay2/"], request_timeout: 8000 }
428
+ * });
429
+ * const pubky = Pubky.withClient(client);
430
+ */
431
+ constructor(config_opt?: PubkyClientConfig | null);
432
+ /**
433
+ * Create a client wired for **local testnet**.
434
+ *
435
+ * Configures PKARR relays for the testnet and remembers the hostname for WASM `_pubky` mapping.
436
+ *
437
+ * @param {string} [host="localhost"]
438
+ * Testnet hostname or IP.
439
+ *
440
+ * @returns {Client}
441
+ * A client ready to talk to your local testnet.
442
+ *
443
+ * @example
444
+ * const client = Client.testnet(); // localhost
445
+ * const pubky = Pubky.withClient(client);
446
+ *
447
+ * @example
448
+ * const client = Client.testnet("docker0"); // custom host
449
+ */
450
+ static testnet(host?: string | null): Client;
451
+ }
452
+
453
+ /**
454
+ * A single event from the event stream.
455
+ *
456
+ * @example
457
+ * ```typescript
458
+ * for await (const event of stream) {
459
+ * console.log(event.eventType); // "PUT" or "DEL"
460
+ * console.log(event.cursor); // cursor string for pagination
461
+ *
462
+ * if (event.eventType === "PUT") {
463
+ * console.log("Hash:", event.contentHash);
464
+ * }
465
+ *
466
+ * // Access resource details
467
+ * console.log(event.resource.owner.z32()); // User's public key
468
+ * console.log(event.resource.path); // "/pub/example.txt"
469
+ * console.log(event.resource.toPubkyUrl()); // Full pubky:// URL
470
+ * }
471
+ * ```
472
+ */
473
+ export class Event {
474
+ private constructor();
475
+ free(): void;
476
+ [Symbol.dispose](): void;
477
+ /**
478
+ * Get the content hash (only for PUT events).
479
+ * Returns the blake3 hash in base64 format, or undefined for DELETE events.
480
+ */
481
+ readonly contentHash: string | undefined;
482
+ /**
483
+ * Get the cursor for pagination.
484
+ */
485
+ readonly cursor: string;
486
+ /**
487
+ * Get the event type ("PUT" or "DEL").
488
+ */
489
+ readonly eventType: string;
490
+ /**
491
+ * Get the resource that was created, updated, or deleted.
492
+ */
493
+ readonly resource: PubkyResource;
466
494
  }
495
+
496
+ /**
497
+ * Builder for creating an event stream subscription.
498
+ *
499
+ * Construct via `Pubky.eventStreamForUser()` or `Pubky.eventStreamFor()`.
500
+ *
501
+ * @example
502
+ * ```typescript
503
+ * const stream = await pubky.eventStreamForUser(userPubkey, null)
504
+ * .live()
505
+ * .limit(100)
506
+ * .path("/pub/")
507
+ * .subscribe();
508
+ *
509
+ * for await (const event of stream) {
510
+ * console.log(event.eventType, event.resource.path);
511
+ * }
512
+ * ```
513
+ */
514
+ export class EventStreamBuilder {
515
+ private constructor();
516
+ free(): void;
517
+ [Symbol.dispose](): void;
518
+ /**
519
+ * Add multiple users to the event stream subscription at once.
520
+ *
521
+ * Each user can have an independent cursor position. If a user already exists,
522
+ * their cursor value is overwritten.
523
+ *
524
+ * @param {Array<[string, string | null]>} users - Array of [z32PublicKey, cursor] tuples
525
+ * @returns {EventStreamBuilder} - Builder for chaining
526
+ * @throws {Error} - If total users would exceed 50 or if any cursor/pubkey is invalid
527
+ *
528
+ * @example
529
+ * ```typescript
530
+ * const users: [string, string | null][] = [
531
+ * [user1.z32(), null],
532
+ * [user2.z32(), "100"],
533
+ * ];
534
+ * const stream = await pubky.eventStreamFor(homeserver)
535
+ * .addUsers(users)
536
+ * .live()
537
+ * .subscribe();
538
+ * ```
539
+ */
540
+ addUsers(users: Array<any>): EventStreamBuilder;
541
+ /**
542
+ * Set maximum number of events to receive before closing the connection.
543
+ *
544
+ * If omitted:
545
+ * - With `live=false`: sends all historical events, then closes
546
+ * - With `live=true`: sends all historical events, then enters live mode (infinite stream)
547
+ *
548
+ * @param {number} limit - Maximum number of events (1-65535)
549
+ * @returns {EventStreamBuilder} - Builder for chaining
550
+ */
551
+ limit(limit: number): EventStreamBuilder;
552
+ /**
553
+ * Enable live streaming mode.
554
+ *
555
+ * When called, the stream will:
556
+ * 1. First deliver all historical events (oldest first)
557
+ * 2. Then remain open to stream new events as they occur in real-time
558
+ *
559
+ * Without this flag (default): Stream only delivers historical events and closes.
560
+ *
561
+ * **Note**: Cannot be combined with `reverse()`.
562
+ *
563
+ * ## Cleanup
564
+ * To stop a live stream, use the reader's `cancel()` method:
565
+ * ```typescript
566
+ * const stream = await pubky.eventStreamForUser(user, null).live().subscribe();
567
+ * const reader = stream.getReader();
568
+ *
569
+ * while (true) {
570
+ * const { done, value } = await reader.read();
571
+ * if (shouldStop) {
572
+ * await reader.cancel(); // Closes the connection
573
+ * break;
574
+ * }
575
+ * }
576
+ * ```
577
+ *
578
+ * @returns {EventStreamBuilder} - Builder for chaining
579
+ */
580
+ live(): EventStreamBuilder;
581
+ /**
582
+ * Filter events by path prefix.
583
+ *
584
+ * Format: Path WITHOUT `pubky://` scheme or user pubkey (e.g., "/pub/files/" or "/pub/").
585
+ * Only events whose path starts with this prefix are returned.
586
+ *
587
+ * @param {string} path - Path prefix to filter by
588
+ * @returns {EventStreamBuilder} - Builder for chaining
589
+ */
590
+ path(path: string): EventStreamBuilder;
591
+ /**
592
+ * Return events in reverse chronological order (newest first).
593
+ *
594
+ * When called, events are delivered from newest to oldest, then the stream closes.
595
+ *
596
+ * Without this flag (default): Events are delivered oldest first.
597
+ *
598
+ * **Note**: Cannot be combined with `live()`.
599
+ *
600
+ * @returns {EventStreamBuilder} - Builder for chaining
601
+ */
602
+ reverse(): EventStreamBuilder;
603
+ /**
604
+ * Subscribe to the event stream.
605
+ *
606
+ * This performs the following steps:
607
+ * 1. Resolves the user's homeserver via DHT/PKDNS
608
+ * 2. Constructs the `/events-stream` URL with query parameters
609
+ * 3. Makes the HTTP request
610
+ * 4. Returns a Web ReadableStream of parsed events
611
+ *
612
+ * @returns {Promise<ReadableStream>} - A Web ReadableStream that yields Event objects
613
+ *
614
+ * @throws {PubkyError}
615
+ * - `{ name: "RequestError" }` if the homeserver cannot be resolved
616
+ * - `{ name: "ValidationError" }` if `live=true` and `reverse=true` (invalid combination)
617
+ * - Propagates HTTP request errors
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * const stream = await builder.subscribe();
622
+ * for await (const event of stream) {
623
+ * console.log(`${event.eventType}: ${event.resource.path}`);
624
+ * }
625
+ * ```
626
+ */
627
+ subscribe(): Promise<ReadableStream>;
628
+ }
629
+
467
630
  export class IntoUnderlyingByteSource {
468
- private constructor();
469
- free(): void;
470
- [Symbol.dispose](): void;
471
- start(controller: ReadableByteStreamController): void;
472
- pull(controller: ReadableByteStreamController): Promise<any>;
473
- cancel(): void;
474
- readonly type: ReadableStreamType;
475
- readonly autoAllocateChunkSize: number;
631
+ private constructor();
632
+ free(): void;
633
+ [Symbol.dispose](): void;
634
+ cancel(): void;
635
+ pull(controller: ReadableByteStreamController): Promise<any>;
636
+ start(controller: ReadableByteStreamController): void;
637
+ readonly autoAllocateChunkSize: number;
638
+ readonly type: ReadableStreamType;
476
639
  }
640
+
477
641
  export class IntoUnderlyingSink {
478
- private constructor();
479
- free(): void;
480
- [Symbol.dispose](): void;
481
- write(chunk: any): Promise<any>;
482
- close(): Promise<any>;
483
- abort(reason: any): Promise<any>;
642
+ private constructor();
643
+ free(): void;
644
+ [Symbol.dispose](): void;
645
+ abort(reason: any): Promise<any>;
646
+ close(): Promise<any>;
647
+ write(chunk: any): Promise<any>;
484
648
  }
649
+
485
650
  export class IntoUnderlyingSource {
486
- private constructor();
487
- free(): void;
488
- [Symbol.dispose](): void;
489
- pull(controller: ReadableStreamDefaultController): Promise<any>;
490
- cancel(): void;
651
+ private constructor();
652
+ free(): void;
653
+ [Symbol.dispose](): void;
654
+ cancel(): void;
655
+ pull(controller: ReadableStreamDefaultController): Promise<any>;
491
656
  }
657
+
492
658
  export class Keypair {
493
- private constructor();
494
- free(): void;
495
- [Symbol.dispose](): void;
496
- /**
497
- * Generate a random [Keypair]
498
- */
499
- static random(): Keypair;
500
- /**
501
- * Generate a [Keypair] from a 32-byte secret.
502
- */
503
- static fromSecret(secret: Uint8Array): Keypair;
504
- /**
505
- * Returns the secret of this keypair.
506
- */
507
- secret(): Uint8Array;
508
- /**
509
- * Create a recovery file for this keypair (encrypted with the given passphrase).
510
- */
511
- createRecoveryFile(passphrase: string): Uint8Array;
512
- /**
513
- * Decrypt a recovery file and return a Keypair (decrypted with the given passphrase).
514
- */
515
- static fromRecoveryFile(recovery_file: Uint8Array, passphrase: string): Keypair;
516
- /**
517
- * Returns the [PublicKey] of this keypair.
518
- *
519
- * Use `.toString()` on the returned `PublicKey` to get the string form
520
- * or `.z32()` to get the z32 string form without prefix.
521
- * Transport/storage (query params, headers, persistence) should use `.z32()`.
522
- *
523
- * @example
524
- * const who = keypair.publicKey.toString();
525
- */
526
- readonly publicKey: PublicKey;
659
+ private constructor();
660
+ free(): void;
661
+ [Symbol.dispose](): void;
662
+ /**
663
+ * Create a recovery file for this keypair (encrypted with the given passphrase).
664
+ */
665
+ createRecoveryFile(passphrase: string): Uint8Array;
666
+ /**
667
+ * Decrypt a recovery file and return a Keypair (decrypted with the given passphrase).
668
+ */
669
+ static fromRecoveryFile(recovery_file: Uint8Array, passphrase: string): Keypair;
670
+ /**
671
+ * Generate a [Keypair] from a 32-byte secret.
672
+ */
673
+ static fromSecret(secret: Uint8Array): Keypair;
674
+ /**
675
+ * Generate a random [Keypair]
676
+ */
677
+ static random(): Keypair;
678
+ /**
679
+ * Returns the secret of this keypair.
680
+ */
681
+ secret(): Uint8Array;
682
+ /**
683
+ * Returns the [PublicKey] of this keypair.
684
+ *
685
+ * Use `.toString()` on the returned `PublicKey` to get the string form
686
+ * or `.z32()` to get the z32 string form without prefix.
687
+ * Transport/storage (query params, headers, persistence) should use `.z32()`.
688
+ *
689
+ * @example
690
+ * const who = keypair.publicKey.toString();
691
+ */
692
+ readonly publicKey: PublicKey;
527
693
  }
694
+
528
695
  /**
529
696
  * Resolve/publish `_pubky` PKDNS records (homeserver pointers).
530
697
  */
531
698
  export class Pkdns {
532
- free(): void;
533
- [Symbol.dispose](): void;
534
- /**
535
- * Read-only PKDNS actor (no keypair; resolve only).
536
- */
537
- constructor();
538
- /**
539
- * PKDNS actor with publishing enabled (requires a keypair).
540
- */
541
- static fromKeypair(keypair: Keypair): Pkdns;
542
- /**
543
- * Resolve the homeserver for a given public key (read-only).
544
- *
545
- * @param {PublicKey} user
546
- * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
547
- */
548
- getHomeserverOf(pubky: PublicKey): Promise<PublicKey | undefined>;
549
- /**
550
- * Resolve the homeserver for **this** user (requires keypair).
551
- *
552
- * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
553
- */
554
- getHomeserver(): Promise<PublicKey | undefined>;
555
- /**
556
- * Force publish homeserver immediately (even if fresh).
557
- *
558
- * Requires keypair or to be signer bound.
559
- *
560
- * @param {PublicKey=} overrideHost Optional new homeserver to publish (migration).
561
- * @returns {Promise<void>}
562
- */
563
- publishHomeserverForce(host_override?: PublicKey | null): Promise<void>;
564
- /**
565
- * Republish homeserver if record is missing/stale.
566
- *
567
- * Requires keypair or to be signer bound.
568
- *
569
- * @param {PublicKey=} overrideHost Optional new homeserver to publish (migration).
570
- * @returns {Promise<void>}
571
- */
572
- publishHomeserverIfStale(host_override?: PublicKey | null): Promise<void>;
699
+ free(): void;
700
+ [Symbol.dispose](): void;
701
+ /**
702
+ * PKDNS actor with publishing enabled (requires a keypair).
703
+ */
704
+ static fromKeypair(keypair: Keypair): Pkdns;
705
+ /**
706
+ * Resolve the homeserver for **this** user (requires keypair).
707
+ *
708
+ * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
709
+ */
710
+ getHomeserver(): Promise<PublicKey | undefined>;
711
+ /**
712
+ * Resolve the homeserver for a given public key (read-only).
713
+ *
714
+ * @param {PublicKey} user
715
+ * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
716
+ */
717
+ getHomeserverOf(pubky: PublicKey): Promise<PublicKey | undefined>;
718
+ /**
719
+ * Read-only PKDNS actor (no keypair; resolve only).
720
+ */
721
+ constructor();
722
+ /**
723
+ * Force publish homeserver immediately (even if fresh).
724
+ *
725
+ * Requires keypair or to be signer bound.
726
+ *
727
+ * @param {PublicKey=} overrideHost Optional new homeserver to publish (migration).
728
+ * @returns {Promise<void>}
729
+ */
730
+ publishHomeserverForce(host_override?: PublicKey | null): Promise<void>;
731
+ /**
732
+ * Republish homeserver if record is missing/stale.
733
+ *
734
+ * Requires keypair or to be signer bound.
735
+ *
736
+ * @param {PublicKey=} overrideHost Optional new homeserver to publish (migration).
737
+ * @returns {Promise<void>}
738
+ */
739
+ publishHomeserverIfStale(host_override?: PublicKey | null): Promise<void>;
573
740
  }
741
+
574
742
  /**
575
743
  * High-level entrypoint to the Pubky SDK.
576
744
  */
577
745
  export class Pubky {
578
- free(): void;
579
- [Symbol.dispose](): void;
580
- /**
581
- * Create a Pubky facade wired for **mainnet** defaults (public relays).
582
- *
583
- * Prefer to instantiate only once and use trough your application a single shared `Pubky`
584
- * instead of constructing one per request. This avoids reinitializing transports and keeps
585
- * the same client available for repeated usage.
586
- *
587
- * @returns {Pubky}
588
- * A new facade instance. Use this to create signers, start auth flows, etc.
589
- *
590
- * @example
591
- * const pubky = new Pubky();
592
- * const signer = pubky.signer(Keypair.random());
593
- */
594
- constructor();
595
- /**
596
- * Create a Pubky facade preconfigured for a **local testnet**.
597
- *
598
- * If `host` is provided, PKARR and HTTP endpoints are derived as `http://<host>:ports/...`.
599
- * If omitted, `"localhost"` is assumed (handy for `cargo install pubky-testnet`).
600
- *
601
- * @param {string=} host Optional host (e.g. `"localhost"`, `"docker-host"`, `"127.0.0.1"`).
602
- * @returns {Pubky}
603
- *
604
- * @example
605
- * const pubky = Pubky.testnet(); // localhost default
606
- * const pubky = Pubky.testnet("docker-host"); // custom hostname/IP
607
- */
608
- static testnet(host?: string | null): Pubky;
609
- /**
610
- * Wrap an existing configured HTTP client into a Pubky facade.
611
- *
612
- * @param {Client} client A previously constructed client.
613
- * @returns {Pubky}
614
- *
615
- * @example
616
- * const client = Client.testnet();
617
- * const pubky = Pubky.withClient(client);
618
- */
619
- static withClient(client: Client): Pubky;
620
- /**
621
- * Start a **pubkyauth** flow.
622
- *
623
- * Provide a **capabilities string** and (optionally) a relay base URL.
624
- * The capabilities string is a comma-separated list of entries:
625
- * `"<scope>:<actions>"`, where:
626
- * - `scope` starts with `/` (e.g. `/pub/example.com/`).
627
- * - `actions` is any combo of `r` and/or `w` (order normalized; `wr` -> `rw`).
628
- * Pass `""` for no scopes (read-only public session).
629
- *
630
- * @param {string} capabilities Comma-separated caps, e.g. `"/pub/app/:rw,/pub/foo/file:r"`.
631
- * @param {AuthFlowKind} kind The kind of authentication flow to perform.
632
- * Examples:
633
- * - `AuthFlowKind.signin()` - Sign in to an existing account.
634
- * - `AuthFlowKind.signup(homeserverPublicKey, signupToken)` - Sign up for a new account.
635
- * @param {string=} relay Optional HTTP relay base (e.g. `"https://…/link/"`).
636
- * @returns {AuthFlow}
637
- * A running auth flow. Show `authorizationUrl` as QR/deeplink,
638
- * then `awaitApproval()` to obtain a `Session`.
639
- *
640
- * @throws {PubkyError}
641
- * - `{ name: "InvalidInput" }` for malformed capabilities or bad relay URL
642
- * - `{ name: "RequestError" }` if the flow cannot be started (network/relay)
643
- *
644
- * @example
645
- * const flow = pubky.startAuthFlow("/pub/my-cool-app/:rw");
646
- * renderQr(flow.authorizationUrl);
647
- * const session = await flow.awaitApproval();
648
- */
649
- startAuthFlow(capabilities: Capabilities, kind: AuthFlowKind, relay?: string | null): AuthFlow;
650
- /**
651
- * Create a `Signer` from an existing `Keypair`.
652
- *
653
- * @param {Keypair} keypair The user’s keys.
654
- * @returns {Signer}
655
- *
656
- * @example
657
- * const signer = pubky.signer(Keypair.random());
658
- * const session = await signer.signup(homeserverPk, null);
659
- */
660
- signer(keypair: Keypair): Signer;
661
- /**
662
- * Resolve the homeserver for a given public key (read-only).
663
- *
664
- * Uses an internal read-only Pkdns actor.
665
- *
666
- * @param {PublicKey} user
667
- * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
668
- */
669
- getHomeserverOf(user_public_key: PublicKey): Promise<PublicKey | undefined>;
670
- /**
671
- * Restore a session from a previously exported snapshot, using this instance's client.
672
- *
673
- * This does **not** read or write any secrets. It revalidates the session metadata with
674
- * the server using the browser-managed HTTP-only cookie that must still be present.
675
- *
676
- * @param {string} exported A string produced by `session.export()`.
677
- * @returns {Promise<Session>}
678
- * A rehydrated session bound to this SDK's HTTP client.
679
- *
680
- * @example
681
- * const restored = await pubky.restoreSession(localStorage.getItem("pubky-session")!);
682
- */
683
- restoreSession(exported: string): Promise<Session>;
684
- /**
685
- * Public, unauthenticated storage API.
686
- *
687
- * Use for **read-only** public access via addressed paths:
688
- * `"pubky<user>/pub/…"`.
689
- *
690
- * @returns {PublicStorage}
691
- *
692
- * @example
693
- * const text = await pubky.publicStorage.getText(`${userPk.toString()}/pub/example.com/hello.txt`);
694
- */
695
- readonly publicStorage: PublicStorage;
696
- /**
697
- * Access the underlying HTTP client (advanced).
698
- *
699
- * @returns {Client}
700
- * Use this for low-level `fetch()` calls or testing with raw URLs.
701
- *
702
- * @example
703
- * const r = await pubky.client.fetch(`pubky://${userPk.z32()}/pub/app/file.txt`, { credentials: "include" });
704
- */
705
- readonly client: Client;
746
+ free(): void;
747
+ [Symbol.dispose](): void;
748
+ /**
749
+ * Create an event stream builder for a specific homeserver.
750
+ *
751
+ * Use this when you already know the homeserver pubkey. This avoids
752
+ * Pkarr resolution overhead. Obtain a homeserver pubkey via `getHomeserverOf()`.
753
+ *
754
+ * @param {PublicKey} homeserver - The homeserver public key
755
+ * @returns {EventStreamBuilder} - Builder for configuring and subscribing to the stream
756
+ *
757
+ * @example
758
+ * ```typescript
759
+ * const homeserver = await pubky.getHomeserverOf(user1);
760
+ * const stream = await pubky.eventStreamFor(homeserver)
761
+ * .addUsers([[user1.z32(), null], [user2.z32(), null]])
762
+ * .live()
763
+ * .subscribe();
764
+ *
765
+ * for await (const event of stream) {
766
+ * console.log(`${event.eventType}: ${event.resource.path}`);
767
+ * }
768
+ * ```
769
+ */
770
+ eventStreamFor(homeserver: PublicKey): EventStreamBuilder;
771
+ /**
772
+ * Create an event stream builder for a single user.
773
+ *
774
+ * This is the simplest way to subscribe to events for one user. The homeserver
775
+ * is automatically resolved from the user's Pkarr record.
776
+ *
777
+ * @param {PublicKey} user - The user's public key
778
+ * @param {string | null} cursor - Optional cursor position to start from
779
+ * @returns {EventStreamBuilder} - Builder for configuring and subscribing to the stream
780
+ *
781
+ * @example
782
+ * ```typescript
783
+ * const user = PublicKey.from("o1gg96ewuojmopcjbz8895478wdtxtzzuxnfjjz8o8e77csa1ngo");
784
+ * const stream = await pubky.eventStreamForUser(user, null)
785
+ * .live()
786
+ * .subscribe();
787
+ *
788
+ * for await (const event of stream) {
789
+ * console.log(`${event.eventType}: ${event.resource.path}`);
790
+ * }
791
+ * ```
792
+ */
793
+ eventStreamForUser(user: PublicKey, cursor?: string | null): EventStreamBuilder;
794
+ /**
795
+ * Resolve the homeserver for a given public key (read-only).
796
+ *
797
+ * Uses an internal read-only Pkdns actor.
798
+ *
799
+ * @param {PublicKey} user
800
+ * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
801
+ */
802
+ getHomeserverOf(user_public_key: PublicKey): Promise<PublicKey | undefined>;
803
+ /**
804
+ * Create a Pubky facade wired for **mainnet** defaults (public relays).
805
+ *
806
+ * Prefer to instantiate only once and use trough your application a single shared `Pubky`
807
+ * instead of constructing one per request. This avoids reinitializing transports and keeps
808
+ * the same client available for repeated usage.
809
+ *
810
+ * @returns {Pubky}
811
+ * A new facade instance. Use this to create signers, start auth flows, etc.
812
+ *
813
+ * @example
814
+ * const pubky = new Pubky();
815
+ * const signer = pubky.signer(Keypair.random());
816
+ */
817
+ constructor();
818
+ /**
819
+ * Restore a session from a previously exported snapshot, using this instance's client.
820
+ *
821
+ * This does **not** read or write any secrets. It revalidates the session metadata with
822
+ * the server using the browser-managed HTTP-only cookie that must still be present.
823
+ *
824
+ * @param {string} exported A string produced by `session.export()`.
825
+ * @returns {Promise<Session>}
826
+ * A rehydrated session bound to this SDK's HTTP client.
827
+ *
828
+ * @example
829
+ * const restored = await pubky.restoreSession(localStorage.getItem("pubky-session")!);
830
+ */
831
+ restoreSession(exported: string): Promise<Session>;
832
+ /**
833
+ * Resume a previously started **pubkyauth** flow from its saved `authorizationUrl`.
834
+ *
835
+ * The relay inbox retains messages for **~5 minutes**. Resume is only
836
+ * viable within that window; afterwards start a fresh flow.
837
+ *
838
+ * **Security:** The URL contains the `client_secret` in plaintext.
839
+ * Delete it from storage as soon as the resumed flow completes.
840
+ * See `startAuthFlow()` docs for full storage guidance.
841
+ *
842
+ * @param {string} authorizationUrl The `pubkyauth://…` URL from a previous flow.
843
+ * @returns {AuthFlow} A flow reconnected to the original relay channel.
844
+ * @throws {PubkyError}
845
+ * - `{ name: "AuthenticationError" }` if the URL is invalid or not a signin/signup link
846
+ * - `{ name: "RequestError" }` on network/relay failure
847
+ */
848
+ resumeAuthFlow(authorization_url: string): AuthFlow;
849
+ /**
850
+ * Create a `Signer` from an existing `Keypair`.
851
+ *
852
+ * @param {Keypair} keypair The user’s keys.
853
+ * @returns {Signer}
854
+ *
855
+ * @example
856
+ * const signer = pubky.signer(Keypair.random());
857
+ * const session = await signer.signup(homeserverPk, null);
858
+ */
859
+ signer(keypair: Keypair): Signer;
860
+ /**
861
+ * Start a **pubkyauth** flow.
862
+ *
863
+ * Provide a **capabilities string** and (optionally) a relay base URL.
864
+ * The capabilities string is a comma-separated list of entries:
865
+ * `"<scope>:<actions>"`, where:
866
+ * - `scope` starts with `/` (e.g. `/pub/example.com/`).
867
+ * - `actions` is any combo of `r` and/or `w` (order normalized; `wr` -> `rw`).
868
+ * Pass `""` for no scopes (read-only public session).
869
+ *
870
+ * **Security:** `authorizationUrl` contains the `client_secret` in plaintext.
871
+ * If you need resume after refresh/app switch, save it in `sessionStorage`
872
+ * (not `localStorage`), then delete it once approval arrives or is abandoned.
873
+ *
874
+ * @param {string} capabilities Comma-separated caps, e.g. `"/pub/app/:rw,/pub/foo/file:r"`.
875
+ * @param {AuthFlowKind} kind The kind of authentication flow to perform.
876
+ * Examples:
877
+ * - `AuthFlowKind.signin()` - Sign in to an existing account.
878
+ * - `AuthFlowKind.signup(homeserverPublicKey, signupToken)` - Sign up for a new account.
879
+ * @param {string=} relay Optional HTTP relay base (e.g. `"https://…/inbox/"`).
880
+ * @returns {AuthFlow}
881
+ * A running auth flow. Show `authorizationUrl` as QR/deeplink,
882
+ * then `awaitApproval()` to obtain a `Session`.
883
+ *
884
+ * @throws {PubkyError}
885
+ * - `{ name: "InvalidInput" }` for malformed capabilities or bad relay URL
886
+ * - `{ name: "RequestError" }` if the flow cannot be started (network/relay)
887
+ *
888
+ * @example
889
+ * const flow = pubky.startAuthFlow("/pub/my-cool-app/:rw");
890
+ * renderQr(flow.authorizationUrl);
891
+ * const session = await flow.awaitApproval();
892
+ */
893
+ startAuthFlow(capabilities: Capabilities, kind: AuthFlowKind, relay?: string | null): AuthFlow;
894
+ /**
895
+ * Create a Pubky facade preconfigured for a **local testnet**.
896
+ *
897
+ * If `host` is provided, PKARR and HTTP endpoints are derived as `http://<host>:ports/...`.
898
+ * If omitted, `"localhost"` is assumed (handy for `cargo install pubky-testnet`).
899
+ *
900
+ * @param {string=} host Optional host (e.g. `"localhost"`, `"docker-host"`, `"127.0.0.1"`).
901
+ * @returns {Pubky}
902
+ *
903
+ * @example
904
+ * const pubky = Pubky.testnet(); // localhost default
905
+ * const pubky = Pubky.testnet("docker-host"); // custom hostname/IP
906
+ */
907
+ static testnet(host?: string | null): Pubky;
908
+ /**
909
+ * Wrap an existing configured HTTP client into a Pubky facade.
910
+ *
911
+ * @param {Client} client A previously constructed client.
912
+ * @returns {Pubky}
913
+ *
914
+ * @example
915
+ * const client = Client.testnet();
916
+ * const pubky = Pubky.withClient(client);
917
+ */
918
+ static withClient(client: Client): Pubky;
919
+ /**
920
+ * Access the underlying HTTP client (advanced).
921
+ *
922
+ * @returns {Client}
923
+ * Use this for low-level `fetch()` calls or testing with raw URLs.
924
+ *
925
+ * @example
926
+ * const r = await pubky.client.fetch(`pubky://${userPk.z32()}/pub/app/file.txt`, { credentials: "include" });
927
+ */
928
+ readonly client: Client;
929
+ /**
930
+ * Public, unauthenticated storage API.
931
+ *
932
+ * Use for **read-only** public access via addressed paths:
933
+ * `"pubky<user>/pub/…"`.
934
+ *
935
+ * @returns {PublicStorage}
936
+ *
937
+ * @example
938
+ * const text = await pubky.publicStorage.getText(`${userPk.toString()}/pub/example.com/hello.txt`);
939
+ */
940
+ readonly publicStorage: PublicStorage;
941
+ }
942
+
943
+ /**
944
+ * An addressed resource: a user's public key paired with an absolute path.
945
+ *
946
+ * This represents a specific file or directory on a user's homeserver.
947
+ *
948
+ * @example
949
+ * ```typescript
950
+ * // Parse from a pubky URL
951
+ * const resource = PubkyResource.parse("pubky://o1gg96ewuojmopcjbz8895478wdtxtzzuxnfjjz8o8e77csa1ngo/pub/example.txt");
952
+ * console.log(resource.owner.z32()); // The user's public key
953
+ * console.log(resource.path); // "/pub/example.txt"
954
+ * console.log(resource.toPubkyUrl()); // "pubky://o1gg96.../pub/example.txt"
955
+ * ```
956
+ */
957
+ export class PubkyResource {
958
+ private constructor();
959
+ free(): void;
960
+ [Symbol.dispose](): void;
961
+ /**
962
+ * Parse a pubky resource from a string.
963
+ *
964
+ * Accepts:
965
+ * - `pubky://<public_key>/<path>` (URL form)
966
+ * - `pubky<public_key>/<path>` (identifier form)
967
+ *
968
+ * @param {string} value - The resource string to parse
969
+ * @returns {PubkyResource} - The parsed resource
970
+ * @throws {Error} - If the string is not a valid pubky resource
971
+ */
972
+ static parse(value: string): PubkyResource;
973
+ /**
974
+ * Render as `pubky://<owner>/<path>` (deep-link/URL form).
975
+ */
976
+ toPubkyUrl(): string;
977
+ /**
978
+ * Render as `pubky<owner>/<path>` (identifier form).
979
+ */
980
+ toString(): string;
981
+ /**
982
+ * Get the owner's public key.
983
+ */
984
+ readonly owner: PublicKey;
985
+ /**
986
+ * Get the absolute path (e.g., "/pub/example.txt").
987
+ */
988
+ readonly path: string;
706
989
  }
990
+
707
991
  export class PublicKey {
708
- private constructor();
709
- free(): void;
710
- [Symbol.dispose](): void;
711
- /**
712
- * Convert the PublicKey to Uint8Array
713
- */
714
- toUint8Array(): Uint8Array;
715
- /**
716
- * Returns the z-base32 encoding of this public key
717
- */
718
- z32(): string;
719
- /**
720
- * Returns the identifier form with the `pubky` prefix.
721
- * Use for display only; transport/storage should use `.z32()`.
722
- */
723
- toString(): string;
724
- /**
725
- * @throws
726
- */
727
- static from(value: string): PublicKey;
992
+ private constructor();
993
+ free(): void;
994
+ [Symbol.dispose](): void;
995
+ /**
996
+ * @throws
997
+ */
998
+ static from(value: string): PublicKey;
999
+ /**
1000
+ * Returns the identifier form with the `pubky` prefix.
1001
+ * Use for display only; transport/storage should use `.z32()`.
1002
+ */
1003
+ toString(): string;
1004
+ /**
1005
+ * Convert the PublicKey to Uint8Array
1006
+ */
1007
+ toUint8Array(): Uint8Array;
1008
+ /**
1009
+ * Returns the z-base32 encoding of this public key
1010
+ */
1011
+ z32(): string;
728
1012
  }
1013
+
729
1014
  /**
730
1015
  * Read-only public storage using addressed paths (`"pubky<user>/pub/..."`).
731
1016
  */
732
1017
  export class PublicStorage {
733
- free(): void;
734
- [Symbol.dispose](): void;
735
- /**
736
- * Construct PublicStorage using global client (mainline relays).
737
- */
738
- constructor();
739
- /**
740
- * List a directory. Results are `pubky://…` identifier URLs.
741
- *
742
- * @param {Address} address Addressed directory (must end with `/`).
743
- * @param {string|null=} cursor Optional suffix or full URL to start **after**.
744
- * @param {boolean=} reverse Default `false`. When `true`, newest/lexicographically-last first.
745
- * @param {number=} limit Optional result limit.
746
- * @param {boolean=} shallow Default `false`. When `true`, lists only first-level entries.
747
- * @returns {Promise<string[]>}
748
- */
749
- list(address: Address, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
750
- /**
751
- * Perform a streaming `GET` and expose the raw `Response` object.
752
- *
753
- * @param {Address} address
754
- * @returns {Promise<Response>}
755
- */
756
- get(address: Address): Promise<Response>;
757
- /**
758
- * Fetch bytes from an addressed path.
759
- *
760
- * @param {Address} address
761
- * @returns {Promise<Uint8Array>}
762
- */
763
- getBytes(address: Address): Promise<Uint8Array>;
764
- /**
765
- * Fetch text from an addressed path as UTF-8 text.
766
- *
767
- * @param {Address} address
768
- * @returns {Promise<string>}
769
- */
770
- getText(address: Address): Promise<string>;
771
- /**
772
- * Fetch JSON from an addressed path.
773
- *
774
- * @param {Address} address `"pubky<user>/pub/.../file.json"` (preferred) or `pubky://<user>/pub/...`.
775
- * @returns {Promise<any>}
776
- */
777
- getJson(address: Address): Promise<any>;
778
- /**
779
- * Check if a path exists.
780
- *
781
- * @param {Address} address
782
- * @returns {Promise<boolean>}
783
- */
784
- exists(address: Address): Promise<boolean>;
785
- /**
786
- * Get metadata for an address
787
- *
788
- * @param {Address} address `"pubky<user>/pub/.../file.json"` (preferred) or `pubky://<user>/pub/...`.
789
- * @returns {Promise<ResourceStats|undefined>} `undefined` if the resource does not exist.
790
- * @throws {PubkyError} On invalid input or transport/server errors.
791
- */
792
- stats(address: Address): Promise<ResourceStats | undefined>;
1018
+ free(): void;
1019
+ [Symbol.dispose](): void;
1020
+ /**
1021
+ * Check if a path exists.
1022
+ *
1023
+ * @param {Address} address
1024
+ * @returns {Promise<boolean>}
1025
+ */
1026
+ exists(address: Address): Promise<boolean>;
1027
+ /**
1028
+ * Perform a streaming `GET` and expose the raw `Response` object.
1029
+ *
1030
+ * @param {Address} address
1031
+ * @returns {Promise<Response>}
1032
+ */
1033
+ get(address: Address): Promise<Response>;
1034
+ /**
1035
+ * Fetch bytes from an addressed path.
1036
+ *
1037
+ * @param {Address} address
1038
+ * @returns {Promise<Uint8Array>}
1039
+ */
1040
+ getBytes(address: Address): Promise<Uint8Array>;
1041
+ /**
1042
+ * Fetch JSON from an addressed path.
1043
+ *
1044
+ * @param {Address} address `"pubky<user>/pub/.../file.json"` (preferred) or `pubky://<user>/pub/...`.
1045
+ * @returns {Promise<any>}
1046
+ */
1047
+ getJson(address: Address): Promise<any>;
1048
+ /**
1049
+ * Fetch text from an addressed path as UTF-8 text.
1050
+ *
1051
+ * @param {Address} address
1052
+ * @returns {Promise<string>}
1053
+ */
1054
+ getText(address: Address): Promise<string>;
1055
+ /**
1056
+ * List a directory. Results are `pubky://…` identifier URLs.
1057
+ *
1058
+ * @param {Address} address Addressed directory (must end with `/`).
1059
+ * @param {string|null=} cursor Optional suffix or full URL to start **after**.
1060
+ * @param {boolean=} reverse Default `false`. When `true`, newest/lexicographically-last first.
1061
+ * @param {number=} limit Optional result limit.
1062
+ * @param {boolean=} shallow Default `false`. When `true`, lists only first-level entries.
1063
+ * @returns {Promise<string[]>}
1064
+ */
1065
+ list(address: Address, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
1066
+ /**
1067
+ * Construct PublicStorage using global client (mainline relays).
1068
+ */
1069
+ constructor();
1070
+ /**
1071
+ * Get metadata for an address
1072
+ *
1073
+ * @param {Address} address `"pubky<user>/pub/.../file.json"` (preferred) or `pubky://<user>/pub/...`.
1074
+ * @returns {Promise<ResourceStats|undefined>} `undefined` if the resource does not exist.
1075
+ * @throws {PubkyError} On invalid input or transport/server errors.
1076
+ */
1077
+ stats(address: Address): Promise<ResourceStats | undefined>;
793
1078
  }
1079
+
794
1080
  export class SeedExportDeepLink {
795
- private constructor();
796
- free(): void;
797
- [Symbol.dispose](): void;
798
- static parse(url: string): SeedExportDeepLink;
799
- toString(): string;
800
- readonly secret: Uint8Array;
1081
+ private constructor();
1082
+ free(): void;
1083
+ [Symbol.dispose](): void;
1084
+ static parse(url: string): SeedExportDeepLink;
1085
+ toString(): string;
1086
+ readonly secret: Uint8Array;
801
1087
  }
1088
+
802
1089
  /**
803
1090
  * An authenticated context “as the user”.
804
1091
  * - Use `storage` for reads/writes (absolute paths like `/pub/app/file.txt`)
805
1092
  * - Cookie is managed automatically by the underlying fetch client
806
1093
  */
807
1094
  export class Session {
808
- private constructor();
809
- free(): void;
810
- [Symbol.dispose](): void;
811
- /**
812
- * Invalidate the session on the server (clears server cookie).
813
- * Further calls to storage API will fail.
814
- *
815
- * @returns {Promise<void>}
816
- */
817
- signout(): Promise<void>;
818
- /**
819
- * Export the session metadata so it can be restored after a tab refresh.
820
- *
821
- * The export string contains **no secrets**; it only serializes the public `SessionInfo`.
822
- * Browsers remain responsible for persisting the HTTP-only session cookie.
823
- *
824
- * @returns {string}
825
- * A base64 string to store (e.g. in `localStorage`).
826
- */
827
- export(): string;
828
- /**
829
- * Restore a session from an `export()` string.
830
- *
831
- * The HTTP-only cookie must still be present in the browser; this function does not
832
- * read or write any secrets.
833
- *
834
- * @param {string} exported
835
- * A string produced by `session.export()`.
836
- * @param {Client=} client
837
- * Optional client to reuse transport configuration.
838
- * @returns {Promise<Session>}
839
- */
840
- static restore(exported: string, client?: Client | null): Promise<Session>;
841
- /**
842
- * Retrieve immutable info about this session (user & capabilities).
843
- *
844
- * @returns {SessionInfo}
845
- */
846
- readonly info: SessionInfo;
847
- /**
848
- * Access the session-scoped storage API (read/write).
849
- *
850
- * @returns {SessionStorage}
851
- */
852
- readonly storage: SessionStorage;
1095
+ private constructor();
1096
+ free(): void;
1097
+ [Symbol.dispose](): void;
1098
+ /**
1099
+ * Export the session metadata so it can be restored after a tab refresh.
1100
+ *
1101
+ * The export string contains **no secrets**; it only serializes the public `SessionInfo`.
1102
+ * Browsers remain responsible for persisting the HTTP-only session cookie.
1103
+ *
1104
+ * @returns {string}
1105
+ * A base64 string to store (e.g. in `localStorage`).
1106
+ */
1107
+ export(): string;
1108
+ /**
1109
+ * Restore a session from an `export()` string.
1110
+ *
1111
+ * The HTTP-only cookie must still be present in the browser; this function does not
1112
+ * read or write any secrets.
1113
+ *
1114
+ * @param {string} exported
1115
+ * A string produced by `session.export()`.
1116
+ * @param {Client=} client
1117
+ * Optional client to reuse transport configuration.
1118
+ * @returns {Promise<Session>}
1119
+ */
1120
+ static restore(exported: string, client?: Client | null): Promise<Session>;
1121
+ /**
1122
+ * Invalidate the session on the server (clears server cookie).
1123
+ * Further calls to storage API will fail.
1124
+ *
1125
+ * @returns {Promise<void>}
1126
+ */
1127
+ signout(): Promise<void>;
1128
+ /**
1129
+ * Retrieve immutable info about this session (user & capabilities).
1130
+ *
1131
+ * @returns {SessionInfo}
1132
+ */
1133
+ readonly info: SessionInfo;
1134
+ /**
1135
+ * Access the session-scoped storage API (read/write).
1136
+ *
1137
+ * @returns {SessionStorage}
1138
+ */
1139
+ readonly storage: SessionStorage;
853
1140
  }
1141
+
854
1142
  /**
855
1143
  * Static snapshot of session metadata.
856
1144
  */
857
1145
  export class SessionInfo {
858
- private constructor();
859
- free(): void;
860
- [Symbol.dispose](): void;
861
- /**
862
- * The user’s public key for this session.
863
- *
864
- * Use `.toString()` on the returned `PublicKey` to get the `pubky<z32>` identifier.
865
- * Call `.z32()` when you specifically need the raw z-base32 value (e.g. hostnames).
866
- *
867
- * @returns {PublicKey}
868
- *
869
- * @example
870
- * const who = sessionInfo.publicKey.toString();
871
- */
872
- readonly publicKey: PublicKey;
873
- /**
874
- * Effective capabilities granted to this session.
875
- *
876
- * @returns {string[]} Normalized capability entries (e.g. `"/pub/app/:rw"`).
877
- */
878
- readonly capabilities: string[];
1146
+ private constructor();
1147
+ free(): void;
1148
+ [Symbol.dispose](): void;
1149
+ /**
1150
+ * Effective capabilities granted to this session.
1151
+ *
1152
+ * @returns {string[]} Normalized capability entries (e.g. `"/pub/app/:rw"`).
1153
+ */
1154
+ readonly capabilities: string[];
1155
+ /**
1156
+ * The user’s public key for this session.
1157
+ *
1158
+ * Use `.toString()` on the returned `PublicKey` to get the `pubky<z32>` identifier.
1159
+ * Call `.z32()` when you specifically need the raw z-base32 value (e.g. hostnames).
1160
+ *
1161
+ * @returns {PublicKey}
1162
+ *
1163
+ * @example
1164
+ * const who = sessionInfo.publicKey.toString();
1165
+ */
1166
+ readonly publicKey: PublicKey;
879
1167
  }
1168
+
880
1169
  /**
881
1170
  * Read/write storage scoped to **your** session (absolute paths: `/pub/...`).
882
1171
  */
883
1172
  export class SessionStorage {
884
- private constructor();
885
- free(): void;
886
- [Symbol.dispose](): void;
887
- /**
888
- * List a directory (absolute session path). Returns `pubky://…` URLs.
889
- *
890
- * @param {Path} path Must end with `/`.
891
- * @param {string|null=} cursor Optional suffix or full URL to start **after**.
892
- * @param {boolean=} reverse Default `false`.
893
- * @param {number=} limit Optional result limit.
894
- * @param {boolean=} shallow Default `false`.
895
- * @returns {Promise<string[]>}
896
- */
897
- list(path: Path, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
898
- /**
899
- * GET a streaming response for an absolute session path.
900
- *
901
- * @param {Path} path
902
- * @returns {Promise<Response>}
903
- */
904
- get(path: Path): Promise<Response>;
905
- /**
906
- * GET bytes from an absolute session path.
907
- *
908
- * @param {Path} path
909
- * @returns {Promise<Uint8Array>}
910
- */
911
- getBytes(path: Path): Promise<Uint8Array>;
912
- /**
913
- * GET text from an absolute session path.
914
- *
915
- * @param {Path} path
916
- * @returns {Promise<string>}
917
- */
918
- getText(path: Path): Promise<string>;
919
- /**
920
- * GET JSON from an absolute session path.
921
- *
922
- * @param {Path} path
923
- * @returns {Promise<any>}
924
- */
925
- getJson(path: Path): Promise<any>;
926
- /**
927
- * Check existence.
928
- *
929
- * @param {Path} path
930
- * @returns {Promise<boolean>}
931
- */
932
- exists(path: Path): Promise<boolean>;
933
- /**
934
- * Get metadata for an absolute, session-scoped path (e.g. `"/pub/app/file.json"`).
935
- *
936
- * @param {Path} path Absolute path under your user (starts with `/`).
937
- * @returns {Promise<ResourceStats|undefined>} `undefined` if the resource does not exist.
938
- * @throws {PubkyError} On invalid input or transport/server errors.
939
- */
940
- stats(path: Path): Promise<ResourceStats | undefined>;
941
- /**
942
- * PUT binary at an absolute session path.
943
- *
944
- * @param {Path} path
945
- * @param {Uint8Array} bytes
946
- * @returns {Promise<void>}
947
- */
948
- putBytes(path: Path, body: Uint8Array): Promise<void>;
949
- /**
950
- * PUT text at an absolute session path.
951
- *
952
- * @param {Path} path
953
- * @param {string} text
954
- * @returns {Promise<void>}
955
- */
956
- putText(path: Path, body: string): Promise<void>;
957
- /**
958
- * PUT JSON at an absolute session path.
959
- *
960
- * @param {Path} path Absolute path (e.g. `"/pub/app/data.json"`).
961
- * @param {any} value JSON-serializable value.
962
- * @returns {Promise<void>}
963
- */
964
- putJson(path: Path, body: any): Promise<void>;
965
- /**
966
- * Delete a path (file or empty directory).
967
- *
968
- * @param {Path} path
969
- * @returns {Promise<void>}
970
- */
971
- delete(path: Path): Promise<void>;
1173
+ private constructor();
1174
+ free(): void;
1175
+ [Symbol.dispose](): void;
1176
+ /**
1177
+ * Delete a path (file or empty directory).
1178
+ *
1179
+ * @param {Path} path
1180
+ * @returns {Promise<void>}
1181
+ */
1182
+ delete(path: Path): Promise<void>;
1183
+ /**
1184
+ * Check existence.
1185
+ *
1186
+ * @param {Path} path
1187
+ * @returns {Promise<boolean>}
1188
+ */
1189
+ exists(path: Path): Promise<boolean>;
1190
+ /**
1191
+ * GET a streaming response for an absolute session path.
1192
+ *
1193
+ * @param {Path} path
1194
+ * @returns {Promise<Response>}
1195
+ */
1196
+ get(path: Path): Promise<Response>;
1197
+ /**
1198
+ * GET bytes from an absolute session path.
1199
+ *
1200
+ * @param {Path} path
1201
+ * @returns {Promise<Uint8Array>}
1202
+ */
1203
+ getBytes(path: Path): Promise<Uint8Array>;
1204
+ /**
1205
+ * GET JSON from an absolute session path.
1206
+ *
1207
+ * @param {Path} path
1208
+ * @returns {Promise<any>}
1209
+ */
1210
+ getJson(path: Path): Promise<any>;
1211
+ /**
1212
+ * GET text from an absolute session path.
1213
+ *
1214
+ * @param {Path} path
1215
+ * @returns {Promise<string>}
1216
+ */
1217
+ getText(path: Path): Promise<string>;
1218
+ /**
1219
+ * List a directory (absolute session path). Returns `pubky://…` URLs.
1220
+ *
1221
+ * @param {Path} path Must end with `/`.
1222
+ * @param {string|null=} cursor Optional suffix or full URL to start **after**.
1223
+ * @param {boolean=} reverse Default `false`.
1224
+ * @param {number=} limit Optional result limit.
1225
+ * @param {boolean=} shallow Default `false`.
1226
+ * @returns {Promise<string[]>}
1227
+ */
1228
+ list(path: Path, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
1229
+ /**
1230
+ * PUT binary at an absolute session path.
1231
+ *
1232
+ * @param {Path} path
1233
+ * @param {Uint8Array} bytes
1234
+ * @returns {Promise<void>}
1235
+ */
1236
+ putBytes(path: Path, body: Uint8Array): Promise<void>;
1237
+ /**
1238
+ * PUT JSON at an absolute session path.
1239
+ *
1240
+ * @param {Path} path Absolute path (e.g. `"/pub/app/data.json"`).
1241
+ * @param {any} value JSON-serializable value.
1242
+ * @returns {Promise<void>}
1243
+ */
1244
+ putJson(path: Path, body: any): Promise<void>;
1245
+ /**
1246
+ * PUT text at an absolute session path.
1247
+ *
1248
+ * @param {Path} path
1249
+ * @param {string} text
1250
+ * @returns {Promise<void>}
1251
+ */
1252
+ putText(path: Path, body: string): Promise<void>;
1253
+ /**
1254
+ * Get metadata for an absolute, session-scoped path (e.g. `"/pub/app/file.json"`).
1255
+ *
1256
+ * @param {Path} path Absolute path under your user (starts with `/`).
1257
+ * @returns {Promise<ResourceStats|undefined>} `undefined` if the resource does not exist.
1258
+ * @throws {PubkyError} On invalid input or transport/server errors.
1259
+ */
1260
+ stats(path: Path): Promise<ResourceStats | undefined>;
972
1261
  }
1262
+
973
1263
  /**
974
1264
  * Holds a user’s `Keypair` and performs identity operations:
975
1265
  * - `signup` creates a new homeserver user.
@@ -978,87 +1268,133 @@ export class SessionStorage {
978
1268
  * - Publish PKDNS when signer-bound
979
1269
  */
980
1270
  export class Signer {
981
- private constructor();
982
- free(): void;
983
- [Symbol.dispose](): void;
984
- /**
985
- * Create a signer from a `Keypair` (prefer `pubky.signer(kp)`).
986
- *
987
- * @param {Keypair} keypair
988
- * @returns {Signer}
989
- */
990
- static fromKeypair(keypair: Keypair): Signer;
991
- /**
992
- * Sign up at a homeserver. Returns a ready `Session`.
993
- *
994
- * Creates a valid homeserver Session with root capabilities
995
- *
996
- * @param {PublicKey} homeserver The homeserver’s public key.
997
- * @param {string|null} signupToken Invite/registration token or `null`.
998
- * @returns {Promise<Session>}
999
- *
1000
- * @throws {PubkyError}
1001
- * - `AuthenticationError` (bad/expired token)
1002
- * - `RequestError` (network/server)
1003
- */
1004
- signup(homeserver: PublicKey, signup_token?: string | null): Promise<Session>;
1005
- /**
1006
- * Fast sign-in for a returning user. Publishes PKDNS in the background.
1007
- *
1008
- * Creates a valid homeserver Session with root capabilities
1009
- *
1010
- * @returns {Promise<Session>}
1011
- *
1012
- * @throws {PubkyError}
1013
- */
1014
- signin(): Promise<Session>;
1015
- /**
1016
- * Blocking sign-in. Waits for PKDNS publish to complete (slower; safer).
1017
- *
1018
- * Creates a valid homeserver Session with root capabilities
1019
- *
1020
- * @returns {Promise<Session>}
1021
- */
1022
- signinBlocking(): Promise<Session>;
1023
- /**
1024
- * Approve a `pubkyauth://` request URL (encrypts & POSTs the signed AuthToken).
1025
- */
1026
- approveAuthRequest(pubkyauth_url: string): Promise<void>;
1027
- /**
1028
- * Get the public key of this signer.
1029
- *
1030
- * @returns {PublicKey}
1031
- */
1032
- readonly publicKey: PublicKey;
1033
- /**
1034
- * Get a PKDNS actor bound to this signer's client & keypair (publishing enabled).
1035
- *
1036
- * @returns {Pkdns}
1037
- *
1038
- * @example
1039
- * await signer.pkdns.publishHomeserverIfStale(homeserverPk);
1040
- */
1041
- readonly pkdns: Pkdns;
1271
+ private constructor();
1272
+ free(): void;
1273
+ [Symbol.dispose](): void;
1274
+ /**
1275
+ * Approve a `pubkyauth://` request URL (encrypts & POSTs the signed AuthToken).
1276
+ */
1277
+ approveAuthRequest(pubkyauth_url: string): Promise<void>;
1278
+ /**
1279
+ * Create a signer from a `Keypair` (prefer `pubky.signer(kp)`).
1280
+ *
1281
+ * @param {Keypair} keypair
1282
+ * @returns {Signer}
1283
+ */
1284
+ static fromKeypair(keypair: Keypair): Signer;
1285
+ /**
1286
+ * Fast sign-in for a returning user. Publishes PKDNS in the background.
1287
+ *
1288
+ * Creates a valid homeserver Session with root capabilities
1289
+ *
1290
+ * @returns {Promise<Session>}
1291
+ *
1292
+ * @throws {PubkyError}
1293
+ */
1294
+ signin(): Promise<Session>;
1295
+ /**
1296
+ * Blocking sign-in. Waits for PKDNS publish to complete (slower; safer).
1297
+ *
1298
+ * Creates a valid homeserver Session with root capabilities
1299
+ *
1300
+ * @returns {Promise<Session>}
1301
+ */
1302
+ signinBlocking(): Promise<Session>;
1303
+ /**
1304
+ * Sign up at a homeserver. Returns a ready `Session`.
1305
+ *
1306
+ * Creates a valid homeserver Session with root capabilities
1307
+ *
1308
+ * @param {PublicKey} homeserver The homeserver’s public key.
1309
+ * @param {string|null} signupToken Invite/registration token or `null`.
1310
+ * @returns {Promise<Session>}
1311
+ *
1312
+ * @throws {PubkyError}
1313
+ * - `AuthenticationError` (bad/expired token)
1314
+ * - `RequestError` (network/server)
1315
+ */
1316
+ signup(homeserver: PublicKey, signup_token?: string | null): Promise<Session>;
1317
+ /**
1318
+ * Get a PKDNS actor bound to this signer's client & keypair (publishing enabled).
1319
+ *
1320
+ * @returns {Pkdns}
1321
+ *
1322
+ * @example
1323
+ * await signer.pkdns.publishHomeserverIfStale(homeserverPk);
1324
+ */
1325
+ readonly pkdns: Pkdns;
1326
+ /**
1327
+ * Get the public key of this signer.
1328
+ *
1329
+ * @returns {PublicKey}
1330
+ */
1331
+ readonly publicKey: PublicKey;
1042
1332
  }
1333
+
1043
1334
  export class SigninDeepLink {
1044
- private constructor();
1045
- free(): void;
1046
- [Symbol.dispose](): void;
1047
- static parse(url: string): SigninDeepLink;
1048
- toString(): string;
1049
- readonly capabilities: string;
1050
- readonly baseRelayUrl: string;
1051
- readonly secret: Uint8Array;
1335
+ private constructor();
1336
+ free(): void;
1337
+ [Symbol.dispose](): void;
1338
+ static parse(url: string): SigninDeepLink;
1339
+ toString(): string;
1340
+ readonly baseRelayUrl: string;
1341
+ readonly capabilities: string;
1342
+ readonly secret: Uint8Array;
1052
1343
  }
1344
+
1053
1345
  export class SignupDeepLink {
1054
- private constructor();
1055
- free(): void;
1056
- [Symbol.dispose](): void;
1057
- static parse(url: string): SignupDeepLink;
1058
- toString(): string;
1059
- readonly capabilities: string;
1060
- readonly baseRelayUrl: string;
1061
- readonly secret: Uint8Array;
1062
- readonly homeserver: PublicKey;
1063
- readonly signupToken: string | undefined;
1346
+ private constructor();
1347
+ free(): void;
1348
+ [Symbol.dispose](): void;
1349
+ static parse(url: string): SignupDeepLink;
1350
+ toString(): string;
1351
+ readonly baseRelayUrl: string;
1352
+ readonly capabilities: string;
1353
+ readonly homeserver: PublicKey;
1354
+ readonly secret: Uint8Array;
1355
+ readonly signupToken: string | undefined;
1064
1356
  }
1357
+
1358
+ /**
1359
+ * Resolve a `pubky://` or `pubky<pk>/…` identifier into the homeserver transport URL.
1360
+ *
1361
+ * @param {string} identifier Either `pubky<pk>/...` (preferred) or `pubky://<pk>/...`.
1362
+ * @returns {string} HTTPS URL in the form `https://_pubky.<pk>/...`.
1363
+ */
1364
+ export function resolvePubky(identifier: string): string;
1365
+
1366
+ /**
1367
+ * Set the global logging verbosity for the WASM Pubky SDK. Routes Rust `log` output to the browser console.
1368
+ *
1369
+ * Accepted values (case-sensitive): "error" | "warn" | "info" | "debug" | "trace".
1370
+ * Effects:
1371
+ * - Initializes the logger once; subsequent calls may throw if the logger is already set.
1372
+ * - Emits a single info log: `Log level set to: <level>`.
1373
+ * - Messages at or above `level` are forwarded to the appropriate `console.*` method.
1374
+ *
1375
+ * @param {Level} level
1376
+ * Minimum log level to enable. One of: "error" | "warn" | "info" | "debug" | "trace".
1377
+ *
1378
+ * @returns {void}
1379
+ *
1380
+ * @throws {Error}
1381
+ * If `level` is invalid ("Invalid log level") or the logger cannot be initialized
1382
+ * (e.g., already initialized).
1383
+ *
1384
+ * Usage:
1385
+ * Call once at application startup, before invoking other SDK APIs.
1386
+ */
1387
+ export function setLogLevel(level: Level): void;
1388
+
1389
+ /**
1390
+ * Validate and normalize a capabilities string.
1391
+ *
1392
+ * - Normalizes action order (`wr` -> `rw`)
1393
+ * - Throws `InvalidInput` listing malformed entries.
1394
+ *
1395
+ * @param {string} input
1396
+ * @returns {string} Normalized string (same shape as input).
1397
+ * @throws {PubkyError} `{ name: "InvalidInput" }` with a helpful message.
1398
+ * The error's `data` field is `{ invalidEntries: string[] }` listing malformed tokens.
1399
+ */
1400
+ export function validateCapabilities(input: string): string;