@palettelab/sdk 0.1.19 → 0.1.21
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 +45 -1
- package/dist/components/index.d.mts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/{index-D0i35Hem.d.ts → index-CGSwI4TZ.d.ts} +1 -1
- package/dist/{index-DsfTFnZb.d.mts → index-CmY9M7Rg.d.mts} +1 -1
- package/dist/index.d.mts +163 -4
- package/dist/index.d.ts +163 -4
- package/dist/index.js +273 -3
- package/dist/index.mjs +268 -3
- package/dist/{plugin-dpLzOtF6.d.mts → plugin-DXqw6d0s.d.mts} +37 -1
- package/dist/{plugin-dpLzOtF6.d.ts → plugin-DXqw6d0s.d.ts} +37 -1
- package/dist/router/index.d.mts +2 -2
- package/dist/router/index.d.ts +2 -2
- package/dist/router/index.js +18 -2
- package/dist/router/index.mjs +18 -2
- package/dist/types/index.d.mts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
+
BrokerCallError: () => BrokerCallError,
|
|
23
24
|
DataRoomClient: () => DataRoomClient,
|
|
24
25
|
Link: () => Link,
|
|
25
26
|
OrganizationClient: () => OrganizationClient,
|
|
@@ -31,12 +32,14 @@ __export(src_exports, {
|
|
|
31
32
|
UserClient: () => UserClient,
|
|
32
33
|
apiFetch: () => apiFetch,
|
|
33
34
|
apiUpload: () => apiUpload,
|
|
35
|
+
broker: () => broker,
|
|
34
36
|
createMockPlatformContext: () => createMockPlatformContext,
|
|
35
37
|
createPaletteClient: () => createPaletteClient,
|
|
36
38
|
createSandboxBridge: () => createSandboxBridge,
|
|
37
39
|
dataRooms: () => dataRooms,
|
|
38
40
|
disconnectConnection: () => disconnectConnection,
|
|
39
41
|
errorFromResponse: () => errorFromResponse,
|
|
42
|
+
events: () => events,
|
|
40
43
|
getBaseUrl: () => getBaseUrl,
|
|
41
44
|
getConnections: () => getConnections,
|
|
42
45
|
getInstallConfig: () => getInstallConfig,
|
|
@@ -47,7 +50,9 @@ __export(src_exports, {
|
|
|
47
50
|
isSandboxRuntime: () => isSandboxRuntime,
|
|
48
51
|
normalizePaletteLanguage: () => normalizePaletteLanguage,
|
|
49
52
|
notFound: () => notFound,
|
|
53
|
+
palette: () => palette,
|
|
50
54
|
requireConnection: () => requireConnection,
|
|
55
|
+
servicesProxy: () => servicesProxy,
|
|
51
56
|
setBaseUrl: () => setBaseUrl,
|
|
52
57
|
startConnection: () => startConnection,
|
|
53
58
|
translate: () => translate,
|
|
@@ -385,6 +390,238 @@ var DataRoomClient = class {
|
|
|
385
390
|
};
|
|
386
391
|
var dataRooms = new DataRoomClient();
|
|
387
392
|
|
|
393
|
+
// src/services.ts
|
|
394
|
+
var BrokerCallError = class extends Error {
|
|
395
|
+
constructor(message, target, status) {
|
|
396
|
+
super(message);
|
|
397
|
+
this.target = target;
|
|
398
|
+
this.status = status;
|
|
399
|
+
this.name = "BrokerCallError";
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
var CALLER_HEADER = "X-Palette-Caller-App";
|
|
403
|
+
function currentPluginId() {
|
|
404
|
+
if (typeof window === "undefined") return void 0;
|
|
405
|
+
const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
|
|
406
|
+
return match ? decodeURIComponent(match[1]) : void 0;
|
|
407
|
+
}
|
|
408
|
+
async function brokerCallDirect(target, payload, options = {}) {
|
|
409
|
+
const callerAppId = options.callerAppId ?? currentPluginId();
|
|
410
|
+
const headers = {};
|
|
411
|
+
if (callerAppId) headers[CALLER_HEADER] = callerAppId;
|
|
412
|
+
const res = await apiFetch("/api/v1/os-broker/dispatch", {
|
|
413
|
+
method: "POST",
|
|
414
|
+
headers,
|
|
415
|
+
body: JSON.stringify({ target, payload: payload ?? {}, caller_app_id: callerAppId }),
|
|
416
|
+
signal: options.signal
|
|
417
|
+
});
|
|
418
|
+
if (!res.ok) {
|
|
419
|
+
let detail;
|
|
420
|
+
try {
|
|
421
|
+
detail = (await res.json()).detail;
|
|
422
|
+
} catch {
|
|
423
|
+
detail = res.statusText;
|
|
424
|
+
}
|
|
425
|
+
throw new BrokerCallError(detail ?? `broker dispatch failed: ${res.status}`, target, res.status);
|
|
426
|
+
}
|
|
427
|
+
const body = await res.json();
|
|
428
|
+
return body.result;
|
|
429
|
+
}
|
|
430
|
+
async function brokerCallSandboxed(target, payload, options = {}) {
|
|
431
|
+
return sandboxRequest({
|
|
432
|
+
kind: "palette.broker.call",
|
|
433
|
+
target,
|
|
434
|
+
payload: payload ?? {},
|
|
435
|
+
callerAppId: options.callerAppId
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
async function brokerEmitDirect(target, payload, options = {}) {
|
|
439
|
+
const callerAppId = options.callerAppId ?? currentPluginId();
|
|
440
|
+
if (!callerAppId) {
|
|
441
|
+
throw new BrokerCallError(
|
|
442
|
+
"events.emit requires a caller app id \u2014 only plugins may emit declared events",
|
|
443
|
+
target
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
const res = await apiFetch("/api/v1/os-broker/events/emit", {
|
|
447
|
+
method: "POST",
|
|
448
|
+
headers: { [CALLER_HEADER]: callerAppId },
|
|
449
|
+
body: JSON.stringify({ target, payload: payload ?? {}, caller_app_id: callerAppId }),
|
|
450
|
+
signal: options.signal
|
|
451
|
+
});
|
|
452
|
+
if (!res.ok) {
|
|
453
|
+
let detail;
|
|
454
|
+
try {
|
|
455
|
+
detail = (await res.json()).detail;
|
|
456
|
+
} catch {
|
|
457
|
+
detail = res.statusText;
|
|
458
|
+
}
|
|
459
|
+
throw new BrokerCallError(detail ?? `event emit failed: ${res.status}`, target, res.status);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async function brokerEmitSandboxed(target, payload, options = {}) {
|
|
463
|
+
await sandboxRequest({
|
|
464
|
+
kind: "palette.broker.emit",
|
|
465
|
+
target,
|
|
466
|
+
payload: payload ?? {},
|
|
467
|
+
callerAppId: options.callerAppId
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
function sandboxRequest(message) {
|
|
471
|
+
if (typeof window === "undefined") {
|
|
472
|
+
return Promise.reject(new BrokerCallError("sandbox bridge unavailable", message.target));
|
|
473
|
+
}
|
|
474
|
+
return new Promise((resolve, reject) => {
|
|
475
|
+
const id = `${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
476
|
+
const onMessage = (ev) => {
|
|
477
|
+
const data = ev.data;
|
|
478
|
+
if (!data || data.id !== id) return;
|
|
479
|
+
window.removeEventListener("message", onMessage);
|
|
480
|
+
if (data.error) {
|
|
481
|
+
reject(new BrokerCallError(data.error.message, message.target, data.error.status));
|
|
482
|
+
} else {
|
|
483
|
+
resolve(data.result);
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
window.addEventListener("message", onMessage);
|
|
487
|
+
window.parent?.postMessage({ ...message, id }, "*");
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
var broker = {
|
|
491
|
+
async call(target, payload, options) {
|
|
492
|
+
return isSandboxRuntime() ? brokerCallSandboxed(target, payload, options) : brokerCallDirect(target, payload, options);
|
|
493
|
+
},
|
|
494
|
+
async emit(target, payload, options) {
|
|
495
|
+
if (isSandboxRuntime()) return brokerEmitSandboxed(target, payload, options);
|
|
496
|
+
return brokerEmitDirect(target, payload, options);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
function servicesProxy(namespaceVersion) {
|
|
500
|
+
if (!namespaceVersion.includes("/")) {
|
|
501
|
+
throw new BrokerCallError("namespaceVersion must look like 'org/v1'", namespaceVersion);
|
|
502
|
+
}
|
|
503
|
+
const buildProxy = (segments) => new Proxy(function() {
|
|
504
|
+
}, {
|
|
505
|
+
get(_target, prop) {
|
|
506
|
+
if (typeof prop !== "string") return void 0;
|
|
507
|
+
return buildProxy([...segments, prop]);
|
|
508
|
+
},
|
|
509
|
+
apply(_target, _thisArg, args) {
|
|
510
|
+
const method = segments.join(".");
|
|
511
|
+
if (!method) {
|
|
512
|
+
throw new BrokerCallError("missing method name", namespaceVersion);
|
|
513
|
+
}
|
|
514
|
+
const [payload, options] = args;
|
|
515
|
+
return broker.call(`${namespaceVersion}#${method}`, payload, options);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
return buildProxy([]);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// src/events.ts
|
|
522
|
+
var SUBSCRIBERS = /* @__PURE__ */ new Map();
|
|
523
|
+
var activeStream = null;
|
|
524
|
+
var activeStreamUrl = null;
|
|
525
|
+
var sandboxBound = false;
|
|
526
|
+
function currentPluginId2() {
|
|
527
|
+
if (typeof window === "undefined") return void 0;
|
|
528
|
+
const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
|
|
529
|
+
return match ? decodeURIComponent(match[1]) : void 0;
|
|
530
|
+
}
|
|
531
|
+
function streamUrl() {
|
|
532
|
+
const params = new URLSearchParams();
|
|
533
|
+
const targets = Array.from(SUBSCRIBERS.keys());
|
|
534
|
+
if (targets.length) params.set("targets", targets.join(","));
|
|
535
|
+
const callerAppId = currentPluginId2();
|
|
536
|
+
if (callerAppId) params.set("caller_app_id", callerAppId);
|
|
537
|
+
const query = params.toString();
|
|
538
|
+
return `/api/v1/os-broker/events/stream${query ? `?${query}` : ""}`;
|
|
539
|
+
}
|
|
540
|
+
function ensureStream() {
|
|
541
|
+
if (activeStream || typeof window === "undefined") return;
|
|
542
|
+
activeStreamUrl = streamUrl();
|
|
543
|
+
activeStream = new EventSource(activeStreamUrl, { withCredentials: true });
|
|
544
|
+
activeStream.onmessage = (ev) => {
|
|
545
|
+
try {
|
|
546
|
+
const data = JSON.parse(ev.data);
|
|
547
|
+
const handlers = SUBSCRIBERS.get(data.target);
|
|
548
|
+
if (!handlers) return;
|
|
549
|
+
for (const handler of handlers) {
|
|
550
|
+
try {
|
|
551
|
+
handler(data.payload, data.meta);
|
|
552
|
+
} catch (err) {
|
|
553
|
+
console.error("palette.events handler threw", err);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
} catch (err) {
|
|
557
|
+
console.warn("palette.events: malformed event", err);
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
activeStream.onerror = () => {
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
function refreshStream() {
|
|
564
|
+
if (typeof window === "undefined" || isSandboxRuntime()) return;
|
|
565
|
+
const nextUrl = streamUrl();
|
|
566
|
+
if (activeStream && activeStreamUrl === nextUrl) return;
|
|
567
|
+
activeStream?.close();
|
|
568
|
+
activeStream = null;
|
|
569
|
+
activeStreamUrl = null;
|
|
570
|
+
if (SUBSCRIBERS.size > 0) ensureStream();
|
|
571
|
+
}
|
|
572
|
+
function ensureSandboxBound() {
|
|
573
|
+
if (sandboxBound || typeof window === "undefined") return;
|
|
574
|
+
sandboxBound = true;
|
|
575
|
+
window.addEventListener("message", (ev) => {
|
|
576
|
+
const data = ev.data;
|
|
577
|
+
if (!data || data.kind !== "palette.broker.event" || !data.target) return;
|
|
578
|
+
const handlers = SUBSCRIBERS.get(data.target);
|
|
579
|
+
if (!handlers) return;
|
|
580
|
+
const meta = data.meta ?? { target: data.target, organizationId: null, occurredAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
581
|
+
for (const handler of handlers) {
|
|
582
|
+
try {
|
|
583
|
+
handler(data.payload, meta);
|
|
584
|
+
} catch (err) {
|
|
585
|
+
console.error("palette.events handler threw", err);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
var events = {
|
|
591
|
+
on(target, handler) {
|
|
592
|
+
let handlers = SUBSCRIBERS.get(target);
|
|
593
|
+
if (!handlers) {
|
|
594
|
+
handlers = /* @__PURE__ */ new Set();
|
|
595
|
+
SUBSCRIBERS.set(target, handlers);
|
|
596
|
+
}
|
|
597
|
+
handlers.add(handler);
|
|
598
|
+
if (isSandboxRuntime()) {
|
|
599
|
+
ensureSandboxBound();
|
|
600
|
+
window.parent?.postMessage({ kind: "palette.broker.subscribe", target }, "*");
|
|
601
|
+
} else {
|
|
602
|
+
refreshStream();
|
|
603
|
+
}
|
|
604
|
+
return () => {
|
|
605
|
+
handlers.delete(handler);
|
|
606
|
+
if (handlers.size === 0) {
|
|
607
|
+
SUBSCRIBERS.delete(target);
|
|
608
|
+
if (isSandboxRuntime()) {
|
|
609
|
+
window.parent?.postMessage({ kind: "palette.broker.unsubscribe", target }, "*");
|
|
610
|
+
} else {
|
|
611
|
+
refreshStream();
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
},
|
|
616
|
+
async emit(target, payload) {
|
|
617
|
+
await broker.emit(target, payload);
|
|
618
|
+
},
|
|
619
|
+
/** Diagnostic: list active subscriptions in this page. */
|
|
620
|
+
active() {
|
|
621
|
+
return Array.from(SUBSCRIBERS.keys());
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
|
|
388
625
|
// src/permissions.ts
|
|
389
626
|
function hasPermission(ctx, permission) {
|
|
390
627
|
return ctx.permissions?.includes(permission) ?? false;
|
|
@@ -714,9 +951,21 @@ function createPaletteClient(ctx) {
|
|
|
714
951
|
success: (message) => ctx?.showToast(message, "success"),
|
|
715
952
|
error: (message) => ctx?.showToast(message, "error"),
|
|
716
953
|
info: (message) => ctx?.showToast(message, "info")
|
|
717
|
-
}
|
|
954
|
+
},
|
|
955
|
+
/**
|
|
956
|
+
* OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
|
|
957
|
+
* The proxy resolves a dotted method chain into a qualified target string
|
|
958
|
+
* and dispatches via the broker (in-process for plugins on the host,
|
|
959
|
+
* postMessage for sandboxed iframe apps).
|
|
960
|
+
*/
|
|
961
|
+
services: (namespaceVersion) => servicesProxy(namespaceVersion),
|
|
962
|
+
/** Low-level broker accessor when you don't want the typed proxy. */
|
|
963
|
+
broker,
|
|
964
|
+
/** OS-broker pub/sub. `events.on(target, fn)` returns an unsubscribe function. */
|
|
965
|
+
events
|
|
718
966
|
};
|
|
719
967
|
}
|
|
968
|
+
var palette = createPaletteClient();
|
|
720
969
|
|
|
721
970
|
// src/i18n.ts
|
|
722
971
|
var import_react3 = require("react");
|
|
@@ -841,6 +1090,21 @@ function currentSearchParams() {
|
|
|
841
1090
|
if (typeof window === "undefined") return new URLSearchParams();
|
|
842
1091
|
return new URLSearchParams(window.location.search);
|
|
843
1092
|
}
|
|
1093
|
+
function preserveCurrentPreviewParams(path, pluginId) {
|
|
1094
|
+
if (typeof window === "undefined" || !pluginId || /^https?:\/\//i.test(path)) return path;
|
|
1095
|
+
const currentParams = new URLSearchParams(window.location.search);
|
|
1096
|
+
const previewPublishId = currentParams.get("preview_publish_id");
|
|
1097
|
+
const previewToken = currentParams.get("preview_token");
|
|
1098
|
+
if (!previewPublishId || !previewToken) return path;
|
|
1099
|
+
const [beforeHash, hash = ""] = path.split("#", 2);
|
|
1100
|
+
const [pathname, query = ""] = beforeHash.split("?", 2);
|
|
1101
|
+
if (pathname !== `/apps/${pluginId}` && !pathname.startsWith(`/apps/${pluginId}/`)) return path;
|
|
1102
|
+
const params = new URLSearchParams(query);
|
|
1103
|
+
params.set("preview_publish_id", previewPublishId);
|
|
1104
|
+
params.set("preview_token", previewToken);
|
|
1105
|
+
const serialized = params.toString();
|
|
1106
|
+
return `${pathname}${serialized ? `?${serialized}` : ""}${hash ? `#${hash}` : ""}`;
|
|
1107
|
+
}
|
|
844
1108
|
var PaletteRouteErrorBoundary = class extends import_react4.Component {
|
|
845
1109
|
constructor() {
|
|
846
1110
|
super(...arguments);
|
|
@@ -918,8 +1182,9 @@ function PaletteAppRouter({
|
|
|
918
1182
|
const currentPath = typeof window === "undefined" ? "" : window.location.pathname;
|
|
919
1183
|
const inPalettePath = platform.pluginId && (currentPath.startsWith(`/apps/${platform.pluginId}`) || platform.routePath !== void 0);
|
|
920
1184
|
const osPath = inPalettePath && platform.pluginId ? `/apps/${platform.pluginId}${pathname === "/" ? "" : pathname}${queryPart ? `?${queryPart}` : ""}` : next;
|
|
921
|
-
|
|
922
|
-
|
|
1185
|
+
const preservedOsPath = preserveCurrentPreviewParams(osPath, platform.pluginId);
|
|
1186
|
+
if (replace && typeof window !== "undefined") window.history.replaceState(null, "", preservedOsPath);
|
|
1187
|
+
else platform.navigate(preservedOsPath);
|
|
923
1188
|
}, [platform]);
|
|
924
1189
|
const state = (0, import_react4.useMemo)(() => ({
|
|
925
1190
|
pathname: location.pathname,
|
|
@@ -1163,6 +1428,7 @@ function usePluginChat(agentId) {
|
|
|
1163
1428
|
}
|
|
1164
1429
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1165
1430
|
0 && (module.exports = {
|
|
1431
|
+
BrokerCallError,
|
|
1166
1432
|
DataRoomClient,
|
|
1167
1433
|
Link,
|
|
1168
1434
|
OrganizationClient,
|
|
@@ -1174,12 +1440,14 @@ function usePluginChat(agentId) {
|
|
|
1174
1440
|
UserClient,
|
|
1175
1441
|
apiFetch,
|
|
1176
1442
|
apiUpload,
|
|
1443
|
+
broker,
|
|
1177
1444
|
createMockPlatformContext,
|
|
1178
1445
|
createPaletteClient,
|
|
1179
1446
|
createSandboxBridge,
|
|
1180
1447
|
dataRooms,
|
|
1181
1448
|
disconnectConnection,
|
|
1182
1449
|
errorFromResponse,
|
|
1450
|
+
events,
|
|
1183
1451
|
getBaseUrl,
|
|
1184
1452
|
getConnections,
|
|
1185
1453
|
getInstallConfig,
|
|
@@ -1190,7 +1458,9 @@ function usePluginChat(agentId) {
|
|
|
1190
1458
|
isSandboxRuntime,
|
|
1191
1459
|
normalizePaletteLanguage,
|
|
1192
1460
|
notFound,
|
|
1461
|
+
palette,
|
|
1193
1462
|
requireConnection,
|
|
1463
|
+
servicesProxy,
|
|
1194
1464
|
setBaseUrl,
|
|
1195
1465
|
startConnection,
|
|
1196
1466
|
translate,
|
package/dist/index.mjs
CHANGED
|
@@ -317,6 +317,238 @@ var DataRoomClient = class {
|
|
|
317
317
|
};
|
|
318
318
|
var dataRooms = new DataRoomClient();
|
|
319
319
|
|
|
320
|
+
// src/services.ts
|
|
321
|
+
var BrokerCallError = class extends Error {
|
|
322
|
+
constructor(message, target, status) {
|
|
323
|
+
super(message);
|
|
324
|
+
this.target = target;
|
|
325
|
+
this.status = status;
|
|
326
|
+
this.name = "BrokerCallError";
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
var CALLER_HEADER = "X-Palette-Caller-App";
|
|
330
|
+
function currentPluginId() {
|
|
331
|
+
if (typeof window === "undefined") return void 0;
|
|
332
|
+
const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
|
|
333
|
+
return match ? decodeURIComponent(match[1]) : void 0;
|
|
334
|
+
}
|
|
335
|
+
async function brokerCallDirect(target, payload, options = {}) {
|
|
336
|
+
const callerAppId = options.callerAppId ?? currentPluginId();
|
|
337
|
+
const headers = {};
|
|
338
|
+
if (callerAppId) headers[CALLER_HEADER] = callerAppId;
|
|
339
|
+
const res = await apiFetch("/api/v1/os-broker/dispatch", {
|
|
340
|
+
method: "POST",
|
|
341
|
+
headers,
|
|
342
|
+
body: JSON.stringify({ target, payload: payload ?? {}, caller_app_id: callerAppId }),
|
|
343
|
+
signal: options.signal
|
|
344
|
+
});
|
|
345
|
+
if (!res.ok) {
|
|
346
|
+
let detail;
|
|
347
|
+
try {
|
|
348
|
+
detail = (await res.json()).detail;
|
|
349
|
+
} catch {
|
|
350
|
+
detail = res.statusText;
|
|
351
|
+
}
|
|
352
|
+
throw new BrokerCallError(detail ?? `broker dispatch failed: ${res.status}`, target, res.status);
|
|
353
|
+
}
|
|
354
|
+
const body = await res.json();
|
|
355
|
+
return body.result;
|
|
356
|
+
}
|
|
357
|
+
async function brokerCallSandboxed(target, payload, options = {}) {
|
|
358
|
+
return sandboxRequest({
|
|
359
|
+
kind: "palette.broker.call",
|
|
360
|
+
target,
|
|
361
|
+
payload: payload ?? {},
|
|
362
|
+
callerAppId: options.callerAppId
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
async function brokerEmitDirect(target, payload, options = {}) {
|
|
366
|
+
const callerAppId = options.callerAppId ?? currentPluginId();
|
|
367
|
+
if (!callerAppId) {
|
|
368
|
+
throw new BrokerCallError(
|
|
369
|
+
"events.emit requires a caller app id \u2014 only plugins may emit declared events",
|
|
370
|
+
target
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
const res = await apiFetch("/api/v1/os-broker/events/emit", {
|
|
374
|
+
method: "POST",
|
|
375
|
+
headers: { [CALLER_HEADER]: callerAppId },
|
|
376
|
+
body: JSON.stringify({ target, payload: payload ?? {}, caller_app_id: callerAppId }),
|
|
377
|
+
signal: options.signal
|
|
378
|
+
});
|
|
379
|
+
if (!res.ok) {
|
|
380
|
+
let detail;
|
|
381
|
+
try {
|
|
382
|
+
detail = (await res.json()).detail;
|
|
383
|
+
} catch {
|
|
384
|
+
detail = res.statusText;
|
|
385
|
+
}
|
|
386
|
+
throw new BrokerCallError(detail ?? `event emit failed: ${res.status}`, target, res.status);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
async function brokerEmitSandboxed(target, payload, options = {}) {
|
|
390
|
+
await sandboxRequest({
|
|
391
|
+
kind: "palette.broker.emit",
|
|
392
|
+
target,
|
|
393
|
+
payload: payload ?? {},
|
|
394
|
+
callerAppId: options.callerAppId
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
function sandboxRequest(message) {
|
|
398
|
+
if (typeof window === "undefined") {
|
|
399
|
+
return Promise.reject(new BrokerCallError("sandbox bridge unavailable", message.target));
|
|
400
|
+
}
|
|
401
|
+
return new Promise((resolve, reject) => {
|
|
402
|
+
const id = `${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
403
|
+
const onMessage = (ev) => {
|
|
404
|
+
const data = ev.data;
|
|
405
|
+
if (!data || data.id !== id) return;
|
|
406
|
+
window.removeEventListener("message", onMessage);
|
|
407
|
+
if (data.error) {
|
|
408
|
+
reject(new BrokerCallError(data.error.message, message.target, data.error.status));
|
|
409
|
+
} else {
|
|
410
|
+
resolve(data.result);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
window.addEventListener("message", onMessage);
|
|
414
|
+
window.parent?.postMessage({ ...message, id }, "*");
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
var broker = {
|
|
418
|
+
async call(target, payload, options) {
|
|
419
|
+
return isSandboxRuntime() ? brokerCallSandboxed(target, payload, options) : brokerCallDirect(target, payload, options);
|
|
420
|
+
},
|
|
421
|
+
async emit(target, payload, options) {
|
|
422
|
+
if (isSandboxRuntime()) return brokerEmitSandboxed(target, payload, options);
|
|
423
|
+
return brokerEmitDirect(target, payload, options);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
function servicesProxy(namespaceVersion) {
|
|
427
|
+
if (!namespaceVersion.includes("/")) {
|
|
428
|
+
throw new BrokerCallError("namespaceVersion must look like 'org/v1'", namespaceVersion);
|
|
429
|
+
}
|
|
430
|
+
const buildProxy = (segments) => new Proxy(function() {
|
|
431
|
+
}, {
|
|
432
|
+
get(_target, prop) {
|
|
433
|
+
if (typeof prop !== "string") return void 0;
|
|
434
|
+
return buildProxy([...segments, prop]);
|
|
435
|
+
},
|
|
436
|
+
apply(_target, _thisArg, args) {
|
|
437
|
+
const method = segments.join(".");
|
|
438
|
+
if (!method) {
|
|
439
|
+
throw new BrokerCallError("missing method name", namespaceVersion);
|
|
440
|
+
}
|
|
441
|
+
const [payload, options] = args;
|
|
442
|
+
return broker.call(`${namespaceVersion}#${method}`, payload, options);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
return buildProxy([]);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// src/events.ts
|
|
449
|
+
var SUBSCRIBERS = /* @__PURE__ */ new Map();
|
|
450
|
+
var activeStream = null;
|
|
451
|
+
var activeStreamUrl = null;
|
|
452
|
+
var sandboxBound = false;
|
|
453
|
+
function currentPluginId2() {
|
|
454
|
+
if (typeof window === "undefined") return void 0;
|
|
455
|
+
const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
|
|
456
|
+
return match ? decodeURIComponent(match[1]) : void 0;
|
|
457
|
+
}
|
|
458
|
+
function streamUrl() {
|
|
459
|
+
const params = new URLSearchParams();
|
|
460
|
+
const targets = Array.from(SUBSCRIBERS.keys());
|
|
461
|
+
if (targets.length) params.set("targets", targets.join(","));
|
|
462
|
+
const callerAppId = currentPluginId2();
|
|
463
|
+
if (callerAppId) params.set("caller_app_id", callerAppId);
|
|
464
|
+
const query = params.toString();
|
|
465
|
+
return `/api/v1/os-broker/events/stream${query ? `?${query}` : ""}`;
|
|
466
|
+
}
|
|
467
|
+
function ensureStream() {
|
|
468
|
+
if (activeStream || typeof window === "undefined") return;
|
|
469
|
+
activeStreamUrl = streamUrl();
|
|
470
|
+
activeStream = new EventSource(activeStreamUrl, { withCredentials: true });
|
|
471
|
+
activeStream.onmessage = (ev) => {
|
|
472
|
+
try {
|
|
473
|
+
const data = JSON.parse(ev.data);
|
|
474
|
+
const handlers = SUBSCRIBERS.get(data.target);
|
|
475
|
+
if (!handlers) return;
|
|
476
|
+
for (const handler of handlers) {
|
|
477
|
+
try {
|
|
478
|
+
handler(data.payload, data.meta);
|
|
479
|
+
} catch (err) {
|
|
480
|
+
console.error("palette.events handler threw", err);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
} catch (err) {
|
|
484
|
+
console.warn("palette.events: malformed event", err);
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
activeStream.onerror = () => {
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
function refreshStream() {
|
|
491
|
+
if (typeof window === "undefined" || isSandboxRuntime()) return;
|
|
492
|
+
const nextUrl = streamUrl();
|
|
493
|
+
if (activeStream && activeStreamUrl === nextUrl) return;
|
|
494
|
+
activeStream?.close();
|
|
495
|
+
activeStream = null;
|
|
496
|
+
activeStreamUrl = null;
|
|
497
|
+
if (SUBSCRIBERS.size > 0) ensureStream();
|
|
498
|
+
}
|
|
499
|
+
function ensureSandboxBound() {
|
|
500
|
+
if (sandboxBound || typeof window === "undefined") return;
|
|
501
|
+
sandboxBound = true;
|
|
502
|
+
window.addEventListener("message", (ev) => {
|
|
503
|
+
const data = ev.data;
|
|
504
|
+
if (!data || data.kind !== "palette.broker.event" || !data.target) return;
|
|
505
|
+
const handlers = SUBSCRIBERS.get(data.target);
|
|
506
|
+
if (!handlers) return;
|
|
507
|
+
const meta = data.meta ?? { target: data.target, organizationId: null, occurredAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
508
|
+
for (const handler of handlers) {
|
|
509
|
+
try {
|
|
510
|
+
handler(data.payload, meta);
|
|
511
|
+
} catch (err) {
|
|
512
|
+
console.error("palette.events handler threw", err);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
var events = {
|
|
518
|
+
on(target, handler) {
|
|
519
|
+
let handlers = SUBSCRIBERS.get(target);
|
|
520
|
+
if (!handlers) {
|
|
521
|
+
handlers = /* @__PURE__ */ new Set();
|
|
522
|
+
SUBSCRIBERS.set(target, handlers);
|
|
523
|
+
}
|
|
524
|
+
handlers.add(handler);
|
|
525
|
+
if (isSandboxRuntime()) {
|
|
526
|
+
ensureSandboxBound();
|
|
527
|
+
window.parent?.postMessage({ kind: "palette.broker.subscribe", target }, "*");
|
|
528
|
+
} else {
|
|
529
|
+
refreshStream();
|
|
530
|
+
}
|
|
531
|
+
return () => {
|
|
532
|
+
handlers.delete(handler);
|
|
533
|
+
if (handlers.size === 0) {
|
|
534
|
+
SUBSCRIBERS.delete(target);
|
|
535
|
+
if (isSandboxRuntime()) {
|
|
536
|
+
window.parent?.postMessage({ kind: "palette.broker.unsubscribe", target }, "*");
|
|
537
|
+
} else {
|
|
538
|
+
refreshStream();
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
},
|
|
543
|
+
async emit(target, payload) {
|
|
544
|
+
await broker.emit(target, payload);
|
|
545
|
+
},
|
|
546
|
+
/** Diagnostic: list active subscriptions in this page. */
|
|
547
|
+
active() {
|
|
548
|
+
return Array.from(SUBSCRIBERS.keys());
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
|
|
320
552
|
// src/permissions.ts
|
|
321
553
|
function hasPermission(ctx, permission) {
|
|
322
554
|
return ctx.permissions?.includes(permission) ?? false;
|
|
@@ -646,9 +878,21 @@ function createPaletteClient(ctx) {
|
|
|
646
878
|
success: (message) => ctx?.showToast(message, "success"),
|
|
647
879
|
error: (message) => ctx?.showToast(message, "error"),
|
|
648
880
|
info: (message) => ctx?.showToast(message, "info")
|
|
649
|
-
}
|
|
881
|
+
},
|
|
882
|
+
/**
|
|
883
|
+
* OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
|
|
884
|
+
* The proxy resolves a dotted method chain into a qualified target string
|
|
885
|
+
* and dispatches via the broker (in-process for plugins on the host,
|
|
886
|
+
* postMessage for sandboxed iframe apps).
|
|
887
|
+
*/
|
|
888
|
+
services: (namespaceVersion) => servicesProxy(namespaceVersion),
|
|
889
|
+
/** Low-level broker accessor when you don't want the typed proxy. */
|
|
890
|
+
broker,
|
|
891
|
+
/** OS-broker pub/sub. `events.on(target, fn)` returns an unsubscribe function. */
|
|
892
|
+
events
|
|
650
893
|
};
|
|
651
894
|
}
|
|
895
|
+
var palette = createPaletteClient();
|
|
652
896
|
|
|
653
897
|
// src/i18n.ts
|
|
654
898
|
import { useCallback } from "react";
|
|
@@ -782,6 +1026,21 @@ function currentSearchParams() {
|
|
|
782
1026
|
if (typeof window === "undefined") return new URLSearchParams();
|
|
783
1027
|
return new URLSearchParams(window.location.search);
|
|
784
1028
|
}
|
|
1029
|
+
function preserveCurrentPreviewParams(path, pluginId) {
|
|
1030
|
+
if (typeof window === "undefined" || !pluginId || /^https?:\/\//i.test(path)) return path;
|
|
1031
|
+
const currentParams = new URLSearchParams(window.location.search);
|
|
1032
|
+
const previewPublishId = currentParams.get("preview_publish_id");
|
|
1033
|
+
const previewToken = currentParams.get("preview_token");
|
|
1034
|
+
if (!previewPublishId || !previewToken) return path;
|
|
1035
|
+
const [beforeHash, hash = ""] = path.split("#", 2);
|
|
1036
|
+
const [pathname, query = ""] = beforeHash.split("?", 2);
|
|
1037
|
+
if (pathname !== `/apps/${pluginId}` && !pathname.startsWith(`/apps/${pluginId}/`)) return path;
|
|
1038
|
+
const params = new URLSearchParams(query);
|
|
1039
|
+
params.set("preview_publish_id", previewPublishId);
|
|
1040
|
+
params.set("preview_token", previewToken);
|
|
1041
|
+
const serialized = params.toString();
|
|
1042
|
+
return `${pathname}${serialized ? `?${serialized}` : ""}${hash ? `#${hash}` : ""}`;
|
|
1043
|
+
}
|
|
785
1044
|
var PaletteRouteErrorBoundary = class extends Component {
|
|
786
1045
|
constructor() {
|
|
787
1046
|
super(...arguments);
|
|
@@ -859,8 +1118,9 @@ function PaletteAppRouter({
|
|
|
859
1118
|
const currentPath = typeof window === "undefined" ? "" : window.location.pathname;
|
|
860
1119
|
const inPalettePath = platform.pluginId && (currentPath.startsWith(`/apps/${platform.pluginId}`) || platform.routePath !== void 0);
|
|
861
1120
|
const osPath = inPalettePath && platform.pluginId ? `/apps/${platform.pluginId}${pathname === "/" ? "" : pathname}${queryPart ? `?${queryPart}` : ""}` : next;
|
|
862
|
-
|
|
863
|
-
|
|
1121
|
+
const preservedOsPath = preserveCurrentPreviewParams(osPath, platform.pluginId);
|
|
1122
|
+
if (replace && typeof window !== "undefined") window.history.replaceState(null, "", preservedOsPath);
|
|
1123
|
+
else platform.navigate(preservedOsPath);
|
|
864
1124
|
}, [platform]);
|
|
865
1125
|
const state = useMemo(() => ({
|
|
866
1126
|
pathname: location.pathname,
|
|
@@ -1103,6 +1363,7 @@ function usePluginChat(agentId) {
|
|
|
1103
1363
|
};
|
|
1104
1364
|
}
|
|
1105
1365
|
export {
|
|
1366
|
+
BrokerCallError,
|
|
1106
1367
|
DataRoomClient,
|
|
1107
1368
|
Link,
|
|
1108
1369
|
OrganizationClient,
|
|
@@ -1114,12 +1375,14 @@ export {
|
|
|
1114
1375
|
UserClient,
|
|
1115
1376
|
apiFetch,
|
|
1116
1377
|
apiUpload,
|
|
1378
|
+
broker,
|
|
1117
1379
|
createMockPlatformContext,
|
|
1118
1380
|
createPaletteClient,
|
|
1119
1381
|
createSandboxBridge,
|
|
1120
1382
|
dataRooms,
|
|
1121
1383
|
disconnectConnection,
|
|
1122
1384
|
errorFromResponse,
|
|
1385
|
+
events,
|
|
1123
1386
|
getBaseUrl,
|
|
1124
1387
|
getConnections,
|
|
1125
1388
|
getInstallConfig,
|
|
@@ -1130,7 +1393,9 @@ export {
|
|
|
1130
1393
|
isSandboxRuntime,
|
|
1131
1394
|
normalizePaletteLanguage,
|
|
1132
1395
|
notFound,
|
|
1396
|
+
palette,
|
|
1133
1397
|
requireConnection,
|
|
1398
|
+
servicesProxy,
|
|
1134
1399
|
setBaseUrl,
|
|
1135
1400
|
startConnection,
|
|
1136
1401
|
translate,
|