@returningai/widget-sdk 1.7.0 → 1.7.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/CHANGELOG.md +10 -0
- package/dist/rai-banner.iife.js +1 -1
- package/dist/rai-banner.js +1 -1
- package/dist/rai-widget.iife.js +2 -2
- package/dist/rai-widget.js +80 -21
- package/dist/types/core/bundle-runtime-cache.d.ts +20 -0
- package/package.json +7 -2
package/dist/rai-widget.js
CHANGED
|
@@ -12542,6 +12542,80 @@ async function waitForBundleMountReadiness(mountResult, firstPaint, timeoutMs =
|
|
|
12542
12542
|
);
|
|
12543
12543
|
return "deep-ready";
|
|
12544
12544
|
}
|
|
12545
|
+
function isWidgetBundleRuntime(value) {
|
|
12546
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.mount === "function";
|
|
12547
|
+
}
|
|
12548
|
+
function normalizeBundleUrl(url, baseUrl) {
|
|
12549
|
+
const normalized = new URL(url, baseUrl);
|
|
12550
|
+
normalized.hash = "";
|
|
12551
|
+
return normalized.href;
|
|
12552
|
+
}
|
|
12553
|
+
function createBundleRuntimeLoader({
|
|
12554
|
+
loadScript,
|
|
12555
|
+
readGlobal,
|
|
12556
|
+
baseUrl
|
|
12557
|
+
}) {
|
|
12558
|
+
const runtimePromises = /* @__PURE__ */ new Map();
|
|
12559
|
+
const globalLoadTails = /* @__PURE__ */ new Map();
|
|
12560
|
+
return async function getBundleRuntime(globalName, bundleUrl) {
|
|
12561
|
+
const normalizedUrl = normalizeBundleUrl(bundleUrl, baseUrl());
|
|
12562
|
+
const cacheKey = `${globalName}:${normalizedUrl}`;
|
|
12563
|
+
const cachedRuntime = runtimePromises.get(cacheKey);
|
|
12564
|
+
if (cachedRuntime) return cachedRuntime;
|
|
12565
|
+
const previousLoad = globalLoadTails.get(globalName) || Promise.resolve();
|
|
12566
|
+
const runtimePromise = previousLoad.then(async () => {
|
|
12567
|
+
await loadScript(normalizedUrl);
|
|
12568
|
+
const runtime = readGlobal(globalName);
|
|
12569
|
+
if (!isWidgetBundleRuntime(runtime)) {
|
|
12570
|
+
throw new Error(
|
|
12571
|
+
`window.${globalName}.mount not found after loading ${normalizedUrl}`
|
|
12572
|
+
);
|
|
12573
|
+
}
|
|
12574
|
+
const mount = runtime.mount;
|
|
12575
|
+
return {
|
|
12576
|
+
mount(container, config) {
|
|
12577
|
+
return mount.call(runtime, container, config);
|
|
12578
|
+
}
|
|
12579
|
+
};
|
|
12580
|
+
});
|
|
12581
|
+
runtimePromises.set(cacheKey, runtimePromise);
|
|
12582
|
+
const loadTail = runtimePromise.then(
|
|
12583
|
+
() => void 0,
|
|
12584
|
+
() => void 0
|
|
12585
|
+
);
|
|
12586
|
+
globalLoadTails.set(globalName, loadTail);
|
|
12587
|
+
void loadTail.then(() => {
|
|
12588
|
+
if (globalLoadTails.get(globalName) === loadTail) {
|
|
12589
|
+
globalLoadTails.delete(globalName);
|
|
12590
|
+
}
|
|
12591
|
+
});
|
|
12592
|
+
try {
|
|
12593
|
+
return await runtimePromise;
|
|
12594
|
+
} catch (error) {
|
|
12595
|
+
if (runtimePromises.get(cacheKey) === runtimePromise) {
|
|
12596
|
+
runtimePromises.delete(cacheKey);
|
|
12597
|
+
}
|
|
12598
|
+
throw error;
|
|
12599
|
+
}
|
|
12600
|
+
};
|
|
12601
|
+
}
|
|
12602
|
+
function appendScript(url) {
|
|
12603
|
+
return new Promise((resolve, reject) => {
|
|
12604
|
+
const script = document.createElement("script");
|
|
12605
|
+
script.src = url;
|
|
12606
|
+
script.onload = () => resolve();
|
|
12607
|
+
script.onerror = () => reject(new Error(`Failed to load ${url}`));
|
|
12608
|
+
document.head.appendChild(script);
|
|
12609
|
+
});
|
|
12610
|
+
}
|
|
12611
|
+
const loadBrowserBundleRuntime = createBundleRuntimeLoader({
|
|
12612
|
+
loadScript: appendScript,
|
|
12613
|
+
readGlobal: (globalName) => window[globalName],
|
|
12614
|
+
baseUrl: () => document.baseURI
|
|
12615
|
+
});
|
|
12616
|
+
function getOrLoadBundleRuntime(globalName, bundleUrl) {
|
|
12617
|
+
return loadBrowserBundleRuntime(globalName, bundleUrl);
|
|
12618
|
+
}
|
|
12545
12619
|
function assertCallbackName(callbackName) {
|
|
12546
12620
|
if (!callbackName || typeof callbackName !== "string") {
|
|
12547
12621
|
throw new TypeError("ReturningAI callback name must be a non-empty string");
|
|
@@ -12860,15 +12934,6 @@ function resolveWidgetServerUrl(domainKey) {
|
|
|
12860
12934
|
function resolveV2ApiUrl(domainKey) {
|
|
12861
12935
|
return DOMAIN_KEY_TO_V2_API_URL[domainKey] || DOMAIN_KEY_TO_V2_API_URL.PROD;
|
|
12862
12936
|
}
|
|
12863
|
-
function loadScript(url) {
|
|
12864
|
-
return new Promise((resolve, reject) => {
|
|
12865
|
-
const s = document.createElement("script");
|
|
12866
|
-
s.src = url;
|
|
12867
|
-
s.onload = () => resolve();
|
|
12868
|
-
s.onerror = () => reject(new Error(`Failed to load ${url}`));
|
|
12869
|
-
document.head.appendChild(s);
|
|
12870
|
-
});
|
|
12871
|
-
}
|
|
12872
12937
|
const loadedFonts = /* @__PURE__ */ new Set();
|
|
12873
12938
|
function ensureGoogleFontLoaded(family) {
|
|
12874
12939
|
if (!family || loadedFonts.has(family)) return;
|
|
@@ -13718,7 +13783,6 @@ class BaseWidget extends HTMLElement {
|
|
|
13718
13783
|
}
|
|
13719
13784
|
// ── Bundle mode (no-iframe) ──────────────────────────────────────────
|
|
13720
13785
|
async mountWidget(initId) {
|
|
13721
|
-
var _a;
|
|
13722
13786
|
let container = null;
|
|
13723
13787
|
try {
|
|
13724
13788
|
this.teardownMountedWidget();
|
|
@@ -13742,16 +13806,11 @@ class BaseWidget extends HTMLElement {
|
|
|
13742
13806
|
window.loadingAnimation = this.state.loadingAnimation;
|
|
13743
13807
|
}
|
|
13744
13808
|
const globalName = WIDGET_GLOBALS[this.config.widgetType];
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13809
|
+
const widgetGlobal = await getOrLoadBundleRuntime(
|
|
13810
|
+
globalName,
|
|
13811
|
+
this.config.bundleUrl
|
|
13812
|
+
);
|
|
13748
13813
|
if (!this.isCurrentInit(initId)) return;
|
|
13749
|
-
const widgetGlobal = window[globalName];
|
|
13750
|
-
if (!(widgetGlobal == null ? void 0 : widgetGlobal.mount)) {
|
|
13751
|
-
throw new Error(
|
|
13752
|
-
`window.${globalName}.mount not found after loading bundle`
|
|
13753
|
-
);
|
|
13754
|
-
}
|
|
13755
13814
|
container = document.createElement("div");
|
|
13756
13815
|
const hideNestedBundleUntilReady = this.config.widgetType === "custom";
|
|
13757
13816
|
container.className = "rai-widget-root";
|
|
@@ -14007,7 +14066,7 @@ class CustomWidget extends BaseWidget {
|
|
|
14007
14066
|
}
|
|
14008
14067
|
}
|
|
14009
14068
|
}
|
|
14010
|
-
console.log(`[rai-widget] v${"1.7.
|
|
14069
|
+
console.log(`[rai-widget] v${"1.7.1"}`);
|
|
14011
14070
|
class StoreWidgetCompat extends StoreWidget {
|
|
14012
14071
|
}
|
|
14013
14072
|
const WIDGET_REGISTRY = [
|
|
@@ -14071,7 +14130,7 @@ function exposePublicApi() {
|
|
|
14071
14130
|
})();
|
|
14072
14131
|
const widget = container == null ? void 0 : container.querySelector(ALL_WIDGET_SELECTOR);
|
|
14073
14132
|
window.ReturningAIWidget = {
|
|
14074
|
-
version: "1.7.
|
|
14133
|
+
version: "1.7.1",
|
|
14075
14134
|
reload: () => (widget == null ? void 0 : widget.reload()) ?? Promise.resolve(),
|
|
14076
14135
|
logout: () => (widget == null ? void 0 : widget.logoutPublic()) ?? Promise.resolve(),
|
|
14077
14136
|
isAuthenticated: () => (widget == null ? void 0 : widget.isAuthenticated()) ?? false,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface WidgetBundleRuntime {
|
|
2
|
+
mount(container: HTMLElement, config: unknown): unknown;
|
|
3
|
+
}
|
|
4
|
+
interface BundleRuntimeLoaderOptions {
|
|
5
|
+
loadScript: (url: string) => Promise<void>;
|
|
6
|
+
readGlobal: (globalName: string) => unknown;
|
|
7
|
+
baseUrl: () => string;
|
|
8
|
+
}
|
|
9
|
+
export declare function normalizeBundleUrl(url: string, baseUrl: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Cache widget runtimes by both their window global and normalized bundle URL.
|
|
12
|
+
*
|
|
13
|
+
* Different custom-widget bundles intentionally reuse the same global name, so
|
|
14
|
+
* the current value on window is not enough to identify the requested runtime.
|
|
15
|
+
* Capturing the runtime immediately after its script loads also lets A -> B -> A
|
|
16
|
+
* reuse A without re-evaluating its IIFE.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createBundleRuntimeLoader({ loadScript, readGlobal, baseUrl, }: BundleRuntimeLoaderOptions): (globalName: string, bundleUrl: string) => Promise<WidgetBundleRuntime>;
|
|
19
|
+
export declare function getOrLoadBundleRuntime(globalName: string, bundleUrl: string): Promise<WidgetBundleRuntime>;
|
|
20
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@returningai/widget-sdk",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Shadow DOM isolated widget SDK for ReturningAI",
|
|
5
5
|
"main": "dist/rai-widget.iife.js",
|
|
6
6
|
"module": "dist/rai-widget.js",
|
|
@@ -26,13 +26,18 @@
|
|
|
26
26
|
"build:all": "npm run build && npm run build:banner",
|
|
27
27
|
"build:all:min": "npm run build:min && npm run build:banner:min",
|
|
28
28
|
"types": "tsc --emitDeclarationOnly --outDir dist/types && cp src/jsx.d.ts dist/types/jsx.d.ts",
|
|
29
|
-
"test": "npm run test:host-callback && npm run test:bundle-readiness && npm run test:jsx-types",
|
|
29
|
+
"test": "npm run test:host-callback && npm run test:bundle-readiness && npm run test:bundle-runtime-cache && npm run test:jsx-types",
|
|
30
30
|
"test:host-callback": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/postmessage-host-callback.test.js",
|
|
31
31
|
"test:bundle-readiness": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/bundle-readiness.test.js",
|
|
32
|
+
"test:bundle-runtime-cache": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/bundle-runtime-cache.test.js",
|
|
32
33
|
"test:jsx-types": "tsc --noEmit --strict --lib ES2020,DOM --skipLibCheck false src/jsx.d.ts",
|
|
34
|
+
"coverage:repowise": "rm -rf coverage && npm run coverage:host-callback && npm run coverage:bundle-readiness && npm run test:jsx-types",
|
|
35
|
+
"coverage:host-callback": "rm -rf test/.tmp && tsc -p test/tsconfig.json && c8 --reporter=lcov --reports-dir=coverage/host-callback --exclude-after-remap --exclude='**/*.test.ts' node test/.tmp/test/postmessage-host-callback.test.js && node scripts/name-lcov-test.mjs coverage/host-callback/lcov.info test/postmessage-host-callback.test.ts",
|
|
36
|
+
"coverage:bundle-readiness": "rm -rf test/.tmp && tsc -p test/tsconfig.json && c8 --reporter=lcov --reports-dir=coverage/bundle-readiness --exclude-after-remap --exclude='**/*.test.ts' node test/.tmp/test/bundle-readiness.test.js && node scripts/name-lcov-test.mjs coverage/bundle-readiness/lcov.info test/bundle-readiness.test.ts",
|
|
33
37
|
"prepublishOnly": "npm run build:all:min && npm run types"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
40
|
+
"c8": "^11.0.0",
|
|
36
41
|
"terser": "^5.46.0",
|
|
37
42
|
"typescript": "^5.3.3",
|
|
38
43
|
"vite": "^5.1.0"
|