@matterfact/embed 0.8.0 → 0.10.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 +191 -0
- package/dist/{chunk-R2ZEJARX.js → chunk-4AE5WINC.js} +233 -17
- package/dist/chunk-4AE5WINC.js.map +1 -0
- package/dist/{chunk-PNSYFXXU.js → chunk-CFDPCZO3.js} +233 -15
- package/dist/chunk-CFDPCZO3.js.map +1 -0
- package/dist/{chunk-UD7CAQXV.js → chunk-DXLHTFB4.js} +2 -2
- package/dist/chunk-RL6VIGWK.js +2 -0
- package/dist/chunk-TWMHQF7O.js +3 -0
- package/dist/chunk-TWMHQF7O.js.map +7 -0
- package/dist/{context-MVGSYIMB.js → context-HOOW63MO.js} +6 -2
- package/dist/context-SSQ4HUP3.js +3 -0
- package/dist/{context-ARBB2XD6.js.map → context-SSQ4HUP3.js.map} +1 -1
- package/dist/embed.js +1 -1
- package/dist/embed.js.map +2 -2
- package/dist/index.cjs +243 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -2
- package/dist/index.d.ts +92 -2
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +299 -16
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +172 -1
- package/dist/react.d.ts +172 -1
- package/dist/react.js +60 -4
- package/dist/react.js.map +1 -1
- package/dist/{snapshot-GL4YBMXD.js → snapshot-CRY2IBX6.js} +3 -3
- package/dist/{snapshot-GL4YBMXD.js.map → snapshot-CRY2IBX6.js.map} +1 -1
- package/dist/{snapshot-UGTXZVB6.js → snapshot-EYRXPLRC.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-PNSYFXXU.js.map +0 -1
- package/dist/chunk-R2ZEJARX.js.map +0 -1
- package/dist/chunk-UQCETVRF.js +0 -2
- package/dist/chunk-W52Q7G4J.js +0 -3
- package/dist/chunk-W52Q7G4J.js.map +0 -7
- package/dist/context-ARBB2XD6.js +0 -3
- /package/dist/{chunk-UD7CAQXV.js.map → chunk-DXLHTFB4.js.map} +0 -0
- /package/dist/{chunk-UQCETVRF.js.map → chunk-RL6VIGWK.js.map} +0 -0
- /package/dist/{context-MVGSYIMB.js.map → context-HOOW63MO.js.map} +0 -0
- /package/dist/{snapshot-UGTXZVB6.js.map → snapshot-EYRXPLRC.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -403,6 +403,155 @@ var init_hoist_runtime = __esm({
|
|
|
403
403
|
init_redact();
|
|
404
404
|
}
|
|
405
405
|
});
|
|
406
|
+
|
|
407
|
+
// src/adapters/registry.ts
|
|
408
|
+
function mfGlobal(win) {
|
|
409
|
+
return win?.matterfact ?? {};
|
|
410
|
+
}
|
|
411
|
+
function toolClass(name) {
|
|
412
|
+
if (name.startsWith("hoist.")) return "hoist";
|
|
413
|
+
if (name.startsWith("mf.")) return "mf";
|
|
414
|
+
return "app";
|
|
415
|
+
}
|
|
416
|
+
function emitToolEvent(win, e) {
|
|
417
|
+
const cb = mfGlobal(win).onToolEvent;
|
|
418
|
+
if (typeof cb !== "function") return;
|
|
419
|
+
try {
|
|
420
|
+
cb(e);
|
|
421
|
+
} catch {
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
function mfTools(win) {
|
|
425
|
+
const { document: document2, artifact } = mfGlobal(win).resolve ?? {};
|
|
426
|
+
const out = [];
|
|
427
|
+
if (typeof document2 === "function") {
|
|
428
|
+
out.push({
|
|
429
|
+
name: "mf.resolveDocument",
|
|
430
|
+
description: 'Resolve a matterfact document (dossier, report, briefing) that is NOT on the current page to a concrete id. Call it with the document type and a key (e.g. a ticker) when the site map shows the document lives on another route. Returns {id, label, href}. Cite the result inline as <MFRef kind="document" id="<id>" label="<label>" /> \u2014 it renders as a chip that opens the document in the side panel; href is its "open on page" deeplink.',
|
|
431
|
+
inputSchema: {
|
|
432
|
+
type: "object",
|
|
433
|
+
properties: {
|
|
434
|
+
doctype: { type: "string" },
|
|
435
|
+
key: { type: "string" }
|
|
436
|
+
},
|
|
437
|
+
required: ["doctype", "key"]
|
|
438
|
+
},
|
|
439
|
+
readOnly: true,
|
|
440
|
+
confirm: "auto"
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
if (typeof artifact === "function") {
|
|
444
|
+
out.push({
|
|
445
|
+
name: "mf.resolveArtifact",
|
|
446
|
+
description: 'Resolve a matterfact artifact (an interactive board) that is NOT co-embedded on the current page to a read grant. Call it with the artifact slug. Returns {id, owner, token, label}; the grant is applied for you. Cite the result inline as <MFRef kind="artifact" id="<id>" label="<label>" /> \u2014 it renders as a chip that opens the artifact in the side panel.',
|
|
447
|
+
inputSchema: {
|
|
448
|
+
type: "object",
|
|
449
|
+
properties: { slug: { type: "string" } },
|
|
450
|
+
required: ["slug"]
|
|
451
|
+
},
|
|
452
|
+
readOnly: true,
|
|
453
|
+
confirm: "auto"
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
return out;
|
|
457
|
+
}
|
|
458
|
+
function appName(name) {
|
|
459
|
+
return name.startsWith("app.") ? name : `app.${name}`;
|
|
460
|
+
}
|
|
461
|
+
function appTools(win) {
|
|
462
|
+
const defs = mfGlobal(win).tools;
|
|
463
|
+
if (!Array.isArray(defs)) return [];
|
|
464
|
+
const out = [];
|
|
465
|
+
for (const d of defs) {
|
|
466
|
+
const raw = (d?.name ?? "").trim();
|
|
467
|
+
if (!raw || typeof d.handler !== "function") continue;
|
|
468
|
+
const name = appName(raw);
|
|
469
|
+
if (!APP_NAME_RE.test(name)) continue;
|
|
470
|
+
out.push({
|
|
471
|
+
name,
|
|
472
|
+
description: String(d.description ?? `Run the host tool ${name}.`),
|
|
473
|
+
inputSchema: d.inputSchema ?? { type: "object", properties: {} },
|
|
474
|
+
readOnly: false,
|
|
475
|
+
confirm: d.confirm === "auto" ? "auto" : "required"
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
return out;
|
|
479
|
+
}
|
|
480
|
+
function advertise(win = typeof window !== "undefined" ? window : void 0) {
|
|
481
|
+
const merged = [];
|
|
482
|
+
const seen = /* @__PURE__ */ new Set();
|
|
483
|
+
const push = (tools) => {
|
|
484
|
+
for (const t of tools) {
|
|
485
|
+
if (seen.has(t.name)) continue;
|
|
486
|
+
seen.add(t.name);
|
|
487
|
+
merged.push(t);
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
try {
|
|
491
|
+
push(advertiseTools(win));
|
|
492
|
+
} catch {
|
|
493
|
+
}
|
|
494
|
+
try {
|
|
495
|
+
push(mfTools(win));
|
|
496
|
+
push(appTools(win));
|
|
497
|
+
} catch {
|
|
498
|
+
}
|
|
499
|
+
return merged.slice(0, MAX_TOOLS);
|
|
500
|
+
}
|
|
501
|
+
function timeout(ms) {
|
|
502
|
+
return new Promise(
|
|
503
|
+
(_, reject) => setTimeout(() => reject(new Error("host tool timed out")), ms)
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
function redactResult(value) {
|
|
507
|
+
if (value === void 0 || value === null) return value;
|
|
508
|
+
if (typeof value === "string") return redact(value);
|
|
509
|
+
try {
|
|
510
|
+
return JSON.parse(redact(JSON.stringify(value)));
|
|
511
|
+
} catch {
|
|
512
|
+
return redact(String(value));
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
async function execute(call, win = typeof window !== "undefined" ? window : void 0) {
|
|
516
|
+
const cls = toolClass(call.name);
|
|
517
|
+
try {
|
|
518
|
+
if (cls === "hoist") {
|
|
519
|
+
return executeHostTool(call, win);
|
|
520
|
+
}
|
|
521
|
+
const handler = resolveHandler(win, call.name);
|
|
522
|
+
if (!handler) return { ok: false, error: "unknown tool" };
|
|
523
|
+
const result = await Promise.race([
|
|
524
|
+
Promise.resolve(handler(call.args ?? {})),
|
|
525
|
+
timeout(HOST_HANDLER_TIMEOUT_MS)
|
|
526
|
+
]);
|
|
527
|
+
return { ok: true, result: redactResult(result) };
|
|
528
|
+
} catch (e) {
|
|
529
|
+
return {
|
|
530
|
+
ok: false,
|
|
531
|
+
error: redact(e instanceof Error ? e.message : "host tool failed")
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function resolveHandler(win, name) {
|
|
536
|
+
const mf = mfGlobal(win);
|
|
537
|
+
if (name === "mf.resolveDocument") return mf.resolve?.document;
|
|
538
|
+
if (name === "mf.resolveArtifact") return mf.resolve?.artifact;
|
|
539
|
+
if (name.startsWith("app.")) {
|
|
540
|
+
const def = (mf.tools ?? []).find((d) => appName((d?.name ?? "").trim()) === name);
|
|
541
|
+
return def?.handler;
|
|
542
|
+
}
|
|
543
|
+
return void 0;
|
|
544
|
+
}
|
|
545
|
+
var MAX_TOOLS, HOST_HANDLER_TIMEOUT_MS, APP_NAME_RE;
|
|
546
|
+
var init_registry = __esm({
|
|
547
|
+
"src/adapters/registry.ts"() {
|
|
548
|
+
init_redact();
|
|
549
|
+
init_hoist_runtime();
|
|
550
|
+
MAX_TOOLS = 16;
|
|
551
|
+
HOST_HANDLER_TIMEOUT_MS = 3e4;
|
|
552
|
+
APP_NAME_RE = /^[A-Za-z0-9._-]+$/;
|
|
553
|
+
}
|
|
554
|
+
});
|
|
406
555
|
function createStyleCache() {
|
|
407
556
|
const cache = /* @__PURE__ */ new WeakMap();
|
|
408
557
|
return ((el, pseudo) => {
|
|
@@ -878,7 +1027,9 @@ __export(context_exports, {
|
|
|
878
1027
|
callTool: () => callTool,
|
|
879
1028
|
grantsFromIframeSrcs: () => grantsFromIframeSrcs,
|
|
880
1029
|
isPrivate: () => isPrivate,
|
|
1030
|
+
navigateHost: () => navigateHost,
|
|
881
1031
|
provideContext: () => provideContext,
|
|
1032
|
+
readDeclaredGrants: () => readDeclaredGrants,
|
|
882
1033
|
readPageContext: () => readPageContext,
|
|
883
1034
|
redact: () => redact,
|
|
884
1035
|
sendRegion: () => sendRegion,
|
|
@@ -978,6 +1129,7 @@ async function publishContext() {
|
|
|
978
1129
|
}
|
|
979
1130
|
function provideContext() {
|
|
980
1131
|
void publishContext();
|
|
1132
|
+
publishSitemap();
|
|
981
1133
|
}
|
|
982
1134
|
function grantsFromIframeSrcs(srcs, origin) {
|
|
983
1135
|
const out = [];
|
|
@@ -999,16 +1151,56 @@ function grantsFromIframeSrcs(srcs, origin) {
|
|
|
999
1151
|
}
|
|
1000
1152
|
return out;
|
|
1001
1153
|
}
|
|
1154
|
+
function readDeclaredGrants() {
|
|
1155
|
+
const declared = window.matterfact?.artifacts;
|
|
1156
|
+
if (!Array.isArray(declared)) return [];
|
|
1157
|
+
const out = [];
|
|
1158
|
+
for (const a of declared) {
|
|
1159
|
+
const id = (a?.slug || "").trim();
|
|
1160
|
+
const owner = (a?.owner || "").trim();
|
|
1161
|
+
const token = (a?.token || "").trim();
|
|
1162
|
+
if (!id || !owner || !token) continue;
|
|
1163
|
+
if (out.some((g) => g.id === id)) continue;
|
|
1164
|
+
out.push({ id, owner, token });
|
|
1165
|
+
}
|
|
1166
|
+
return out;
|
|
1167
|
+
}
|
|
1002
1168
|
function readArtifactGrants() {
|
|
1003
1169
|
if (!widgetOrigin) return [];
|
|
1004
1170
|
const srcs = Array.from(document.querySelectorAll("iframe")).map(
|
|
1005
1171
|
(f) => f.getAttribute("src") || ""
|
|
1006
1172
|
);
|
|
1007
|
-
|
|
1173
|
+
const scanned = grantsFromIframeSrcs(srcs, widgetOrigin);
|
|
1174
|
+
const out = [...scanned];
|
|
1175
|
+
for (const g of readDeclaredGrants()) {
|
|
1176
|
+
if (!out.some((s) => s.id === g.id)) out.push(g);
|
|
1177
|
+
}
|
|
1178
|
+
return out;
|
|
1008
1179
|
}
|
|
1009
1180
|
function publishArtifactGrants() {
|
|
1010
1181
|
send?.({ type: "host.artifactGrants", grants: readArtifactGrants() });
|
|
1011
1182
|
}
|
|
1183
|
+
function readSitemap2() {
|
|
1184
|
+
const s = window.matterfact?.sitemap;
|
|
1185
|
+
return Array.isArray(s) ? s : [];
|
|
1186
|
+
}
|
|
1187
|
+
function publishSitemap() {
|
|
1188
|
+
if (!pageContextOn) return;
|
|
1189
|
+
const sitemap = readSitemap2();
|
|
1190
|
+
if (sitemap.length) send?.({ type: "host.sitemap", sitemap });
|
|
1191
|
+
}
|
|
1192
|
+
function navigateHost(href) {
|
|
1193
|
+
if (typeof href !== "string" || !href) return;
|
|
1194
|
+
let target;
|
|
1195
|
+
try {
|
|
1196
|
+
target = new URL(href, location.href);
|
|
1197
|
+
} catch {
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
if (target.protocol !== "http:" && target.protocol !== "https:") return;
|
|
1201
|
+
if (target.origin !== location.origin) return;
|
|
1202
|
+
location.assign(target.href);
|
|
1203
|
+
}
|
|
1012
1204
|
function pushActivity(e) {
|
|
1013
1205
|
activity.push({ ...e, seq: ++activitySeq, ts: Date.now() });
|
|
1014
1206
|
if (activity.length > MAX_ACTIVITY) activity.shift();
|
|
@@ -1071,10 +1263,8 @@ function watchNavigation() {
|
|
|
1071
1263
|
pushActivity({ type: "nav", summary: `navigated to ${url}` });
|
|
1072
1264
|
void publishContext();
|
|
1073
1265
|
publishArtifactGrants();
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
tools: advertiseTools(typeof window !== "undefined" ? window : void 0)
|
|
1077
|
-
});
|
|
1266
|
+
publishSitemap();
|
|
1267
|
+
publishTools();
|
|
1078
1268
|
};
|
|
1079
1269
|
navFire = fire;
|
|
1080
1270
|
for (const name of ["pushState", "replaceState"]) {
|
|
@@ -1178,10 +1368,24 @@ async function callTool(call, emit) {
|
|
|
1178
1368
|
});
|
|
1179
1369
|
return;
|
|
1180
1370
|
}
|
|
1181
|
-
const
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1371
|
+
const win = typeof window !== "undefined" ? window : void 0;
|
|
1372
|
+
const cls = toolClass(call.name);
|
|
1373
|
+
const startedAt = Date.now();
|
|
1374
|
+
emitToolEvent(win, {
|
|
1375
|
+
phase: "call",
|
|
1376
|
+
name: call.name,
|
|
1377
|
+
toolClass: cls,
|
|
1378
|
+
args: call.args
|
|
1379
|
+
});
|
|
1380
|
+
const r = await execute(call, win);
|
|
1381
|
+
emitToolEvent(win, {
|
|
1382
|
+
phase: "result",
|
|
1383
|
+
name: call.name,
|
|
1384
|
+
toolClass: cls,
|
|
1385
|
+
ok: r.ok,
|
|
1386
|
+
error: r.error,
|
|
1387
|
+
ms: Date.now() - startedAt
|
|
1388
|
+
});
|
|
1185
1389
|
emit({
|
|
1186
1390
|
type: "host.toolResult",
|
|
1187
1391
|
callId: call.callId,
|
|
@@ -1230,6 +1434,7 @@ function start(emit, origin, pageContext = true, provider) {
|
|
|
1230
1434
|
if (pageContextOn) {
|
|
1231
1435
|
void publishContext();
|
|
1232
1436
|
publishArtifactGrants();
|
|
1437
|
+
publishSitemap();
|
|
1233
1438
|
watchNavigation();
|
|
1234
1439
|
document.addEventListener("click", onClick, {
|
|
1235
1440
|
capture: true,
|
|
@@ -1258,10 +1463,30 @@ function start(emit, origin, pageContext = true, provider) {
|
|
|
1258
1463
|
const theme = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
1259
1464
|
emit({ type: "host.theme", mode: theme });
|
|
1260
1465
|
if (pageContextOn) {
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
-
)
|
|
1264
|
-
|
|
1466
|
+
const w = typeof window !== "undefined" ? window : void 0;
|
|
1467
|
+
const tools = advertise(w);
|
|
1468
|
+
if (tools.length) {
|
|
1469
|
+
emit({ type: "host.tools", tools });
|
|
1470
|
+
for (const t of tools) {
|
|
1471
|
+
emitToolEvent(w, {
|
|
1472
|
+
phase: "advertise",
|
|
1473
|
+
name: t.name,
|
|
1474
|
+
toolClass: toolClass(t.name)
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
function publishTools() {
|
|
1481
|
+
const win = typeof window !== "undefined" ? window : void 0;
|
|
1482
|
+
const tools = advertise(win);
|
|
1483
|
+
send?.({ type: "host.tools", tools });
|
|
1484
|
+
for (const t of tools) {
|
|
1485
|
+
emitToolEvent(win, {
|
|
1486
|
+
phase: "advertise",
|
|
1487
|
+
name: t.name,
|
|
1488
|
+
toolClass: toolClass(t.name)
|
|
1489
|
+
});
|
|
1265
1490
|
}
|
|
1266
1491
|
}
|
|
1267
1492
|
var widgetOrigin, MAX_ACTIVITY, send, activitySeq, activity, lastUrl, pageContextOn, contextProvider, navFire, origPushState, origReplaceState, snapshotModule, FORM_CONTROLS, ACTIONABLE, lastFocus, focusTimer, snapshotSeq;
|
|
@@ -1270,6 +1495,7 @@ var init_context = __esm({
|
|
|
1270
1495
|
init_redact();
|
|
1271
1496
|
init_hoist();
|
|
1272
1497
|
init_hoist_runtime();
|
|
1498
|
+
init_registry();
|
|
1273
1499
|
init_redact();
|
|
1274
1500
|
widgetOrigin = "";
|
|
1275
1501
|
MAX_ACTIVITY = 40;
|
|
@@ -1291,7 +1517,7 @@ var init_context = __esm({
|
|
|
1291
1517
|
});
|
|
1292
1518
|
|
|
1293
1519
|
// src/protocol.ts
|
|
1294
|
-
var PROTOCOL_VERSION =
|
|
1520
|
+
var PROTOCOL_VERSION = 3;
|
|
1295
1521
|
var CHANNEL = "mf-embed";
|
|
1296
1522
|
function envelope(payload, id) {
|
|
1297
1523
|
return {
|
|
@@ -1891,6 +2117,9 @@ var EmbedHost = class {
|
|
|
1891
2117
|
case "widget.needsAuth":
|
|
1892
2118
|
void this.provideAuth();
|
|
1893
2119
|
break;
|
|
2120
|
+
case "widget.navigate":
|
|
2121
|
+
void this.loadContext().then((m) => m.navigateHost(msg.href));
|
|
2122
|
+
break;
|
|
1894
2123
|
}
|
|
1895
2124
|
}
|
|
1896
2125
|
/**
|