@synonymdev/pubky 0.6.0-rc.6 → 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.
- package/README.md +58 -13
- package/index.cjs +923 -454
- package/index.js +1037 -566
- package/package.json +1 -1
- package/pubky.d.ts +192 -72
- package/pubky_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Module system + TS types: ESM and CommonJS both supported; TypeScript typings ge
|
|
|
17
17
|
## Getting Started
|
|
18
18
|
|
|
19
19
|
```js
|
|
20
|
-
import { Pubky, PublicKey, Keypair } from "@synonymdev/pubky";
|
|
20
|
+
import { Pubky, PublicKey, Keypair, AuthFlowKind } from "@synonymdev/pubky";
|
|
21
21
|
|
|
22
22
|
// Initiate a Pubky SDK facade wired for default mainnet Pkarr relays.
|
|
23
23
|
const pubky = new Pubky(); // or: const pubky = Pubky.testnet(); for localhost testnet.
|
|
@@ -28,7 +28,7 @@ const signer = pubky.signer(keypair);
|
|
|
28
28
|
|
|
29
29
|
// 2) Sign up at a homeserver (optionally with an invite)
|
|
30
30
|
const homeserver = PublicKey.from(
|
|
31
|
-
"8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"
|
|
31
|
+
"8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"
|
|
32
32
|
);
|
|
33
33
|
const signupToken = "<your-invite-code-or-null>";
|
|
34
34
|
const session = await signer.signup(homeserver, signupToken);
|
|
@@ -43,19 +43,23 @@ const addr = `pubky${userPk}/pub/example.com/hello.json`;
|
|
|
43
43
|
const json = await pubky.publicStorage.getJson(addr); // -> { hello: "world" }
|
|
44
44
|
|
|
45
45
|
// 5) Authenticate on a 3rd-party app
|
|
46
|
-
const authFlow = pubky.startAuthFlow("/pub/my
|
|
46
|
+
const authFlow = pubky.startAuthFlow("/pub/my-cool-app/:rw", AuthFlowKind::signin()); // require permissions to read and write into `my.app`
|
|
47
47
|
renderQr(authFlow.authorizationUrl); // show to user
|
|
48
48
|
const session = await authFlow.awaitApproval();
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
Find here [**ready-to-run examples**](https://github.com/pubky/pubky-core/tree/main/examples).
|
|
52
52
|
|
|
53
|
+
### Initialization & events
|
|
54
|
+
|
|
55
|
+
The npm package bundles the WebAssembly module and **initializes it before exposing any APIs**. This avoids the common wasm-pack pitfall where events fire before the module finishes instantiating. Long-polling flows such as `authFlow.awaitApproval()` or `authFlow.tryPollOnce()` only start their relay calls after the underlying module is ready, so you won't miss approvals while the bundle is loading.
|
|
56
|
+
|
|
53
57
|
## API Overview
|
|
54
58
|
|
|
55
59
|
Use `new Pubky()` to quickly get any flow started:
|
|
56
60
|
|
|
57
61
|
```js
|
|
58
|
-
import { Pubky, Keypair } from "@synonymdev/pubky";
|
|
62
|
+
import { Pubky, Keypair, AuthFlowKind } from "@synonymdev/pubky";
|
|
59
63
|
|
|
60
64
|
// Mainnet (default relays)
|
|
61
65
|
const pubky = new Pubky();
|
|
@@ -68,7 +72,7 @@ const pubkyLocal = Pubky.testnet("localhost");
|
|
|
68
72
|
const signer = pubky.signer(Keypair.random());
|
|
69
73
|
|
|
70
74
|
// Pubky Auth flow (with capabilities)
|
|
71
|
-
const authFlow = pubky.startAuthFlow("/pub/my
|
|
75
|
+
const authFlow = pubky.startAuthFlow("/pub/my-cool-app/:rw", AuthFlowKind::signin());
|
|
72
76
|
|
|
73
77
|
// Public storage (read-only)
|
|
74
78
|
const publicStorage = pubky.publicStorage;
|
|
@@ -153,6 +157,20 @@ const caps = session.info.capabilities; // -> string[] permissions and paths
|
|
|
153
157
|
const storage = session.storage; // -> This User's storage API (absolute paths)
|
|
154
158
|
```
|
|
155
159
|
|
|
160
|
+
**Persist a session across tab refreshes (browser)**
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
// Save the session snapshot (no secrets inside; relies on the HTTP-only cookie).
|
|
164
|
+
const snapshot = session.export();
|
|
165
|
+
localStorage.setItem("pubky-session", snapshot);
|
|
166
|
+
|
|
167
|
+
// Later (after a reload), rehydrate using the browser's stored cookie.
|
|
168
|
+
const restored = await pubky.restoreSession(localStorage.getItem("pubky-session")!);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
> The exported string contains only public session metadata. The browser must keep the
|
|
172
|
+
> HTTP-only cookie alive for the restored session to remain authenticated.
|
|
173
|
+
|
|
156
174
|
**Approve a pubkyauth request URL**
|
|
157
175
|
|
|
158
176
|
```js
|
|
@@ -166,17 +184,17 @@ await signer.approveAuthRequest("pubkyauth:///?caps=...&secret=...&relay=...");
|
|
|
166
184
|
End-to-end auth (3rd-party app asks a user to approve via QR/deeplink, E.g. Pubky Ring).
|
|
167
185
|
|
|
168
186
|
```js
|
|
169
|
-
import { Pubky } from "@synonymdev/pubky";
|
|
187
|
+
import { Pubky, AuthFlowKind } from "@synonymdev/pubky";
|
|
170
188
|
const pubky = new Pubky();
|
|
171
189
|
|
|
172
190
|
// Comma-separated capabilities string
|
|
173
|
-
const caps = "/pub/my
|
|
191
|
+
const caps = "/pub/my-cool-app/:rw,/pub/another-app/folder/:w";
|
|
174
192
|
|
|
175
193
|
// Optional relay; defaults to Synonym-hosted relay if omitted
|
|
176
194
|
const relay = "https://httprelay.pubky.app/link/"; // optional (defaults to this)
|
|
177
195
|
|
|
178
196
|
// Start the auth polling
|
|
179
|
-
const flow = pubky.startAuthFlow(caps, relay);
|
|
197
|
+
const flow = pubky.startAuthFlow(caps, AuthFlowKind::signin(), relay);
|
|
180
198
|
|
|
181
199
|
renderQr(flow.authorizationUrl); // show to user
|
|
182
200
|
|
|
@@ -192,7 +210,7 @@ normalized string (ordering actions like `:rw`) and throws a structured error
|
|
|
192
210
|
when the input is malformed.
|
|
193
211
|
|
|
194
212
|
```js
|
|
195
|
-
import { Pubky, validateCapabilities } from "@synonymdev/pubky";
|
|
213
|
+
import { Pubky, validateCapabilities, AuthFlowKind } from "@synonymdev/pubky";
|
|
196
214
|
|
|
197
215
|
const pubky = new Pubky();
|
|
198
216
|
|
|
@@ -200,7 +218,7 @@ const rawCaps = formData.get("caps");
|
|
|
200
218
|
|
|
201
219
|
try {
|
|
202
220
|
const caps = validateCapabilities(rawCaps ?? "");
|
|
203
|
-
const flow = pubky.startAuthFlow(caps);
|
|
221
|
+
const flow = pubky.startAuthFlow(caps, AuthFlowKind::signin());
|
|
204
222
|
renderQr(flow.authorizationUrl);
|
|
205
223
|
const session = await flow.awaitApproval();
|
|
206
224
|
// ...
|
|
@@ -233,6 +251,9 @@ surface precise feedback to the user.
|
|
|
233
251
|
const pub = pubky.publicStorage;
|
|
234
252
|
|
|
235
253
|
// Reads
|
|
254
|
+
const response = await pub.get(
|
|
255
|
+
`pubky${userPk.z32()}/pub/example.com/data.json`
|
|
256
|
+
); // -> Response (stream it)
|
|
236
257
|
await pub.getJson(`pubky${userPk.z32()}/pub/example.com/data.json`);
|
|
237
258
|
await pub.getText(`pubky${userPk.z32()}/pub/example.com/readme.txt`);
|
|
238
259
|
await pub.getBytes(`pubky${userPk.z32()}/pub/example.com/icon.png`); // Uint8Array
|
|
@@ -243,9 +264,17 @@ await pub.stats(`pubky${userPk.z32()}/pub/example.com/foo`); // { content_length
|
|
|
243
264
|
|
|
244
265
|
// List directory (addressed path "<pubky>/pub/.../") must include trailing `/`.
|
|
245
266
|
// list(addr, cursor=null|suffix|fullUrl, reverse=false, limit?, shallow=false)
|
|
246
|
-
await pub.list(
|
|
267
|
+
await pub.list(
|
|
268
|
+
`pubky${userPk.z32()}/pub/example.com/`,
|
|
269
|
+
null,
|
|
270
|
+
false,
|
|
271
|
+
100,
|
|
272
|
+
false
|
|
273
|
+
);
|
|
247
274
|
```
|
|
248
275
|
|
|
276
|
+
Use `get()` when you need the raw `Response` for streaming or custom parsing.
|
|
277
|
+
|
|
249
278
|
#### SessionStorage (read/write; uses cookies)
|
|
250
279
|
|
|
251
280
|
```js
|
|
@@ -257,6 +286,7 @@ await s.putText("/pub/example.com/note.txt", "hello");
|
|
|
257
286
|
await s.putBytes("/pub/example.com/img.bin", new Uint8Array([1, 2, 3]));
|
|
258
287
|
|
|
259
288
|
// Reads
|
|
289
|
+
const response = await s.get("/pub/example.com/data.json"); // -> Response (stream it)
|
|
260
290
|
await s.getJson("/pub/example.com/data.json");
|
|
261
291
|
await s.getText("/pub/example.com/note.txt");
|
|
262
292
|
await s.getBytes("/pub/example.com/img.bin");
|
|
@@ -272,12 +302,14 @@ await s.list("/pub/example.com/", null, false, 100, false);
|
|
|
272
302
|
await s.delete("/pub/example.com/data.json");
|
|
273
303
|
```
|
|
274
304
|
|
|
305
|
+
`get()` exposes the underlying `Response`, which is handy for streaming bodies or inspecting headers before consuming content.
|
|
306
|
+
|
|
275
307
|
Path rules:
|
|
276
308
|
|
|
277
309
|
- Session storage uses **absolute** paths like `"/pub/app/file.txt"`.
|
|
278
310
|
- Public storage uses **addressed** form `pubky<user>/pub/app/file.txt` (preferred) or `pubky://<user>/...`.
|
|
279
311
|
|
|
280
|
-
**Convention:** put your app’s public data under a domain-like folder in `/pub`, e.g. `/pub/
|
|
312
|
+
**Convention:** put your app’s public data under a domain-like folder in `/pub`, e.g. `/pub/my-new-app/`.
|
|
281
313
|
|
|
282
314
|
---
|
|
283
315
|
|
|
@@ -323,7 +355,8 @@ Use `resolvePubky()` when you need to feed an addressed resource into a raw HTTP
|
|
|
323
355
|
```js
|
|
324
356
|
import { resolvePubky } from "@synonymdev/pubky";
|
|
325
357
|
|
|
326
|
-
const identifier =
|
|
358
|
+
const identifier =
|
|
359
|
+
"pubkyoperrr8wsbpr3ue9d4qj41ge1kcc6r7fdiy6o3ugjrrhi4y77rdo/pub/pubky.app/posts/0033X02JAN0SG";
|
|
327
360
|
const url = resolvePubky(identifier);
|
|
328
361
|
// -> "https://_pubky.operrr8wsbpr3ue9d4qj41ge1kcc6r7fdiy6o3ugjrrhi4y77rdo/pub/pubky.app/posts/0033X02JAN0SG"
|
|
329
362
|
```
|
|
@@ -332,6 +365,12 @@ Both `pubky<pk>/…` (preferred) and `pubky://<pk>/…` resolve to the same HTTP
|
|
|
332
365
|
|
|
333
366
|
---
|
|
334
367
|
|
|
368
|
+
## WASM memory (`free()` helpers)
|
|
369
|
+
|
|
370
|
+
`wasm-bindgen` generates `free()` methods on exported classes (for example `Pubky`, `AuthFlow` `PublicKey`). JavaScript's GC eventually releases the underlying Rust structs on its own, but calling `free()` lets you drop them **immediately** if you are creating many short-lived instances (e.g. in a long-running worker). It is safe to skip manual frees in typical browser or Node apps.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
335
374
|
## Errors
|
|
336
375
|
|
|
337
376
|
All async methods throw a structured `PubkyError`:
|
|
@@ -369,6 +408,12 @@ try {
|
|
|
369
408
|
}
|
|
370
409
|
```
|
|
371
410
|
|
|
411
|
+
## Browser environment notes
|
|
412
|
+
|
|
413
|
+
- Keep the Pubky client UI and the homeserver on the **same origin family** (both local or both remote). Browsers partition cookies by scheme/host, and cross-site requests (e.g., http://localhost calling https://staging…) can silently drop or cache `SameSite`/`Secure` session cookies.
|
|
414
|
+
- If you must mix environments, use a reverse proxy so the browser always talks to one consistent origin (or disable caching via devtools and clear cookies between switches).
|
|
415
|
+
- When troubleshooting auth/session caching: open a fresh incognito window, clear site data for the target origin, and verify the request includes credentials.
|
|
416
|
+
|
|
372
417
|
---
|
|
373
418
|
|
|
374
419
|
## Local Test & Development
|