@ethisyscore/extension-runtime 1.9.0 → 1.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.
@@ -1,7 +1,10 @@
1
- import { M as McpTransport } from '../transport-DVn2GVZh.cjs';
1
+ import { M as McpTransport, P as PortBridgeClient, T as ThemePayload, L as LocalePayload } from '../bridge-client-CIThO7jZ.cjs';
2
+ export { A as A11yPayload, B as BridgePortShim, D as DensityPayload, N as NavPayload, S as SessionTokenPayload, c as createPortBridgeClient } from '../bridge-client-CIThO7jZ.cjs';
3
+ import * as react from 'react';
2
4
  import { ReactNode } from 'react';
3
5
  import { SduiNode, RenderMode } from '@ethisyscore/protocol';
4
6
  import { RemoteConnection } from '@remote-dom/core';
7
+ import '../bridge-envelopes-BRKGSiSC.cjs';
5
8
 
6
9
  interface ExtensionRuntimeProviderProps {
7
10
  transport: McpTransport;
@@ -397,4 +400,49 @@ interface PortShim {
397
400
  */
398
401
  declare function createPortMcpTransport(port: MessagePort | PortShim, options?: CreatePortMcpTransportOptions): McpTransport;
399
402
 
400
- export { type CreatePortMcpTransportOptions, type CreateRemoteRootOptions, type DeclarativePluginConfig, type EthisysPluginConfig, ExtensionRuntimeProvider, type ExtensionRuntimeProviderProps, type ItemsResponse, McpTransport, type PortShim, type RemoteRoot, type UseMcpQueryOptions, type UseMcpQueryResult, type UseMcpResourceOptions, type UseMcpResourceResult, type UseMcpToolOptions, type UseMcpToolResult, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useMcpQuery, useMcpResource, useMcpTool };
403
+ /**
404
+ * React context carrying the plugin's active {@link PortBridgeClient}.
405
+ * Provided by the host mount (WorkerMockHost in dev, real bridge in production)
406
+ * and consumed by `useBridgeTheme`, `useBridgeLocale`, and the `plugin-ui` hooks.
407
+ */
408
+ declare const BridgeClientContext: react.Context<PortBridgeClient | null>;
409
+ /**
410
+ * Returns the bridge client from context, throwing a clear error when missing.
411
+ * Used by the `useBridge*` hooks to fail loudly on misconfiguration.
412
+ */
413
+ declare function useBridgeClient(): PortBridgeClient;
414
+
415
+ /**
416
+ * Subscribe to host theme pushes. Returns the most recently pushed theme,
417
+ * or `undefined` before the first push (e.g. during initial render before
418
+ * the host has sent its first `BRIDGE_PUSH_THEME` message).
419
+ *
420
+ * The hook re-registers with the bridge client if the client identity changes
421
+ * (e.g. on hot-reload of the mock host in dev), keeping state consistent.
422
+ */
423
+ declare function useBridgeTheme(): ThemePayload | undefined;
424
+
425
+ /**
426
+ * Subscribe to host locale pushes. Returns the most recently pushed locale
427
+ * and text direction, or `undefined` before the first push.
428
+ */
429
+ declare function useBridgeLocale(): LocalePayload | undefined;
430
+
431
+ interface UseFrontendSessionTokenResult {
432
+ /** The compact-serialised JWT, or null while loading / on error. */
433
+ token: string | null;
434
+ /** True while the first fetch (or a refresh) is in-flight. */
435
+ isLoading: boolean;
436
+ /** Set when the bridge rejects; null otherwise. */
437
+ error: Error | null;
438
+ }
439
+ /**
440
+ * Returns the current FE-session token fetched from the host bridge.
441
+ * Schedules silent refresh 30 s before the token expires.
442
+ *
443
+ * @param transport The {@link McpTransport} to use. Typically the context
444
+ * transport from the extension runtime provider.
445
+ */
446
+ declare function useFrontendSessionToken(transport: McpTransport): UseFrontendSessionTokenResult;
447
+
448
+ export { BridgeClientContext, type CreatePortMcpTransportOptions, type CreateRemoteRootOptions, type DeclarativePluginConfig, type EthisysPluginConfig, ExtensionRuntimeProvider, type ExtensionRuntimeProviderProps, type ItemsResponse, LocalePayload, McpTransport, PortBridgeClient, type PortShim, type RemoteRoot, ThemePayload, type UseFrontendSessionTokenResult, type UseMcpQueryOptions, type UseMcpQueryResult, type UseMcpResourceOptions, type UseMcpResourceResult, type UseMcpToolOptions, type UseMcpToolResult, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useBridgeClient, useBridgeLocale, useBridgeTheme, useFrontendSessionToken, useMcpQuery, useMcpResource, useMcpTool };
@@ -1,7 +1,10 @@
1
- import { M as McpTransport } from '../transport-DVn2GVZh.js';
1
+ import { M as McpTransport, P as PortBridgeClient, T as ThemePayload, L as LocalePayload } from '../bridge-client-UK3qcGoi.js';
2
+ export { A as A11yPayload, B as BridgePortShim, D as DensityPayload, N as NavPayload, S as SessionTokenPayload, c as createPortBridgeClient } from '../bridge-client-UK3qcGoi.js';
3
+ import * as react from 'react';
2
4
  import { ReactNode } from 'react';
3
5
  import { SduiNode, RenderMode } from '@ethisyscore/protocol';
4
6
  import { RemoteConnection } from '@remote-dom/core';
7
+ import '../bridge-envelopes-BRKGSiSC.js';
5
8
 
6
9
  interface ExtensionRuntimeProviderProps {
7
10
  transport: McpTransport;
@@ -397,4 +400,49 @@ interface PortShim {
397
400
  */
398
401
  declare function createPortMcpTransport(port: MessagePort | PortShim, options?: CreatePortMcpTransportOptions): McpTransport;
399
402
 
400
- export { type CreatePortMcpTransportOptions, type CreateRemoteRootOptions, type DeclarativePluginConfig, type EthisysPluginConfig, ExtensionRuntimeProvider, type ExtensionRuntimeProviderProps, type ItemsResponse, McpTransport, type PortShim, type RemoteRoot, type UseMcpQueryOptions, type UseMcpQueryResult, type UseMcpResourceOptions, type UseMcpResourceResult, type UseMcpToolOptions, type UseMcpToolResult, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useMcpQuery, useMcpResource, useMcpTool };
403
+ /**
404
+ * React context carrying the plugin's active {@link PortBridgeClient}.
405
+ * Provided by the host mount (WorkerMockHost in dev, real bridge in production)
406
+ * and consumed by `useBridgeTheme`, `useBridgeLocale`, and the `plugin-ui` hooks.
407
+ */
408
+ declare const BridgeClientContext: react.Context<PortBridgeClient | null>;
409
+ /**
410
+ * Returns the bridge client from context, throwing a clear error when missing.
411
+ * Used by the `useBridge*` hooks to fail loudly on misconfiguration.
412
+ */
413
+ declare function useBridgeClient(): PortBridgeClient;
414
+
415
+ /**
416
+ * Subscribe to host theme pushes. Returns the most recently pushed theme,
417
+ * or `undefined` before the first push (e.g. during initial render before
418
+ * the host has sent its first `BRIDGE_PUSH_THEME` message).
419
+ *
420
+ * The hook re-registers with the bridge client if the client identity changes
421
+ * (e.g. on hot-reload of the mock host in dev), keeping state consistent.
422
+ */
423
+ declare function useBridgeTheme(): ThemePayload | undefined;
424
+
425
+ /**
426
+ * Subscribe to host locale pushes. Returns the most recently pushed locale
427
+ * and text direction, or `undefined` before the first push.
428
+ */
429
+ declare function useBridgeLocale(): LocalePayload | undefined;
430
+
431
+ interface UseFrontendSessionTokenResult {
432
+ /** The compact-serialised JWT, or null while loading / on error. */
433
+ token: string | null;
434
+ /** True while the first fetch (or a refresh) is in-flight. */
435
+ isLoading: boolean;
436
+ /** Set when the bridge rejects; null otherwise. */
437
+ error: Error | null;
438
+ }
439
+ /**
440
+ * Returns the current FE-session token fetched from the host bridge.
441
+ * Schedules silent refresh 30 s before the token expires.
442
+ *
443
+ * @param transport The {@link McpTransport} to use. Typically the context
444
+ * transport from the extension runtime provider.
445
+ */
446
+ declare function useFrontendSessionToken(transport: McpTransport): UseFrontendSessionTokenResult;
447
+
448
+ export { BridgeClientContext, type CreatePortMcpTransportOptions, type CreateRemoteRootOptions, type DeclarativePluginConfig, type EthisysPluginConfig, ExtensionRuntimeProvider, type ExtensionRuntimeProviderProps, type ItemsResponse, LocalePayload, McpTransport, PortBridgeClient, type PortShim, type RemoteRoot, ThemePayload, type UseFrontendSessionTokenResult, type UseMcpQueryOptions, type UseMcpQueryResult, type UseMcpResourceOptions, type UseMcpResourceResult, type UseMcpToolOptions, type UseMcpToolResult, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useBridgeClient, useBridgeLocale, useBridgeTheme, useFrontendSessionToken, useMcpQuery, useMcpResource, useMcpTool };
@@ -520,6 +520,204 @@ function abortError() {
520
520
  return e;
521
521
  }
522
522
 
523
- export { ExtensionRuntimeProvider, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useMcpQuery, useMcpResource, useMcpTool };
523
+ // src/host/worker/bridge-envelopes.ts
524
+ var BRIDGE_PUSH_THEME = "ethisys:bridge:theme";
525
+ var BRIDGE_PUSH_LOCALE = "ethisys:bridge:locale";
526
+ var BRIDGE_PUSH_DENSITY = "ethisys:bridge:density";
527
+ var BRIDGE_PUSH_A11Y = "ethisys:bridge:a11y";
528
+ var BRIDGE_NAV_PUSH = "ethisys:bridge:nav";
529
+ var BRIDGE_CHROME_REQUEST = "ethisys:bridge:chrome:request";
530
+ var BRIDGE_CHROME_RESPONSE = "ethisys:bridge:chrome:response";
531
+ var BRIDGE_SESSION_TOKEN_PUSH = "ethisys:bridge:token";
532
+ var BRIDGE_A11Y_ANNOUNCE = "ethisys:bridge:a11y:announce";
533
+ function isObj(v) {
534
+ return v !== null && typeof v === "object";
535
+ }
536
+ function isBridgePushTheme(v) {
537
+ return isObj(v) && v["type"] === BRIDGE_PUSH_THEME && typeof v["mode"] === "string";
538
+ }
539
+ function isBridgePushLocale(v) {
540
+ return isObj(v) && v["type"] === BRIDGE_PUSH_LOCALE && typeof v["locale"] === "string";
541
+ }
542
+ function isBridgePushDensity(v) {
543
+ return isObj(v) && v["type"] === BRIDGE_PUSH_DENSITY && typeof v["density"] === "string";
544
+ }
545
+ function isBridgePushA11y(v) {
546
+ return isObj(v) && v["type"] === BRIDGE_PUSH_A11Y && typeof v["reducedMotion"] === "boolean" && typeof v["highContrast"] === "boolean";
547
+ }
548
+ function isBridgeNavPush(v) {
549
+ return isObj(v) && v["type"] === BRIDGE_NAV_PUSH && typeof v["path"] === "string";
550
+ }
551
+ function isBridgeChromeResponse(v) {
552
+ return isObj(v) && v["type"] === BRIDGE_CHROME_RESPONSE && typeof v["id"] === "string";
553
+ }
554
+ function isBridgeSessionTokenPush(v) {
555
+ return isObj(v) && v["type"] === BRIDGE_SESSION_TOKEN_PUSH && typeof v["token"] === "string" && typeof v["expiresAtMs"] === "number";
556
+ }
557
+
558
+ // src/plugin/bridge-client.ts
559
+ var _requestCounter = 0;
560
+ function nextId2() {
561
+ _requestCounter += 1;
562
+ return `br-${_requestCounter}`;
563
+ }
564
+ function createPortBridgeClient(port) {
565
+ let themeCb;
566
+ let localeCb;
567
+ let densityCb;
568
+ let a11yCb;
569
+ let navCb;
570
+ let tokenCb;
571
+ const pending = /* @__PURE__ */ new Map();
572
+ port.onmessage = (ev) => {
573
+ const msg = ev.data;
574
+ if (isBridgePushTheme(msg)) {
575
+ themeCb?.({ mode: msg.mode, tokens: msg.tokens });
576
+ return;
577
+ }
578
+ if (isBridgePushLocale(msg)) {
579
+ localeCb?.({ locale: msg.locale, dir: msg.dir });
580
+ return;
581
+ }
582
+ if (isBridgePushDensity(msg)) {
583
+ densityCb?.({ density: msg.density });
584
+ return;
585
+ }
586
+ if (isBridgePushA11y(msg)) {
587
+ a11yCb?.({ reducedMotion: msg.reducedMotion, highContrast: msg.highContrast });
588
+ return;
589
+ }
590
+ if (isBridgeNavPush(msg)) {
591
+ navCb?.({ path: msg.path, historyLength: msg.historyLength });
592
+ return;
593
+ }
594
+ if (isBridgeSessionTokenPush(msg)) {
595
+ tokenCb?.({ token: msg.token, expiresAtMs: msg.expiresAtMs });
596
+ return;
597
+ }
598
+ if (isBridgeChromeResponse(msg)) {
599
+ const p = pending.get(msg.id);
600
+ if (p === void 0) {
601
+ return;
602
+ }
603
+ pending.delete(msg.id);
604
+ if (msg.ok) {
605
+ p.resolve(msg.result ?? null);
606
+ } else {
607
+ p.reject(new Error(typeof msg.error === "string" ? msg.error : "Chrome request failed"));
608
+ }
609
+ }
610
+ };
611
+ return {
612
+ onTheme(cb) {
613
+ themeCb = cb;
614
+ },
615
+ onLocale(cb) {
616
+ localeCb = cb;
617
+ },
618
+ onDensity(cb) {
619
+ densityCb = cb;
620
+ },
621
+ onA11y(cb) {
622
+ a11yCb = cb;
623
+ },
624
+ onNav(cb) {
625
+ navCb = cb;
626
+ },
627
+ onSessionToken(cb) {
628
+ tokenCb = cb;
629
+ },
630
+ requestChrome(action, payload) {
631
+ const id = nextId2();
632
+ return new Promise((resolve, reject) => {
633
+ pending.set(id, { resolve, reject });
634
+ port.postMessage({ type: BRIDGE_CHROME_REQUEST, id, action, payload });
635
+ });
636
+ },
637
+ announceA11y(message, politeness) {
638
+ port.postMessage({ type: BRIDGE_A11Y_ANNOUNCE, message, politeness });
639
+ }
640
+ };
641
+ }
642
+ var BridgeClientContext = createContext(null);
643
+ function useBridgeClient() {
644
+ const client = useContext(BridgeClientContext);
645
+ if (client === null) {
646
+ throw new Error(
647
+ "No PortBridgeClient available. Wrap your plugin in <BridgeClientProvider> or ensure the host mount wires a BridgeClientContext.Provider."
648
+ );
649
+ }
650
+ return client;
651
+ }
652
+ function useBridgeTheme() {
653
+ const client = useBridgeClient();
654
+ const [theme, setTheme] = useState(void 0);
655
+ useEffect(() => {
656
+ client.onTheme((payload) => setTheme(payload));
657
+ }, [client]);
658
+ return theme;
659
+ }
660
+ function useBridgeLocale() {
661
+ const client = useBridgeClient();
662
+ const [locale, setLocale] = useState(void 0);
663
+ useEffect(() => {
664
+ client.onLocale((payload) => setLocale(payload));
665
+ }, [client]);
666
+ return locale;
667
+ }
668
+ var SESSION_TOKEN_URI = "ethisys:session-token";
669
+ var REFRESH_SKEW_MS = 3e4;
670
+ function useFrontendSessionToken(transport) {
671
+ const [token, setToken] = useState(null);
672
+ const [isLoading, setIsLoading] = useState(true);
673
+ const [error, setError] = useState(null);
674
+ const refreshTimerRef = useRef(null);
675
+ const mountedRef = useRef(true);
676
+ const fetch = useCallback(async () => {
677
+ if (refreshTimerRef.current !== null) {
678
+ clearTimeout(refreshTimerRef.current);
679
+ refreshTimerRef.current = null;
680
+ }
681
+ try {
682
+ const { data } = await transport.getResource(
683
+ SESSION_TOKEN_URI
684
+ );
685
+ if (!mountedRef.current) {
686
+ return;
687
+ }
688
+ setToken(data.accessToken);
689
+ setError(null);
690
+ setIsLoading(false);
691
+ const expiresAtMs = Date.parse(data.expiresAtUtc);
692
+ const refreshIn = expiresAtMs - Date.now() - REFRESH_SKEW_MS;
693
+ if (refreshIn > 0) {
694
+ refreshTimerRef.current = setTimeout(() => {
695
+ void fetch();
696
+ }, refreshIn);
697
+ }
698
+ } catch (err) {
699
+ if (!mountedRef.current) {
700
+ return;
701
+ }
702
+ setError(err instanceof Error ? err : new Error(String(err)));
703
+ setToken(null);
704
+ setIsLoading(false);
705
+ }
706
+ }, [transport]);
707
+ useEffect(() => {
708
+ mountedRef.current = true;
709
+ setIsLoading(true);
710
+ void fetch();
711
+ return () => {
712
+ mountedRef.current = false;
713
+ if (refreshTimerRef.current !== null) {
714
+ clearTimeout(refreshTimerRef.current);
715
+ }
716
+ };
717
+ }, [fetch]);
718
+ return { token, isLoading, error };
719
+ }
720
+
721
+ export { BridgeClientContext, ExtensionRuntimeProvider, createPortBridgeClient, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useBridgeClient, useBridgeLocale, useBridgeTheme, useFrontendSessionToken, useMcpQuery, useMcpResource, useMcpTool };
524
722
  //# sourceMappingURL=index.js.map
525
723
  //# sourceMappingURL=index.js.map