@oceanum/eidos 0.9.1 → 0.9.2
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/index.cjs +8 -0
- package/dist/index.js +4631 -0
- package/package.json +4 -1
- package/index.html +0 -13
- package/project.json +0 -4
- package/scripts/debug-schema.js +0 -30
- package/scripts/generate-interfaces.js +0 -48
- package/scripts/schema-bundler.js +0 -609
- package/scripts/schema-to-typescript.js +0 -604
- package/src/index.ts +0 -7
- package/src/lib/eidosmodel.ts +0 -46
- package/src/lib/react.tsx +0 -70
- package/src/lib/render.ts +0 -176
- package/src/schema/interfaces.ts +0 -1171
- package/test-example.js +0 -64
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -25
- package/tsconfig.spec.json +0 -31
- package/vite.config.ts +0 -44
- /package/{public → dist}/favicon.ico +0 -0
package/src/lib/react.tsx
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext, useEffect, useRef, useState, ReactNode } from 'react';
|
|
2
|
-
import { useSnapshot } from 'valtio';
|
|
3
|
-
import { Proxy } from 'valtio/vanilla';
|
|
4
|
-
import { EidosSpec } from '../schema/interfaces';
|
|
5
|
-
import { render, RenderOptions } from './render';
|
|
6
|
-
|
|
7
|
-
// Context to hold the EIDOS spec proxy
|
|
8
|
-
const EidosSpecContext = createContext<Proxy<EidosSpec> | null>(null);
|
|
9
|
-
|
|
10
|
-
// Hook to get the spec proxy from context
|
|
11
|
-
// Can be used for both reading and mutations - valtio tracks reads automatically
|
|
12
|
-
export const useEidosSpec = () => {
|
|
13
|
-
const spec = useContext(EidosSpecContext);
|
|
14
|
-
if (!spec) {
|
|
15
|
-
throw new Error('useEidosSpec must be used within an EidosProvider');
|
|
16
|
-
}
|
|
17
|
-
return spec;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// Props for the EidosProvider component
|
|
21
|
-
interface EidosProviderProps {
|
|
22
|
-
children: ReactNode;
|
|
23
|
-
initialSpec: EidosSpec;
|
|
24
|
-
options?: Omit<RenderOptions, 'id'>;
|
|
25
|
-
containerStyle?: React.CSSProperties;
|
|
26
|
-
onInitialized?: (spec: Proxy<EidosSpec>) => void;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Provider component that renders EIDOS and provides spec to children
|
|
30
|
-
export const EidosProvider = ({
|
|
31
|
-
children,
|
|
32
|
-
initialSpec,
|
|
33
|
-
options = {},
|
|
34
|
-
containerStyle = { width: '100%', height: '100%', position: 'absolute' },
|
|
35
|
-
onInitialized,
|
|
36
|
-
}: EidosProviderProps) => {
|
|
37
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
38
|
-
const [spec, setSpec] = useState<Proxy<EidosSpec> | null>(null);
|
|
39
|
-
const initializedRef = useRef(false);
|
|
40
|
-
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
if (!containerRef.current || initializedRef.current) return;
|
|
43
|
-
|
|
44
|
-
initializedRef.current = true;
|
|
45
|
-
|
|
46
|
-
const initEidos = async () => {
|
|
47
|
-
try {
|
|
48
|
-
const result = await render(containerRef.current!, initialSpec, options);
|
|
49
|
-
setSpec(result.spec);
|
|
50
|
-
onInitialized?.(result.spec);
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error('Failed to initialize EIDOS:', error);
|
|
53
|
-
initializedRef.current = false;
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
initEidos();
|
|
58
|
-
}, [initialSpec, options, onInitialized]);
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<div style={{ position: 'relative', width: '100%', height: '100%' }}>
|
|
62
|
-
<div ref={containerRef} style={containerStyle} />
|
|
63
|
-
{spec && (
|
|
64
|
-
<EidosSpecContext.Provider value={spec}>
|
|
65
|
-
{children}
|
|
66
|
-
</EidosSpecContext.Provider>
|
|
67
|
-
)}
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
};
|
package/src/lib/render.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { proxy, subscribe, snapshot, Proxy } from 'valtio/vanilla';
|
|
2
|
-
import { validateSchema } from './eidosmodel';
|
|
3
|
-
import { EidosSpec } from '../schema/interfaces';
|
|
4
|
-
|
|
5
|
-
const DEFAULT_RENDERER = 'https://render.eidos.oceanum.io';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Options for rendering an EIDOS spec
|
|
9
|
-
*/
|
|
10
|
-
export interface RenderOptions {
|
|
11
|
-
/** The unique identifier for the EIDOS spec (optional, defaults to spec.id) */
|
|
12
|
-
id?: string;
|
|
13
|
-
/** Optional callback for handling events from the renderer */
|
|
14
|
-
eventListener?: (payload: unknown) => void;
|
|
15
|
-
/** URL of the EIDOS renderer */
|
|
16
|
-
renderer?: string;
|
|
17
|
-
/** Authentication token to pass to the renderer for data fetching */
|
|
18
|
-
authToken?: string | (() => string | Promise<string>);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Result from the render function
|
|
23
|
-
*/
|
|
24
|
-
export interface RenderResult {
|
|
25
|
-
/** The reactive EIDOS spec proxy */
|
|
26
|
-
spec: Proxy<EidosSpec>;
|
|
27
|
-
/** Update the auth token sent to the renderer */
|
|
28
|
-
updateAuth: (
|
|
29
|
-
token: string | (() => string | Promise<string>),
|
|
30
|
-
) => Promise<void>;
|
|
31
|
-
/** The iframe element */
|
|
32
|
-
iframe: HTMLIFrameElement;
|
|
33
|
-
/** Destroy the renderer and clean up resources */
|
|
34
|
-
destroy: () => void;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Embed the EIDOS iframe and set up message passing
|
|
39
|
-
* @param element HTML element to render the EIDOS spec into
|
|
40
|
-
* @param spec The EIDOS specification object
|
|
41
|
-
* @param options Render options including id, eventListener, renderer URL, and authToken
|
|
42
|
-
* @returns A RenderResult object containing the spec proxy and control methods
|
|
43
|
-
*/
|
|
44
|
-
const render = async (
|
|
45
|
-
element: HTMLElement,
|
|
46
|
-
spec: EidosSpec,
|
|
47
|
-
options: RenderOptions = {},
|
|
48
|
-
): Promise<RenderResult> => {
|
|
49
|
-
const { id, eventListener, renderer = DEFAULT_RENDERER, authToken } = options;
|
|
50
|
-
|
|
51
|
-
// Check if this container is already initialized
|
|
52
|
-
// We check both for an existing iframe and a marker on the container itself
|
|
53
|
-
// This prevents double-mounting even if destroy() was called but the container is being reused
|
|
54
|
-
const existingIframe = element.querySelector('iframe[data-eidos-renderer]');
|
|
55
|
-
const isInitialized = element.getAttribute('data-eidos-initialized') === 'true';
|
|
56
|
-
|
|
57
|
-
if (existingIframe || isInitialized) {
|
|
58
|
-
throw new Error('EIDOS renderer already mounted in this container. Call destroy() before re-rendering.');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Mark container as initialized
|
|
62
|
-
element.setAttribute('data-eidos-initialized', 'true');
|
|
63
|
-
|
|
64
|
-
// Validate the spec before creating proxy
|
|
65
|
-
try {
|
|
66
|
-
await validateSchema(spec);
|
|
67
|
-
} catch (e: any) {
|
|
68
|
-
throw new Error(`Invalid Eidos Spec: ${e.message}`);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Create Valtio proxy - naturally mutable, no unprotect needed
|
|
72
|
-
const eidos = proxy(structuredClone(spec));
|
|
73
|
-
const _id = id || spec.id;
|
|
74
|
-
|
|
75
|
-
return new Promise((resolve, reject) => {
|
|
76
|
-
const iframe = document.createElement('iframe');
|
|
77
|
-
iframe.src = `${renderer}?id=${_id}`;
|
|
78
|
-
iframe.width = '100%';
|
|
79
|
-
iframe.height = '100%';
|
|
80
|
-
iframe.frameBorder = '0';
|
|
81
|
-
// Mark this as an EIDOS iframe for duplicate detection
|
|
82
|
-
iframe.setAttribute('data-eidos-renderer', 'true');
|
|
83
|
-
element.appendChild(iframe);
|
|
84
|
-
|
|
85
|
-
let messageHandler: ((event: MessageEvent) => void) | null = null;
|
|
86
|
-
let unsubscribe: (() => void) | null = null;
|
|
87
|
-
|
|
88
|
-
iframe.onload = () => {
|
|
89
|
-
const win = iframe.contentWindow;
|
|
90
|
-
|
|
91
|
-
// Helper to send auth token to iframe
|
|
92
|
-
const sendAuth = async (
|
|
93
|
-
token: string | (() => string | Promise<string>),
|
|
94
|
-
) => {
|
|
95
|
-
const resolvedToken =
|
|
96
|
-
typeof token === 'function' ? await token() : token;
|
|
97
|
-
win?.postMessage(
|
|
98
|
-
{
|
|
99
|
-
id: _id,
|
|
100
|
-
type: 'auth',
|
|
101
|
-
payload: resolvedToken,
|
|
102
|
-
},
|
|
103
|
-
'*',
|
|
104
|
-
);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
messageHandler = (event: MessageEvent) => {
|
|
108
|
-
if (event.source !== win) return;
|
|
109
|
-
|
|
110
|
-
// Check ID only if both message and expected ID exist
|
|
111
|
-
// Some EIDOS renderers may not include ID in event messages
|
|
112
|
-
if (event.data.id && event.data.id !== _id) return;
|
|
113
|
-
|
|
114
|
-
if (event.data.type === 'init') {
|
|
115
|
-
// Send initial spec
|
|
116
|
-
win?.postMessage(
|
|
117
|
-
{
|
|
118
|
-
id: _id,
|
|
119
|
-
type: 'spec',
|
|
120
|
-
payload: structuredClone(eidos),
|
|
121
|
-
},
|
|
122
|
-
'*',
|
|
123
|
-
);
|
|
124
|
-
// Send auth token on init if provided
|
|
125
|
-
if (authToken) {
|
|
126
|
-
sendAuth(authToken);
|
|
127
|
-
}
|
|
128
|
-
} else if (event.data.type || event.data.action || event.data.control) {
|
|
129
|
-
// Process as event - EIDOS events may not have 'type' but have 'action' and 'control'
|
|
130
|
-
eventListener?.(event.data);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
window.addEventListener('message', messageHandler);
|
|
134
|
-
|
|
135
|
-
// Subscribe to changes and send patches to renderer
|
|
136
|
-
unsubscribe = subscribe(eidos, () => {
|
|
137
|
-
win?.postMessage(
|
|
138
|
-
{
|
|
139
|
-
id: _id,
|
|
140
|
-
type: 'spec',
|
|
141
|
-
payload: snapshot(eidos),
|
|
142
|
-
},
|
|
143
|
-
'*',
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Send initial auth token if provided (in case init already happened)
|
|
148
|
-
if (authToken) {
|
|
149
|
-
sendAuth(authToken);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
resolve({
|
|
153
|
-
spec: eidos,
|
|
154
|
-
updateAuth: sendAuth,
|
|
155
|
-
iframe,
|
|
156
|
-
destroy: () => {
|
|
157
|
-
if (messageHandler) {
|
|
158
|
-
window.removeEventListener('message', messageHandler);
|
|
159
|
-
}
|
|
160
|
-
if (unsubscribe) {
|
|
161
|
-
unsubscribe();
|
|
162
|
-
}
|
|
163
|
-
iframe.remove();
|
|
164
|
-
// Clear the initialization marker when explicitly destroyed
|
|
165
|
-
element.removeAttribute('data-eidos-initialized');
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
iframe.onerror = () => {
|
|
171
|
-
reject(new Error('Failed to load EIDOS renderer'));
|
|
172
|
-
};
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
export { render };
|