dynim-react 1.0.38 → 1.0.40

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,244 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React, { useState, useEffect, useCallback, useRef } from 'react';
3
- import ReactDOM from 'react-dom';
4
- import { createBundleLoader, BundleNotFoundError, BundleAuthError, isSharedRegistryReady, } from 'dynim-core';
5
- import { createSharedContext } from './sharedContext';
6
- /**
7
- * Default loading component shown while bundle is loading
8
- */
9
- function DefaultLoadingComponent() {
10
- return (_jsx("div", { style: {
11
- display: 'flex',
12
- justifyContent: 'center',
13
- alignItems: 'center',
14
- padding: '20px',
15
- }, children: _jsx("span", { children: "Loading customizations..." }) }));
16
- }
17
- /**
18
- * Default error banner component
19
- */
20
- function DefaultErrorBanner({ error }) {
21
- return (_jsxs("div", { style: {
22
- background: '#fee2e2',
23
- border: '1px solid #ef4444',
24
- borderRadius: '4px',
25
- padding: '12px 16px',
26
- marginBottom: '16px',
27
- color: '#991b1b',
28
- }, children: [_jsx("strong", { children: "Customization Error:" }), " ", error.message] }));
29
- }
30
- /**
31
- * InferenceProvider - A React component that dynamically loads tenant-specific bundles.
32
- *
33
- * This provider handles the lifecycle of loading, rendering, and cleaning up
34
- * tenant customization bundles. It supports optional pre-checks to determine
35
- * if a tenant has customizations before attempting to load them.
36
- *
37
- * Uses createBundleLoader from dynim-core for the actual bundle loading.
38
- *
39
- * @example
40
- * ```tsx
41
- * <InferenceProvider tenantId={user?.tenantId}>
42
- * <YourBaseApp />
43
- * </InferenceProvider>
44
- * ```
45
- */
46
- /** Internal bundle URL pattern - not exposed to users */
47
- const BUNDLE_URL_PATTERN = '/api/bundles/{tenantId}';
48
- export function InferenceProvider({ tenantId, checkCustomizations, loadingComponent, errorBanner = false, onError, onLoad, children, packages = {}, hooks = {}, contexts = {}, }) {
49
- const [state, setState] = useState({
50
- status: 'idle',
51
- error: null,
52
- currentTenantId: null,
53
- });
54
- const [bundleModule, setBundleModule] = useState(null);
55
- // Auto-setup shared context so bundles can access React (only once)
56
- const hasSetupSharedContextRef = useRef(false);
57
- useEffect(() => {
58
- // Only setup if not already done (by this component or BuilderProvider)
59
- if (!hasSetupSharedContextRef.current && !isSharedRegistryReady()) {
60
- createSharedContext({
61
- React,
62
- ReactDOM,
63
- packages,
64
- hooks,
65
- contexts,
66
- });
67
- hasSetupSharedContextRef.current = true;
68
- }
69
- }, []); // Run once on mount
70
- // Bundle loader ref (created once per component instance)
71
- const bundleLoaderRef = useRef(null);
72
- // Get or create the bundle loader (no auth needed - uses session cookies)
73
- const getBundleLoader = useCallback(() => {
74
- if (!bundleLoaderRef.current) {
75
- bundleLoaderRef.current = createBundleLoader({
76
- includeCredentials: true, // Use session cookies for auth
77
- });
78
- }
79
- return bundleLoaderRef.current;
80
- }, []);
81
- /**
82
- * Resolves the bundle URL for a given tenant ID
83
- */
84
- const resolveBundleUrl = useCallback((id) => {
85
- return BUNDLE_URL_PATTERN.replace('{tenantId}', id);
86
- }, []);
87
- /**
88
- * Cleans up previously loaded bundle module
89
- */
90
- const cleanup = useCallback(() => {
91
- if (bundleModule?.cleanup) {
92
- bundleModule.cleanup();
93
- }
94
- setBundleModule(null);
95
- }, [bundleModule]);
96
- /**
97
- * Main effect to handle tenant bundle loading
98
- */
99
- useEffect(() => {
100
- // No tenant - reset to idle and show children
101
- if (!tenantId) {
102
- cleanup();
103
- setState({
104
- status: 'idle',
105
- error: null,
106
- currentTenantId: null,
107
- });
108
- return;
109
- }
110
- // Same tenant already loaded - do nothing
111
- if (state.currentTenantId === tenantId && state.status === 'loaded') {
112
- return;
113
- }
114
- let cancelled = false;
115
- async function loadBundle() {
116
- const loader = getBundleLoader();
117
- try {
118
- // Step 1: Check if tenant has customizations (if check function provided)
119
- if (checkCustomizations) {
120
- setState((prev) => ({ ...prev, status: 'checking' }));
121
- const hasCustomizations = await checkCustomizations(tenantId);
122
- if (cancelled)
123
- return;
124
- if (!hasCustomizations) {
125
- cleanup();
126
- setState({
127
- status: 'no-customization',
128
- error: null,
129
- currentTenantId: tenantId,
130
- });
131
- return;
132
- }
133
- }
134
- // Step 2: Load the bundle using core's bundle loader
135
- setState((prev) => ({ ...prev, status: 'loading' }));
136
- // Clean up previous bundle
137
- cleanup();
138
- const url = resolveBundleUrl(tenantId);
139
- // Load bundle via createBundleLoader from dynim-core
140
- const result = await loader.load(url);
141
- if (cancelled) {
142
- result.cleanup();
143
- return;
144
- }
145
- // Create BundleModule from loader result
146
- const module = {
147
- App: result.App,
148
- cleanup: result.cleanup,
149
- };
150
- setBundleModule(module);
151
- setState({
152
- status: 'loaded',
153
- error: null,
154
- currentTenantId: tenantId,
155
- });
156
- onLoad?.(tenantId);
157
- }
158
- catch (err) {
159
- if (cancelled)
160
- return;
161
- // Convert core errors to appropriate Error instances
162
- let error;
163
- if (err instanceof BundleNotFoundError) {
164
- error = new Error('Bundle not found');
165
- }
166
- else if (err instanceof BundleAuthError) {
167
- error = new Error('Bundle token is invalid or expired');
168
- }
169
- else {
170
- error = err instanceof Error ? err : new Error(String(err));
171
- }
172
- setState({
173
- status: 'error',
174
- error,
175
- currentTenantId: tenantId,
176
- });
177
- onError?.(error, tenantId);
178
- }
179
- }
180
- loadBundle();
181
- return () => {
182
- cancelled = true;
183
- // Abort any in-flight load
184
- const loader = bundleLoaderRef.current;
185
- if (loader?.isLoading()) {
186
- loader.abort();
187
- }
188
- };
189
- }, [
190
- tenantId,
191
- checkCustomizations,
192
- resolveBundleUrl,
193
- cleanup,
194
- onError,
195
- onLoad,
196
- state.currentTenantId,
197
- state.status,
198
- getBundleLoader,
199
- ]);
200
- /**
201
- * Cleanup on unmount
202
- */
203
- useEffect(() => {
204
- return () => {
205
- cleanup();
206
- };
207
- }, [cleanup]);
208
- // Render error banner if enabled and there's an error
209
- const renderErrorBanner = () => {
210
- if (!errorBanner || state.status !== 'error' || !state.error) {
211
- return null;
212
- }
213
- if (errorBanner === true) {
214
- return _jsx(DefaultErrorBanner, { error: state.error });
215
- }
216
- return errorBanner;
217
- };
218
- // Determine what to render based on state
219
- const renderContent = () => {
220
- switch (state.status) {
221
- case 'checking':
222
- case 'loading':
223
- return loadingComponent ?? _jsx(DefaultLoadingComponent, {});
224
- case 'loaded':
225
- // Render the loaded App component directly
226
- if (bundleModule?.App) {
227
- const TenantApp = bundleModule.App;
228
- return _jsx(TenantApp, {});
229
- }
230
- // Fallback if no App component found
231
- return children;
232
- case 'error':
233
- // Show children as fallback with optional error banner
234
- return (_jsxs(_Fragment, { children: [renderErrorBanner(), children] }));
235
- case 'no-customization':
236
- case 'idle':
237
- default:
238
- // No customizations or no tenant - render base app
239
- return children;
240
- }
241
- };
242
- return _jsx(_Fragment, { children: renderContent() });
243
- }
244
- export default InferenceProvider;
@@ -1,6 +0,0 @@
1
- /**
2
- * Inference exports
3
- */
4
- export { createSharedContext, updateSharedContext, getSharedContext, isSharedContextReady, } from './sharedContext';
5
- export type { DynimSDKConfig, DynimGlobal } from './types';
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/inference/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Inference exports
3
- */
4
- // Shared context utilities
5
- export { createSharedContext, updateSharedContext, getSharedContext, isSharedContextReady, } from './sharedContext';