@kehto/shell 0.20.1 → 0.21.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/README.md +4 -3
- package/dist/index.d.ts +13 -31
- package/dist/index.js +43 -9
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ pnpm add @kehto/shell
|
|
|
15
15
|
## Published Napplet Compatibility
|
|
16
16
|
|
|
17
17
|
`@kehto/shell` publishes against `@napplet/core` and `@napplet/nap`
|
|
18
|
-
`>=0.
|
|
18
|
+
`>=0.32.0 <0.33.0`. The installed core 0.32.0 / nap 0.32.0 contracts follow
|
|
19
19
|
NAP-INTENT authority `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24`, napplet/web#199
|
|
20
20
|
source `3037200c932488f14f7f369b8583c39c9c16510a` / merge
|
|
21
21
|
`b3f0007867eac109fa4917fac9c285d3b7cc6155`, and Version Packages #198 release
|
|
@@ -34,7 +34,8 @@ Current draft behaviors this package enforces:
|
|
|
34
34
|
when the runtime can identify it. The shell forwards this optional context
|
|
35
35
|
without imposing a consent policy; host runtimes may ignore it or use it to
|
|
36
36
|
resolve their own identity-scoped signer decisions.
|
|
37
|
-
- `injectNappletNamespacePrelude()` implements the NIP-5D injected-domain bootstrap and mandatory NAP-SHELL shim: hosts prepend it to `srcdoc` outside verified artifact bytes, install the parent-bound `shell.init` receiver, emit one `shell.ready`, and expose callable NAP interfaces before authored scripts run. Optional namespaces are filtered to the bare-domain allowlist; `shell` is always retained. Published core 0.
|
|
37
|
+
- `injectNappletNamespacePrelude()` implements the NIP-5D injected-domain bootstrap and mandatory NAP-SHELL shim: hosts prepend it to `srcdoc` outside verified artifact bytes, install the parent-bound `shell.init` receiver, emit one `shell.ready`, and expose callable NAP interfaces before authored scripts run. Optional namespaces are filtered to the bare-domain allowlist; `shell` is always retained. Published core 0.32.0 and shim 0.30.0 omit generic mandatory shell, so Kehto retains this host-owned prelude under NAP-SHELL `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24` until an upstream correction is reviewed.
|
|
38
|
+
- The injected resource projection follows draft NAP-RESOURCE `9511232f69313aa7953d110e35d32cc28d506f66`: `bytes(url, { servers? })` carries advisory Blossom locations and `bytesMany(requests)` keeps each `{ url, servers? }` entry intact.
|
|
38
39
|
- `window.napplet.shell.supports(domain)` answers synchronously and locally from the cached first `shell.init` environment. It returns `false` before `shell.init`, for unknown values, and for domains that are not live and granted to that napplet; it never sends a support-query message.
|
|
39
40
|
- Five optional per-domain proxies — `createIdentityProxy`, `createThemeProxy`, `createKeysProxy`, `createMediaProxy`, `createNotifyProxy` — can be composed between napplet and runtime to intercept request traffic per NAP. They are NOT wired by default. Identity/theme proxy `emit()` compatibility members fail closed; hosts must deliver automatic changes through `ShellBridge.publishIdentityChanged()` / `publishTheme()`, which enforce live session, granted domain, and current ACL.
|
|
40
41
|
- `keys.forward` is napplet-to-shell only. Active napplets suppress locally-bound keys from `keys.bindings` before forwarding; shell-initiated action triggers use `keys.action`.
|
|
@@ -60,7 +61,7 @@ dispatch, and does not infer payload kinds. Runtime delivery supplies the
|
|
|
60
61
|
**runtime-attested dTag**; no caller sender is accepted, topic source exclusion
|
|
61
62
|
is runtime-owned, and IDs and payloads are opaque.
|
|
62
63
|
|
|
63
|
-
Merged NAP-INC and released `@napplet/nap@0.
|
|
64
|
+
Merged NAP-INC and released `@napplet/nap@0.32.0` both deliver one `IncEvent`
|
|
64
65
|
to `on(topic, callback)`.
|
|
65
66
|
|
|
66
67
|
For channels, runtime ACL checks are open-only rather than per-message. The
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export { ALL_CAPABILITIES, AclChecker, Capability, ConsentRequest, EnforceConfig
|
|
|
3
3
|
import { NappletMessage, NostrEvent, NostrFilter } from '@napplet/core';
|
|
4
4
|
export { NappletMessage, NostrEvent, NostrFilter, TOPICS, TopicKey, TopicValue } from '@napplet/core';
|
|
5
5
|
import { Theme } from '@napplet/nap/theme/types';
|
|
6
|
+
import { ResourceBytesItem, ResourceBytesRequest as ResourceBytesRequest$1, ResourceInfo } from '@napplet/nap/resource/types';
|
|
7
|
+
export { ResourceInfo } from '@napplet/nap/resource/types';
|
|
6
8
|
|
|
7
9
|
/** NIP-5D identity metadata associated with a registered iframe window. */
|
|
8
10
|
interface OriginIdentity {
|
|
@@ -1303,15 +1305,11 @@ declare function createNotifyProxy(deps: NotifyProxyDeps): NotifyProxy;
|
|
|
1303
1305
|
* @file internal-resource.ts
|
|
1304
1306
|
*
|
|
1305
1307
|
* Kehto-internal shell-side resource wire types. Per PROJECT.md Decision #31,
|
|
1306
|
-
* this is NOT a staging-ground duplicate of upstream `@napplet/nap/resource
|
|
1307
|
-
*
|
|
1308
|
-
*
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1311
|
-
* vocabularies (kehto: 4 codes `{denied, canceled, network-error, invalid-url}`;
|
|
1312
|
-
* upstream: 8 codes `{not-found, blocked-by-policy,
|
|
1313
|
-
* timeout, too-large, unsupported-scheme, decode-failed, network-error,
|
|
1314
|
-
* quota-exceeded}`).
|
|
1308
|
+
* this is NOT a staging-ground duplicate of upstream `@napplet/nap/resource`.
|
|
1309
|
+
* Canonical resource info, per-resource request, and result-item shapes are
|
|
1310
|
+
* imported from the published package. The remaining local envelopes retain
|
|
1311
|
+
* Kehto's legacy compatibility fields (`requestId`, `bodyBase64`, status, and
|
|
1312
|
+
* headers) alongside the current `id`, `blob`, and `mime` fields.
|
|
1315
1313
|
*
|
|
1316
1314
|
* `resource-service.ts` now emits both legacy single-fetch compatibility
|
|
1317
1315
|
* fields and the current upstream-compatible fields.
|
|
@@ -1322,20 +1320,12 @@ declare function createNotifyProxy(deps: NotifyProxyDeps): NotifyProxy;
|
|
|
1322
1320
|
* resource.bytes.result, resource.bytes.error,
|
|
1323
1321
|
* resource.bytesMany.result, resource.bytesMany.error
|
|
1324
1322
|
*/
|
|
1323
|
+
|
|
1325
1324
|
/**
|
|
1326
1325
|
* Unique id for correlating a `resource.bytes` request to its later result /
|
|
1327
1326
|
* error / cancel envelope.
|
|
1328
1327
|
*/
|
|
1329
1328
|
type ResourceRequestId = string;
|
|
1330
|
-
/** Advisory resource capability and policy limits disclosed by the runtime. */
|
|
1331
|
-
interface ResourceInfo {
|
|
1332
|
-
schemes: readonly {
|
|
1333
|
-
scheme: string;
|
|
1334
|
-
enabled: boolean;
|
|
1335
|
-
}[];
|
|
1336
|
-
maxBytes?: number;
|
|
1337
|
-
maxUrls?: number;
|
|
1338
|
-
}
|
|
1339
1329
|
/** Inbound: napplet asks for advisory resource policy and scheme support. */
|
|
1340
1330
|
interface ResourceInfoRequest {
|
|
1341
1331
|
type: 'resource.info';
|
|
@@ -1353,6 +1343,8 @@ interface ResourceBytesRequest {
|
|
|
1353
1343
|
/** Legacy Kehto correlation ID. */
|
|
1354
1344
|
requestId?: ResourceRequestId;
|
|
1355
1345
|
url: string;
|
|
1346
|
+
/** Advisory Blossom server locations. Ignored for other schemes. */
|
|
1347
|
+
servers?: readonly string[];
|
|
1356
1348
|
/** Optional subset of fetch init (method, headers). Body bytes are shell-proxy-internal. */
|
|
1357
1349
|
init?: {
|
|
1358
1350
|
method?: string;
|
|
@@ -1377,7 +1369,7 @@ interface ResourceCancelRequest {
|
|
|
1377
1369
|
interface ResourceBytesManyRequest {
|
|
1378
1370
|
type: 'resource.bytesMany';
|
|
1379
1371
|
id: ResourceRequestId;
|
|
1380
|
-
|
|
1372
|
+
requests: readonly ResourceBytesRequest$1[];
|
|
1381
1373
|
}
|
|
1382
1374
|
/**
|
|
1383
1375
|
* Outbound: successful fetch result.
|
|
@@ -1420,17 +1412,7 @@ interface ResourceBytesError {
|
|
|
1420
1412
|
/**
|
|
1421
1413
|
* Current NAP-RESOURCE bulk result item.
|
|
1422
1414
|
*/
|
|
1423
|
-
type ResourceBytesManyItem =
|
|
1424
|
-
url: string;
|
|
1425
|
-
ok: true;
|
|
1426
|
-
blob: Blob;
|
|
1427
|
-
mime: string;
|
|
1428
|
-
} | {
|
|
1429
|
-
url: string;
|
|
1430
|
-
ok: false;
|
|
1431
|
-
error: string;
|
|
1432
|
-
message?: string;
|
|
1433
|
-
};
|
|
1415
|
+
type ResourceBytesManyItem = ResourceBytesItem;
|
|
1434
1416
|
/**
|
|
1435
1417
|
* Outbound: ordered bulk fetch result.
|
|
1436
1418
|
*/
|
|
@@ -1470,4 +1452,4 @@ type ResourceInbound = ResourceInfoRequest | ResourceBytesRequest | ResourceByte
|
|
|
1470
1452
|
*/
|
|
1471
1453
|
type ResourceOutbound = ResourceInfoResult | ResourceInfoError | ResourceBytesResult | ResourceBytesError | ResourceBytesManyResult | ResourceBytesManyError;
|
|
1472
1454
|
|
|
1473
|
-
export { type AclCheckEvent, type AclEntry, type AclStore, type AudioManager, type AudioSource, type AuthHooks, type BleHooks, type BrowserDeps, type CapabilityHooks, type CommonHooks, type ConfigHooks, type CryptoHooks, type DmHooks, type HotkeyHooks, type IdentityProxy, type IdentityProxyDeps, type IntentHooks, type KeysProxy, type KeysProxyDeps, type LinkHooks, type ListsHooks, type ManifestCache, type ManifestCacheEntry, type MediaProxy, type MediaProxyDeps, type NappletNamespacePreludeOptions, type NotifyProxy, type NotifyProxyDeps, type OriginIdentity, type OriginRegistry, type ProxyOriginRegistry, type RelayConfigHooks, type RelayPoolHooks, type RelayPoolLike, type ResourceBytesError, type ResourceBytesManyError, type ResourceBytesManyItem, type ResourceBytesManyRequest, type ResourceBytesManyResult, type ResourceBytesRequest, type ResourceBytesResult, type ResourceCancelRequest, type ResourceErrorCode, type ResourceInbound, type
|
|
1455
|
+
export { type AclCheckEvent, type AclEntry, type AclStore, type AudioManager, type AudioSource, type AuthHooks, type BleHooks, type BrowserDeps, type CapabilityHooks, type CommonHooks, type ConfigHooks, type CryptoHooks, type DmHooks, type HotkeyHooks, type IdentityProxy, type IdentityProxyDeps, type IntentHooks, type KeysProxy, type KeysProxyDeps, type LinkHooks, type ListsHooks, type ManifestCache, type ManifestCacheEntry, type MediaProxy, type MediaProxyDeps, type NappletNamespacePreludeOptions, type NotifyProxy, type NotifyProxyDeps, type OriginIdentity, type OriginRegistry, type ProxyOriginRegistry, type RelayConfigHooks, type RelayPoolHooks, type RelayPoolLike, type ResourceBytesError, type ResourceBytesManyError, type ResourceBytesManyItem, type ResourceBytesManyRequest, type ResourceBytesManyResult, type ResourceBytesRequest, type ResourceBytesResult, type ResourceCancelRequest, type ResourceErrorCode, type ResourceInbound, type ResourceInfoError, type ResourceInfoRequest, type ResourceInfoResult, type ResourceOutbound, type ResourceRequestId, type SerialHooks, type SessionRegistry, type ShellAdapter, type ShellBridge, type ShellCapabilities, type ShellEnvironment, type ThemeProxy, type ThemeProxyDeps, type UnroutedMessageInfo, type UploadBackendLike, type UploadHooks, type WebrtcHooks, type WindowManagerHooks, type WorkerRelayHooks, type WorkerRelayLike, adaptHooks, audioManager, buildShellCapabilities, createIdentityProxy, createKeysProxy, createMediaProxy, createNotifyProxy, createShellBridge, createThemeProxy, injectNappletNamespacePrelude, manifestCache, nappKeyRegistry, originRegistry, renderNappletNamespacePrelude, resolveShellEnvironment, sessionRegistry };
|
package/dist/index.js
CHANGED
|
@@ -1302,16 +1302,29 @@ function nappletNamespacePrelude(domains) {
|
|
|
1302
1302
|
function request(message, resultType, map, options = {}) {
|
|
1303
1303
|
const requestId = message.id ?? id();
|
|
1304
1304
|
const outbound = { ...message, id: requestId };
|
|
1305
|
+
const timeoutMs = options.timeoutMs === void 0 ? requestTimeoutMs : options.timeoutMs;
|
|
1306
|
+
if (options.signal?.aborted) return Promise.reject(new DOMException("Aborted", "AbortError"));
|
|
1305
1307
|
return new Promise((resolve, reject) => {
|
|
1306
|
-
|
|
1308
|
+
let timer;
|
|
1309
|
+
let off;
|
|
1310
|
+
const cleanup = () => {
|
|
1311
|
+
off?.();
|
|
1312
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1313
|
+
options.signal?.removeEventListener("abort", abort);
|
|
1314
|
+
};
|
|
1315
|
+
const abort = () => {
|
|
1316
|
+
cleanup();
|
|
1317
|
+
if (options.cancelOnAbort) post({ type: "resource.cancel", id: requestId });
|
|
1318
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
1319
|
+
};
|
|
1320
|
+
off = listen((event) => {
|
|
1307
1321
|
if (!isParentMessage(event)) return;
|
|
1308
1322
|
const incoming = event.data;
|
|
1309
1323
|
if (typeof incoming !== "object" || incoming === null) return;
|
|
1310
1324
|
const msg = incoming;
|
|
1311
1325
|
if (msg.type !== resultType && msg.type !== `${message.type}.error`) return;
|
|
1312
1326
|
if (msg.id !== requestId) return;
|
|
1313
|
-
|
|
1314
|
-
clearTimeout(timer);
|
|
1327
|
+
cleanup();
|
|
1315
1328
|
const error = typeof msg.error === "string" ? msg.error : "";
|
|
1316
1329
|
if (error && options.rejectOnError !== false) {
|
|
1317
1330
|
reject(new Error(error));
|
|
@@ -1323,10 +1336,13 @@ function nappletNamespacePrelude(domains) {
|
|
|
1323
1336
|
reject(err);
|
|
1324
1337
|
}
|
|
1325
1338
|
});
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1339
|
+
if (timeoutMs !== null) {
|
|
1340
|
+
timer = setTimeout(() => {
|
|
1341
|
+
cleanup();
|
|
1342
|
+
reject(new Error(`${message.type} timed out`));
|
|
1343
|
+
}, timeoutMs);
|
|
1344
|
+
}
|
|
1345
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
1330
1346
|
post(outbound);
|
|
1331
1347
|
});
|
|
1332
1348
|
}
|
|
@@ -2071,11 +2087,29 @@ function nappletNamespacePrelude(domains) {
|
|
|
2071
2087
|
}
|
|
2072
2088
|
function makeResource() {
|
|
2073
2089
|
const objectUrls = /* @__PURE__ */ new Set();
|
|
2074
|
-
const bytes = (url) => request({
|
|
2090
|
+
const bytes = (url, options) => request({
|
|
2091
|
+
type: "resource.bytes",
|
|
2092
|
+
url,
|
|
2093
|
+
...Array.isArray(options?.servers) ? { servers: Array.from(options.servers) } : {}
|
|
2094
|
+
}, "resource.bytes.result", (msg) => msg.blob, {
|
|
2095
|
+
timeoutMs: null,
|
|
2096
|
+
signal: options?.signal,
|
|
2097
|
+
cancelOnAbort: true
|
|
2098
|
+
});
|
|
2075
2099
|
return {
|
|
2076
2100
|
info: () => request({ type: "resource.info" }, "resource.info.result", (msg) => msg.info),
|
|
2077
2101
|
bytes,
|
|
2078
|
-
bytesMany: (
|
|
2102
|
+
bytesMany: (requests, options) => request({
|
|
2103
|
+
type: "resource.bytesMany",
|
|
2104
|
+
requests: Array.from(requests || [], (entry) => ({
|
|
2105
|
+
url: entry.url,
|
|
2106
|
+
...Array.isArray(entry.servers) ? { servers: Array.from(entry.servers) } : {}
|
|
2107
|
+
}))
|
|
2108
|
+
}, "resource.bytesMany.result", (msg) => Array.isArray(msg.items) ? msg.items : [], {
|
|
2109
|
+
timeoutMs: null,
|
|
2110
|
+
signal: options?.signal,
|
|
2111
|
+
cancelOnAbort: true
|
|
2112
|
+
}),
|
|
2079
2113
|
bytesAsObjectURL(url) {
|
|
2080
2114
|
let objectUrl = "";
|
|
2081
2115
|
const handle = {
|