From 4b102638c2980b35540fced78193a9c13481b16d Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 26 Mar 2025 22:46:59 +0100 Subject: [PATCH 1/3] feat(sdk-js): add option to manually provide implementation for shared modules --- libs/sdk-js/src/react-ui/client.tsx | 13 +++++++++++++ libs/sdk-js/src/react-ui/index.ts | 6 +++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libs/sdk-js/src/react-ui/client.tsx b/libs/sdk-js/src/react-ui/client.tsx index 6c8804d72..2edcfe0aa 100644 --- a/libs/sdk-js/src/react-ui/client.tsx +++ b/libs/sdk-js/src/react-ui/client.tsx @@ -109,6 +109,7 @@ class ComponentStore { const COMPONENT_STORE = new ComponentStore(); const EXT_STORE_SYMBOL = Symbol.for("LGUI_EXT_STORE"); const REQUIRE_SYMBOL = Symbol.for("LGUI_REQUIRE"); +const REQUIRE_EXTRA_SYMBOL = Symbol.for("LGUI_REQUIRE_EXTRA"); interface LoadExternalComponentProps extends Pick, "style" | "className"> { @@ -197,9 +198,17 @@ declare global { interface Window { [EXT_STORE_SYMBOL]: ComponentStore; [REQUIRE_SYMBOL]: (name: string) => unknown; + [REQUIRE_EXTRA_SYMBOL]: Record; } } +export function experimental_loadShare(name: string, module: unknown) { + if (typeof window === "undefined") { + throw new Error("Cannot register module in server context"); + } + window[REQUIRE_EXTRA_SYMBOL][name] = module; +} + export function bootstrapUiContext() { if (typeof window === "undefined") { console.warn( @@ -224,6 +233,10 @@ export function bootstrapUiContext() { }; } + if (name in window[REQUIRE_EXTRA_SYMBOL]) { + return window[REQUIRE_EXTRA_SYMBOL][name]; + } + throw new Error(`Unknown module...: ${name}`); }; } diff --git a/libs/sdk-js/src/react-ui/index.ts b/libs/sdk-js/src/react-ui/index.ts index 902adecee..e54ce73e6 100644 --- a/libs/sdk-js/src/react-ui/index.ts +++ b/libs/sdk-js/src/react-ui/index.ts @@ -1,7 +1,11 @@ import { bootstrapUiContext } from "./client.js"; bootstrapUiContext(); -export { useStreamContext, LoadExternalComponent } from "./client.js"; +export { + useStreamContext, + LoadExternalComponent, + experimental_loadShare, +} from "./client.js"; export { uiMessageReducer, type UIMessage, From 5cdab86d48bb6440540662e3bb05299d81d289bb Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Thu, 27 Mar 2025 20:58:39 +0100 Subject: [PATCH 2/3] Fix object assignment --- libs/sdk-js/src/react-ui/client.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/sdk-js/src/react-ui/client.tsx b/libs/sdk-js/src/react-ui/client.tsx index 2edcfe0aa..4ede43aa2 100644 --- a/libs/sdk-js/src/react-ui/client.tsx +++ b/libs/sdk-js/src/react-ui/client.tsx @@ -206,6 +206,8 @@ export function experimental_loadShare(name: string, module: unknown) { if (typeof window === "undefined") { throw new Error("Cannot register module in server context"); } + + window[REQUIRE_EXTRA_SYMBOL] ??= {}; window[REQUIRE_EXTRA_SYMBOL][name] = module; } @@ -233,7 +235,11 @@ export function bootstrapUiContext() { }; } - if (name in window[REQUIRE_EXTRA_SYMBOL]) { + if ( + window[REQUIRE_EXTRA_SYMBOL] != null && + typeof window[REQUIRE_EXTRA_SYMBOL] === "object" && + name in window[REQUIRE_EXTRA_SYMBOL] + ) { return window[REQUIRE_EXTRA_SYMBOL][name]; } From 3ba7c7fbed17bcc5e1c80e4d7f55f347fcb18a37 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Thu, 27 Mar 2025 21:03:54 +0100 Subject: [PATCH 3/3] Do not throw error if window is undefined due to Next --- libs/sdk-js/src/react-ui/client.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/sdk-js/src/react-ui/client.tsx b/libs/sdk-js/src/react-ui/client.tsx index 4ede43aa2..ab5d4abe0 100644 --- a/libs/sdk-js/src/react-ui/client.tsx +++ b/libs/sdk-js/src/react-ui/client.tsx @@ -203,9 +203,7 @@ declare global { } export function experimental_loadShare(name: string, module: unknown) { - if (typeof window === "undefined") { - throw new Error("Cannot register module in server context"); - } + if (typeof window === "undefined") return; window[REQUIRE_EXTRA_SYMBOL] ??= {}; window[REQUIRE_EXTRA_SYMBOL][name] = module;