@synonymdev/pubky 0.6.0-rc.2 → 0.6.0-rc.7

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 +167 -45
  2. package/index.cjs +1335 -514
  3. package/index.js +1454 -601
  4. package/package.json +9 -5
  5. package/pubky.d.ts +397 -167
  6. package/pubky_bg.wasm +0 -0
package/pubky.d.ts CHANGED
@@ -3,13 +3,13 @@
3
3
  /**
4
4
  * Set the global logging verbosity for the WASM Pubky SDK. Routes Rust `log` output to the browser console.
5
5
  *
6
- * Accepted values (case-insensitive): "error" | "warn" | "info" | "debug" | "trace".
6
+ * Accepted values (case-sensitive): "error" | "warn" | "info" | "debug" | "trace".
7
7
  * Effects:
8
8
  * - Initializes the logger once; subsequent calls may throw if the logger is already set.
9
9
  * - Emits a single info log: `Log level set to: <level>`.
10
10
  * - Messages at or above `level` are forwarded to the appropriate `console.*` method.
11
11
  *
12
- * @param {string} level
12
+ * @param {Level} level
13
13
  * Minimum log level to enable. One of: "error" | "warn" | "info" | "debug" | "trace".
14
14
  *
15
15
  * @returns {void}
@@ -21,7 +21,14 @@
21
21
  * Usage:
22
22
  * Call once at application startup, before invoking other SDK APIs.
23
23
  */
24
- export function setLogLevel(level: string): void;
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;
25
32
  /**
26
33
  * Validate and normalize a capabilities string.
27
34
  *
@@ -30,12 +37,58 @@ export function setLogLevel(level: string): void;
30
37
  *
31
38
  * @param {string} input
32
39
  * @returns {string} Normalized string (same shape as input).
33
- * @throws {PubkyJsError} `{ name: "InvalidInput" }` with a helpful message.
40
+ * @throws {PubkyError} `{ name: "InvalidInput" }` with a helpful message.
41
+ * The error's `data` field is `{ invalidEntries: string[] }` listing malformed tokens.
34
42
  */
35
43
  export function validateCapabilities(input: string): string;
44
+ /**
45
+ * An enum representing the available verbosity levels of the logger.
46
+ */
47
+ type Level = "error" | "warn" | "info" | "debug" | "trace";
48
+ /**
49
+ * The `ReadableStreamType` enum.
50
+ *
51
+ * *This API requires the following crate features to be activated: `ReadableStreamType`*
52
+ */
53
+ type ReadableStreamType = "bytes";
54
+ export type Path = `/pub/${string}`;
55
+
56
+ export type Address = `pubky${string}/pub/${string}` | `pubky://${string}/pub/${string}`;
57
+
58
+ /**
59
+ * Pkarr Config
60
+ */
61
+ export interface PkarrConfig {
62
+ /**
63
+ * The list of relays to access the DHT with.
64
+ */
65
+ relays?: string[];
66
+ /**
67
+ * The timeout for DHT requests in milliseconds.
68
+ * Default is 2000ms.
69
+ */
70
+ requestTimeout?: number;
71
+ }
72
+
73
+ /**
74
+ * Pubky Client Config
75
+ */
76
+ export interface PubkyClientConfig {
77
+ /**
78
+ * Configuration on how to access pkarr packets on the mainline DHT.
79
+ */
80
+ pkarr?: PkarrConfig;
81
+ }
82
+
83
+ export type CapabilityAction = "r" | "w" | "rw";
84
+ export type CapabilityScope = `/${string}`;
85
+ export type CapabilityEntry = `${CapabilityScope}:${CapabilityAction}`;
86
+ type CapabilitiesTail = `,${CapabilityEntry}${string}`;
87
+ export type Capabilities = "" | CapabilityEntry | `${CapabilityEntry}${CapabilitiesTail}`;
88
+
36
89
  /**
37
90
  * A union type of all possible machine-readable codes for the `name` property
38
- * of a {@link PubkyJsError}.
91
+ * of a {@link PubkyError}.
39
92
  *
40
93
  * Provides a simplified, actionable set of error categories for developers
41
94
  * to handle in their code.
@@ -55,46 +108,58 @@ export type PubkyErrorName = "RequestError" | "InvalidInput" | "AuthenticationEr
55
108
  * try {
56
109
  * await client.signup(...);
57
110
  * } catch (e) {
58
- * const error = e as PubkyJsError;
59
- * if (error.name === \'RequestError\' && error.statusCode === 404) {
111
+ * const error = e as PubkyError;
112
+ * if (
113
+ * error.name === \'RequestError\' &&
114
+ * typeof error.data === \'object\' &&
115
+ * error.data !== null &&
116
+ * \'statusCode\' in error.data &&
117
+ * (error.data as { statusCode?: number }).statusCode === 404
118
+ * ) {
60
119
  * // Handle not found...
61
120
  * }
62
121
  * }
63
122
  * ```
64
123
  */
65
- export interface PubkyJsError {
124
+ export interface PubkyError {
66
125
  name: PubkyErrorName;
67
126
  message: string;
68
127
  /**
69
- * For `RequestError::Server`, this carries the numeric HTTP status code (e.g. 404).
70
- * Otherwise `undefined` on the JS side.
71
- */
72
- statusCode?: number;
73
- }
74
-
75
- /**
76
- * Pkarr Config
77
- */
78
- export interface PkarrConfig {
79
- /**
80
- * The list of relays to access the DHT with.
81
- */
82
- relays?: string[];
83
- /**
84
- * The timeout for DHT requests in milliseconds.
85
- * Default is 2000ms.
128
+ * Optional structured context associated with the error.
86
129
  */
87
- requestTimeout?: number;
130
+ data?: unknown;
88
131
  }
89
132
 
90
133
  /**
91
- * Pubky Client Config
134
+ * Represents the standard error structure for all exceptions thrown by the Pubky
135
+ * WASM client.
136
+ *
137
+ * @property name - A machine-readable error code from {@link PubkyErrorName}. Use this for programmatic error handling.
138
+ * @property message - A human-readable, descriptive error message suitable for logging.
139
+ * @property data - An optional payload containing structured context for an error. For a `RequestError`, this may contain an object with the HTTP status code, e.g., `{ statusCode: 404 }`.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * try {
144
+ * await client.signup(...);
145
+ * } catch (e) {
146
+ * const error = e as PubkyError;
147
+ * if (
148
+ * error.name === "RequestError" &&
149
+ * typeof error.data === "object" &&
150
+ * error.data !== null &&
151
+ * "statusCode" in error.data &&
152
+ * (error.data as { statusCode?: number }).statusCode === 404
153
+ * ) {
154
+ * // Handle not found...
155
+ * }
156
+ * }
157
+ * ```
92
158
  */
93
- export interface PubkyClientConfig {
94
- /**
95
- * Configuration on how to access pkarr packets on the mainline DHT.
96
- */
97
- pkarr?: PkarrConfig;
159
+ export interface PubkyError extends Error {
160
+ name: PubkyErrorName;
161
+ message: string;
162
+ data?: unknown;
98
163
  }
99
164
 
100
165
  /**
@@ -107,7 +172,7 @@ export interface PubkyClientConfig {
107
172
  * @property {string=} etag Opaque server ETag for the current version.
108
173
  *
109
174
  * @example
110
- * const stats = await pubky.publicStorage().stats(`${user}/pub/app/file.json`);
175
+ * const stats = await pubky.publicStorage.stats(`${user}/pub/app/file.json`);
111
176
  * if (stats) {
112
177
  * console.log(stats.contentLength, stats.contentType, stats.lastModifiedMs);
113
178
  * }
@@ -147,17 +212,25 @@ export interface ResourceStats {
147
212
  export class AuthFlow {
148
213
  private constructor();
149
214
  free(): void;
215
+ [Symbol.dispose](): void;
150
216
  /**
151
217
  * Start a flow (standalone).
152
- * Prefer `pubky.startAuthFlow()` to reuse a façade client.
218
+ * Prefer `pubky.startAuthFlow()` to reuse a facade client.
153
219
  *
154
220
  * @param {string} capabilities
155
221
  * Comma-separated capabilities, e.g. `"/pub/app/:rw,/priv/foo.txt:r"`.
156
222
  * Each entry must be `"<scope>:<actions>"`, where:
157
- * - `scope` starts with `/` (e.g. `/pub/example.app/`)
223
+ * - `scope` starts with `/` (e.g. `/pub/example.com/`)
158
224
  * - `actions` is any combo of `r` and/or `w` (order is normalized; `wr` -> `rw`)
159
225
  * Empty string is allowed (no scopes).
160
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
+ *
161
234
  * @param {string} [relay]
162
235
  * Optional HTTP relay base, e.g. `"https://demo.httprelay.io/link/"`.
163
236
  * Defaults to the default Synonym-hosted relay when omitted.
@@ -165,31 +238,22 @@ export class AuthFlow {
165
238
  * @returns {AuthFlow}
166
239
  * A running auth flow. Call `authorizationUrl()` to show the deep link,
167
240
  * then `awaitApproval()` to receive a `Session`.
168
- * @throws {PubkyJsError}
241
+ * @throws {PubkyError}
169
242
  * - `{ name: "InvalidInput", message: string }` if any capability entry is invalid
170
243
  * or for an invalid relay URL.
171
244
  * @example
172
- * const flow = AuthFlow.start("/pub/my.app/:rw,/pub/pubky.app/:w");
245
+ * const flow = AuthFlow.start("/pub/my-cool-app/:rw,/pub/pubky.app/:w");
173
246
  * renderQRCode(flow.authorizationUrl());
174
247
  * const session = await flow.awaitApproval();
175
248
  */
176
- static start(capabilities: string, relay?: string | null): AuthFlow;
177
- /**
178
- * Return the authorization deep link (URL) to show as QR or open on the signer device.
179
- *
180
- * @returns {string} A `pubkyauth://…` or `https://…` URL with channel info.
181
- *
182
- * @example
183
- * renderQr(flow.authorizationUrl());
184
- */
185
- authorizationUrl(): string;
249
+ static start(capabilities: Capabilities, kind: AuthFlowKind, relay?: string | null): AuthFlow;
186
250
  /**
187
251
  * Block until the user approves on their signer device; returns a `Session`.
188
252
  *
189
253
  * @returns {Promise<Session>}
190
254
  * Resolves when approved; rejects on timeout/cancel/network errors.
191
255
  *
192
- * @throws {PubkyJsError}
256
+ * @throws {PubkyError}
193
257
  * - `RequestError` if relay/network fails
194
258
  * - `AuthenticationError` if approval is denied/invalid
195
259
  */
@@ -200,16 +264,52 @@ export class AuthFlow {
200
264
  * @returns {Promise<AuthToken>}
201
265
  * Resolves when approved; rejects on timeout/cancel/network errors.
202
266
  *
203
- * @throws {PubkyJsError}
267
+ * @throws {PubkyError}
204
268
  * - `RequestError` if relay/network fails
205
269
  */
206
270
  awaitToken(): Promise<AuthToken>;
207
271
  /**
208
272
  * Non-blocking single poll step (advanced UIs).
209
273
  *
210
- * @returns {Promise<Session|null>} A session if the approval arrived, otherwise `null`.
274
+ * @returns {Promise<Session|undefined>} A session if the approval arrived, otherwise `undefined`.
211
275
  */
212
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;
286
+ }
287
+ /**
288
+ * The kind of authentication flow to perform.
289
+ * This can either be a sign in or a sign up flow.
290
+ */
291
+ 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;
213
313
  }
214
314
  /**
215
315
  * AuthToken: signed, time-bound proof of key ownership.
@@ -240,6 +340,7 @@ export class AuthFlow {
240
340
  export class AuthToken {
241
341
  private constructor();
242
342
  free(): void;
343
+ [Symbol.dispose](): void;
243
344
  /**
244
345
  * Parse and verify an `AuthToken` from its canonical bytes.
245
346
  *
@@ -269,15 +370,25 @@ export class AuthToken {
269
370
  */
270
371
  static fromBytes(bytes: Uint8Array): AuthToken;
271
372
  /**
272
- * Returns the **public key** that authenticated with this token.
373
+ * Serialize the token to a `Uint8Array` in its **canonical** (postcard) binary format.
273
374
  *
274
- * Use `.z32()` on the returned `PublicKey` to get the string form.
375
+ * Use this to send the token to a backend for verification.
275
376
  *
276
377
  * ```js
277
- * const who = token.publicKey().z32();
378
+ * const bytes = token.toBytes();
379
+ * await fetch("/api/verify", { method: "POST", body: bytes });
278
380
  * ```
279
381
  */
280
- publicKey(): PublicKey;
382
+ toBytes(): Uint8Array;
383
+ /**
384
+ * Returns the **public key** that authenticated with this token.
385
+ *
386
+ * Use `.z32()` on the returned `PublicKey` to get the string form.
387
+ *
388
+ * @example
389
+ * const who = sessionInfo.publicKey.z32();
390
+ */
391
+ readonly publicKey: PublicKey;
281
392
  /**
282
393
  * Returns the **capabilities** requested by the flow at the time this token was signed.
283
394
  *
@@ -286,29 +397,19 @@ export class AuthToken {
286
397
  *
287
398
  * Returns: `string[]`, where each item is the canonical entry `"<scope>:<actions>"`.
288
399
  *
289
- * Example entry: `"/pub/my.app/:rw"`
290
- */
291
- capabilities(): Array<any>;
292
- /**
293
- * Serialize the token to a `Uint8Array` in its **canonical** (postcard) binary format.
294
- *
295
- * Use this to send the token to a backend for verification.
296
- *
297
- * ```js
298
- * const bytes = token.toBytes();
299
- * await fetch("/api/verify", { method: "POST", body: bytes });
300
- * ```
400
+ * Example entry: `"/pub/my-cool-app/:rw"`
301
401
  */
302
- toBytes(): Uint8Array;
402
+ readonly capabilities: string[];
303
403
  }
304
404
  /**
305
- * Low-level HTTP bridge used by the Pubky façade and actors.
405
+ * Low-level HTTP bridge used by the Pubky facade and actors.
306
406
  *
307
- * - Supports `pubky://<user-z32>/<abs-path>` and `http(s)://` URLs.
407
+ * - Supports `http(s)://` URLs targeting Pubky or ICANN hosts.
308
408
  * - In browsers/undici, passes `credentials: "include"` to send cookies.
309
409
  */
310
410
  export class Client {
311
411
  free(): void;
412
+ [Symbol.dispose](): void;
312
413
  /**
313
414
  * Create a Pubky HTTP client.
314
415
  *
@@ -317,7 +418,7 @@ export class Client {
317
418
  * `{ pkarr?: { relays?: string[], request_timeout?: number } }`.
318
419
  *
319
420
  * @returns {Client}
320
- * A configured low-level client. Prefer `new Pubky().client()` unless you
421
+ * A configured low-level client. Prefer `new Pubky().client` unless you
321
422
  * need custom relays/timeouts.
322
423
  *
323
424
  * @throws {InvalidInput}
@@ -333,8 +434,7 @@ export class Client {
333
434
  /**
334
435
  * Create a client wired for **local testnet**.
335
436
  *
336
- * Sets PKARR relays to `http://<host>:15411/` and enables WASM `pubky://`
337
- * mapping for that host.
437
+ * Configures PKARR relays for the testnet and remembers the hostname for WASM `_pubky` mapping.
338
438
  *
339
439
  * @param {string} [host="localhost"]
340
440
  * Testnet hostname or IP.
@@ -351,21 +451,47 @@ export class Client {
351
451
  */
352
452
  static testnet(host?: string | null): Client;
353
453
  /**
354
- * Perform a raw fetch. Works with `pubky://` or `http(s)://` URLs.
454
+ * Perform a raw fetch. Works with `http(s)://` URLs.
355
455
  *
356
456
  * @param {string} url
357
- * @param {RequestInit=} init Standard fetch options; `credentials: "include"` recommended for session I/O.
457
+ * @param {RequestInit} init Standard fetch options; `credentials: "include"` recommended for session I/O.
358
458
  * @returns {Promise<Response>}
359
459
  *
360
460
  * @example
361
- * const client = pubky.client();
362
- * const res = await client.fetch(`pubky://${user}/pub/app/file.txt`, { method: "PUT", body: "hi", credentials: "include" });
461
+ * const client = pubky.client;
462
+ * const res = await client.fetch(`https://_pubky.${user}/pub/app/file.txt`, { method: "PUT", body: "hi", credentials: "include" });
363
463
  */
364
- fetch(url: string, init?: any | null): Promise<Promise<any>>;
464
+ fetch(url: string, init?: RequestInit | null): Promise<Response>;
465
+ }
466
+ export class IntoUnderlyingByteSource {
467
+ private constructor();
468
+ free(): void;
469
+ [Symbol.dispose](): void;
470
+ start(controller: ReadableByteStreamController): void;
471
+ pull(controller: ReadableByteStreamController): Promise<any>;
472
+ cancel(): void;
473
+ readonly type: ReadableStreamType;
474
+ readonly autoAllocateChunkSize: number;
475
+ }
476
+ export class IntoUnderlyingSink {
477
+ private constructor();
478
+ free(): void;
479
+ [Symbol.dispose](): void;
480
+ write(chunk: any): Promise<any>;
481
+ close(): Promise<any>;
482
+ abort(reason: any): Promise<any>;
483
+ }
484
+ export class IntoUnderlyingSource {
485
+ private constructor();
486
+ free(): void;
487
+ [Symbol.dispose](): void;
488
+ pull(controller: ReadableStreamDefaultController): Promise<any>;
489
+ cancel(): void;
365
490
  }
366
491
  export class Keypair {
367
492
  private constructor();
368
493
  free(): void;
494
+ [Symbol.dispose](): void;
369
495
  /**
370
496
  * Generate a random [Keypair]
371
497
  */
@@ -378,10 +504,6 @@ export class Keypair {
378
504
  * Returns the secret key of this keypair.
379
505
  */
380
506
  secretKey(): Uint8Array;
381
- /**
382
- * Returns the [PublicKey] of this keypair.
383
- */
384
- publicKey(): PublicKey;
385
507
  /**
386
508
  * Create a recovery file for this keypair (encrypted with the given passphrase).
387
509
  */
@@ -390,12 +512,22 @@ export class Keypair {
390
512
  * Decrypt a recovery file and return a Keypair (decrypted with the given passphrase).
391
513
  */
392
514
  static fromRecoveryFile(recovery_file: Uint8Array, passphrase: string): Keypair;
515
+ /**
516
+ * Returns the [PublicKey] of this keypair.
517
+ *
518
+ * Use `.z32()` on the returned `PublicKey` to get the string form.
519
+ *
520
+ * @example
521
+ * const who = keypair.publicKey.z32();
522
+ */
523
+ readonly publicKey: PublicKey;
393
524
  }
394
525
  /**
395
526
  * Resolve/publish `_pubky` PKDNS records (homeserver pointers).
396
527
  */
397
528
  export class Pkdns {
398
529
  free(): void;
530
+ [Symbol.dispose](): void;
399
531
  /**
400
532
  * Read-only PKDNS actor (no keypair; resolve only).
401
533
  */
@@ -408,17 +540,17 @@ export class Pkdns {
408
540
  * Resolve the homeserver for a given public key (read-only).
409
541
  *
410
542
  * @param {PublicKey} user
411
- * @returns {Promise<string|undefined>} Homeserver public key (z32) or `undefined` if not found.
543
+ * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
412
544
  */
413
- getHomeserverOf(pubky: PublicKey): Promise<string | undefined>;
545
+ getHomeserverOf(pubky: PublicKey): Promise<PublicKey | undefined>;
414
546
  /**
415
547
  * Resolve the homeserver for **this** user (requires keypair).
416
548
  *
417
- * @returns {Promise<string|undefined>} Homeserver public key (z32) or `undefined` if not found.
549
+ * @returns {Promise<PublicKey|undefined>} Homeserver public key or `undefined` if not found.
418
550
  */
419
- getHomeserver(): Promise<string | undefined>;
551
+ getHomeserver(): Promise<PublicKey | undefined>;
420
552
  /**
421
- * Republish homeserver if record is missing/stale.
553
+ * Force publish homeserver immediately (even if fresh).
422
554
  *
423
555
  * Requires keypair or to be signer bound.
424
556
  *
@@ -427,7 +559,7 @@ export class Pkdns {
427
559
  */
428
560
  publishHomeserverForce(host_override?: PublicKey | null): Promise<void>;
429
561
  /**
430
- * Force publish homeserver immediately (even if fresh).
562
+ * Republish homeserver if record is missing/stale.
431
563
  *
432
564
  * Requires keypair or to be signer bound.
433
565
  *
@@ -441,11 +573,12 @@ export class Pkdns {
441
573
  */
442
574
  export class Pubky {
443
575
  free(): void;
576
+ [Symbol.dispose](): void;
444
577
  /**
445
- * Create a Pubky façade wired for **mainnet** defaults (public relays).
578
+ * Create a Pubky facade wired for **mainnet** defaults (public relays).
446
579
  *
447
580
  * @returns {Pubky}
448
- * A new façade instance. Use this to create signers, start auth flows, etc.
581
+ * A new facade instance. Use this to create signers, start auth flows, etc.
449
582
  *
450
583
  * @example
451
584
  * const pubky = new Pubky();
@@ -453,7 +586,7 @@ export class Pubky {
453
586
  */
454
587
  constructor();
455
588
  /**
456
- * Create a Pubky façade preconfigured for a **local testnet**.
589
+ * Create a Pubky facade preconfigured for a **local testnet**.
457
590
  *
458
591
  * If `host` is provided, PKARR and HTTP endpoints are derived as `http://<host>:ports/...`.
459
592
  * If omitted, `"localhost"` is assumed (handy for `cargo install pubky-testnet`).
@@ -467,7 +600,7 @@ export class Pubky {
467
600
  */
468
601
  static testnet(host?: string | null): Pubky;
469
602
  /**
470
- * Wrap an existing configured HTTP client into a Pubky façade.
603
+ * Wrap an existing configured HTTP client into a Pubky facade.
471
604
  *
472
605
  * @param {Client} client A previously constructed client.
473
606
  * @returns {Pubky}
@@ -483,26 +616,30 @@ export class Pubky {
483
616
  * Provide a **capabilities string** and (optionally) a relay base URL.
484
617
  * The capabilities string is a comma-separated list of entries:
485
618
  * `"<scope>:<actions>"`, where:
486
- * - `scope` starts with `/` (e.g. `/pub/example.app/`).
619
+ * - `scope` starts with `/` (e.g. `/pub/example.com/`).
487
620
  * - `actions` is any combo of `r` and/or `w` (order normalized; `wr` -> `rw`).
488
621
  * Pass `""` for no scopes (read-only public session).
489
622
  *
490
623
  * @param {string} capabilities Comma-separated caps, e.g. `"/pub/app/:rw,/pub/foo/file:r"`.
624
+ * @param {AuthFlowKind} kind The kind of authentication flow to perform.
625
+ * Examples:
626
+ * - `AuthFlowKind.signin()` - Sign in to an existing account.
627
+ * - `AuthFlowKind.signup(homeserverPublicKey, signupToken)` - Sign up for a new account.
491
628
  * @param {string=} relay Optional HTTP relay base (e.g. `"https://…/link/"`).
492
629
  * @returns {AuthFlow}
493
- * A running auth flow. Call `authorizationUrl()` to show a QR/deeplink,
630
+ * A running auth flow. Show `authorizationUrl` as QR/deeplink,
494
631
  * then `awaitApproval()` to obtain a `Session`.
495
632
  *
496
- * @throws {PubkyJsError}
633
+ * @throws {PubkyError}
497
634
  * - `{ name: "InvalidInput" }` for malformed capabilities or bad relay URL
498
635
  * - `{ name: "RequestError" }` if the flow cannot be started (network/relay)
499
636
  *
500
637
  * @example
501
- * const flow = pubky.startAuthFlow("/pub/my.app/:rw");
502
- * renderQr(flow.authorizationUrl());
638
+ * const flow = pubky.startAuthFlow("/pub/my-cool-app/:rw");
639
+ * renderQr(flow.authorizationUrl);
503
640
  * const session = await flow.awaitApproval();
504
641
  */
505
- startAuthFlow(capabilities: string, relay?: string | null): AuthFlow;
642
+ startAuthFlow(capabilities: Capabilities, kind: AuthFlowKind, relay?: string | null): AuthFlow;
506
643
  /**
507
644
  * Create a `Signer` from an existing `Keypair`.
508
645
  *
@@ -515,28 +652,40 @@ export class Pubky {
515
652
  */
516
653
  signer(keypair: Keypair): Signer;
517
654
  /**
518
- * Public, unauthenticated storage API.
655
+ * Resolve the homeserver for a given public key (read-only).
519
656
  *
520
- * Use for **read-only** public access via addressed paths:
521
- * `"<user-z32>/pub/…"`.
657
+ * Uses an internal read-only Pkdns actor.
522
658
  *
523
- * @returns {PublicStorage}
659
+ * @param {PublicKey} user
660
+ * @returns {Promise<PublicKey|undefined>} Homeserver public key (z32) or `undefined` if not found.
661
+ */
662
+ getHomeserverOf(user_public_key: PublicKey): Promise<PublicKey | undefined>;
663
+ /**
664
+ * Restore a session from a previously exported snapshot, using this instance's client.
665
+ *
666
+ * This does **not** read or write any secrets. It revalidates the session metadata with
667
+ * the server using the browser-managed HTTP-only cookie that must still be present.
668
+ *
669
+ * @param {string} exported A string produced by `session.export()`.
670
+ * @returns {Promise<Session>}
671
+ * A rehydrated session bound to this SDK's HTTP client.
524
672
  *
525
673
  * @example
526
- * const pub = pubky.publicStorage();
527
- * const text = await pub.getText(`${userPk.z32()}/pub/example.com/hello.txt`);
674
+ * const restored = await pubky.restoreSession(localStorage.getItem("pubky-session")!);
528
675
  */
529
- publicStorage(): PublicStorage;
676
+ restoreSession(exported: string): Promise<Session>;
530
677
  /**
531
- * Read-only PKDNS (Pkarr) resolver.
678
+ * Public, unauthenticated storage API.
532
679
  *
533
- * @returns {Pkdns}
680
+ * Use for **read-only** public access via addressed paths:
681
+ * `"<user-z32>/pub/…"`.
682
+ *
683
+ * @returns {PublicStorage}
534
684
  *
535
685
  * @example
536
- * const dns = pubky.pkdns();
537
- * const homeserver = await dns.getHomeserverOf(userPk);
686
+ * const text = await pubky.publicStorage.getText(`${userPk.z32()}/pub/example.com/hello.txt`);
538
687
  */
539
- pkdns(): Pkdns;
688
+ readonly publicStorage: PublicStorage;
540
689
  /**
541
690
  * Access the underlying HTTP client (advanced).
542
691
  *
@@ -544,13 +693,14 @@ export class Pubky {
544
693
  * Use this for low-level `fetch()` calls or testing with raw URLs.
545
694
  *
546
695
  * @example
547
- * const r = await pubky.client().fetch(`pubky://${user}/pub/app/file.txt`, { credentials: "include" });
696
+ * const r = await pubky.client.fetch(`pubky://${user}/pub/app/file.txt`, { credentials: "include" });
548
697
  */
549
- client(): Client;
698
+ readonly client: Client;
550
699
  }
551
700
  export class PublicKey {
552
701
  private constructor();
553
702
  free(): void;
703
+ [Symbol.dispose](): void;
554
704
  /**
555
705
  * Convert the PublicKey to Uint8Array
556
706
  */
@@ -569,85 +719,125 @@ export class PublicKey {
569
719
  */
570
720
  export class PublicStorage {
571
721
  free(): void;
722
+ [Symbol.dispose](): void;
572
723
  /**
573
724
  * Construct PublicStorage using global client (mainline relays).
574
725
  */
575
726
  constructor();
576
727
  /**
577
- * List a directory. Results are `pubky://…` absolute URLs.
728
+ * List a directory. Results are `pubky://…` identifier URLs.
578
729
  *
579
- * @param {string} address Addressed directory (must end with `/`).
730
+ * @param {Address} address Addressed directory (must end with `/`).
580
731
  * @param {string|null=} cursor Optional suffix or full URL to start **after**.
581
732
  * @param {boolean=} reverse Default `false`. When `true`, newest/lexicographically-last first.
582
733
  * @param {number=} limit Optional result limit.
583
734
  * @param {boolean=} shallow Default `false`. When `true`, lists only first-level entries.
584
735
  * @returns {Promise<string[]>}
585
736
  */
586
- list(address: string, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
737
+ list(address: Address, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
738
+ /**
739
+ * Perform a streaming `GET` and expose the raw `Response` object.
740
+ *
741
+ * @param {Address} address
742
+ * @returns {Promise<Response>}
743
+ */
744
+ get(address: Address): Promise<Response>;
587
745
  /**
588
746
  * Fetch bytes from an addressed path.
589
747
  *
590
- * @param {string} address
748
+ * @param {Address} address
591
749
  * @returns {Promise<Uint8Array>}
592
750
  */
593
- getBytes(address: string): Promise<Uint8Array>;
751
+ getBytes(address: Address): Promise<Uint8Array>;
594
752
  /**
595
753
  * Fetch text from an addressed path as UTF-8 text.
596
754
  *
597
- * @param {string} address
755
+ * @param {Address} address
598
756
  * @returns {Promise<string>}
599
757
  */
600
- getText(address: string): Promise<string>;
758
+ getText(address: Address): Promise<string>;
601
759
  /**
602
760
  * Fetch JSON from an addressed path.
603
761
  *
604
- * @param {string} address `"<user-z32>/pub/.../file.json"` or `pubky://<user>/pub/...`.
762
+ * @param {Address} address `"pubky<user>/pub/.../file.json"` (preferred) or `pubky://<user>/pub/...`.
605
763
  * @returns {Promise<any>}
606
764
  */
607
- getJson(address: string): Promise<any>;
765
+ getJson(address: Address): Promise<any>;
608
766
  /**
609
767
  * Check if a path exists.
610
768
  *
611
- * @param {string} address
769
+ * @param {Address} address
612
770
  * @returns {Promise<boolean>}
613
771
  */
614
- exists(address: string): Promise<boolean>;
772
+ exists(address: Address): Promise<boolean>;
615
773
  /**
616
774
  * Get metadata for an address
617
775
  *
618
- * @param {string} address `"<user-z32>/pub/.../file.json"` or `pubky://<user>/pub/...`.
776
+ * @param {Address} address `"pubky<user>/pub/.../file.json"` (preferred) or `pubky://<user>/pub/...`.
619
777
  * @returns {Promise<ResourceStats|undefined>} `undefined` if the resource does not exist.
620
- * @throws {PubkyJsError} On invalid input or transport/server errors.
778
+ * @throws {PubkyError} On invalid input or transport/server errors.
621
779
  */
622
- stats(address: string): Promise<ResourceStats | undefined>;
780
+ stats(address: Address): Promise<ResourceStats | undefined>;
781
+ }
782
+ export class SeedExportDeepLink {
783
+ private constructor();
784
+ free(): void;
785
+ [Symbol.dispose](): void;
786
+ static parse(url: string): SeedExportDeepLink;
787
+ toString(): string;
788
+ readonly secret: Uint8Array;
623
789
  }
624
790
  /**
625
791
  * An authenticated context “as the user”.
626
- * - Use `storage()` for reads/writes (absolute paths like `/pub/app/file.txt`)
792
+ * - Use `storage` for reads/writes (absolute paths like `/pub/app/file.txt`)
627
793
  * - Cookie is managed automatically by the underlying fetch client
628
794
  */
629
795
  export class Session {
630
796
  private constructor();
631
797
  free(): void;
798
+ [Symbol.dispose](): void;
799
+ /**
800
+ * Invalidate the session on the server (clears server cookie).
801
+ * Further calls to storage API will fail.
802
+ *
803
+ * @returns {Promise<void>}
804
+ */
805
+ signout(): Promise<void>;
806
+ /**
807
+ * Export the session metadata so it can be restored after a tab refresh.
808
+ *
809
+ * The export string contains **no secrets**; it only serializes the public `SessionInfo`.
810
+ * Browsers remain responsible for persisting the HTTP-only session cookie.
811
+ *
812
+ * @returns {string}
813
+ * A base64 string to store (e.g. in `localStorage`).
814
+ */
815
+ export(): string;
816
+ /**
817
+ * Restore a session from an `export()` string.
818
+ *
819
+ * The HTTP-only cookie must still be present in the browser; this function does not
820
+ * read or write any secrets.
821
+ *
822
+ * @param {string} exported
823
+ * A string produced by `session.export()`.
824
+ * @param {Client=} client
825
+ * Optional client to reuse transport configuration.
826
+ * @returns {Promise<Session>}
827
+ */
828
+ static restore(exported: string, client?: Client | null): Promise<Session>;
632
829
  /**
633
830
  * Retrieve immutable info about this session (user & capabilities).
634
831
  *
635
832
  * @returns {SessionInfo}
636
833
  */
637
- info(): SessionInfo;
834
+ readonly info: SessionInfo;
638
835
  /**
639
836
  * Access the session-scoped storage API (read/write).
640
837
  *
641
838
  * @returns {SessionStorage}
642
839
  */
643
- storage(): SessionStorage;
644
- /**
645
- * Invalidate the session on the server (clears server cookie).
646
- * It also consumes this JS/Wasm Session. Further calls will fail.
647
- *
648
- * @returns {Promise<void>}
649
- */
650
- signout(): Promise<void>;
840
+ readonly storage: SessionStorage;
651
841
  }
652
842
  /**
653
843
  * Static snapshot of session metadata.
@@ -655,18 +845,24 @@ export class Session {
655
845
  export class SessionInfo {
656
846
  private constructor();
657
847
  free(): void;
848
+ [Symbol.dispose](): void;
658
849
  /**
659
850
  * The user’s public key for this session.
660
851
  *
852
+ * Use `.z32()` on the returned `PublicKey` to get the string form.
853
+ *
661
854
  * @returns {PublicKey}
855
+ *
856
+ * @example
857
+ * const who = sessionInfo.publicKey.z32();
662
858
  */
663
- publicKey(): PublicKey;
859
+ readonly publicKey: PublicKey;
664
860
  /**
665
861
  * Effective capabilities granted to this session.
666
862
  *
667
863
  * @returns {string[]} Normalized capability entries (e.g. `"/pub/app/:rw"`).
668
864
  */
669
- capabilities(): string[];
865
+ readonly capabilities: string[];
670
866
  }
671
867
  /**
672
868
  * Read/write storage scoped to **your** session (absolute paths: `/pub/...`).
@@ -674,84 +870,92 @@ export class SessionInfo {
674
870
  export class SessionStorage {
675
871
  private constructor();
676
872
  free(): void;
873
+ [Symbol.dispose](): void;
677
874
  /**
678
875
  * List a directory (absolute session path). Returns `pubky://…` URLs.
679
876
  *
680
- * @param {string} path Must end with `/`.
877
+ * @param {Path} path Must end with `/`.
681
878
  * @param {string|null=} cursor Optional suffix or full URL to start **after**.
682
879
  * @param {boolean=} reverse Default `false`.
683
880
  * @param {number=} limit Optional result limit.
684
881
  * @param {boolean=} shallow Default `false`.
685
882
  * @returns {Promise<string[]>}
686
883
  */
687
- list(path: string, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
884
+ list(path: Path, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
885
+ /**
886
+ * GET a streaming response for an absolute session path.
887
+ *
888
+ * @param {Path} path
889
+ * @returns {Promise<Response>}
890
+ */
891
+ get(path: Path): Promise<Response>;
688
892
  /**
689
893
  * GET bytes from an absolute session path.
690
894
  *
691
- * @param {string} path
895
+ * @param {Path} path
692
896
  * @returns {Promise<Uint8Array>}
693
897
  */
694
- getBytes(path: string): Promise<Uint8Array>;
898
+ getBytes(path: Path): Promise<Uint8Array>;
695
899
  /**
696
900
  * GET text from an absolute session path.
697
901
  *
698
- * @param {string} path
902
+ * @param {Path} path
699
903
  * @returns {Promise<string>}
700
904
  */
701
- getText(path: string): Promise<string>;
905
+ getText(path: Path): Promise<string>;
702
906
  /**
703
907
  * GET JSON from an absolute session path.
704
908
  *
705
- * @param {string} path
909
+ * @param {Path} path
706
910
  * @returns {Promise<any>}
707
911
  */
708
- getJson(addr: string): Promise<any>;
912
+ getJson(path: Path): Promise<any>;
709
913
  /**
710
914
  * Check existence.
711
915
  *
712
- * @param {string} path
916
+ * @param {Path} path
713
917
  * @returns {Promise<boolean>}
714
918
  */
715
- exists(path: string): Promise<boolean>;
919
+ exists(path: Path): Promise<boolean>;
716
920
  /**
717
921
  * Get metadata for an absolute, session-scoped path (e.g. `"/pub/app/file.json"`).
718
922
  *
719
- * @param {string} path Absolute path under your user (starts with `/`).
923
+ * @param {Path} path Absolute path under your user (starts with `/`).
720
924
  * @returns {Promise<ResourceStats|undefined>} `undefined` if the resource does not exist.
721
- * @throws {PubkyJsError} On invalid input or transport/server errors.
925
+ * @throws {PubkyError} On invalid input or transport/server errors.
722
926
  */
723
- stats(path: string): Promise<ResourceStats | undefined>;
927
+ stats(path: Path): Promise<ResourceStats | undefined>;
724
928
  /**
725
929
  * PUT binary at an absolute session path.
726
930
  *
727
- * @param {string} path
931
+ * @param {Path} path
728
932
  * @param {Uint8Array} bytes
729
933
  * @returns {Promise<void>}
730
934
  */
731
- putBytes(path: string, body: Uint8Array): Promise<void>;
935
+ putBytes(path: Path, body: Uint8Array): Promise<void>;
732
936
  /**
733
937
  * PUT text at an absolute session path.
734
938
  *
735
- * @param {string} path
939
+ * @param {Path} path
736
940
  * @param {string} text
737
941
  * @returns {Promise<void>}
738
942
  */
739
- putText(path: string, body: string): Promise<void>;
943
+ putText(path: Path, body: string): Promise<void>;
740
944
  /**
741
945
  * PUT JSON at an absolute session path.
742
946
  *
743
- * @param {string} path Absolute path (e.g. `"/pub/app/data.json"`).
947
+ * @param {Path} path Absolute path (e.g. `"/pub/app/data.json"`).
744
948
  * @param {any} value JSON-serializable value.
745
949
  * @returns {Promise<void>}
746
950
  */
747
- putJson(path: string, body: any): Promise<void>;
951
+ putJson(path: Path, body: any): Promise<void>;
748
952
  /**
749
953
  * Delete a path (file or empty directory).
750
954
  *
751
- * @param {string} path
955
+ * @param {Path} path
752
956
  * @returns {Promise<void>}
753
957
  */
754
- delete(path: string): Promise<void>;
958
+ delete(path: Path): Promise<void>;
755
959
  }
756
960
  /**
757
961
  * Holds a user’s `Keypair` and performs identity operations:
@@ -763,6 +967,7 @@ export class SessionStorage {
763
967
  export class Signer {
764
968
  private constructor();
765
969
  free(): void;
970
+ [Symbol.dispose](): void;
766
971
  /**
767
972
  * Create a signer from a `Keypair` (prefer `pubky.signer(kp)`).
768
973
  *
@@ -770,12 +975,6 @@ export class Signer {
770
975
  * @returns {Signer}
771
976
  */
772
977
  static fromKeypair(keypair: Keypair): Signer;
773
- /**
774
- * Get the public key of this signer.
775
- *
776
- * @returns {PublicKey}
777
- */
778
- publicKey(): PublicKey;
779
978
  /**
780
979
  * Sign up at a homeserver. Returns a ready `Session`.
781
980
  *
@@ -785,7 +984,7 @@ export class Signer {
785
984
  * @param {string|null} signupToken Invite/registration token or `null`.
786
985
  * @returns {Promise<Session>}
787
986
  *
788
- * @throws {PubkyJsError}
987
+ * @throws {PubkyError}
789
988
  * - `AuthenticationError` (bad/expired token)
790
989
  * - `RequestError` (network/server)
791
990
  */
@@ -797,7 +996,7 @@ export class Signer {
797
996
  *
798
997
  * @returns {Promise<Session>}
799
998
  *
800
- * @throws {PubkyJsError}
999
+ * @throws {PubkyError}
801
1000
  */
802
1001
  signin(): Promise<Session>;
803
1002
  /**
@@ -812,10 +1011,41 @@ export class Signer {
812
1011
  * Approve a `pubkyauth://` request URL (encrypts & POSTs the signed AuthToken).
813
1012
  */
814
1013
  approveAuthRequest(pubkyauth_url: string): Promise<void>;
1014
+ /**
1015
+ * Get the public key of this signer.
1016
+ *
1017
+ * @returns {PublicKey}
1018
+ */
1019
+ readonly publicKey: PublicKey;
815
1020
  /**
816
1021
  * Get a PKDNS actor bound to this signer's client & keypair (publishing enabled).
817
1022
  *
818
1023
  * @returns {Pkdns}
1024
+ *
1025
+ * @example
1026
+ * await signer.pkdns.publishHomeserverIfStale(homeserverPk);
819
1027
  */
820
- pkdns(): Pkdns;
1028
+ readonly pkdns: Pkdns;
1029
+ }
1030
+ export class SigninDeepLink {
1031
+ private constructor();
1032
+ free(): void;
1033
+ [Symbol.dispose](): void;
1034
+ static parse(url: string): SigninDeepLink;
1035
+ toString(): string;
1036
+ readonly capabilities: string;
1037
+ readonly baseRelayUrl: string;
1038
+ readonly secret: Uint8Array;
1039
+ }
1040
+ export class SignupDeepLink {
1041
+ private constructor();
1042
+ free(): void;
1043
+ [Symbol.dispose](): void;
1044
+ static parse(url: string): SignupDeepLink;
1045
+ toString(): string;
1046
+ readonly capabilities: string;
1047
+ readonly baseRelayUrl: string;
1048
+ readonly secret: Uint8Array;
1049
+ readonly homeserver: PublicKey;
1050
+ readonly signupToken: string | undefined;
821
1051
  }