@kehto/services 0.7.0 → 0.9.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 +2 -2
- package/dist/index.d.ts +307 -58
- package/dist/index.js +227 -158
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -231,156 +231,6 @@ function createNotificationService(options) {
|
|
|
231
231
|
|
|
232
232
|
// src/identity-service.ts
|
|
233
233
|
var IDENTITY_SERVICE_VERSION = "1.0.0";
|
|
234
|
-
var DECRYPT_ERROR_CODES = [
|
|
235
|
-
"class-forbidden",
|
|
236
|
-
"signer-denied",
|
|
237
|
-
"signer-unavailable",
|
|
238
|
-
"decrypt-failed",
|
|
239
|
-
"malformed-wrap",
|
|
240
|
-
"impersonation",
|
|
241
|
-
"unsupported-encryption",
|
|
242
|
-
"policy-denied"
|
|
243
|
-
];
|
|
244
|
-
var DECRYPT_ERROR_CODE_SET = new Set(DECRYPT_ERROR_CODES);
|
|
245
|
-
function isDecryptErrorCode(value) {
|
|
246
|
-
return typeof value === "string" && DECRYPT_ERROR_CODE_SET.has(value);
|
|
247
|
-
}
|
|
248
|
-
function normalizeDecryptError(error) {
|
|
249
|
-
if (isDecryptErrorCode(error)) return error;
|
|
250
|
-
if (typeof error === "object" && error !== null) {
|
|
251
|
-
const candidate = error;
|
|
252
|
-
if (isDecryptErrorCode(candidate.code)) return candidate.code;
|
|
253
|
-
if (isDecryptErrorCode(candidate.error)) return candidate.error;
|
|
254
|
-
if (isDecryptErrorCode(candidate.message)) return candidate.message;
|
|
255
|
-
}
|
|
256
|
-
return "decrypt-failed";
|
|
257
|
-
}
|
|
258
|
-
function sendDecryptError(id, error, send) {
|
|
259
|
-
const result = {
|
|
260
|
-
type: "identity.decrypt.error",
|
|
261
|
-
id,
|
|
262
|
-
error
|
|
263
|
-
};
|
|
264
|
-
send(result);
|
|
265
|
-
}
|
|
266
|
-
function isStringArrayArray(value) {
|
|
267
|
-
return Array.isArray(value) && value.every(
|
|
268
|
-
(tag) => Array.isArray(tag) && tag.every((part) => typeof part === "string")
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
|
-
function isNostrEvent(value) {
|
|
272
|
-
const event = value;
|
|
273
|
-
return typeof event === "object" && event !== null && typeof event.id === "string" && typeof event.pubkey === "string" && typeof event.created_at === "number" && typeof event.kind === "number" && isStringArrayArray(event.tags) && typeof event.content === "string" && typeof event.sig === "string";
|
|
274
|
-
}
|
|
275
|
-
function isRumor(value) {
|
|
276
|
-
const rumor = value;
|
|
277
|
-
return typeof rumor === "object" && rumor !== null && typeof rumor.id === "string" && typeof rumor.pubkey === "string" && typeof rumor.created_at === "number" && typeof rumor.kind === "number" && isStringArrayArray(rumor.tags) && typeof rumor.content === "string";
|
|
278
|
-
}
|
|
279
|
-
function isGiftWrapDecryptResult(value) {
|
|
280
|
-
const result = value;
|
|
281
|
-
return typeof result === "object" && result !== null && isNostrEvent(result.seal) && isRumor(result.rumor);
|
|
282
|
-
}
|
|
283
|
-
function firstDecodedByte(content) {
|
|
284
|
-
const trimmed = content.trim();
|
|
285
|
-
if (trimmed.length === 0) return null;
|
|
286
|
-
const normalized = trimmed.replace(/-/g, "+").replace(/_/g, "/");
|
|
287
|
-
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
|
|
288
|
-
try {
|
|
289
|
-
const decoded = atob(padded);
|
|
290
|
-
return decoded.length > 0 ? decoded.charCodeAt(0) : null;
|
|
291
|
-
} catch {
|
|
292
|
-
return null;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
function detectEncryptionMode(event) {
|
|
296
|
-
if (event.kind === 4) return "nip04";
|
|
297
|
-
if (event.kind === 1059) return "nip17";
|
|
298
|
-
if (event.kind === 14 || firstDecodedByte(event.content) === 2) {
|
|
299
|
-
return "nip44-direct";
|
|
300
|
-
}
|
|
301
|
-
return null;
|
|
302
|
-
}
|
|
303
|
-
function rumorFromSignedEvent(event, content) {
|
|
304
|
-
return {
|
|
305
|
-
id: event.id,
|
|
306
|
-
pubkey: event.pubkey,
|
|
307
|
-
kind: event.kind,
|
|
308
|
-
tags: event.tags,
|
|
309
|
-
created_at: event.created_at,
|
|
310
|
-
content
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
async function handleDecrypt(id, message, send, options) {
|
|
314
|
-
const event = message.event;
|
|
315
|
-
if (!isNostrEvent(event)) {
|
|
316
|
-
sendDecryptError(id, "malformed-wrap", send);
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
const verifyEvent = options.verifyEvent ?? (() => true);
|
|
320
|
-
let verified;
|
|
321
|
-
try {
|
|
322
|
-
verified = await Promise.resolve(verifyEvent(event));
|
|
323
|
-
} catch {
|
|
324
|
-
sendDecryptError(id, "malformed-wrap", send);
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
if (!verified) {
|
|
328
|
-
sendDecryptError(id, "malformed-wrap", send);
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
const mode = detectEncryptionMode(event);
|
|
332
|
-
if (!mode) {
|
|
333
|
-
sendDecryptError(id, "unsupported-encryption", send);
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
const decryptor = options.getDecryptor?.() ?? null;
|
|
337
|
-
if (!decryptor) {
|
|
338
|
-
sendDecryptError(id, "signer-unavailable", send);
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
try {
|
|
342
|
-
if (mode === "nip04") {
|
|
343
|
-
const plaintext = await decryptor.nip04Decrypt(event.pubkey, event.content);
|
|
344
|
-
const result2 = {
|
|
345
|
-
type: "identity.decrypt.result",
|
|
346
|
-
id,
|
|
347
|
-
rumor: rumorFromSignedEvent(event, plaintext),
|
|
348
|
-
sender: event.pubkey
|
|
349
|
-
};
|
|
350
|
-
send(result2);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
if (mode === "nip44-direct") {
|
|
354
|
-
const plaintext = await decryptor.nip44Decrypt(event.pubkey, event.content);
|
|
355
|
-
const result2 = {
|
|
356
|
-
type: "identity.decrypt.result",
|
|
357
|
-
id,
|
|
358
|
-
rumor: rumorFromSignedEvent(event, plaintext),
|
|
359
|
-
sender: event.pubkey
|
|
360
|
-
};
|
|
361
|
-
send(result2);
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
const unwrapped = await decryptor.unwrapGiftWrap(event);
|
|
365
|
-
if (!isGiftWrapDecryptResult(unwrapped)) {
|
|
366
|
-
sendDecryptError(id, "malformed-wrap", send);
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
if (unwrapped.seal.pubkey !== unwrapped.rumor.pubkey) {
|
|
370
|
-
sendDecryptError(id, "impersonation", send);
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
const result = {
|
|
374
|
-
type: "identity.decrypt.result",
|
|
375
|
-
id,
|
|
376
|
-
rumor: unwrapped.rumor,
|
|
377
|
-
sender: unwrapped.seal.pubkey
|
|
378
|
-
};
|
|
379
|
-
send(result);
|
|
380
|
-
} catch (error) {
|
|
381
|
-
sendDecryptError(id, normalizeDecryptError(error), send);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
234
|
function createIdentityService(options) {
|
|
385
235
|
return {
|
|
386
236
|
descriptor: {
|
|
@@ -496,10 +346,6 @@ function createIdentityService(options) {
|
|
|
496
346
|
send(result);
|
|
497
347
|
return;
|
|
498
348
|
}
|
|
499
|
-
case "identity.decrypt": {
|
|
500
|
-
void handleDecrypt(id, message, send, options);
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
349
|
default:
|
|
504
350
|
sendError(message.type, `Unknown identity method: ${message.type}`);
|
|
505
351
|
}
|
|
@@ -2550,6 +2396,227 @@ function toErrorMessage3(err) {
|
|
|
2550
2396
|
return "upload failed";
|
|
2551
2397
|
}
|
|
2552
2398
|
|
|
2399
|
+
// src/intent-service.ts
|
|
2400
|
+
var INTENT_SERVICE_VERSION = "1.0.0";
|
|
2401
|
+
var INTENT_DESCRIPTOR = {
|
|
2402
|
+
name: "intent",
|
|
2403
|
+
version: INTENT_SERVICE_VERSION,
|
|
2404
|
+
description: "NAP-INTENT archetype intent dispatch \u2014 invoke/available/handlers"
|
|
2405
|
+
};
|
|
2406
|
+
function toErrorMessage4(err) {
|
|
2407
|
+
if (err instanceof Error) return err.message;
|
|
2408
|
+
if (typeof err === "string") return err;
|
|
2409
|
+
return "intent request failed";
|
|
2410
|
+
}
|
|
2411
|
+
function createIntentService(options) {
|
|
2412
|
+
if (!options || typeof options.resolver !== "object" || options.resolver === null) {
|
|
2413
|
+
throw new Error("createIntentService: options.resolver is required");
|
|
2414
|
+
}
|
|
2415
|
+
const { resolver } = options;
|
|
2416
|
+
const windows = /* @__PURE__ */ new Map();
|
|
2417
|
+
resolver.onChanged?.((availability) => {
|
|
2418
|
+
for (const send of windows.values()) {
|
|
2419
|
+
send({ type: "intent.changed", availability });
|
|
2420
|
+
}
|
|
2421
|
+
});
|
|
2422
|
+
function settle(call, send, resultType, id, onValue) {
|
|
2423
|
+
let pending;
|
|
2424
|
+
try {
|
|
2425
|
+
pending = Promise.resolve(call());
|
|
2426
|
+
} catch (err) {
|
|
2427
|
+
send({ type: resultType, id, error: toErrorMessage4(err) });
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
pending.then((value) => send(onValue(value))).catch((err) => send({ type: resultType, id, error: toErrorMessage4(err) }));
|
|
2431
|
+
}
|
|
2432
|
+
function handleInvoke(windowId, msg, send) {
|
|
2433
|
+
const m = msg;
|
|
2434
|
+
const id = m.id ?? "";
|
|
2435
|
+
const request = m.request;
|
|
2436
|
+
if (!request || typeof request !== "object" || typeof request.archetype !== "string" || request.archetype.length === 0) {
|
|
2437
|
+
send({ type: "intent.invoke.result", id, error: "invalid request" });
|
|
2438
|
+
return;
|
|
2439
|
+
}
|
|
2440
|
+
settle(
|
|
2441
|
+
() => resolver.invoke(request, { windowId }),
|
|
2442
|
+
send,
|
|
2443
|
+
"intent.invoke.result",
|
|
2444
|
+
id,
|
|
2445
|
+
(result) => ({ type: "intent.invoke.result", id, result })
|
|
2446
|
+
);
|
|
2447
|
+
}
|
|
2448
|
+
function handleAvailable(msg, send) {
|
|
2449
|
+
const m = msg;
|
|
2450
|
+
const id = m.id ?? "";
|
|
2451
|
+
if (typeof m.archetype !== "string" || m.archetype.length === 0) {
|
|
2452
|
+
send({ type: "intent.available.result", id, error: "invalid archetype" });
|
|
2453
|
+
return;
|
|
2454
|
+
}
|
|
2455
|
+
const archetype = m.archetype;
|
|
2456
|
+
settle(
|
|
2457
|
+
() => resolver.available(archetype),
|
|
2458
|
+
send,
|
|
2459
|
+
"intent.available.result",
|
|
2460
|
+
id,
|
|
2461
|
+
(availability) => ({ type: "intent.available.result", id, availability })
|
|
2462
|
+
);
|
|
2463
|
+
}
|
|
2464
|
+
function handleHandlers(msg, send) {
|
|
2465
|
+
const m = msg;
|
|
2466
|
+
const id = m.id ?? "";
|
|
2467
|
+
settle(
|
|
2468
|
+
() => resolver.handlers(),
|
|
2469
|
+
send,
|
|
2470
|
+
"intent.handlers.result",
|
|
2471
|
+
id,
|
|
2472
|
+
(handlers) => ({ type: "intent.handlers.result", id, handlers })
|
|
2473
|
+
);
|
|
2474
|
+
}
|
|
2475
|
+
return {
|
|
2476
|
+
descriptor: INTENT_DESCRIPTOR,
|
|
2477
|
+
handleMessage(windowId, message, send) {
|
|
2478
|
+
windows.set(windowId, send);
|
|
2479
|
+
switch (message.type) {
|
|
2480
|
+
case "intent.invoke":
|
|
2481
|
+
handleInvoke(windowId, message, send);
|
|
2482
|
+
return;
|
|
2483
|
+
case "intent.available":
|
|
2484
|
+
handleAvailable(message, send);
|
|
2485
|
+
return;
|
|
2486
|
+
case "intent.handlers":
|
|
2487
|
+
handleHandlers(message, send);
|
|
2488
|
+
return;
|
|
2489
|
+
default:
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
},
|
|
2493
|
+
onWindowDestroyed(windowId) {
|
|
2494
|
+
windows.delete(windowId);
|
|
2495
|
+
}
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// src/catalog-intent-resolver.ts
|
|
2500
|
+
function candidatesFor(catalog, archetype, defaultHandler) {
|
|
2501
|
+
const candidates = [];
|
|
2502
|
+
for (const entry of catalog) {
|
|
2503
|
+
const support = entry.archetypes[archetype];
|
|
2504
|
+
if (!support) continue;
|
|
2505
|
+
candidates.push({
|
|
2506
|
+
dTag: entry.dTag,
|
|
2507
|
+
...entry.title === void 0 ? {} : { title: entry.title },
|
|
2508
|
+
actions: support.actions,
|
|
2509
|
+
protocols: support.protocols,
|
|
2510
|
+
...entry.dTag === defaultHandler ? { isDefault: true } : {}
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
return candidates;
|
|
2514
|
+
}
|
|
2515
|
+
function fail(archetype, action, error) {
|
|
2516
|
+
return { ok: false, archetype, action, handled: false, error };
|
|
2517
|
+
}
|
|
2518
|
+
function createCatalogIntentResolver(options) {
|
|
2519
|
+
if (!options || typeof options.loadCatalog !== "function") {
|
|
2520
|
+
throw new Error("createCatalogIntentResolver: options.loadCatalog is required");
|
|
2521
|
+
}
|
|
2522
|
+
if (!options.windows || typeof options.windows.open !== "function") {
|
|
2523
|
+
throw new Error("createCatalogIntentResolver: options.windows is required");
|
|
2524
|
+
}
|
|
2525
|
+
const { loadCatalog, windows, getDefaultHandler, chooseHandler, defaultProtocol } = options;
|
|
2526
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2527
|
+
async function availabilityFor(archetype) {
|
|
2528
|
+
const catalog = await loadCatalog();
|
|
2529
|
+
const def = getDefaultHandler?.(archetype);
|
|
2530
|
+
const candidates = candidatesFor(catalog, archetype, def);
|
|
2531
|
+
return {
|
|
2532
|
+
archetype,
|
|
2533
|
+
available: candidates.length > 0,
|
|
2534
|
+
candidates,
|
|
2535
|
+
hasDefault: def !== void 0 && candidates.some((c) => c.dTag === def)
|
|
2536
|
+
};
|
|
2537
|
+
}
|
|
2538
|
+
async function pickHandler(archetype, candidates, preference, callerWindowId) {
|
|
2539
|
+
if (typeof preference === "string" && preference !== "default" && preference !== "choose") {
|
|
2540
|
+
return preference;
|
|
2541
|
+
}
|
|
2542
|
+
if (preference === "choose") {
|
|
2543
|
+
const picked = await chooseHandler?.(archetype, candidates, callerWindowId);
|
|
2544
|
+
return picked ?? null;
|
|
2545
|
+
}
|
|
2546
|
+
const def = getDefaultHandler?.(archetype);
|
|
2547
|
+
if (def !== void 0 && candidates.some((c) => c.dTag === def)) return def;
|
|
2548
|
+
if (candidates.length === 1) return candidates[0].dTag;
|
|
2549
|
+
if (chooseHandler) {
|
|
2550
|
+
const picked = await chooseHandler(archetype, candidates, callerWindowId);
|
|
2551
|
+
return picked ?? null;
|
|
2552
|
+
}
|
|
2553
|
+
return candidates[0].dTag;
|
|
2554
|
+
}
|
|
2555
|
+
async function invoke(request, context) {
|
|
2556
|
+
const archetype = request.archetype;
|
|
2557
|
+
const action = request.action ?? "open";
|
|
2558
|
+
const catalog = await loadCatalog();
|
|
2559
|
+
const candidates = candidatesFor(catalog, archetype, getDefaultHandler?.(archetype));
|
|
2560
|
+
if (candidates.length === 0) return fail(archetype, action, "no handler");
|
|
2561
|
+
const pickedDTag = await pickHandler(archetype, candidates, request.handler, context.windowId);
|
|
2562
|
+
if (pickedDTag === null) return fail(archetype, action, "user cancelled");
|
|
2563
|
+
const handler = candidates.find((c) => c.dTag === pickedDTag);
|
|
2564
|
+
if (!handler) return fail(archetype, action, "no handler");
|
|
2565
|
+
if (!handler.actions.includes(action)) return fail(archetype, action, "unsupported action");
|
|
2566
|
+
const protocol = request.protocol ?? defaultProtocol?.(archetype) ?? handler.protocols[0];
|
|
2567
|
+
if (protocol !== void 0 && handler.protocols.length > 0 && !handler.protocols.includes(protocol)) {
|
|
2568
|
+
return fail(archetype, action, "unsupported protocol");
|
|
2569
|
+
}
|
|
2570
|
+
let windowId;
|
|
2571
|
+
try {
|
|
2572
|
+
const opened = await windows.open({
|
|
2573
|
+
dTag: handler.dTag,
|
|
2574
|
+
archetype,
|
|
2575
|
+
action,
|
|
2576
|
+
...protocol === void 0 ? {} : { protocol },
|
|
2577
|
+
...request.payload === void 0 ? {} : { payload: request.payload },
|
|
2578
|
+
...request.behavior === void 0 ? {} : { behavior: request.behavior },
|
|
2579
|
+
callerWindowId: context.windowId
|
|
2580
|
+
});
|
|
2581
|
+
windowId = opened.windowId;
|
|
2582
|
+
} catch {
|
|
2583
|
+
return fail(archetype, action, "invoke failed");
|
|
2584
|
+
}
|
|
2585
|
+
return {
|
|
2586
|
+
ok: true,
|
|
2587
|
+
archetype,
|
|
2588
|
+
action,
|
|
2589
|
+
handled: true,
|
|
2590
|
+
handler: handler.dTag,
|
|
2591
|
+
windowId,
|
|
2592
|
+
...protocol === void 0 ? {} : { protocol }
|
|
2593
|
+
};
|
|
2594
|
+
}
|
|
2595
|
+
async function handlers() {
|
|
2596
|
+
const catalog = await loadCatalog();
|
|
2597
|
+
const archetypes = /* @__PURE__ */ new Set();
|
|
2598
|
+
for (const entry of catalog) {
|
|
2599
|
+
for (const slug of Object.keys(entry.archetypes)) archetypes.add(slug);
|
|
2600
|
+
}
|
|
2601
|
+
return Promise.all([...archetypes].map((a) => availabilityFor(a)));
|
|
2602
|
+
}
|
|
2603
|
+
return {
|
|
2604
|
+
invoke,
|
|
2605
|
+
available: availabilityFor,
|
|
2606
|
+
handlers,
|
|
2607
|
+
onChanged(listener) {
|
|
2608
|
+
listeners.add(listener);
|
|
2609
|
+
return () => listeners.delete(listener);
|
|
2610
|
+
},
|
|
2611
|
+
notifyChanged(archetype) {
|
|
2612
|
+
if (listeners.size === 0) return;
|
|
2613
|
+
void availabilityFor(archetype).then((availability) => {
|
|
2614
|
+
for (const listener of listeners) listener(availability);
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2553
2620
|
// src/cvm-service.ts
|
|
2554
2621
|
var CVM_SERVICE_VERSION = "1.0.0";
|
|
2555
2622
|
var CVM_DESCRIPTOR = {
|
|
@@ -2592,7 +2659,7 @@ function createCvmService(options) {
|
|
|
2592
2659
|
const m = msg;
|
|
2593
2660
|
const id = m.id ?? "";
|
|
2594
2661
|
void transport.discover(m.query).then((servers) => send({ type: "cvm.discover.result", id, servers })).catch(
|
|
2595
|
-
(err) => send({ type: "cvm.discover.result", id, servers: [], error:
|
|
2662
|
+
(err) => send({ type: "cvm.discover.result", id, servers: [], error: toErrorMessage5(err) })
|
|
2596
2663
|
);
|
|
2597
2664
|
}
|
|
2598
2665
|
function handleRequest(windowId, msg, send) {
|
|
@@ -2608,7 +2675,7 @@ function createCvmService(options) {
|
|
|
2608
2675
|
}
|
|
2609
2676
|
openSession(windowId, m.server, send);
|
|
2610
2677
|
void transport.request(m.server, m.message, m.options).then((message) => send({ type: "cvm.request.result", id, message })).catch(
|
|
2611
|
-
(err) => send({ type: "cvm.request.result", id, error:
|
|
2678
|
+
(err) => send({ type: "cvm.request.result", id, error: toErrorMessage5(err) })
|
|
2612
2679
|
);
|
|
2613
2680
|
}
|
|
2614
2681
|
function handleClose(windowId, msg, send) {
|
|
@@ -2619,7 +2686,7 @@ function createCvmService(options) {
|
|
|
2619
2686
|
return;
|
|
2620
2687
|
}
|
|
2621
2688
|
closeSession(windowId, m.server.pubkey);
|
|
2622
|
-
void transport.close(m.server).then(() => send({ type: "cvm.close.result", id })).catch((err) => send({ type: "cvm.close.result", id, error:
|
|
2689
|
+
void transport.close(m.server).then(() => send({ type: "cvm.close.result", id })).catch((err) => send({ type: "cvm.close.result", id, error: toErrorMessage5(err) }));
|
|
2623
2690
|
}
|
|
2624
2691
|
return {
|
|
2625
2692
|
descriptor: CVM_DESCRIPTOR,
|
|
@@ -2650,7 +2717,7 @@ function createCvmService(options) {
|
|
|
2650
2717
|
}
|
|
2651
2718
|
};
|
|
2652
2719
|
}
|
|
2653
|
-
function
|
|
2720
|
+
function toErrorMessage5(err) {
|
|
2654
2721
|
if (err instanceof Error) return err.message;
|
|
2655
2722
|
if (typeof err === "string") return err;
|
|
2656
2723
|
return "cvm request failed";
|
|
@@ -2659,11 +2726,13 @@ export {
|
|
|
2659
2726
|
createAudioService,
|
|
2660
2727
|
createBrowserMediaBridge,
|
|
2661
2728
|
createCacheService,
|
|
2729
|
+
createCatalogIntentResolver,
|
|
2662
2730
|
createConfigService,
|
|
2663
2731
|
createCoordinatedRelay,
|
|
2664
2732
|
createCvmService,
|
|
2665
2733
|
createHttpUploader,
|
|
2666
2734
|
createIdentityService,
|
|
2735
|
+
createIntentService,
|
|
2667
2736
|
createKeysService,
|
|
2668
2737
|
createMediaService,
|
|
2669
2738
|
createNotificationService,
|