@kehto/services 0.10.1 → 0.11.1

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/dist/index.js CHANGED
@@ -14,12 +14,12 @@ function createAudioService(options) {
14
14
  return {
15
15
  descriptor,
16
16
  handleMessage(windowId, message, send) {
17
- if (message.type !== "ifc.emit") return;
18
- const ifcMessage = message;
19
- const topic = typeof ifcMessage.topic === "string" ? ifcMessage.topic : void 0;
17
+ if (message.type !== "inc.emit") return;
18
+ const incMessage = message;
19
+ const topic = typeof incMessage.topic === "string" ? incMessage.topic : void 0;
20
20
  if (!topic?.startsWith("audio:")) return;
21
21
  const action = topic.slice(6);
22
- const payload = ifcMessage.payload && typeof ifcMessage.payload === "object" ? ifcMessage.payload : {};
22
+ const payload = incMessage.payload && typeof incMessage.payload === "object" ? incMessage.payload : {};
23
23
  switch (action) {
24
24
  case "register": {
25
25
  const nappletClass = typeof payload.nappletClass === "string" ? payload.nappletClass : "";
@@ -51,7 +51,7 @@ function createAudioService(options) {
51
51
  source.muted = muted;
52
52
  notify2();
53
53
  }
54
- send({ type: "ifc.event", topic: "napplet:audio-muted", payload: { muted } });
54
+ send({ type: "inc.event", topic: "napplet:audio-muted", payload: { muted } });
55
55
  break;
56
56
  }
57
57
  default:
@@ -168,13 +168,13 @@ function handleNotifyEnvelope(store, windowId, action, msg, send) {
168
168
  break;
169
169
  }
170
170
  }
171
- function handleIfcNotification(store, windowId, action, payload, send) {
171
+ function handleIncNotification(store, windowId, action, payload, send) {
172
172
  switch (action) {
173
173
  case "create": {
174
174
  const title = typeof payload.title === "string" ? payload.title : "";
175
175
  const body = typeof payload.body === "string" ? payload.body : "";
176
176
  const notification = createNotification(store, windowId, title, body);
177
- send({ type: "ifc.event", topic: "notifications:created", payload: { id: notification.id } });
177
+ send({ type: "inc.event", topic: "notifications:created", payload: { id: notification.id } });
178
178
  break;
179
179
  }
180
180
  case "dismiss": {
@@ -189,7 +189,7 @@ function handleIfcNotification(store, windowId, action, payload, send) {
189
189
  }
190
190
  case "list": {
191
191
  const windowNotifs = store.notifications.get(windowId) ?? [];
192
- send({ type: "ifc.event", topic: "notifications:listed", payload: { notifications: windowNotifs } });
192
+ send({ type: "inc.event", topic: "notifications:listed", payload: { notifications: windowNotifs } });
193
193
  break;
194
194
  }
195
195
  default:
@@ -215,11 +215,11 @@ function createNotificationService(options) {
215
215
  handleNotifyEnvelope(store, windowId, message.type.slice(7), msg, send);
216
216
  return;
217
217
  }
218
- if (message.type !== "ifc.emit") return;
218
+ if (message.type !== "inc.emit") return;
219
219
  const topic = msg.topic;
220
220
  if (!topic?.startsWith("notifications:")) return;
221
221
  const payload = msg.payload ?? {};
222
- handleIfcNotification(store, windowId, topic.slice(14), payload, send);
222
+ handleIncNotification(store, windowId, topic.slice(14), payload, send);
223
223
  },
224
224
  onWindowDestroyed(windowId) {
225
225
  if (store.notifications.delete(windowId)) {
@@ -231,124 +231,193 @@ function createNotificationService(options) {
231
231
 
232
232
  // src/identity-service.ts
233
233
  var IDENTITY_SERVICE_VERSION = "1.0.0";
234
+ function sendProviderError(send, result, fallback, err) {
235
+ send({
236
+ ...result,
237
+ error: err?.message ?? fallback
238
+ });
239
+ }
240
+ async function getCurrentPubkey(options) {
241
+ const currentSigner = options.getSigner();
242
+ if (!currentSigner?.getPublicKey) return "";
243
+ try {
244
+ return await currentSigner.getPublicKey() ?? "";
245
+ } catch {
246
+ return "";
247
+ }
248
+ }
249
+ function sendOptionalProviderResult(options, send, fallbackResult, errorFallback, buildResult) {
250
+ if (!buildResult) {
251
+ send(fallbackResult);
252
+ return;
253
+ }
254
+ Promise.resolve(getCurrentPubkey(options)).then((pubkey) => buildResult(pubkey)).then((result) => send(result)).catch((err) => sendProviderError(send, fallbackResult, errorFallback, err));
255
+ }
256
+ function sendIdentityError(send, id, typeBase, error) {
257
+ send({ type: `${typeBase}.error`, id, error });
258
+ }
259
+ function sendSignerError(send, id, typeBase, fallback, err) {
260
+ sendIdentityError(send, id, typeBase, err?.message ?? fallback);
261
+ }
262
+ function handleGetPublicKey(options, id, send) {
263
+ const signer = options.getSigner();
264
+ if (!signer) {
265
+ const result = {
266
+ type: "identity.getPublicKey.result",
267
+ id,
268
+ pubkey: ""
269
+ };
270
+ send(result);
271
+ return;
272
+ }
273
+ Promise.resolve(signer.getPublicKey?.()).then((pubkey) => {
274
+ const result = {
275
+ type: "identity.getPublicKey.result",
276
+ id,
277
+ pubkey: pubkey ?? ""
278
+ };
279
+ send(result);
280
+ }).catch((err) => sendSignerError(send, id, "identity.getPublicKey", "getPublicKey failed", err));
281
+ }
282
+ function handleGetRelays(options, id, send) {
283
+ const signer = options.getSigner();
284
+ if (!signer) {
285
+ sendIdentityError(send, id, "identity.getRelays", "no signer configured");
286
+ return;
287
+ }
288
+ Promise.resolve(signer.getRelays?.() ?? {}).then((relays) => {
289
+ const result = {
290
+ type: "identity.getRelays.result",
291
+ id,
292
+ relays
293
+ };
294
+ send(result);
295
+ }).catch((err) => sendSignerError(send, id, "identity.getRelays", "getRelays failed", err));
296
+ }
297
+ function handleReadProvider(options, id, message, send) {
298
+ switch (message.type) {
299
+ case "identity.getProfile":
300
+ sendOptionalProviderResult(
301
+ options,
302
+ send,
303
+ { type: "identity.getProfile.result", id, profile: null },
304
+ "getProfile failed",
305
+ options.getProfile ? async (pubkey) => ({
306
+ type: "identity.getProfile.result",
307
+ id,
308
+ profile: await options.getProfile(pubkey, message)
309
+ }) : void 0
310
+ );
311
+ return true;
312
+ case "identity.getFollows":
313
+ sendOptionalProviderResult(
314
+ options,
315
+ send,
316
+ { type: "identity.getFollows.result", id, pubkeys: [] },
317
+ "getFollows failed",
318
+ options.getFollows ? async (pubkey) => ({
319
+ type: "identity.getFollows.result",
320
+ id,
321
+ pubkeys: await options.getFollows(pubkey, message)
322
+ }) : void 0
323
+ );
324
+ return true;
325
+ case "identity.getList":
326
+ handleGetList(options, id, message, send);
327
+ return true;
328
+ case "identity.getZaps":
329
+ sendOptionalProviderResult(
330
+ options,
331
+ send,
332
+ { type: "identity.getZaps.result", id, zaps: [] },
333
+ "getZaps failed",
334
+ options.getZaps ? async (pubkey) => ({
335
+ type: "identity.getZaps.result",
336
+ id,
337
+ zaps: await options.getZaps(pubkey, message)
338
+ }) : void 0
339
+ );
340
+ return true;
341
+ case "identity.getMutes":
342
+ sendOptionalProviderResult(
343
+ options,
344
+ send,
345
+ { type: "identity.getMutes.result", id, pubkeys: [] },
346
+ "getMutes failed",
347
+ options.getMutes ? async (pubkey) => ({
348
+ type: "identity.getMutes.result",
349
+ id,
350
+ pubkeys: await options.getMutes(pubkey, message)
351
+ }) : void 0
352
+ );
353
+ return true;
354
+ case "identity.getBlocked":
355
+ sendOptionalProviderResult(
356
+ options,
357
+ send,
358
+ { type: "identity.getBlocked.result", id, pubkeys: [] },
359
+ "getBlocked failed",
360
+ options.getBlocked ? async (pubkey) => ({
361
+ type: "identity.getBlocked.result",
362
+ id,
363
+ pubkeys: await options.getBlocked(pubkey, message)
364
+ }) : void 0
365
+ );
366
+ return true;
367
+ case "identity.getBadges":
368
+ sendOptionalProviderResult(
369
+ options,
370
+ send,
371
+ { type: "identity.getBadges.result", id, badges: [] },
372
+ "getBadges failed",
373
+ options.getBadges ? async (pubkey) => ({
374
+ type: "identity.getBadges.result",
375
+ id,
376
+ badges: await options.getBadges(pubkey, message)
377
+ }) : void 0
378
+ );
379
+ return true;
380
+ default:
381
+ return false;
382
+ }
383
+ }
384
+ function handleGetList(options, id, message, send) {
385
+ sendOptionalProviderResult(
386
+ options,
387
+ send,
388
+ { type: "identity.getList.result", id, entries: [] },
389
+ "getList failed",
390
+ options.getList ? async (pubkey) => ({
391
+ type: "identity.getList.result",
392
+ id,
393
+ entries: await options.getList(message.listType, pubkey, message)
394
+ }) : void 0
395
+ );
396
+ }
397
+ function handleIdentityServiceMessage(options, message, send) {
398
+ const id = message.id ?? "";
399
+ switch (message.type) {
400
+ case "identity.getPublicKey":
401
+ handleGetPublicKey(options, id, send);
402
+ return;
403
+ case "identity.getRelays":
404
+ handleGetRelays(options, id, send);
405
+ return;
406
+ default:
407
+ if (!handleReadProvider(options, id, message, send)) {
408
+ sendIdentityError(send, id, message.type, `Unknown identity method: ${message.type}`);
409
+ }
410
+ }
411
+ }
234
412
  function createIdentityService(options) {
235
413
  return {
236
414
  descriptor: {
237
415
  name: "identity",
238
416
  version: IDENTITY_SERVICE_VERSION,
239
- description: "NIP-5D identity NUB reference handler (9 read-only identity queries)"
417
+ description: "NIP-5D identity NAP reference handler (9 read-only identity queries)"
240
418
  },
241
419
  handleMessage(_windowId, message, send) {
242
- const id = message.id ?? "";
243
- function sendError(typeBase, error) {
244
- send({ type: `${typeBase}.error`, id, error });
245
- }
246
- function sendSignerError(typeBase, fallback, err) {
247
- sendError(typeBase, err?.message ?? fallback);
248
- }
249
- const signer = options.getSigner();
250
- switch (message.type) {
251
- case "identity.getPublicKey": {
252
- if (!signer) {
253
- const result = {
254
- type: "identity.getPublicKey.result",
255
- id,
256
- pubkey: ""
257
- };
258
- send(result);
259
- return;
260
- }
261
- Promise.resolve(signer.getPublicKey?.()).then((pubkey) => {
262
- const result = {
263
- type: "identity.getPublicKey.result",
264
- id,
265
- pubkey: pubkey ?? ""
266
- };
267
- send(result);
268
- }).catch((err) => sendSignerError("identity.getPublicKey", "getPublicKey failed", err));
269
- return;
270
- }
271
- case "identity.getRelays": {
272
- if (!signer) {
273
- sendError("identity.getRelays", "no signer configured");
274
- return;
275
- }
276
- Promise.resolve(signer.getRelays?.() ?? {}).then((relays) => {
277
- const result = {
278
- type: "identity.getRelays.result",
279
- id,
280
- relays
281
- };
282
- send(result);
283
- }).catch((err) => sendSignerError("identity.getRelays", "getRelays failed", err));
284
- return;
285
- }
286
- case "identity.getProfile": {
287
- const result = {
288
- type: "identity.getProfile.result",
289
- id,
290
- profile: null
291
- };
292
- send(result);
293
- return;
294
- }
295
- case "identity.getFollows": {
296
- const result = {
297
- type: "identity.getFollows.result",
298
- id,
299
- pubkeys: []
300
- };
301
- send(result);
302
- return;
303
- }
304
- case "identity.getList": {
305
- const result = {
306
- type: "identity.getList.result",
307
- id,
308
- entries: []
309
- };
310
- send(result);
311
- return;
312
- }
313
- case "identity.getZaps": {
314
- const result = {
315
- type: "identity.getZaps.result",
316
- id,
317
- zaps: []
318
- };
319
- send(result);
320
- return;
321
- }
322
- case "identity.getMutes": {
323
- const result = {
324
- type: "identity.getMutes.result",
325
- id,
326
- pubkeys: []
327
- };
328
- send(result);
329
- return;
330
- }
331
- case "identity.getBlocked": {
332
- const result = {
333
- type: "identity.getBlocked.result",
334
- id,
335
- pubkeys: []
336
- };
337
- send(result);
338
- return;
339
- }
340
- case "identity.getBadges": {
341
- const result = {
342
- type: "identity.getBadges.result",
343
- id,
344
- badges: []
345
- };
346
- send(result);
347
- return;
348
- }
349
- default:
350
- sendError(message.type, `Unknown identity method: ${message.type}`);
351
- }
420
+ handleIdentityServiceMessage(options, message, send);
352
421
  },
353
422
  // Identity service has no per-window state to clean up.
354
423
  onWindowDestroyed(_windowId) {
@@ -383,7 +452,8 @@ function createRelayPoolService(options) {
383
452
  send({ type: "relay.eose", subId });
384
453
  return;
385
454
  }
386
- const relayUrls = options.selectRelayTier(filters);
455
+ const relayHint = typeof relayMessage.relay === "string" && relayMessage.relay.length > 0 ? relayMessage.relay : void 0;
456
+ const relayUrls = relayHint ? [relayHint] : options.selectRelayTier(filters);
387
457
  let eoseSent = false;
388
458
  const eoseTimer = setTimeout(() => {
389
459
  if (!eoseSent) {
@@ -563,7 +633,8 @@ function createCoordinatedRelay(options) {
563
633
  maybeSendEose(subKey, subId, send);
564
634
  }
565
635
  }, timeoutMs);
566
- const relayUrls = options.relayPool.selectRelayTier(filters);
636
+ const relayHint = typeof relayMessage.relay === "string" && relayMessage.relay.length > 0 ? relayMessage.relay : void 0;
637
+ const relayUrls = relayHint ? [relayHint] : options.relayPool.selectRelayTier(filters);
567
638
  tracked.relayHandle = options.relayPool.subscribe(filters, (item) => {
568
639
  if (item === "EOSE") {
569
640
  clearTimeout(tracked.eoseTimer);
@@ -656,7 +727,7 @@ function createKeysService(options = {}) {
656
727
  const descriptor = {
657
728
  name: "keys",
658
729
  version: KEYS_SERVICE_VERSION,
659
- description: options.hostBridge ? "NIP-5D keys NUB reference handler (host-bridge delegated)" : "NIP-5D keys NUB reference handler (document-level chord listener)"
730
+ description: options.hostBridge ? "NIP-5D keys NAP reference handler (host-bridge delegated)" : "NIP-5D keys NAP reference handler (document-level chord listener)"
660
731
  };
661
732
  function chordSpecKey(spec) {
662
733
  return `${spec.ctrl}|${spec.alt}|${spec.shift}|${spec.meta}|${spec.key}`;
@@ -979,8 +1050,8 @@ function createBrowserMediaBridge(opts = {}) {
979
1050
  }
980
1051
  function applyActionHandlers(actions = DEFAULT_MEDIA_ACTIONS) {
981
1052
  if (!ms) return;
982
- for (const [domAction, nubAction] of ACTION_MATRIX) {
983
- if (!actions.includes(nubAction)) {
1053
+ for (const [domAction, napAction] of ACTION_MATRIX) {
1054
+ if (!actions.includes(napAction)) {
984
1055
  try {
985
1056
  ms.setActionHandler(domAction, null);
986
1057
  } catch {
@@ -989,9 +1060,9 @@ function createBrowserMediaBridge(opts = {}) {
989
1060
  }
990
1061
  ms.setActionHandler(domAction, (details) => {
991
1062
  if (!activeSessionId) return;
992
- const value = nubAction === "seek" && typeof details?.seekTime === "number" ? details.seekTime : void 0;
1063
+ const value = napAction === "seek" && typeof details?.seekTime === "number" ? details.seekTime : void 0;
993
1064
  for (const cb of actionCallbacks) {
994
- cb(activeSessionId, nubAction, value);
1065
+ cb(activeSessionId, napAction, value);
995
1066
  }
996
1067
  });
997
1068
  }
@@ -1275,7 +1346,7 @@ function createMediaService(options = {}) {
1275
1346
  const descriptor = {
1276
1347
  name: "media",
1277
1348
  version: MEDIA_SERVICE_VERSION,
1278
- description: options.hostBridge ? "NIP-5D media NUB reference handler (host-bridge delegated)" : "NIP-5D media NUB reference handler (navigator.mediaSession mirror)"
1349
+ description: options.hostBridge ? "NIP-5D media NAP reference handler (host-bridge delegated)" : "NIP-5D media NAP reference handler (navigator.mediaSession mirror)"
1279
1350
  };
1280
1351
  const bridge = options.hostBridge ?? createBrowserMediaBridge({
1281
1352
  mediaSessionTarget: options.mediaSessionTarget,
@@ -1311,7 +1382,7 @@ function createNotifyService(options = {}) {
1311
1382
  const descriptor = {
1312
1383
  name: "notify",
1313
1384
  version: NOTIFY_SERVICE_VERSION,
1314
- description: "NIP-5D notify NUB reference handler (stub)"
1385
+ description: "NIP-5D notify NAP reference handler (stub)"
1315
1386
  };
1316
1387
  return {
1317
1388
  descriptor,
@@ -1373,7 +1444,7 @@ function createThemeService(options = {}) {
1373
1444
  const descriptor = {
1374
1445
  name: "theme",
1375
1446
  version: THEME_SERVICE_VERSION,
1376
- description: "NIP-5D theme NUB reference handler"
1447
+ description: "NIP-5D theme NAP reference handler"
1377
1448
  };
1378
1449
  const handler = {
1379
1450
  descriptor,
@@ -1475,7 +1546,7 @@ function createConfigService(options) {
1475
1546
  const descriptor = {
1476
1547
  name: "config",
1477
1548
  version: CONFIG_SERVICE_VERSION,
1478
- description: "NUB-CONFIG reference service \u2014 shell-writes, napplet-reads configuration"
1549
+ description: "NAP-CONFIG reference service \u2014 shell-writes, napplet-reads configuration"
1479
1550
  };
1480
1551
  const handler = {
1481
1552
  descriptor,
@@ -1672,7 +1743,7 @@ function createResourceService(options) {
1672
1743
  const descriptor = {
1673
1744
  name: "resource",
1674
1745
  version: RESOURCE_SERVICE_VERSION,
1675
- description: "NUB-RESOURCE reference service \u2014 shell-proxied authenticated fetch (RESOURCE-01..06)"
1746
+ description: "NAP-RESOURCE reference service \u2014 shell-proxied authenticated fetch (RESOURCE-01..06)"
1676
1747
  };
1677
1748
  const handler = {
1678
1749
  descriptor,