@returningai/widget-sdk 1.6.2 → 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 +29 -0
- package/README.md +42 -1
- 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 +1506 -1355
- package/dist/types/BaseWidget.d.ts +12 -21
- package/dist/types/core/bundle-readiness.d.ts +15 -0
- package/dist/types/core/bundle-runtime-cache.d.ts +20 -0
- package/dist/types/core/store-host-callback.d.ts +3 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types.d.ts +38 -2
- package/package.json +8 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ReturningAIWidgetCallback, WidgetConfig } from "./types";
|
|
1
|
+
import type { ReturningAIStoreCallbackFieldOptionsCallback, ReturningAIStorePurchaseSuccessCallback, ReturningAIWidgetCallback, WidgetConfig } from "./types";
|
|
2
|
+
import { STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, STORE_PURCHASE_SUCCESS_CALLBACK_NAME } from "./types";
|
|
2
3
|
export declare function readConfig(el: Element, existingId?: string): WidgetConfig;
|
|
3
4
|
export declare abstract class BaseWidget extends HTMLElement {
|
|
4
5
|
static get observedAttributes(): string[];
|
|
@@ -19,6 +20,8 @@ export declare abstract class BaseWidget extends HTMLElement {
|
|
|
19
20
|
private callbackRegistry;
|
|
20
21
|
private bannerNode;
|
|
21
22
|
constructor();
|
|
23
|
+
registerCallback(callbackName: typeof STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, callback: ReturningAIStoreCallbackFieldOptionsCallback): void;
|
|
24
|
+
registerCallback(callbackName: typeof STORE_PURCHASE_SUCCESS_CALLBACK_NAME, callback: ReturningAIStorePurchaseSuccessCallback): void;
|
|
22
25
|
registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
|
|
23
26
|
lockCallbacks(): void;
|
|
24
27
|
protected abstract buildWidgetUrl(config: WidgetConfig): string;
|
|
@@ -52,15 +55,13 @@ export declare abstract class BaseWidget extends HTMLElement {
|
|
|
52
55
|
private renderShell;
|
|
53
56
|
/**
|
|
54
57
|
* Loads the community loading animation + theme palette from cache or API
|
|
55
|
-
* and renders the animation above the
|
|
56
|
-
* already painted by renderShell so this method only ADDS the animation;
|
|
57
|
-
* users see two states at most: text-only → text + animation.
|
|
58
|
+
* and renders the configured animation above the loading text.
|
|
58
59
|
*
|
|
59
60
|
* Stale-while-revalidate:
|
|
60
61
|
* - Cache hit → apply palette & render animation synchronously, fire
|
|
61
62
|
* background refresh.
|
|
62
|
-
* - Cache miss →
|
|
63
|
-
*
|
|
63
|
+
* - Cache miss → retain the initial shell; await network; apply palette +
|
|
64
|
+
* render the resolved animation or fallback.
|
|
64
65
|
*/
|
|
65
66
|
private fetchAndRenderLoader;
|
|
66
67
|
/**
|
|
@@ -75,22 +76,12 @@ export declare abstract class BaseWidget extends HTMLElement {
|
|
|
75
76
|
private createPresetLoader;
|
|
76
77
|
private hideLoader;
|
|
77
78
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* Strategy:
|
|
83
|
-
* 1. MutationObserver fires when React commits any DOM mutation into
|
|
84
|
-
* the container — synchronous inside mount(), but the callback runs
|
|
85
|
-
* as a microtask, so it observes the first child addition.
|
|
86
|
-
* 2. requestAnimationFrame waits one paint cycle so the React content
|
|
87
|
-
* is actually visible before the SDK loader fades out.
|
|
88
|
-
* 3. 2s fallback covers silent React mount errors so the loader doesn't
|
|
89
|
-
* hang forever.
|
|
90
|
-
*
|
|
91
|
-
* Calls hideLoader() (with its 300ms fade-out) so the transition is smooth.
|
|
79
|
+
* Resolve after a legacy bundle's first rendered child has reached a paint.
|
|
80
|
+
* This remains the fallback for bundles that do not expose a deep-ready
|
|
81
|
+
* handle from mount(). It intentionally does not hide the loader itself so
|
|
82
|
+
* a stronger nested-MFE readiness signal can take ownership of the handoff.
|
|
92
83
|
*/
|
|
93
|
-
private
|
|
84
|
+
private waitForFirstBundlePaint;
|
|
94
85
|
private showError;
|
|
95
86
|
private renderCustomError;
|
|
96
87
|
private resolveBannerApiUrl;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const BUNDLE_READY_TIMEOUT_MS = 30000;
|
|
2
|
+
export interface BundleMountReadyHandle {
|
|
3
|
+
ready: PromiseLike<void>;
|
|
4
|
+
}
|
|
5
|
+
export type BundleMountReadiness = "deep-ready" | "first-paint";
|
|
6
|
+
/**
|
|
7
|
+
* Wait for the strongest readiness signal a bundle provides.
|
|
8
|
+
*
|
|
9
|
+
* Split-bundle loaders may return a promise merely because they dynamically
|
|
10
|
+
* import their app. That promise is not proof that the nested micro-frontend
|
|
11
|
+
* has rendered. A bundle opts into deep readiness by resolving its mount call
|
|
12
|
+
* to an object with a `ready` promise. Legacy bundles keep the first-paint
|
|
13
|
+
* behavior unchanged.
|
|
14
|
+
*/
|
|
15
|
+
export declare function waitForBundleMountReadiness(mountResult: unknown, firstPaint: PromiseLike<void>, timeoutMs?: number): Promise<BundleMountReadiness>;
|
|
@@ -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 {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ReturningAIWidgetCallbacks, StoreCallbackFieldOptionsResult, StoreHostCallbackPayload } from '../types';
|
|
2
|
+
export declare function isSupportedStoreHostCallback(callbackName: string, payload: StoreHostCallbackPayload | null | undefined): boolean;
|
|
3
|
+
export declare function invokeStoreHostCallback(callbacks: ReturningAIWidgetCallbacks, callbackName: string, payload: StoreHostCallbackPayload): Promise<StoreCallbackFieldOptionsResult | undefined>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -18,6 +18,6 @@ declare global {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
export { StoreWidget, ChannelWidget, MilestoneWidget, SocialWidget, CurrencyWidget, ReferralWidget, CustomWidget };
|
|
21
|
-
export type { ReturningAIStoreCallbackFieldOptionsCallback, ReturningAIWidgetCallback, ReturningAIWidgetCallbackRegistration, ReturningAIWidgetActionMessage, ReturningAIWidgetActionResultMessage, ReturningAIWidgetCallbacks, StoreCallbackFieldOptionsContext, StoreCallbackFieldOptionsField, StoreCallbackFieldOptionsFieldType, StoreCallbackFieldOptionsPayload, StoreCallbackFieldOptionsResult, } from './types';
|
|
22
|
-
export { STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, STORE_CALLBACK_FIELD_OPTIONS_SCOPE, STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS, } from './types';
|
|
21
|
+
export type { ReturningAIStoreCallbackFieldOptionsCallback, ReturningAIStoreHostCallbackActionMessage, ReturningAIStorePurchaseSuccessCallback, ReturningAIWidgetCallback, ReturningAIWidgetCallbackRegistration, ReturningAIWidgetActionMessage, ReturningAIWidgetActionResultMessage, ReturningAIWidgetCallbacks, StoreCallbackFieldOptionsContext, StoreCallbackFieldOptionsField, StoreCallbackFieldOptionsFieldType, StoreCallbackFieldOptionsPayload, StoreCallbackFieldOptionsResult, StoreHostCallbackPayload, StorePurchaseSuccessPayload, } from './types';
|
|
22
|
+
export { STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, STORE_CALLBACK_FIELD_OPTIONS_SCOPE, STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS, STORE_PURCHASE_SUCCESS_CALLBACK_NAME, STORE_PURCHASE_SUCCESS_SCOPE, } from './types';
|
|
23
23
|
export type {} from './jsx';
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export declare const STORE_CALLBACK_FIELD_OPTIONS_SCOPE: "store.callback_field_options";
|
|
2
2
|
export declare const STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME: "callbackFieldOptions";
|
|
3
3
|
export declare const STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS = 15000;
|
|
4
|
+
export declare const STORE_PURCHASE_SUCCESS_SCOPE: "store.purchase_success";
|
|
5
|
+
export declare const STORE_PURCHASE_SUCCESS_CALLBACK_NAME: "storePurchaseSuccess";
|
|
4
6
|
export type StoreCallbackFieldOptionsFieldType = 'single-select';
|
|
5
7
|
export interface StoreCallbackFieldOptionsField {
|
|
6
8
|
id: string;
|
|
@@ -21,18 +23,51 @@ export interface StoreCallbackFieldOptionsResult {
|
|
|
21
23
|
fieldOptions: Record<string, string[]>;
|
|
22
24
|
signature?: string;
|
|
23
25
|
}
|
|
26
|
+
export interface StorePurchaseSuccessPayload {
|
|
27
|
+
scope: typeof STORE_PURCHASE_SUCCESS_SCOPE;
|
|
28
|
+
callbackName: typeof STORE_PURCHASE_SUCCESS_CALLBACK_NAME;
|
|
29
|
+
context: {
|
|
30
|
+
event: 'purchased_store_item';
|
|
31
|
+
orderId: string;
|
|
32
|
+
purchaseHistoryId: string;
|
|
33
|
+
server: {
|
|
34
|
+
id: string;
|
|
35
|
+
name?: string | null;
|
|
36
|
+
};
|
|
37
|
+
product: {
|
|
38
|
+
id: string;
|
|
39
|
+
name?: string | null;
|
|
40
|
+
cost: number;
|
|
41
|
+
};
|
|
42
|
+
customer: {
|
|
43
|
+
customIdentifier: string | null;
|
|
44
|
+
};
|
|
45
|
+
coins: {
|
|
46
|
+
beforePurchase: number;
|
|
47
|
+
cost: number;
|
|
48
|
+
afterPurchase: number;
|
|
49
|
+
};
|
|
50
|
+
userInformation?: Record<string, unknown>;
|
|
51
|
+
customRedemptionOption?: Record<string, unknown> | unknown[];
|
|
52
|
+
purchasedAt: string;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export type StoreHostCallbackPayload = StoreCallbackFieldOptionsPayload | StorePurchaseSuccessPayload;
|
|
24
56
|
export type ReturningAIWidgetCallback<TPayload = any, TResult = any> = (payload: TPayload) => Promise<TResult> | TResult;
|
|
25
57
|
export type ReturningAIStoreCallbackFieldOptionsCallback = (payload: StoreCallbackFieldOptionsPayload) => Promise<StoreCallbackFieldOptionsResult> | StoreCallbackFieldOptionsResult;
|
|
58
|
+
export type ReturningAIStorePurchaseSuccessCallback = (payload: StorePurchaseSuccessPayload) => Promise<unknown> | unknown;
|
|
26
59
|
export type ReturningAIWidgetCallbacks = {
|
|
27
60
|
'callbackFieldOptions'?: ReturningAIStoreCallbackFieldOptionsCallback;
|
|
61
|
+
'storePurchaseSuccess'?: ReturningAIStorePurchaseSuccessCallback;
|
|
28
62
|
[callbackName: string]: ReturningAIWidgetCallback | undefined;
|
|
29
63
|
};
|
|
30
64
|
export interface ReturningAIWidgetCallbackRegistration {
|
|
31
65
|
registerCallback(callbackName: typeof STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, callback: ReturningAIStoreCallbackFieldOptionsCallback): void;
|
|
66
|
+
registerCallback(callbackName: typeof STORE_PURCHASE_SUCCESS_CALLBACK_NAME, callback: ReturningAIStorePurchaseSuccessCallback): void;
|
|
32
67
|
registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
|
|
33
68
|
lockCallbacks(): void;
|
|
34
69
|
}
|
|
35
|
-
export interface ReturningAIWidgetActionMessage {
|
|
70
|
+
export interface ReturningAIWidgetActionMessage<TPayload extends StoreHostCallbackPayload = StoreCallbackFieldOptionsPayload> {
|
|
36
71
|
type: 'RETURNINGAI_WIDGET_ACTION';
|
|
37
72
|
requestId: string;
|
|
38
73
|
widgetType: 'store';
|
|
@@ -41,8 +76,9 @@ export interface ReturningAIWidgetActionMessage {
|
|
|
41
76
|
widgetId?: string;
|
|
42
77
|
callbackName: string;
|
|
43
78
|
timeoutMs?: number;
|
|
44
|
-
payload:
|
|
79
|
+
payload: TPayload;
|
|
45
80
|
}
|
|
81
|
+
export type ReturningAIStoreHostCallbackActionMessage = ReturningAIWidgetActionMessage<StoreHostCallbackPayload>;
|
|
46
82
|
export interface ReturningAIWidgetActionResultMessage {
|
|
47
83
|
type: 'RETURNINGAI_WIDGET_ACTION_RESULT';
|
|
48
84
|
requestId: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@returningai/widget-sdk",
|
|
3
|
-
"version": "1.
|
|
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,12 +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: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
|
+
"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",
|
|
31
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",
|
|
32
37
|
"prepublishOnly": "npm run build:all:min && npm run types"
|
|
33
38
|
},
|
|
34
39
|
"devDependencies": {
|
|
40
|
+
"c8": "^11.0.0",
|
|
35
41
|
"terser": "^5.46.0",
|
|
36
42
|
"typescript": "^5.3.3",
|
|
37
43
|
"vite": "^5.1.0"
|