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