@omni-commerce/sdk 0.6.0 → 0.7.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.
package/dist/react.cjs ADDED
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/react.tsx
22
+ var react_exports = {};
23
+ __export(react_exports, {
24
+ OmniChat: () => OmniChat,
25
+ OmniProvider: () => OmniProvider
26
+ });
27
+ module.exports = __toCommonJS(react_exports);
28
+ var import_react = require("react");
29
+
30
+ // src/embed.ts
31
+ function getOmniChatEmbedUrl(options, parentOrigin) {
32
+ if (!/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i.test(
33
+ options.deploymentId
34
+ ))
35
+ throw new Error("A valid chat deployment ID is required.");
36
+ const base = new URL(options.baseUrl ?? "https://omnicommerce.sg");
37
+ if (base.protocol !== "https:" && !(base.protocol === "http:" && ["localhost", "127.0.0.1"].includes(base.hostname)) || base.username || base.password || base.pathname !== "/" || base.search || base.hash)
38
+ throw new Error("Chat baseUrl must be an HTTPS origin, or HTTP localhost.");
39
+ const url = new URL(`/embed/${options.deploymentId}`, base.origin);
40
+ if (parentOrigin)
41
+ url.searchParams.set("parentOrigin", new URL(parentOrigin).origin);
42
+ return url.toString();
43
+ }
44
+ function createOmniChatEmbed(container, options) {
45
+ const document = container.ownerDocument;
46
+ const host = document.defaultView;
47
+ if (!host) throw new Error("A browser document is required to mount chat.");
48
+ const iframe = document.createElement("iframe");
49
+ iframe.src = getOmniChatEmbedUrl(options, host.location.origin);
50
+ iframe.title = options.title ?? "OmniCommerce assistant";
51
+ iframe.referrerPolicy = "strict-origin-when-cross-origin";
52
+ iframe.setAttribute(
53
+ "sandbox",
54
+ "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
55
+ );
56
+ Object.assign(iframe.style, {
57
+ width: "100%",
58
+ height: "100%",
59
+ minHeight: "320px",
60
+ border: "0",
61
+ display: "block"
62
+ });
63
+ const chatOrigin = new URL(iframe.src).origin;
64
+ let destroyed = false;
65
+ let pending;
66
+ let previousToken;
67
+ const controller = new AbortController();
68
+ const mint = async () => {
69
+ if (options.getSession) return options.getSession();
70
+ const response = await host.fetch(
71
+ `${chatOrigin}/api/embed/${options.deploymentId}/session`,
72
+ {
73
+ method: "POST",
74
+ credentials: "include",
75
+ signal: controller.signal,
76
+ headers: {
77
+ "Content-Type": "application/json",
78
+ ...previousToken ? { Authorization: `Bearer ${previousToken}` } : {}
79
+ },
80
+ body: "{}"
81
+ }
82
+ );
83
+ const result = await response.json();
84
+ if (!response.ok) {
85
+ if (response.status === 401 || response.status === 403)
86
+ previousToken = void 0;
87
+ throw new Error(result.error ?? "Could not open the chat session.");
88
+ }
89
+ return result;
90
+ };
91
+ const receive = (event) => {
92
+ if (destroyed || event.source !== iframe.contentWindow || event.origin !== chatOrigin || event.data?.deploymentId !== options.deploymentId)
93
+ return;
94
+ if (event.data.type === "omni-chat:close-request") {
95
+ options.onRequestClose?.();
96
+ return;
97
+ }
98
+ if (event.data.type !== "omni-chat:session-request") return;
99
+ pending ?? (pending = mint());
100
+ void pending.then((session) => {
101
+ if (destroyed) return;
102
+ if (typeof session?.token !== "string" || !session.token || session.token.length > 4096 || typeof session.threadId !== "string" || !session.threadId || !Number.isFinite(session.expiresIn) || session.expiresIn <= 0)
103
+ throw new Error("Invalid chat session response.");
104
+ previousToken = session.token;
105
+ iframe.contentWindow?.postMessage(
106
+ {
107
+ type: "omni-chat:session",
108
+ deploymentId: options.deploymentId,
109
+ session
110
+ },
111
+ chatOrigin
112
+ );
113
+ }).catch((error) => {
114
+ if (destroyed) return;
115
+ const failure = error instanceof Error ? error : new Error("Could not open chat.");
116
+ options.onError?.(failure);
117
+ iframe.contentWindow?.postMessage(
118
+ {
119
+ type: "omni-chat:session-error",
120
+ deploymentId: options.deploymentId,
121
+ error: failure.message
122
+ },
123
+ chatOrigin
124
+ );
125
+ }).finally(() => {
126
+ pending = void 0;
127
+ });
128
+ };
129
+ host.addEventListener("message", receive);
130
+ container.append(iframe);
131
+ return {
132
+ iframe,
133
+ focus() {
134
+ if (destroyed) return;
135
+ iframe.focus();
136
+ iframe.contentWindow?.postMessage(
137
+ {
138
+ type: "omni-chat:focus-composer",
139
+ deploymentId: options.deploymentId
140
+ },
141
+ chatOrigin
142
+ );
143
+ },
144
+ destroy() {
145
+ if (destroyed) return;
146
+ destroyed = true;
147
+ controller.abort();
148
+ previousToken = void 0;
149
+ host.removeEventListener("message", receive);
150
+ iframe.remove();
151
+ }
152
+ };
153
+ }
154
+
155
+ // src/react.tsx
156
+ var import_jsx_runtime = require("react/jsx-runtime");
157
+ var OmniChatContext = (0, import_react.createContext)(null);
158
+ function OmniProvider({ children, ...options }) {
159
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OmniChatContext.Provider, { value: options, children });
160
+ }
161
+ function OmniChat({ className, style, title }) {
162
+ const options = (0, import_react.useContext)(OmniChatContext);
163
+ if (!options)
164
+ throw new Error("OmniChat must be rendered inside OmniProvider.");
165
+ const container = (0, import_react.useRef)(null);
166
+ const { baseUrl, deploymentId, getSession, onError } = options;
167
+ const callbacks = (0, import_react.useRef)({ getSession, onError });
168
+ (0, import_react.useEffect)(() => {
169
+ callbacks.current = { getSession, onError };
170
+ }, [getSession, onError]);
171
+ const hasSessionBroker = Boolean(getSession);
172
+ const frameTitle = title ?? options.title;
173
+ (0, import_react.useEffect)(() => {
174
+ if (!container.current) return;
175
+ const embed = createOmniChatEmbed(container.current, {
176
+ baseUrl,
177
+ deploymentId,
178
+ getSession: hasSessionBroker ? () => callbacks.current.getSession() : void 0,
179
+ onError: (error) => callbacks.current.onError?.(error),
180
+ title: frameTitle
181
+ });
182
+ return () => embed.destroy();
183
+ }, [baseUrl, deploymentId, frameTitle, hasSessionBroker]);
184
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
185
+ "div",
186
+ {
187
+ ref: container,
188
+ className,
189
+ style: { height: "100%", minHeight: 320, ...style }
190
+ }
191
+ );
192
+ }
193
+ // Annotate the CommonJS export names for ESM import in node:
194
+ 0 && (module.exports = {
195
+ OmniChat,
196
+ OmniProvider
197
+ });
198
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react.tsx","../src/embed.ts"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useEffect,\n useRef,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { createOmniChatEmbed, type OmniChatEmbedOptions } from \"./embed\";\n\nconst OmniChatContext = createContext<OmniChatEmbedOptions | null>(null);\nexport type OmniProviderProps = OmniChatEmbedOptions & { children: ReactNode };\n\nexport function OmniProvider({ children, ...options }: OmniProviderProps) {\n return (\n <OmniChatContext.Provider value={options}>\n {children}\n </OmniChatContext.Provider>\n );\n}\nexport interface OmniChatProps {\n className?: string;\n style?: CSSProperties;\n title?: string;\n}\n/** The hosted assistant owns its styles and runtime, so the host needs no Tailwind or assistant-ui dependencies. */\nexport function OmniChat({ className, style, title }: OmniChatProps) {\n const options = useContext(OmniChatContext);\n if (!options)\n throw new Error(\"OmniChat must be rendered inside OmniProvider.\");\n const container = useRef<HTMLDivElement>(null);\n const { baseUrl, deploymentId, getSession, onError } = options;\n const callbacks = useRef({ getSession, onError });\n useEffect(() => {\n callbacks.current = { getSession, onError };\n }, [getSession, onError]);\n const hasSessionBroker = Boolean(getSession);\n const frameTitle = title ?? options.title;\n useEffect(() => {\n if (!container.current) return;\n const embed = createOmniChatEmbed(container.current, {\n baseUrl,\n deploymentId,\n getSession: hasSessionBroker\n ? () => callbacks.current.getSession!()\n : undefined,\n onError: (error) => callbacks.current.onError?.(error),\n title: frameTitle,\n });\n return () => embed.destroy();\n }, [baseUrl, deploymentId, frameTitle, hasSessionBroker]);\n return (\n <div\n ref={container}\n className={className}\n style={{ height: \"100%\", minHeight: 320, ...style }}\n />\n );\n}\nexport type { OmniChatEmbedOptions, OmniChatSession } from \"./embed\";\n","/** A hosted chat session. Keep its short-lived token in memory, never in iframe URLs. */\nexport { createOmniChatWidget, type OmniChatWidgetOptions } from \"./widget\";\nexport { getOmniChatEmbedCode, getOmniChatReactCode } from \"./embed-code\";\nexport interface OmniChatSession {\n token: string;\n threadId: string;\n expiresIn: number;\n}\nexport interface OmniChatEmbedOptions {\n deploymentId: string;\n baseUrl?: string;\n /** Optional authenticated session mint on the host application's server. */\n getSession?: () => Promise<OmniChatSession>;\n title?: string;\n onError?: (error: Error) => void;\n /** Floating widgets use this to close on Escape from the hosted chat. */\n onRequestClose?: () => void;\n}\nexport interface OmniChatEmbed {\n iframe: HTMLIFrameElement;\n /** Focus the hosted composer, including when reopening a retained chat. */\n focus(): void;\n destroy(): void;\n}\n\nexport function getOmniChatEmbedUrl(\n options: Pick<OmniChatEmbedOptions, \"baseUrl\" | \"deploymentId\">,\n parentOrigin?: string,\n): string {\n if (\n !/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/i.test(\n options.deploymentId,\n )\n )\n throw new Error(\"A valid chat deployment ID is required.\");\n const base = new URL(options.baseUrl ?? \"https://omnicommerce.sg\");\n if (\n (base.protocol !== \"https:\" &&\n !(\n base.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\"].includes(base.hostname)\n )) ||\n base.username ||\n base.password ||\n base.pathname !== \"/\" ||\n base.search ||\n base.hash\n )\n throw new Error(\"Chat baseUrl must be an HTTPS origin, or HTTP localhost.\");\n const url = new URL(`/embed/${options.deploymentId}`, base.origin);\n if (parentOrigin)\n url.searchParams.set(\"parentOrigin\", new URL(parentOrigin).origin);\n return url.toString();\n}\n\n/** Browser-only mounting; importing this entry point is safe during SSR. */\nexport function createOmniChatEmbed(\n container: HTMLElement,\n options: OmniChatEmbedOptions,\n): OmniChatEmbed {\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const iframe = document.createElement(\"iframe\");\n iframe.src = getOmniChatEmbedUrl(options, host.location.origin);\n iframe.title = options.title ?? \"OmniCommerce assistant\";\n iframe.referrerPolicy = \"strict-origin-when-cross-origin\";\n iframe.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\",\n );\n Object.assign(iframe.style, {\n width: \"100%\",\n height: \"100%\",\n minHeight: \"320px\",\n border: \"0\",\n display: \"block\",\n });\n const chatOrigin = new URL(iframe.src).origin;\n let destroyed = false;\n let pending: Promise<OmniChatSession> | undefined;\n let previousToken: string | undefined;\n const controller = new AbortController();\n\n const mint = async (): Promise<OmniChatSession> => {\n if (options.getSession) return options.getSession();\n const response = await host.fetch(\n `${chatOrigin}/api/embed/${options.deploymentId}/session`,\n {\n method: \"POST\",\n credentials: \"include\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(previousToken\n ? { Authorization: `Bearer ${previousToken}` }\n : {}),\n },\n body: \"{}\",\n },\n );\n const result = (await response.json()) as OmniChatSession & {\n error?: string;\n };\n if (!response.ok) {\n // A rejected renewal must not keep Retry bound to an obsolete session.\n // The next mint still performs the deployment's full access checks.\n if (response.status === 401 || response.status === 403)\n previousToken = undefined;\n throw new Error(result.error ?? \"Could not open the chat session.\");\n }\n return result;\n };\n const receive = (event: MessageEvent) => {\n if (\n destroyed ||\n event.source !== iframe.contentWindow ||\n event.origin !== chatOrigin ||\n event.data?.deploymentId !== options.deploymentId\n )\n return;\n if (event.data.type === \"omni-chat:close-request\") {\n options.onRequestClose?.();\n return;\n }\n if (event.data.type !== \"omni-chat:session-request\") return;\n pending ??= mint();\n void pending\n .then((session) => {\n if (destroyed) return;\n if (\n typeof session?.token !== \"string\" ||\n !session.token ||\n session.token.length > 4096 ||\n typeof session.threadId !== \"string\" ||\n !session.threadId ||\n !Number.isFinite(session.expiresIn) ||\n session.expiresIn <= 0\n )\n throw new Error(\"Invalid chat session response.\");\n previousToken = session.token;\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session\",\n deploymentId: options.deploymentId,\n session,\n },\n chatOrigin,\n );\n })\n .catch((error: unknown) => {\n if (destroyed) return;\n const failure =\n error instanceof Error ? error : new Error(\"Could not open chat.\");\n options.onError?.(failure);\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session-error\",\n deploymentId: options.deploymentId,\n error: failure.message,\n },\n chatOrigin,\n );\n })\n .finally(() => {\n pending = undefined;\n });\n };\n host.addEventListener(\"message\", receive);\n container.append(iframe);\n return {\n iframe,\n focus() {\n if (destroyed) return;\n iframe.focus();\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:focus-composer\",\n deploymentId: options.deploymentId,\n },\n chatOrigin,\n );\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n controller.abort();\n previousToken = undefined;\n host.removeEventListener(\"message\", receive);\n iframe.remove();\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,18 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { CSSProperties, ReactNode } from 'react';
3
+ import { OmniChatEmbedOptions } from './embed.cjs';
4
+ export { OmniChatSession } from './embed.cjs';
5
+
6
+ type OmniProviderProps = OmniChatEmbedOptions & {
7
+ children: ReactNode;
8
+ };
9
+ declare function OmniProvider({ children, ...options }: OmniProviderProps): react_jsx_runtime.JSX.Element;
10
+ interface OmniChatProps {
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ title?: string;
14
+ }
15
+ /** The hosted assistant owns its styles and runtime, so the host needs no Tailwind or assistant-ui dependencies. */
16
+ declare function OmniChat({ className, style, title }: OmniChatProps): react_jsx_runtime.JSX.Element;
17
+
18
+ export { OmniChat, OmniChatEmbedOptions, type OmniChatProps, OmniProvider, type OmniProviderProps };
@@ -0,0 +1,18 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { CSSProperties, ReactNode } from 'react';
3
+ import { OmniChatEmbedOptions } from './embed.js';
4
+ export { OmniChatSession } from './embed.js';
5
+
6
+ type OmniProviderProps = OmniChatEmbedOptions & {
7
+ children: ReactNode;
8
+ };
9
+ declare function OmniProvider({ children, ...options }: OmniProviderProps): react_jsx_runtime.JSX.Element;
10
+ interface OmniChatProps {
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ title?: string;
14
+ }
15
+ /** The hosted assistant owns its styles and runtime, so the host needs no Tailwind or assistant-ui dependencies. */
16
+ declare function OmniChat({ className, style, title }: OmniChatProps): react_jsx_runtime.JSX.Element;
17
+
18
+ export { OmniChat, OmniChatEmbedOptions, type OmniChatProps, OmniProvider, type OmniProviderProps };
package/dist/react.js ADDED
@@ -0,0 +1,178 @@
1
+ "use client";
2
+
3
+ // src/react.tsx
4
+ import {
5
+ createContext,
6
+ useContext,
7
+ useEffect,
8
+ useRef
9
+ } from "react";
10
+
11
+ // src/embed.ts
12
+ function getOmniChatEmbedUrl(options, parentOrigin) {
13
+ if (!/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i.test(
14
+ options.deploymentId
15
+ ))
16
+ throw new Error("A valid chat deployment ID is required.");
17
+ const base = new URL(options.baseUrl ?? "https://omnicommerce.sg");
18
+ if (base.protocol !== "https:" && !(base.protocol === "http:" && ["localhost", "127.0.0.1"].includes(base.hostname)) || base.username || base.password || base.pathname !== "/" || base.search || base.hash)
19
+ throw new Error("Chat baseUrl must be an HTTPS origin, or HTTP localhost.");
20
+ const url = new URL(`/embed/${options.deploymentId}`, base.origin);
21
+ if (parentOrigin)
22
+ url.searchParams.set("parentOrigin", new URL(parentOrigin).origin);
23
+ return url.toString();
24
+ }
25
+ function createOmniChatEmbed(container, options) {
26
+ const document = container.ownerDocument;
27
+ const host = document.defaultView;
28
+ if (!host) throw new Error("A browser document is required to mount chat.");
29
+ const iframe = document.createElement("iframe");
30
+ iframe.src = getOmniChatEmbedUrl(options, host.location.origin);
31
+ iframe.title = options.title ?? "OmniCommerce assistant";
32
+ iframe.referrerPolicy = "strict-origin-when-cross-origin";
33
+ iframe.setAttribute(
34
+ "sandbox",
35
+ "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
36
+ );
37
+ Object.assign(iframe.style, {
38
+ width: "100%",
39
+ height: "100%",
40
+ minHeight: "320px",
41
+ border: "0",
42
+ display: "block"
43
+ });
44
+ const chatOrigin = new URL(iframe.src).origin;
45
+ let destroyed = false;
46
+ let pending;
47
+ let previousToken;
48
+ const controller = new AbortController();
49
+ const mint = async () => {
50
+ if (options.getSession) return options.getSession();
51
+ const response = await host.fetch(
52
+ `${chatOrigin}/api/embed/${options.deploymentId}/session`,
53
+ {
54
+ method: "POST",
55
+ credentials: "include",
56
+ signal: controller.signal,
57
+ headers: {
58
+ "Content-Type": "application/json",
59
+ ...previousToken ? { Authorization: `Bearer ${previousToken}` } : {}
60
+ },
61
+ body: "{}"
62
+ }
63
+ );
64
+ const result = await response.json();
65
+ if (!response.ok) {
66
+ if (response.status === 401 || response.status === 403)
67
+ previousToken = void 0;
68
+ throw new Error(result.error ?? "Could not open the chat session.");
69
+ }
70
+ return result;
71
+ };
72
+ const receive = (event) => {
73
+ if (destroyed || event.source !== iframe.contentWindow || event.origin !== chatOrigin || event.data?.deploymentId !== options.deploymentId)
74
+ return;
75
+ if (event.data.type === "omni-chat:close-request") {
76
+ options.onRequestClose?.();
77
+ return;
78
+ }
79
+ if (event.data.type !== "omni-chat:session-request") return;
80
+ pending ?? (pending = mint());
81
+ void pending.then((session) => {
82
+ if (destroyed) return;
83
+ if (typeof session?.token !== "string" || !session.token || session.token.length > 4096 || typeof session.threadId !== "string" || !session.threadId || !Number.isFinite(session.expiresIn) || session.expiresIn <= 0)
84
+ throw new Error("Invalid chat session response.");
85
+ previousToken = session.token;
86
+ iframe.contentWindow?.postMessage(
87
+ {
88
+ type: "omni-chat:session",
89
+ deploymentId: options.deploymentId,
90
+ session
91
+ },
92
+ chatOrigin
93
+ );
94
+ }).catch((error) => {
95
+ if (destroyed) return;
96
+ const failure = error instanceof Error ? error : new Error("Could not open chat.");
97
+ options.onError?.(failure);
98
+ iframe.contentWindow?.postMessage(
99
+ {
100
+ type: "omni-chat:session-error",
101
+ deploymentId: options.deploymentId,
102
+ error: failure.message
103
+ },
104
+ chatOrigin
105
+ );
106
+ }).finally(() => {
107
+ pending = void 0;
108
+ });
109
+ };
110
+ host.addEventListener("message", receive);
111
+ container.append(iframe);
112
+ return {
113
+ iframe,
114
+ focus() {
115
+ if (destroyed) return;
116
+ iframe.focus();
117
+ iframe.contentWindow?.postMessage(
118
+ {
119
+ type: "omni-chat:focus-composer",
120
+ deploymentId: options.deploymentId
121
+ },
122
+ chatOrigin
123
+ );
124
+ },
125
+ destroy() {
126
+ if (destroyed) return;
127
+ destroyed = true;
128
+ controller.abort();
129
+ previousToken = void 0;
130
+ host.removeEventListener("message", receive);
131
+ iframe.remove();
132
+ }
133
+ };
134
+ }
135
+
136
+ // src/react.tsx
137
+ import { jsx } from "react/jsx-runtime";
138
+ var OmniChatContext = createContext(null);
139
+ function OmniProvider({ children, ...options }) {
140
+ return /* @__PURE__ */ jsx(OmniChatContext.Provider, { value: options, children });
141
+ }
142
+ function OmniChat({ className, style, title }) {
143
+ const options = useContext(OmniChatContext);
144
+ if (!options)
145
+ throw new Error("OmniChat must be rendered inside OmniProvider.");
146
+ const container = useRef(null);
147
+ const { baseUrl, deploymentId, getSession, onError } = options;
148
+ const callbacks = useRef({ getSession, onError });
149
+ useEffect(() => {
150
+ callbacks.current = { getSession, onError };
151
+ }, [getSession, onError]);
152
+ const hasSessionBroker = Boolean(getSession);
153
+ const frameTitle = title ?? options.title;
154
+ useEffect(() => {
155
+ if (!container.current) return;
156
+ const embed = createOmniChatEmbed(container.current, {
157
+ baseUrl,
158
+ deploymentId,
159
+ getSession: hasSessionBroker ? () => callbacks.current.getSession() : void 0,
160
+ onError: (error) => callbacks.current.onError?.(error),
161
+ title: frameTitle
162
+ });
163
+ return () => embed.destroy();
164
+ }, [baseUrl, deploymentId, frameTitle, hasSessionBroker]);
165
+ return /* @__PURE__ */ jsx(
166
+ "div",
167
+ {
168
+ ref: container,
169
+ className,
170
+ style: { height: "100%", minHeight: 320, ...style }
171
+ }
172
+ );
173
+ }
174
+ export {
175
+ OmniChat,
176
+ OmniProvider
177
+ };
178
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react.tsx","../src/embed.ts"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useEffect,\n useRef,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { createOmniChatEmbed, type OmniChatEmbedOptions } from \"./embed\";\n\nconst OmniChatContext = createContext<OmniChatEmbedOptions | null>(null);\nexport type OmniProviderProps = OmniChatEmbedOptions & { children: ReactNode };\n\nexport function OmniProvider({ children, ...options }: OmniProviderProps) {\n return (\n <OmniChatContext.Provider value={options}>\n {children}\n </OmniChatContext.Provider>\n );\n}\nexport interface OmniChatProps {\n className?: string;\n style?: CSSProperties;\n title?: string;\n}\n/** The hosted assistant owns its styles and runtime, so the host needs no Tailwind or assistant-ui dependencies. */\nexport function OmniChat({ className, style, title }: OmniChatProps) {\n const options = useContext(OmniChatContext);\n if (!options)\n throw new Error(\"OmniChat must be rendered inside OmniProvider.\");\n const container = useRef<HTMLDivElement>(null);\n const { baseUrl, deploymentId, getSession, onError } = options;\n const callbacks = useRef({ getSession, onError });\n useEffect(() => {\n callbacks.current = { getSession, onError };\n }, [getSession, onError]);\n const hasSessionBroker = Boolean(getSession);\n const frameTitle = title ?? options.title;\n useEffect(() => {\n if (!container.current) return;\n const embed = createOmniChatEmbed(container.current, {\n baseUrl,\n deploymentId,\n getSession: hasSessionBroker\n ? () => callbacks.current.getSession!()\n : undefined,\n onError: (error) => callbacks.current.onError?.(error),\n title: frameTitle,\n });\n return () => embed.destroy();\n }, [baseUrl, deploymentId, frameTitle, hasSessionBroker]);\n return (\n <div\n ref={container}\n className={className}\n style={{ height: \"100%\", minHeight: 320, ...style }}\n />\n );\n}\nexport type { OmniChatEmbedOptions, OmniChatSession } from \"./embed\";\n","/** A hosted chat session. Keep its short-lived token in memory, never in iframe URLs. */\nexport { createOmniChatWidget, type OmniChatWidgetOptions } from \"./widget\";\nexport { getOmniChatEmbedCode, getOmniChatReactCode } from \"./embed-code\";\nexport interface OmniChatSession {\n token: string;\n threadId: string;\n expiresIn: number;\n}\nexport interface OmniChatEmbedOptions {\n deploymentId: string;\n baseUrl?: string;\n /** Optional authenticated session mint on the host application's server. */\n getSession?: () => Promise<OmniChatSession>;\n title?: string;\n onError?: (error: Error) => void;\n /** Floating widgets use this to close on Escape from the hosted chat. */\n onRequestClose?: () => void;\n}\nexport interface OmniChatEmbed {\n iframe: HTMLIFrameElement;\n /** Focus the hosted composer, including when reopening a retained chat. */\n focus(): void;\n destroy(): void;\n}\n\nexport function getOmniChatEmbedUrl(\n options: Pick<OmniChatEmbedOptions, \"baseUrl\" | \"deploymentId\">,\n parentOrigin?: string,\n): string {\n if (\n !/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/i.test(\n options.deploymentId,\n )\n )\n throw new Error(\"A valid chat deployment ID is required.\");\n const base = new URL(options.baseUrl ?? \"https://omnicommerce.sg\");\n if (\n (base.protocol !== \"https:\" &&\n !(\n base.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\"].includes(base.hostname)\n )) ||\n base.username ||\n base.password ||\n base.pathname !== \"/\" ||\n base.search ||\n base.hash\n )\n throw new Error(\"Chat baseUrl must be an HTTPS origin, or HTTP localhost.\");\n const url = new URL(`/embed/${options.deploymentId}`, base.origin);\n if (parentOrigin)\n url.searchParams.set(\"parentOrigin\", new URL(parentOrigin).origin);\n return url.toString();\n}\n\n/** Browser-only mounting; importing this entry point is safe during SSR. */\nexport function createOmniChatEmbed(\n container: HTMLElement,\n options: OmniChatEmbedOptions,\n): OmniChatEmbed {\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const iframe = document.createElement(\"iframe\");\n iframe.src = getOmniChatEmbedUrl(options, host.location.origin);\n iframe.title = options.title ?? \"OmniCommerce assistant\";\n iframe.referrerPolicy = \"strict-origin-when-cross-origin\";\n iframe.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\",\n );\n Object.assign(iframe.style, {\n width: \"100%\",\n height: \"100%\",\n minHeight: \"320px\",\n border: \"0\",\n display: \"block\",\n });\n const chatOrigin = new URL(iframe.src).origin;\n let destroyed = false;\n let pending: Promise<OmniChatSession> | undefined;\n let previousToken: string | undefined;\n const controller = new AbortController();\n\n const mint = async (): Promise<OmniChatSession> => {\n if (options.getSession) return options.getSession();\n const response = await host.fetch(\n `${chatOrigin}/api/embed/${options.deploymentId}/session`,\n {\n method: \"POST\",\n credentials: \"include\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(previousToken\n ? { Authorization: `Bearer ${previousToken}` }\n : {}),\n },\n body: \"{}\",\n },\n );\n const result = (await response.json()) as OmniChatSession & {\n error?: string;\n };\n if (!response.ok) {\n // A rejected renewal must not keep Retry bound to an obsolete session.\n // The next mint still performs the deployment's full access checks.\n if (response.status === 401 || response.status === 403)\n previousToken = undefined;\n throw new Error(result.error ?? \"Could not open the chat session.\");\n }\n return result;\n };\n const receive = (event: MessageEvent) => {\n if (\n destroyed ||\n event.source !== iframe.contentWindow ||\n event.origin !== chatOrigin ||\n event.data?.deploymentId !== options.deploymentId\n )\n return;\n if (event.data.type === \"omni-chat:close-request\") {\n options.onRequestClose?.();\n return;\n }\n if (event.data.type !== \"omni-chat:session-request\") return;\n pending ??= mint();\n void pending\n .then((session) => {\n if (destroyed) return;\n if (\n typeof session?.token !== \"string\" ||\n !session.token ||\n session.token.length > 4096 ||\n typeof session.threadId !== \"string\" ||\n !session.threadId ||\n !Number.isFinite(session.expiresIn) ||\n session.expiresIn <= 0\n )\n throw new Error(\"Invalid chat session response.\");\n previousToken = session.token;\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session\",\n deploymentId: options.deploymentId,\n session,\n },\n chatOrigin,\n );\n })\n .catch((error: unknown) => {\n if (destroyed) return;\n const failure =\n error instanceof Error ? error : new Error(\"Could not open chat.\");\n options.onError?.(failure);\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session-error\",\n deploymentId: options.deploymentId,\n error: failure.message,\n },\n chatOrigin,\n );\n })\n .finally(() => {\n pending = undefined;\n });\n };\n host.addEventListener(\"message\", receive);\n container.append(iframe);\n return {\n iframe,\n focus() {\n if (destroyed) return;\n iframe.focus();\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:focus-composer\",\n deploymentId: options.deploymentId,\n },\n chatOrigin,\n );\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n controller.abort();\n previousToken = undefined;\n host.removeEventListener(\"message\", receive);\n iframe.remove();\n },\n };\n}\n"],"mappings":";;;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;;;ACgBA,SAAS,oBACd,SACA,cACQ;AACR,MACE,CAAC,6DAA6D;AAAA,IAC5D,QAAQ;AAAA,EACV;AAEA,UAAM,IAAI,MAAM,yCAAyC;AAC3D,QAAM,OAAO,IAAI,IAAI,QAAQ,WAAW,yBAAyB;AACjE,MACG,KAAK,aAAa,YACjB,EACE,KAAK,aAAa,WAClB,CAAC,aAAa,WAAW,EAAE,SAAS,KAAK,QAAQ,MAErD,KAAK,YACL,KAAK,YACL,KAAK,aAAa,OAClB,KAAK,UACL,KAAK;AAEL,UAAM,IAAI,MAAM,0DAA0D;AAC5E,QAAM,MAAM,IAAI,IAAI,UAAU,QAAQ,YAAY,IAAI,KAAK,MAAM;AACjE,MAAI;AACF,QAAI,aAAa,IAAI,gBAAgB,IAAI,IAAI,YAAY,EAAE,MAAM;AACnE,SAAO,IAAI,SAAS;AACtB;AAGO,SAAS,oBACd,WACA,SACe;AACf,QAAM,WAAW,UAAU;AAC3B,QAAM,OAAO,SAAS;AACtB,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,+CAA+C;AAC1E,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,MAAM,oBAAoB,SAAS,KAAK,SAAS,MAAM;AAC9D,SAAO,QAAQ,QAAQ,SAAS;AAChC,SAAO,iBAAiB;AACxB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACA,SAAO,OAAO,OAAO,OAAO;AAAA,IAC1B,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,SAAS;AAAA,EACX,CAAC;AACD,QAAM,aAAa,IAAI,IAAI,OAAO,GAAG,EAAE;AACvC,MAAI,YAAY;AAChB,MAAI;AACJ,MAAI;AACJ,QAAM,aAAa,IAAI,gBAAgB;AAEvC,QAAM,OAAO,YAAsC;AACjD,QAAI,QAAQ,WAAY,QAAO,QAAQ,WAAW;AAClD,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B,GAAG,UAAU,cAAc,QAAQ,YAAY;AAAA,MAC/C;AAAA,QACE,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAI,gBACA,EAAE,eAAe,UAAU,aAAa,GAAG,IAC3C,CAAC;AAAA,QACP;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,SAAU,MAAM,SAAS,KAAK;AAGpC,QAAI,CAAC,SAAS,IAAI;AAGhB,UAAI,SAAS,WAAW,OAAO,SAAS,WAAW;AACjD,wBAAgB;AAClB,YAAM,IAAI,MAAM,OAAO,SAAS,kCAAkC;AAAA,IACpE;AACA,WAAO;AAAA,EACT;AACA,QAAM,UAAU,CAAC,UAAwB;AACvC,QACE,aACA,MAAM,WAAW,OAAO,iBACxB,MAAM,WAAW,cACjB,MAAM,MAAM,iBAAiB,QAAQ;AAErC;AACF,QAAI,MAAM,KAAK,SAAS,2BAA2B;AACjD,cAAQ,iBAAiB;AACzB;AAAA,IACF;AACA,QAAI,MAAM,KAAK,SAAS,4BAA6B;AACrD,0BAAY,KAAK;AACjB,SAAK,QACF,KAAK,CAAC,YAAY;AACjB,UAAI,UAAW;AACf,UACE,OAAO,SAAS,UAAU,YAC1B,CAAC,QAAQ,SACT,QAAQ,MAAM,SAAS,QACvB,OAAO,QAAQ,aAAa,YAC5B,CAAC,QAAQ,YACT,CAAC,OAAO,SAAS,QAAQ,SAAS,KAClC,QAAQ,aAAa;AAErB,cAAM,IAAI,MAAM,gCAAgC;AAClD,sBAAgB,QAAQ;AACxB,aAAO,eAAe;AAAA,QACpB;AAAA,UACE,MAAM;AAAA,UACN,cAAc,QAAQ;AAAA,UACtB;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAmB;AACzB,UAAI,UAAW;AACf,YAAM,UACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,sBAAsB;AACnE,cAAQ,UAAU,OAAO;AACzB,aAAO,eAAe;AAAA,QACpB;AAAA,UACE,MAAM;AAAA,UACN,cAAc,QAAQ;AAAA,UACtB,OAAO,QAAQ;AAAA,QACjB;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC,EACA,QAAQ,MAAM;AACb,gBAAU;AAAA,IACZ,CAAC;AAAA,EACL;AACA,OAAK,iBAAiB,WAAW,OAAO;AACxC,YAAU,OAAO,MAAM;AACvB,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AACN,UAAI,UAAW;AACf,aAAO,MAAM;AACb,aAAO,eAAe;AAAA,QACpB;AAAA,UACE,MAAM;AAAA,UACN,cAAc,QAAQ;AAAA,QACxB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AACR,UAAI,UAAW;AACf,kBAAY;AACZ,iBAAW,MAAM;AACjB,sBAAgB;AAChB,WAAK,oBAAoB,WAAW,OAAO;AAC3C,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AACF;;;AD/KI;AALJ,IAAM,kBAAkB,cAA2C,IAAI;AAGhE,SAAS,aAAa,EAAE,UAAU,GAAG,QAAQ,GAAsB;AACxE,SACE,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,SAC9B,UACH;AAEJ;AAOO,SAAS,SAAS,EAAE,WAAW,OAAO,MAAM,GAAkB;AACnE,QAAM,UAAU,WAAW,eAAe;AAC1C,MAAI,CAAC;AACH,UAAM,IAAI,MAAM,gDAAgD;AAClE,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,EAAE,SAAS,cAAc,YAAY,QAAQ,IAAI;AACvD,QAAM,YAAY,OAAO,EAAE,YAAY,QAAQ,CAAC;AAChD,YAAU,MAAM;AACd,cAAU,UAAU,EAAE,YAAY,QAAQ;AAAA,EAC5C,GAAG,CAAC,YAAY,OAAO,CAAC;AACxB,QAAM,mBAAmB,QAAQ,UAAU;AAC3C,QAAM,aAAa,SAAS,QAAQ;AACpC,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,QAAS;AACxB,UAAM,QAAQ,oBAAoB,UAAU,SAAS;AAAA,MACnD;AAAA,MACA;AAAA,MACA,YAAY,mBACR,MAAM,UAAU,QAAQ,WAAY,IACpC;AAAA,MACJ,SAAS,CAAC,UAAU,UAAU,QAAQ,UAAU,KAAK;AAAA,MACrD,OAAO;AAAA,IACT,CAAC;AACD,WAAO,MAAM,MAAM,QAAQ;AAAA,EAC7B,GAAG,CAAC,SAAS,cAAc,YAAY,gBAAgB,CAAC;AACxD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL;AAAA,MACA,OAAO,EAAE,QAAQ,QAAQ,WAAW,KAAK,GAAG,MAAM;AAAA;AAAA,EACpD;AAEJ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omni-commerce/sdk",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "TypeScript SDK for the OmniCommerce API. Generated from the public OpenAPI spec.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -21,7 +21,18 @@
21
21
  },
22
22
  "default": "./dist/index.js"
23
23
  },
24
- "./package.json": "./package.json"
24
+ "./react": {
25
+ "types": "./dist/react.d.ts",
26
+ "import": "./dist/react.js",
27
+ "require": "./dist/react.cjs"
28
+ },
29
+ "./embed": {
30
+ "types": "./dist/embed.d.ts",
31
+ "import": "./dist/embed.js",
32
+ "require": "./dist/embed.cjs"
33
+ },
34
+ "./package.json": "./package.json",
35
+ "./embed.global.js": "./dist/embed.global.js"
25
36
  },
26
37
  "files": [
27
38
  "dist",
@@ -43,6 +54,14 @@
43
54
  "prepublishOnly": "yarn build"
44
55
  },
45
56
  "dependencies": {},
57
+ "peerDependencies": {
58
+ "react": "^18.0.0 || ^19.0.0"
59
+ },
60
+ "peerDependenciesMeta": {
61
+ "react": {
62
+ "optional": true
63
+ }
64
+ },
46
65
  "devDependencies": {
47
66
  "@types/node": "^20",
48
67
  "tsup": "^8.5.1"