@synonymdev/pubky 0.10.0-alpha.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -22
- package/index.cjs +1240 -58
- package/index.js +1241 -59
- package/package.json +8 -3
- package/pubky.d.ts +319 -32
- package/pubky_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Pubky
|
|
2
2
|
|
|
3
|
-
JS/WASM SDK for [Pubky](https://github.com/pubky/pubky-
|
|
3
|
+
JS/WASM SDK for [Pubky](https://github.com/pubky/pubky-homeserver).
|
|
4
4
|
|
|
5
5
|
Works in browsers and Node 20+.
|
|
6
6
|
|
|
@@ -33,18 +33,18 @@ const homeserver = PublicKey.from(
|
|
|
33
33
|
const signupToken = "<your-invite-code-or-null>";
|
|
34
34
|
await signer.signup(homeserver, signupToken);
|
|
35
35
|
|
|
36
|
-
// 3a) Signin with the signer directly
|
|
37
|
-
|
|
36
|
+
// 3a) Signin with the signer directly.
|
|
37
|
+
let session = await signer.signin("example.com");
|
|
38
38
|
|
|
39
|
-
// 3b)
|
|
39
|
+
// 3b) Or, if you do not have the keypair available, authenticate on a 3rd-party app
|
|
40
40
|
// by delegating the authentication to a signer with a QR code.
|
|
41
|
-
const authFlow = pubky.startGrantAuthFlow(
|
|
41
|
+
const authFlow = await pubky.startGrantAuthFlow(
|
|
42
42
|
"/pub/my-cool-app/:rw",
|
|
43
43
|
AuthFlowKind.signin(),
|
|
44
44
|
{ clientId: "my-cool-app.example" },
|
|
45
45
|
);
|
|
46
46
|
renderQr(authFlow.authorizationUrl); // Show to user the signin deeplink via a QR code
|
|
47
|
-
|
|
47
|
+
session = await authFlow.awaitApproval();
|
|
48
48
|
|
|
49
49
|
// 4) Write a public JSON file
|
|
50
50
|
const path = "/pub/my-cool-app/hello.json";
|
|
@@ -56,7 +56,7 @@ const addr = `${userPk}/pub/my-cool-app/hello.json`;
|
|
|
56
56
|
const json = await pubky.publicStorage.getJson(addr); // -> { hello: "world" }
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Find here [**ready-to-run examples**](https://github.com/pubky/pubky-
|
|
59
|
+
Find here [**ready-to-run examples**](https://github.com/pubky/pubky-homeserver/tree/main/examples).
|
|
60
60
|
|
|
61
61
|
### Key formats (display vs transport)
|
|
62
62
|
|
|
@@ -93,7 +93,7 @@ const pubkyLocal = Pubky.testnet("localhost");
|
|
|
93
93
|
const signer = pubky.signer(Keypair.random());
|
|
94
94
|
|
|
95
95
|
// Grant Pubky Auth flow (with capabilities)
|
|
96
|
-
const authFlow = pubky.startGrantAuthFlow(
|
|
96
|
+
const authFlow = await pubky.startGrantAuthFlow(
|
|
97
97
|
"/pub/my-cool-app/:rw",
|
|
98
98
|
AuthFlowKind.signin(),
|
|
99
99
|
{ clientId: "my-cool-app.example" },
|
|
@@ -187,16 +187,37 @@ const storage = session.storage; // -> This User's storage API (absolute paths)
|
|
|
187
187
|
**Persist a grant session**
|
|
188
188
|
|
|
189
189
|
```js
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
// Persist explicitly when your app wants reload/returning-user restore.
|
|
191
|
+
// In browsers, this uses IndexedDB and supports multiple accounts.
|
|
192
|
+
const stored = await pubky.browserSessionStore.save(session);
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
const restored = await pubky.
|
|
194
|
+
const accounts = await pubky.browserSessionStore.list();
|
|
195
|
+
const restored = await pubky.browserSessionStore.restore(stored.id);
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
+
`pubky.startGrantAuthFlow(...)` chooses delegated browser PoP keys
|
|
199
|
+
when the runtime supports them, then falls back to local PoP keys. Delegated
|
|
200
|
+
sessions keep the private PoP key non-extractable in browser storage; local
|
|
201
|
+
sessions store bearer-equivalent secret material in IndexedDB.
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
const flow = await pubky.startGrantAuthFlow(
|
|
205
|
+
"/pub/example.com/:rw",
|
|
206
|
+
AuthFlowKind.signin(),
|
|
207
|
+
{ clientId: "example.com" },
|
|
208
|
+
);
|
|
209
|
+
const session = await flow.awaitApproval();
|
|
210
|
+
await pubky.browserSessionStore.save(session);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
For advanced/manual storage, local grant sessions still expose
|
|
214
|
+
`exportLocalSecret()` and `pubky.restoreSession(secret)`. Treat that string
|
|
215
|
+
like a bearer token. Delegated browser grant sessions should use
|
|
216
|
+
`browserSessionStore` because their PoP keys are non-extractable.
|
|
217
|
+
|
|
198
218
|
> `session.export()` is still available for legacy cookie sessions, but new
|
|
199
|
-
> applications should use grant auth plus `
|
|
219
|
+
> applications should use grant auth plus `browserSessionStore` or
|
|
220
|
+
> `exportLocalSecret()`.
|
|
200
221
|
|
|
201
222
|
**Approve a pubkyauth request URL**
|
|
202
223
|
|
|
@@ -204,6 +225,16 @@ const restored = await pubky.restoreSession(localStorage.getItem("pubky-session"
|
|
|
204
225
|
await signer.approveAuthRequest("pubkyauth://signin?caps=...&secret=...&relay=...");
|
|
205
226
|
```
|
|
206
227
|
|
|
228
|
+
**Handle a pubkyauth deep link**
|
|
229
|
+
|
|
230
|
+
General entry point for any supported `pubkyauth://` link. Auth request links
|
|
231
|
+
are approved through their relay (like `approveAuthRequest`), while a
|
|
232
|
+
`direct_signup` link creates the account directly on its target homeserver:
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
await signer.handleDeepLink("pubkyauth://direct_signup?hs=...");
|
|
236
|
+
```
|
|
237
|
+
|
|
207
238
|
---
|
|
208
239
|
|
|
209
240
|
### GrantAuthFlow (pubkyauth)
|
|
@@ -221,10 +252,19 @@ const caps = "/pub/my-cool-app/:rw,/pub/another-app/folder/:w";
|
|
|
221
252
|
const relay = "https://httprelay.pubky.app/inbox/"; // optional (defaults to this)
|
|
222
253
|
|
|
223
254
|
// Start grant auth polling
|
|
224
|
-
const flow = pubky.startGrantAuthFlow(
|
|
255
|
+
const flow = await pubky.startGrantAuthFlow(
|
|
225
256
|
caps,
|
|
226
257
|
AuthFlowKind.signin(),
|
|
227
|
-
{
|
|
258
|
+
{
|
|
259
|
+
clientId: "my-cool-app.example",
|
|
260
|
+
relay,
|
|
261
|
+
xCallback: {
|
|
262
|
+
xSource: "My Cool App",
|
|
263
|
+
xSuccess: "my-cool-app://auth/success?nonce=unique",
|
|
264
|
+
xError: "my-cool-app://auth/error?nonce=unique",
|
|
265
|
+
xCancel: "my-cool-app://auth/cancel?nonce=unique",
|
|
266
|
+
},
|
|
267
|
+
},
|
|
228
268
|
);
|
|
229
269
|
|
|
230
270
|
renderQr(flow.authorizationUrl); // show to user
|
|
@@ -233,6 +273,36 @@ renderQr(flow.authorizationUrl); // show to user
|
|
|
233
273
|
const session = await flow.awaitApproval();
|
|
234
274
|
```
|
|
235
275
|
|
|
276
|
+
The same callback object can be passed as the fourth argument to legacy cookie
|
|
277
|
+
auth: `startCookieAuthFlow(caps, kind, relay, xCallback)`. The SDK emits
|
|
278
|
+
`x-source`, `x-success`, `x-error`, and `x-cancel` using the encoding expected
|
|
279
|
+
by Pubky Ring. Parsed deep-link objects expose them through `xCallback`; the
|
|
280
|
+
legacy `callback` parameter is accepted as an `xSuccess` fallback.
|
|
281
|
+
|
|
282
|
+
#### Resume an auth flow after page refresh
|
|
283
|
+
|
|
284
|
+
Grant auth flows are resumable by saving the pending flow state before refresh and restoring it afterwards:
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
const flow = pubky.startGrantAuthFlow(caps, AuthFlowKind.signin(), {
|
|
288
|
+
clientId: "my-cool-app.example",
|
|
289
|
+
relay,
|
|
290
|
+
});
|
|
291
|
+
sessionStorage.setItem("pubky-grant-auth", flow.save());
|
|
292
|
+
|
|
293
|
+
const saved = sessionStorage.getItem("pubky-grant-auth");
|
|
294
|
+
if (saved) {
|
|
295
|
+
try {
|
|
296
|
+
const resumed = pubky.resumeGrantAuthFlow(saved);
|
|
297
|
+
const session = await resumed.awaitApproval();
|
|
298
|
+
} finally {
|
|
299
|
+
sessionStorage.removeItem("pubky-grant-auth");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Legacy cookie auth flows can be resumed with `pubky.resumeCookieAuthFlow(authorizationUrl)`. Store pending auth state in `sessionStorage`, not `localStorage`, and delete it once the flow completes or is abandoned.
|
|
305
|
+
|
|
236
306
|
#### Validate and normalize capabilities
|
|
237
307
|
|
|
238
308
|
If you accept capability strings from user input (forms, CLI arguments, etc.),
|
|
@@ -249,7 +319,7 @@ const rawCaps = formData.get("caps");
|
|
|
249
319
|
|
|
250
320
|
try {
|
|
251
321
|
const caps = validateCapabilities(rawCaps ?? "");
|
|
252
|
-
const flow = pubky.startGrantAuthFlow(caps, AuthFlowKind.signin(), {
|
|
322
|
+
const flow = await pubky.startGrantAuthFlow(caps, AuthFlowKind.signin(), {
|
|
253
323
|
clientId: "my-cool-app.example",
|
|
254
324
|
});
|
|
255
325
|
renderQr(flow.authorizationUrl);
|
|
@@ -264,9 +334,13 @@ try {
|
|
|
264
334
|
}
|
|
265
335
|
```
|
|
266
336
|
|
|
267
|
-
On invalid input, `validateCapabilities` throws a `PubkyError`
|
|
268
|
-
|
|
269
|
-
surface precise feedback to the user.
|
|
337
|
+
On invalid input, `validateCapabilities` throws a `PubkyError` identifying the
|
|
338
|
+
first malformed entry and its position. Its `data.invalidEntries` array contains
|
|
339
|
+
that entry so applications can surface precise feedback to the user.
|
|
340
|
+
|
|
341
|
+
Capability scopes must be canonical absolute paths. Repeated separators and
|
|
342
|
+
`.` or `..` segments are rejected rather than normalized. Percent sequences are
|
|
343
|
+
literal scope characters; URL encoding is handled by the enclosing deep link.
|
|
270
344
|
|
|
271
345
|
#### Http Relay & reliability
|
|
272
346
|
|
|
@@ -338,11 +412,13 @@ await s.delete("/pub/example.com/data.json");
|
|
|
338
412
|
|
|
339
413
|
Path rules:
|
|
340
414
|
|
|
341
|
-
- Session storage uses **absolute** paths
|
|
415
|
+
- Session storage uses **absolute** paths under `/pub/` or `/priv/`.
|
|
342
416
|
- Public storage uses **addressed** form `pubky<user>/pub/app/file.txt` (preferred) or `pubky://<user>/...`.
|
|
343
417
|
|
|
344
418
|
**Convention:** put your app’s public data under a domain-like folder in `/pub`, e.g. `/pub/my-new-app/`.
|
|
345
419
|
|
|
420
|
+
See [Private Storage](https://github.com/pubky/pubky-homeserver/blob/main/docs/PRIVATE_STORAGE.md) for `/priv/` access and events.
|
|
421
|
+
|
|
346
422
|
---
|
|
347
423
|
|
|
348
424
|
### PKDNS (Pkarr)
|
|
@@ -355,7 +431,8 @@ import { Pubky, PublicKey, Keypair } from "@synonymdev/pubky";
|
|
|
355
431
|
const pubky = new Pubky();
|
|
356
432
|
|
|
357
433
|
// Read-only resolver
|
|
358
|
-
const homeserver = await pubky.getHomeserverOf(PublicKey.from("pubky<z32>")); //
|
|
434
|
+
const homeserver = await pubky.getHomeserverOf(PublicKey.from("pubky<z32>")); // PublicKey | undefined
|
|
435
|
+
// Rejects if PKARR resolution fails or the `_pubky` target is malformed.
|
|
359
436
|
|
|
360
437
|
// With keys (signer-bound)
|
|
361
438
|
const signer = pubky.signer(Keypair.random());
|