@kehto/paja 0.16.2 → 0.16.4
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 +12 -5
- package/dist/browser-host.js +137 -56
- package/dist/browser-host.js.map +1 -1
- package/dist/{chunk-32QBJDAR.js → chunk-AY3UYDP2.js} +47 -2
- package/dist/chunk-AY3UYDP2.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-32QBJDAR.js.map +0 -1
package/README.md
CHANGED
|
@@ -186,7 +186,8 @@ When `PAJA_UPLOAD_SERVERS` is set, the runtime enables the Blossom upload rail
|
|
|
186
186
|
and also makes those servers explicit NAP-RESOURCE fallbacks. It is not needed
|
|
187
187
|
for read-side discovery: resources learned through OUTBOX use their event hints
|
|
188
188
|
and hinted-author/publisher server lists first, then the active shell user's
|
|
189
|
-
published list
|
|
189
|
+
published list, the current window's verified pointer-manifest servers, and
|
|
190
|
+
finally configured runtime fallbacks.
|
|
190
191
|
|
|
191
192
|
## Installed intent handlers and delivery
|
|
192
193
|
|
|
@@ -324,8 +325,8 @@ without prefetching bytes. Resolution tries request and
|
|
|
324
325
|
event-local server hints first, then lazily queries hinted authors' and the
|
|
325
326
|
event publisher's newest BUD-03 kind `10063` lists through the verified
|
|
326
327
|
NIP-65-aware OUTBOX router, then queries the active shell user's BUD-03 list
|
|
327
|
-
through that same router, then uses
|
|
328
|
-
upload-runtime fallbacks. The user-list
|
|
328
|
+
through that same router, then uses the current window's verified
|
|
329
|
+
pointer-manifest servers, followed by upload-runtime fallbacks. The user-list
|
|
329
330
|
lookup works independently of upload mode; an upload runtime may reuse the same
|
|
330
331
|
servers when present. ROM-specific event and publisher locations retain
|
|
331
332
|
priority over the user/runtime fallbacks. The combined list is capped at eight
|
|
@@ -333,8 +334,14 @@ candidates. The only accepted identifier is `blossom:sha256:<hex>`;
|
|
|
333
334
|
Paja refuses redirects, verifies the requested SHA-256, and permits plain-HTTP
|
|
334
335
|
transport only for configured loopback development defaults. Browser-only Paja
|
|
335
336
|
cannot pin DNS results, so production runtimes must add the draft's DNS-time
|
|
336
|
-
private-address checks.
|
|
337
|
-
[NAP-RESOURCE at `
|
|
337
|
+
private-address checks. The current
|
|
338
|
+
[NAP-RESOURCE draft at `fa6bcc6`](https://github.com/napplet/naps/blob/fa6bcc6935aa19e7b70ab2a2c721dafca77c78e1/naps/NAP-RESOURCE.md)
|
|
339
|
+
assigns fetching and policy to the runtime and defines no wire-level Blossom
|
|
340
|
+
server-hint field. Retaining verified manifest servers per window is therefore
|
|
341
|
+
Paja host policy, informed by the current
|
|
342
|
+
[NIP-5D draft at `24711d9`](https://github.com/nostr-protocol/nips/blob/24711d9c47bbdd07908bf1d52bf677d9cbc530f0/5D.md),
|
|
343
|
+
which defines manifest `server` tags. The existing request-server compatibility
|
|
344
|
+
path comes from the earlier NAP-RESOURCE draft at `9511232`, with the merged package implementation
|
|
338
345
|
[`napplet/web#206@19e0029b`](https://github.com/napplet/web/pull/206) released as
|
|
339
346
|
`@napplet/core`/`@napplet/nap` 0.32.0, `@napplet/shim` 0.30.0, and
|
|
340
347
|
`@napplet/sdk` 0.28.0. Publisher discovery follows
|
package/dist/browser-host.js
CHANGED
|
@@ -702,7 +702,7 @@ function createNapEnforceGate(config) {
|
|
|
702
702
|
function formatDenialReason(capability) {
|
|
703
703
|
return `denied: ${capability}`;
|
|
704
704
|
}
|
|
705
|
-
function createSessionRegistry(notifier) {
|
|
705
|
+
function createSessionRegistry(notifier, onRegister) {
|
|
706
706
|
const byWindowId2 = /* @__PURE__ */ new Map();
|
|
707
707
|
const byPubkey2 = /* @__PURE__ */ new Map();
|
|
708
708
|
const byWindowIdEntry = /* @__PURE__ */ new Map();
|
|
@@ -712,6 +712,7 @@ function createSessionRegistry(notifier) {
|
|
|
712
712
|
byWindowId2.set(windowId, entry.pubkey);
|
|
713
713
|
byPubkey2.set(entry.pubkey, entry);
|
|
714
714
|
byWindowIdEntry.set(windowId, entry);
|
|
715
|
+
onRegister?.(windowId);
|
|
715
716
|
},
|
|
716
717
|
unregister(windowId) {
|
|
717
718
|
const pubkey2 = byWindowId2.get(windowId);
|
|
@@ -931,6 +932,12 @@ function createFirewallState(persistence) {
|
|
|
931
932
|
counters = result2.newState;
|
|
932
933
|
return result2;
|
|
933
934
|
},
|
|
935
|
+
resetInitBudget(initKey) {
|
|
936
|
+
if (!Object.hasOwn(counters.bursts, initKey)) return;
|
|
937
|
+
const bursts = { ...counters.bursts };
|
|
938
|
+
delete bursts[initKey];
|
|
939
|
+
counters = { ...counters, bursts };
|
|
940
|
+
},
|
|
934
941
|
setPolicy(napplet, policy) {
|
|
935
942
|
config = setPolicy(config, napplet, policy);
|
|
936
943
|
},
|
|
@@ -2416,8 +2423,8 @@ function buildObservation(envelope, windowId, senderCap, sessionRegistry2, getFo
|
|
|
2416
2423
|
size,
|
|
2417
2424
|
initElapsedMs,
|
|
2418
2425
|
// `windowId` comes from the host's source-bound session lookup, never the
|
|
2419
|
-
// napplet message envelope.
|
|
2420
|
-
//
|
|
2426
|
+
// napplet message envelope. Trusted register() calls retire this key's
|
|
2427
|
+
// previous startup budget; ordinary messages cannot reset it.
|
|
2421
2428
|
initKey: windowId,
|
|
2422
2429
|
focused: focus.focused,
|
|
2423
2430
|
msSinceFocusGain: focus.msSinceFocusGain,
|
|
@@ -2664,7 +2671,10 @@ function createRuntime(hooks) {
|
|
|
2664
2671
|
const subscriptions = /* @__PURE__ */ new Map();
|
|
2665
2672
|
const serviceRegistry = { ...hooks.services };
|
|
2666
2673
|
const registeredServices = createRegisteredServices(serviceRegistry);
|
|
2667
|
-
const
|
|
2674
|
+
const firewallState = createFirewallState(hooks.firewallPersistence);
|
|
2675
|
+
const sessionRegistry2 = createSessionRegistry(hooks.onPendingUpdate, (windowId) => {
|
|
2676
|
+
firewallState.resetInitBudget(windowId);
|
|
2677
|
+
});
|
|
2668
2678
|
let incRuntime = null;
|
|
2669
2679
|
const aclState = createAclState(hooks.aclPersistence, "permissive", (mutation) => {
|
|
2670
2680
|
if (mutation.type === "revoke" && mutation.capability !== "relay:read") return;
|
|
@@ -2674,7 +2684,6 @@ function createRuntime(hooks) {
|
|
|
2674
2684
|
}
|
|
2675
2685
|
}
|
|
2676
2686
|
});
|
|
2677
|
-
const firewallState = createFirewallState(hooks.firewallPersistence);
|
|
2678
2687
|
const manifestCache2 = createManifestCache(hooks.manifestPersistence);
|
|
2679
2688
|
const replayDetector = createReplayDetector(
|
|
2680
2689
|
hooks.getConfigOverrides ? () => hooks.getConfigOverrides().replayWindowSeconds : void 0
|
|
@@ -4033,16 +4042,29 @@ function nappletNamespacePrelude(domains) {
|
|
|
4033
4042
|
function request(message, resultType, map, options = {}) {
|
|
4034
4043
|
const requestId = message.id ?? id();
|
|
4035
4044
|
const outbound = { ...message, id: requestId };
|
|
4045
|
+
const timeoutMs = options.timeoutMs === void 0 ? requestTimeoutMs : options.timeoutMs;
|
|
4046
|
+
if (options.signal?.aborted) return Promise.reject(new DOMException("Aborted", "AbortError"));
|
|
4036
4047
|
return new Promise((resolve, reject2) => {
|
|
4037
|
-
|
|
4048
|
+
let timer;
|
|
4049
|
+
let off;
|
|
4050
|
+
const cleanup = () => {
|
|
4051
|
+
off?.();
|
|
4052
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
4053
|
+
options.signal?.removeEventListener("abort", abort);
|
|
4054
|
+
};
|
|
4055
|
+
const abort = () => {
|
|
4056
|
+
cleanup();
|
|
4057
|
+
if (options.cancelOnAbort) post({ type: "resource.cancel", id: requestId });
|
|
4058
|
+
reject2(new DOMException("Aborted", "AbortError"));
|
|
4059
|
+
};
|
|
4060
|
+
off = listen((event) => {
|
|
4038
4061
|
if (!isParentMessage(event)) return;
|
|
4039
4062
|
const incoming = event.data;
|
|
4040
4063
|
if (typeof incoming !== "object" || incoming === null) return;
|
|
4041
4064
|
const msg = incoming;
|
|
4042
4065
|
if (msg.type !== resultType && msg.type !== `${message.type}.error`) return;
|
|
4043
4066
|
if (msg.id !== requestId) return;
|
|
4044
|
-
|
|
4045
|
-
clearTimeout(timer);
|
|
4067
|
+
cleanup();
|
|
4046
4068
|
const error = typeof msg.error === "string" ? msg.error : "";
|
|
4047
4069
|
if (error && options.rejectOnError !== false) {
|
|
4048
4070
|
reject2(new Error(error));
|
|
@@ -4054,10 +4076,13 @@ function nappletNamespacePrelude(domains) {
|
|
|
4054
4076
|
reject2(err2);
|
|
4055
4077
|
}
|
|
4056
4078
|
});
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4079
|
+
if (timeoutMs !== null) {
|
|
4080
|
+
timer = setTimeout(() => {
|
|
4081
|
+
cleanup();
|
|
4082
|
+
reject2(new Error(`${message.type} timed out`));
|
|
4083
|
+
}, timeoutMs);
|
|
4084
|
+
}
|
|
4085
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
4061
4086
|
post(outbound);
|
|
4062
4087
|
});
|
|
4063
4088
|
}
|
|
@@ -4806,17 +4831,25 @@ function nappletNamespacePrelude(domains) {
|
|
|
4806
4831
|
type: "resource.bytes",
|
|
4807
4832
|
url,
|
|
4808
4833
|
...Array.isArray(options?.servers) ? { servers: Array.from(options.servers) } : {}
|
|
4809
|
-
}, "resource.bytes.result", (msg) => msg.blob
|
|
4834
|
+
}, "resource.bytes.result", (msg) => msg.blob, {
|
|
4835
|
+
timeoutMs: null,
|
|
4836
|
+
signal: options?.signal,
|
|
4837
|
+
cancelOnAbort: true
|
|
4838
|
+
});
|
|
4810
4839
|
return {
|
|
4811
4840
|
info: () => request({ type: "resource.info" }, "resource.info.result", (msg) => msg.info),
|
|
4812
4841
|
bytes,
|
|
4813
|
-
bytesMany: (requests) => request({
|
|
4842
|
+
bytesMany: (requests, options) => request({
|
|
4814
4843
|
type: "resource.bytesMany",
|
|
4815
4844
|
requests: Array.from(requests || [], (entry) => ({
|
|
4816
4845
|
url: entry.url,
|
|
4817
4846
|
...Array.isArray(entry.servers) ? { servers: Array.from(entry.servers) } : {}
|
|
4818
4847
|
}))
|
|
4819
|
-
}, "resource.bytesMany.result", (msg) => Array.isArray(msg.items) ? msg.items : []
|
|
4848
|
+
}, "resource.bytesMany.result", (msg) => Array.isArray(msg.items) ? msg.items : [], {
|
|
4849
|
+
timeoutMs: null,
|
|
4850
|
+
signal: options?.signal,
|
|
4851
|
+
cancelOnAbort: true
|
|
4852
|
+
}),
|
|
4820
4853
|
bytesAsObjectURL(url) {
|
|
4821
4854
|
let objectUrl = "";
|
|
4822
4855
|
const handle = {
|
|
@@ -9572,6 +9605,9 @@ function isValidFilterArray2(value) {
|
|
|
9572
9605
|
function isPlainObject2(value) {
|
|
9573
9606
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9574
9607
|
}
|
|
9608
|
+
function actionRegistryKey(windowId, actionId) {
|
|
9609
|
+
return JSON.stringify([windowId, actionId]);
|
|
9610
|
+
}
|
|
9575
9611
|
var MODIFIER_ALIASES = {
|
|
9576
9612
|
ctrl: "ctrl",
|
|
9577
9613
|
control: "ctrl",
|
|
@@ -9640,7 +9676,7 @@ function bindingsForWindow(windowId, registry2, windowIndex) {
|
|
|
9640
9676
|
if (!actionIds) return [];
|
|
9641
9677
|
const bindings = [];
|
|
9642
9678
|
for (const actionId of actionIds) {
|
|
9643
|
-
const entry = registry2.get(actionId);
|
|
9679
|
+
const entry = registry2.get(actionRegistryKey(windowId, actionId));
|
|
9644
9680
|
if (!entry || entry.windowId !== windowId) continue;
|
|
9645
9681
|
bindings.push({ actionId, key: entry.chordString });
|
|
9646
9682
|
}
|
|
@@ -9653,10 +9689,9 @@ function pushBindings(windowId, registry2, windowIndex, send) {
|
|
|
9653
9689
|
};
|
|
9654
9690
|
send(payload);
|
|
9655
9691
|
}
|
|
9656
|
-
function removeActionFromWindowIndex(actionId, windowIndex) {
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
}
|
|
9692
|
+
function removeActionFromWindowIndex(windowId, actionId, windowIndex) {
|
|
9693
|
+
const actions = windowIndex.get(windowId);
|
|
9694
|
+
if (actions?.delete(actionId) && actions.size === 0) windowIndex.delete(windowId);
|
|
9660
9695
|
}
|
|
9661
9696
|
var KEYS_SERVICE_VERSION = "1.3.0";
|
|
9662
9697
|
function rememberActionForWindow(windowIndex, windowId, actionId) {
|
|
@@ -9664,7 +9699,7 @@ function rememberActionForWindow(windowIndex, windowId, actionId) {
|
|
|
9664
9699
|
windowIndex.get(windowId).add(actionId);
|
|
9665
9700
|
}
|
|
9666
9701
|
function bindActionEntry(registry2, windowIndex, actionId, windowId, chord, chordString) {
|
|
9667
|
-
registry2.set(actionId, { chord, chordString, windowId });
|
|
9702
|
+
registry2.set(actionRegistryKey(windowId, actionId), { actionId, chord, chordString, windowId });
|
|
9668
9703
|
rememberActionForWindow(windowIndex, windowId, actionId);
|
|
9669
9704
|
}
|
|
9670
9705
|
function bindActionAndMarkChanged(registry2, windowIndex, changedWindowIds, actionId, windowId, chord, chordString) {
|
|
@@ -9737,6 +9772,7 @@ function createKeysService(options = {}) {
|
|
|
9737
9772
|
const bridgeSendHandles = /* @__PURE__ */ new Map();
|
|
9738
9773
|
const unsubscribeHandles = /* @__PURE__ */ new Map();
|
|
9739
9774
|
const handleBridgeRegisterAction = (windowId, m, send) => {
|
|
9775
|
+
const registryKey = actionRegistryKey(windowId, m.action.id);
|
|
9740
9776
|
bridgeSendHandles.set(windowId, send);
|
|
9741
9777
|
let binding;
|
|
9742
9778
|
const changedWindowIds = /* @__PURE__ */ new Set();
|
|
@@ -9744,8 +9780,8 @@ function createKeysService(options = {}) {
|
|
|
9744
9780
|
try {
|
|
9745
9781
|
const chord = parseChord(m.action.defaultKey);
|
|
9746
9782
|
const normalizedChord = formatChord(chord);
|
|
9747
|
-
const existingEntry = bridgeActionRegistry.get(
|
|
9748
|
-
const existing = unsubscribeHandles.get(
|
|
9783
|
+
const existingEntry = bridgeActionRegistry.get(registryKey);
|
|
9784
|
+
const existing = unsubscribeHandles.get(registryKey);
|
|
9749
9785
|
let nextUnsubscribe;
|
|
9750
9786
|
if (!isUnavailableBinding(chord)) {
|
|
9751
9787
|
nextUnsubscribe = bridge.subscribe(normalizedChord, (ev) => {
|
|
@@ -9771,13 +9807,13 @@ function createKeysService(options = {}) {
|
|
|
9771
9807
|
existing();
|
|
9772
9808
|
} catch {
|
|
9773
9809
|
}
|
|
9774
|
-
unsubscribeHandles.delete(
|
|
9810
|
+
unsubscribeHandles.delete(registryKey);
|
|
9775
9811
|
}
|
|
9776
9812
|
if (existingEntry) changedWindowIds.add(existingEntry.windowId);
|
|
9777
|
-
removeActionFromWindowIndex(m.action.id, bridgeWindowActions);
|
|
9778
|
-
bridgeActionRegistry.delete(
|
|
9813
|
+
removeActionFromWindowIndex(windowId, m.action.id, bridgeWindowActions);
|
|
9814
|
+
bridgeActionRegistry.delete(registryKey);
|
|
9779
9815
|
if (nextUnsubscribe) {
|
|
9780
|
-
unsubscribeHandles.set(
|
|
9816
|
+
unsubscribeHandles.set(registryKey, nextUnsubscribe);
|
|
9781
9817
|
binding = bindActionAndMarkChanged(
|
|
9782
9818
|
bridgeActionRegistry,
|
|
9783
9819
|
bridgeWindowActions,
|
|
@@ -9807,18 +9843,19 @@ function createKeysService(options = {}) {
|
|
|
9807
9843
|
send
|
|
9808
9844
|
);
|
|
9809
9845
|
};
|
|
9810
|
-
const handleBridgeUnregisterAction = (
|
|
9846
|
+
const handleBridgeUnregisterAction = (windowId, m, send) => {
|
|
9811
9847
|
if (!m.actionId) return;
|
|
9812
|
-
const
|
|
9813
|
-
const
|
|
9848
|
+
const registryKey = actionRegistryKey(windowId, m.actionId);
|
|
9849
|
+
const unsubscribe = unsubscribeHandles.get(registryKey);
|
|
9850
|
+
const entry = bridgeActionRegistry.get(registryKey);
|
|
9814
9851
|
if (!unsubscribe) return;
|
|
9815
9852
|
try {
|
|
9816
9853
|
unsubscribe();
|
|
9817
9854
|
} catch {
|
|
9818
9855
|
}
|
|
9819
|
-
unsubscribeHandles.delete(
|
|
9820
|
-
bridgeActionRegistry.delete(
|
|
9821
|
-
removeActionFromWindowIndex(m.actionId, bridgeWindowActions);
|
|
9856
|
+
unsubscribeHandles.delete(registryKey);
|
|
9857
|
+
bridgeActionRegistry.delete(registryKey);
|
|
9858
|
+
removeActionFromWindowIndex(windowId, m.actionId, bridgeWindowActions);
|
|
9822
9859
|
if (entry) {
|
|
9823
9860
|
const ownerSend = bridgeSendHandles.get(entry.windowId) ?? send;
|
|
9824
9861
|
pushBindings(entry.windowId, bridgeActionRegistry, bridgeWindowActions, ownerSend);
|
|
@@ -9838,15 +9875,16 @@ function createKeysService(options = {}) {
|
|
|
9838
9875
|
const actions = bridgeWindowActions.get(windowId);
|
|
9839
9876
|
if (!actions) return;
|
|
9840
9877
|
for (const actionId of actions) {
|
|
9841
|
-
const
|
|
9878
|
+
const registryKey = actionRegistryKey(windowId, actionId);
|
|
9879
|
+
const unsubscribe = unsubscribeHandles.get(registryKey);
|
|
9842
9880
|
if (unsubscribe) {
|
|
9843
9881
|
try {
|
|
9844
9882
|
unsubscribe();
|
|
9845
9883
|
} catch {
|
|
9846
9884
|
}
|
|
9847
9885
|
}
|
|
9848
|
-
unsubscribeHandles.delete(
|
|
9849
|
-
bridgeActionRegistry.delete(
|
|
9886
|
+
unsubscribeHandles.delete(registryKey);
|
|
9887
|
+
bridgeActionRegistry.delete(registryKey);
|
|
9850
9888
|
}
|
|
9851
9889
|
bridgeWindowActions.delete(windowId);
|
|
9852
9890
|
bridgeSendHandles.delete(windowId);
|
|
@@ -9899,13 +9937,13 @@ function createKeysService(options = {}) {
|
|
|
9899
9937
|
});
|
|
9900
9938
|
}
|
|
9901
9939
|
if (isReserved) return;
|
|
9902
|
-
for (const
|
|
9940
|
+
for (const entry of actionRegistry.values()) {
|
|
9903
9941
|
if (chordMatches(entry.chord, ev)) {
|
|
9904
9942
|
const send = sendHandles.get(entry.windowId);
|
|
9905
9943
|
if (send) {
|
|
9906
9944
|
const payload = {
|
|
9907
9945
|
type: "keys.action",
|
|
9908
|
-
actionId
|
|
9946
|
+
actionId: entry.actionId
|
|
9909
9947
|
};
|
|
9910
9948
|
send(payload);
|
|
9911
9949
|
}
|
|
@@ -9914,6 +9952,7 @@ function createKeysService(options = {}) {
|
|
|
9914
9952
|
};
|
|
9915
9953
|
target.addEventListener("keydown", listener);
|
|
9916
9954
|
const handleDocumentRegisterAction = (windowId, m, send) => {
|
|
9955
|
+
const registryKey = actionRegistryKey(windowId, m.action.id);
|
|
9917
9956
|
sendHandles.set(windowId, send);
|
|
9918
9957
|
let binding;
|
|
9919
9958
|
const changedWindowIds = /* @__PURE__ */ new Set();
|
|
@@ -9921,11 +9960,11 @@ function createKeysService(options = {}) {
|
|
|
9921
9960
|
try {
|
|
9922
9961
|
const chord = parseChord(m.action.defaultKey);
|
|
9923
9962
|
const normalizedChord = formatChord(chord);
|
|
9924
|
-
const existing = actionRegistry.get(
|
|
9963
|
+
const existing = actionRegistry.get(registryKey);
|
|
9925
9964
|
if (existing) {
|
|
9926
9965
|
changedWindowIds.add(existing.windowId);
|
|
9927
|
-
removeActionFromWindowIndex(m.action.id, windowActions);
|
|
9928
|
-
actionRegistry.delete(
|
|
9966
|
+
removeActionFromWindowIndex(windowId, m.action.id, windowActions);
|
|
9967
|
+
actionRegistry.delete(registryKey);
|
|
9929
9968
|
}
|
|
9930
9969
|
if (!isUnavailableBinding(chord)) {
|
|
9931
9970
|
binding = bindActionAndMarkChanged(actionRegistry, windowActions, changedWindowIds, m.action.id, windowId, chord, normalizedChord);
|
|
@@ -9943,10 +9982,12 @@ function createKeysService(options = {}) {
|
|
|
9943
9982
|
sendRegisterActionResult2(send, m, binding);
|
|
9944
9983
|
pushChangedBindings(changedWindowIds, actionRegistry, windowActions, sendHandles, send);
|
|
9945
9984
|
};
|
|
9946
|
-
const handleDocumentUnregisterAction = (
|
|
9947
|
-
if (!m.actionId
|
|
9948
|
-
const
|
|
9949
|
-
actionRegistry.
|
|
9985
|
+
const handleDocumentUnregisterAction = (windowId, m, send) => {
|
|
9986
|
+
if (!m.actionId) return;
|
|
9987
|
+
const registryKey = actionRegistryKey(windowId, m.actionId);
|
|
9988
|
+
const entry = actionRegistry.get(registryKey);
|
|
9989
|
+
if (!entry) return;
|
|
9990
|
+
actionRegistry.delete(registryKey);
|
|
9950
9991
|
const set = windowActions.get(entry.windowId);
|
|
9951
9992
|
if (set) {
|
|
9952
9993
|
set.delete(m.actionId);
|
|
@@ -9966,7 +10007,7 @@ function createKeysService(options = {}) {
|
|
|
9966
10007
|
onWindowDestroyed(windowId) {
|
|
9967
10008
|
const actions = windowActions.get(windowId);
|
|
9968
10009
|
if (actions) {
|
|
9969
|
-
for (const actionId of actions) actionRegistry.delete(actionId);
|
|
10010
|
+
for (const actionId of actions) actionRegistry.delete(actionRegistryKey(windowId, actionId));
|
|
9970
10011
|
windowActions.delete(windowId);
|
|
9971
10012
|
}
|
|
9972
10013
|
sendHandles.delete(windowId);
|
|
@@ -17220,6 +17261,7 @@ function createPajaBlossomEventResolver(options) {
|
|
|
17220
17261
|
const now2 = options.now ?? Date.now;
|
|
17221
17262
|
const ttl = Math.max(0, options.serverListTtlMs ?? DEFAULT_SERVER_LIST_TTL_MS);
|
|
17222
17263
|
const windows = /* @__PURE__ */ new Map();
|
|
17264
|
+
const windowServers = /* @__PURE__ */ new Map();
|
|
17223
17265
|
const serverLists = /* @__PURE__ */ new Map();
|
|
17224
17266
|
const pendingServerLists = /* @__PURE__ */ new Map();
|
|
17225
17267
|
function observe(windowId, results) {
|
|
@@ -17297,9 +17339,20 @@ function createPajaBlossomEventResolver(options) {
|
|
|
17297
17339
|
);
|
|
17298
17340
|
for (const list of lists) appendUnique(servers, list);
|
|
17299
17341
|
}
|
|
17342
|
+
if (windowId) appendUnique(servers, windowServers.get(windowId) ?? []);
|
|
17300
17343
|
appendUnique(servers, options.getConfiguredServers());
|
|
17301
17344
|
return servers.slice(0, PAJA_RESOURCE_MAX_SERVERS);
|
|
17302
17345
|
}
|
|
17346
|
+
function setWindowServers(windowId, servers) {
|
|
17347
|
+
if (!windowId) return;
|
|
17348
|
+
const normalized = [];
|
|
17349
|
+
for (const value of servers) {
|
|
17350
|
+
const server = normalizePublicBlossomServer(value);
|
|
17351
|
+
if (server) appendUnique(normalized, [server]);
|
|
17352
|
+
}
|
|
17353
|
+
if (normalized.length > 0) windowServers.set(windowId, normalized);
|
|
17354
|
+
else windowServers.delete(windowId);
|
|
17355
|
+
}
|
|
17303
17356
|
async function discoverServerList(pubkey2) {
|
|
17304
17357
|
const cached = serverLists.get(pubkey2);
|
|
17305
17358
|
if (cached && cached.expiresAt > now2()) return [...cached.servers];
|
|
@@ -17344,7 +17397,11 @@ function createPajaBlossomEventResolver(options) {
|
|
|
17344
17397
|
observe,
|
|
17345
17398
|
decorate,
|
|
17346
17399
|
getServers,
|
|
17347
|
-
|
|
17400
|
+
setWindowServers,
|
|
17401
|
+
clearWindow(windowId) {
|
|
17402
|
+
windows.delete(windowId);
|
|
17403
|
+
windowServers.delete(windowId);
|
|
17404
|
+
}
|
|
17348
17405
|
};
|
|
17349
17406
|
}
|
|
17350
17407
|
function extractEventResourceLocations(event) {
|
|
@@ -20240,7 +20297,11 @@ function createDevServices(backend, getSimulation, relayConfig, onThemeService,
|
|
|
20240
20297
|
return wasWebrtcEnabled !== webrtcEnabled || dmChanged;
|
|
20241
20298
|
}
|
|
20242
20299
|
refreshAvailability();
|
|
20243
|
-
return {
|
|
20300
|
+
return {
|
|
20301
|
+
services,
|
|
20302
|
+
refreshAvailability,
|
|
20303
|
+
setWindowBlossomServers: blossomEventResolver.setWindowServers
|
|
20304
|
+
};
|
|
20244
20305
|
}
|
|
20245
20306
|
function createPajaAdapter(config, getSimulation, onThemeService, onThemeBroadcast, confirmRequest, signerProvider, getIdentity, onEnvironmentChanged, intentHost, userActivation, notifyOptions, configOptions) {
|
|
20246
20307
|
const resolveIdentity = (windowId) => getIdentity?.(windowId) ?? {
|
|
@@ -20308,6 +20369,7 @@ function createPajaAdapter(config, getSimulation, onThemeService, onThemeBroadca
|
|
|
20308
20369
|
});
|
|
20309
20370
|
return {
|
|
20310
20371
|
ready,
|
|
20372
|
+
setWindowBlossomServers: serviceBundle.setWindowBlossomServers,
|
|
20311
20373
|
relayPool: createPajaRelayHooks(relayBackend, getSimulation, relayConfig),
|
|
20312
20374
|
relayConfig,
|
|
20313
20375
|
windowManager: { createWindow: () => null },
|
|
@@ -20400,7 +20462,7 @@ async function resolvePajaPointer(value, options = {}) {
|
|
|
20400
20462
|
const ownsPool = options.pool === void 0;
|
|
20401
20463
|
try {
|
|
20402
20464
|
const event = await resolvePointerEvent(pointer, pool, relays, normalizeMaxWaitMs(options.maxWaitMs));
|
|
20403
|
-
const blossomServers =
|
|
20465
|
+
const blossomServers = resolvePointerBlossomServers(event, options.blossomServers ?? []);
|
|
20404
20466
|
const resolved = await resolveNapplet({
|
|
20405
20467
|
event,
|
|
20406
20468
|
cache: await openNappletArtifactCache({ requireStorageEstimate: false }),
|
|
@@ -20427,6 +20489,20 @@ async function resolvePajaPointer(value, options = {}) {
|
|
|
20427
20489
|
}
|
|
20428
20490
|
}
|
|
20429
20491
|
}
|
|
20492
|
+
function resolvePointerBlossomServers(event, configured) {
|
|
20493
|
+
const servers = [];
|
|
20494
|
+
for (const value of event.tags.flatMap(
|
|
20495
|
+
(tag) => tag[0] === "server" && tag[1] ? [tag[1]] : []
|
|
20496
|
+
)) {
|
|
20497
|
+
const normalized = normalizePublicBlossomServer(value);
|
|
20498
|
+
if (normalized && !servers.includes(normalized)) servers.push(normalized);
|
|
20499
|
+
}
|
|
20500
|
+
for (const value of configured) {
|
|
20501
|
+
const server = normalizePublicBlossomServer(value) ?? value;
|
|
20502
|
+
if (!servers.includes(server)) servers.push(server);
|
|
20503
|
+
}
|
|
20504
|
+
return servers;
|
|
20505
|
+
}
|
|
20430
20506
|
function injectPajaRuntimeCsp(html, origins) {
|
|
20431
20507
|
const grantedOrigins = [...new Set(origins)].sort();
|
|
20432
20508
|
const connectSrc = grantedOrigins.length > 0 ? `connect-src ${grantedOrigins.join(" ")}` : "connect-src 'none'";
|
|
@@ -21852,6 +21928,9 @@ function resolvedTargetKey(target) {
|
|
|
21852
21928
|
function runtimeTabGenerationId(tab) {
|
|
21853
21929
|
return `${tab.id}:${tab.generation}`;
|
|
21854
21930
|
}
|
|
21931
|
+
function bindRuntimeTabBlossomServers(adapter, windowId, resolvedTarget) {
|
|
21932
|
+
adapter.setWindowBlossomServers(windowId, resolvedTarget.blossomServers);
|
|
21933
|
+
}
|
|
21855
21934
|
function getActiveTab(state) {
|
|
21856
21935
|
return state.tabs.find((tab) => tab.id === state.activeTabId) ?? null;
|
|
21857
21936
|
}
|
|
@@ -22129,23 +22208,25 @@ function startRuntimeTabNavigation(tab, state, context) {
|
|
|
22129
22208
|
tab.status = "booting";
|
|
22130
22209
|
context.setStatus(state, "booting");
|
|
22131
22210
|
renderRuntimeTabs(state);
|
|
22211
|
+
const windowId = runtimeTabWindowId(context.config, tab);
|
|
22212
|
+
bindRuntimeTabBlossomServers(context.adapter, windowId, tab.resolvedTarget);
|
|
22132
22213
|
void context.navigateFrame(
|
|
22133
22214
|
tab.frame,
|
|
22134
22215
|
context.config,
|
|
22135
22216
|
generation,
|
|
22136
22217
|
context.adapter,
|
|
22137
22218
|
tab.resolvedTarget,
|
|
22138
|
-
|
|
22219
|
+
windowId,
|
|
22139
22220
|
() => tab.generation === generation,
|
|
22140
|
-
(
|
|
22221
|
+
(windowId2) => {
|
|
22141
22222
|
if (tab.generation !== generation) return;
|
|
22142
|
-
tab.windowId =
|
|
22143
|
-
if (state.activeTabId === tab.id) context.runtime.currentWindowId =
|
|
22223
|
+
tab.windowId = windowId2;
|
|
22224
|
+
if (state.activeTabId === tab.id) context.runtime.currentWindowId = windowId2;
|
|
22144
22225
|
}
|
|
22145
|
-
).then((
|
|
22226
|
+
).then((windowId2) => {
|
|
22146
22227
|
if (tab.generation !== generation) return;
|
|
22147
|
-
tab.windowId =
|
|
22148
|
-
if (state.activeTabId === tab.id) context.runtime.currentWindowId =
|
|
22228
|
+
tab.windowId = windowId2;
|
|
22229
|
+
if (state.activeTabId === tab.id) context.runtime.currentWindowId = windowId2;
|
|
22149
22230
|
}).catch((error) => {
|
|
22150
22231
|
if (tab.generation !== generation) return;
|
|
22151
22232
|
tab.frame.removeAttribute("src");
|