@almadar/ui 4.10.7 → 4.11.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/avl/index.cjs +66 -35
- package/dist/avl/index.js +66 -35
- package/dist/runtime/BrowserPlayground.d.ts +34 -0
- package/dist/runtime/OrbPreview.d.ts +8 -1
- package/dist/runtime/ServerBridge.d.ts +58 -2
- package/dist/runtime/index.cjs +114 -39
- package/dist/runtime/index.d.ts +2 -1
- package/dist/runtime/index.js +114 -40
- package/package.json +2 -2
package/dist/avl/index.cjs
CHANGED
|
@@ -52200,6 +52200,38 @@ init_EntitySchemaContext();
|
|
|
52200
52200
|
init_useEventBus();
|
|
52201
52201
|
init_logger();
|
|
52202
52202
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
52203
|
+
function createHttpTransport(serverUrl) {
|
|
52204
|
+
return {
|
|
52205
|
+
register: async (schema) => {
|
|
52206
|
+
try {
|
|
52207
|
+
const res = await fetch(`${serverUrl}/register`, {
|
|
52208
|
+
method: "POST",
|
|
52209
|
+
headers: { "Content-Type": "application/json" },
|
|
52210
|
+
body: JSON.stringify({ schema })
|
|
52211
|
+
});
|
|
52212
|
+
const result = await res.json();
|
|
52213
|
+
return !!result.success;
|
|
52214
|
+
} catch (err) {
|
|
52215
|
+
console.error("[ServerBridge] Registration failed:", err);
|
|
52216
|
+
return false;
|
|
52217
|
+
}
|
|
52218
|
+
},
|
|
52219
|
+
unregister: async () => {
|
|
52220
|
+
try {
|
|
52221
|
+
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
52222
|
+
} catch {
|
|
52223
|
+
}
|
|
52224
|
+
},
|
|
52225
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
52226
|
+
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
52227
|
+
method: "POST",
|
|
52228
|
+
headers: { "Content-Type": "application/json" },
|
|
52229
|
+
body: JSON.stringify({ event, payload })
|
|
52230
|
+
});
|
|
52231
|
+
return res.json();
|
|
52232
|
+
}
|
|
52233
|
+
};
|
|
52234
|
+
}
|
|
52203
52235
|
var ServerBridgeContext = React128.createContext(null);
|
|
52204
52236
|
function useServerBridge() {
|
|
52205
52237
|
const ctx = React128.useContext(ServerBridgeContext);
|
|
@@ -52212,40 +52244,34 @@ function useServerBridge() {
|
|
|
52212
52244
|
function ServerBridgeProvider({
|
|
52213
52245
|
schema,
|
|
52214
52246
|
serverUrl,
|
|
52247
|
+
transport: customTransport,
|
|
52215
52248
|
children
|
|
52216
52249
|
}) {
|
|
52250
|
+
if (!serverUrl && !customTransport) {
|
|
52251
|
+
throw new Error("ServerBridgeProvider requires either serverUrl or transport");
|
|
52252
|
+
}
|
|
52253
|
+
if (serverUrl && customTransport) {
|
|
52254
|
+
throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
|
|
52255
|
+
}
|
|
52217
52256
|
const eventBus = useEventBus();
|
|
52218
52257
|
const [connected, setConnected] = React128.useState(false);
|
|
52219
|
-
const
|
|
52220
|
-
|
|
52221
|
-
|
|
52222
|
-
|
|
52223
|
-
|
|
52224
|
-
|
|
52225
|
-
|
|
52226
|
-
|
|
52227
|
-
|
|
52228
|
-
|
|
52229
|
-
|
|
52230
|
-
|
|
52231
|
-
}
|
|
52232
|
-
}, [schema, serverUrl]);
|
|
52233
|
-
const unregisterSchema = React128.useCallback(async () => {
|
|
52234
|
-
try {
|
|
52235
|
-
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
52236
|
-
} catch {
|
|
52237
|
-
}
|
|
52238
|
-
}, [serverUrl]);
|
|
52258
|
+
const transport = React128.useMemo(
|
|
52259
|
+
() => customTransport ?? createHttpTransport(serverUrl),
|
|
52260
|
+
[serverUrl, customTransport]
|
|
52261
|
+
);
|
|
52262
|
+
const registerSchema = React128.useCallback(
|
|
52263
|
+
async () => transport.register(schema),
|
|
52264
|
+
[schema, transport]
|
|
52265
|
+
);
|
|
52266
|
+
const unregisterSchema = React128.useCallback(
|
|
52267
|
+
async () => transport.unregister(),
|
|
52268
|
+
[transport]
|
|
52269
|
+
);
|
|
52239
52270
|
const sendEvent = React128.useCallback(async (orbitalName, event, payload) => {
|
|
52240
52271
|
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
52241
52272
|
if (!connected) return { effects: [], meta: emptyMeta };
|
|
52242
52273
|
try {
|
|
52243
|
-
const
|
|
52244
|
-
method: "POST",
|
|
52245
|
-
headers: { "Content-Type": "application/json" },
|
|
52246
|
-
body: JSON.stringify({ event, payload })
|
|
52247
|
-
});
|
|
52248
|
-
const result = await res.json();
|
|
52274
|
+
const result = await transport.sendEvent(orbitalName, event, payload);
|
|
52249
52275
|
const effects = [];
|
|
52250
52276
|
const responseData = result.data || {};
|
|
52251
52277
|
const dataEntities = {};
|
|
@@ -52303,7 +52329,7 @@ function ServerBridgeProvider({
|
|
|
52303
52329
|
console.error("[ServerBridge] Event send failed:", err);
|
|
52304
52330
|
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
52305
52331
|
}
|
|
52306
|
-
}, [connected,
|
|
52332
|
+
}, [connected, transport, eventBus]);
|
|
52307
52333
|
React128.useEffect(() => {
|
|
52308
52334
|
if (!schema) return;
|
|
52309
52335
|
let cancelled = false;
|
|
@@ -52579,7 +52605,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52579
52605
|
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
|
|
52580
52606
|
return null;
|
|
52581
52607
|
}
|
|
52582
|
-
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
52608
|
+
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
52583
52609
|
const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
|
|
52584
52610
|
const allPageTraits = React128.useMemo(() => {
|
|
52585
52611
|
if (pageName && traits2.length > 0) return traits2;
|
|
@@ -52693,7 +52719,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
52693
52719
|
TraitInitializer,
|
|
52694
52720
|
{
|
|
52695
52721
|
traits: allPageTraits,
|
|
52696
|
-
orbitalNames: serverUrl ? pageOrbitalNames : void 0,
|
|
52722
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
52697
52723
|
traitConfigsByName,
|
|
52698
52724
|
orbitalsByTrait,
|
|
52699
52725
|
onNavigate,
|
|
@@ -52706,8 +52732,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
52706
52732
|
]
|
|
52707
52733
|
}
|
|
52708
52734
|
) }) });
|
|
52709
|
-
if (serverUrl) {
|
|
52710
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
|
|
52735
|
+
if (serverUrl || transport) {
|
|
52736
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
|
|
52711
52737
|
}
|
|
52712
52738
|
return inner;
|
|
52713
52739
|
}
|
|
@@ -52718,8 +52744,12 @@ function OrbPreview({
|
|
|
52718
52744
|
height = "400px",
|
|
52719
52745
|
className,
|
|
52720
52746
|
serverUrl,
|
|
52747
|
+
transport,
|
|
52721
52748
|
initialPagePath
|
|
52722
52749
|
}) {
|
|
52750
|
+
if (serverUrl && transport) {
|
|
52751
|
+
throw new Error("OrbPreview accepts serverUrl OR transport, not both");
|
|
52752
|
+
}
|
|
52723
52753
|
const [localFallback, setLocalFallback] = React128.useState(false);
|
|
52724
52754
|
const eventBus = useEventBus();
|
|
52725
52755
|
const handleLocalFallback = React128.useCallback(() => {
|
|
@@ -52741,21 +52771,21 @@ function OrbPreview({
|
|
|
52741
52771
|
} else {
|
|
52742
52772
|
parsed = schema;
|
|
52743
52773
|
}
|
|
52744
|
-
if (autoMock && !serverUrl) {
|
|
52774
|
+
if (autoMock && !serverUrl && !transport) {
|
|
52745
52775
|
const prepared = prepareSchemaForPreview(parsed);
|
|
52746
52776
|
return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
|
|
52747
52777
|
}
|
|
52748
52778
|
return { ok: true, schema: parsed, mockData: mockData ?? {} };
|
|
52749
|
-
}, [schema, autoMock, serverUrl, mockData]);
|
|
52779
|
+
}, [schema, autoMock, serverUrl, transport, mockData]);
|
|
52750
52780
|
const parsedSchema = parseResult.ok ? parseResult.schema : null;
|
|
52751
52781
|
const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
|
|
52752
52782
|
const persistence = React128.useMemo(() => {
|
|
52753
|
-
if (!parsedSchema || serverUrl) return void 0;
|
|
52783
|
+
if (!parsedSchema || serverUrl || transport) return void 0;
|
|
52754
52784
|
if (!autoMock) return void 0;
|
|
52755
52785
|
const adapter = new runtime.InMemoryPersistence();
|
|
52756
52786
|
adapter.seed(effectiveMockData);
|
|
52757
52787
|
return adapter;
|
|
52758
|
-
}, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
|
|
52788
|
+
}, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
|
|
52759
52789
|
const pages = React128.useMemo(() => {
|
|
52760
52790
|
if (!parsedSchema) return [];
|
|
52761
52791
|
try {
|
|
@@ -52817,6 +52847,7 @@ function OrbPreview({
|
|
|
52817
52847
|
{
|
|
52818
52848
|
schema: parsedSchema,
|
|
52819
52849
|
serverUrl,
|
|
52850
|
+
transport,
|
|
52820
52851
|
mockData: effectiveMockData,
|
|
52821
52852
|
pageName: currentPage,
|
|
52822
52853
|
onNavigate: handleNavigate,
|
package/dist/avl/index.js
CHANGED
|
@@ -52154,6 +52154,38 @@ init_EntitySchemaContext();
|
|
|
52154
52154
|
init_useEventBus();
|
|
52155
52155
|
init_logger();
|
|
52156
52156
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
52157
|
+
function createHttpTransport(serverUrl) {
|
|
52158
|
+
return {
|
|
52159
|
+
register: async (schema) => {
|
|
52160
|
+
try {
|
|
52161
|
+
const res = await fetch(`${serverUrl}/register`, {
|
|
52162
|
+
method: "POST",
|
|
52163
|
+
headers: { "Content-Type": "application/json" },
|
|
52164
|
+
body: JSON.stringify({ schema })
|
|
52165
|
+
});
|
|
52166
|
+
const result = await res.json();
|
|
52167
|
+
return !!result.success;
|
|
52168
|
+
} catch (err) {
|
|
52169
|
+
console.error("[ServerBridge] Registration failed:", err);
|
|
52170
|
+
return false;
|
|
52171
|
+
}
|
|
52172
|
+
},
|
|
52173
|
+
unregister: async () => {
|
|
52174
|
+
try {
|
|
52175
|
+
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
52176
|
+
} catch {
|
|
52177
|
+
}
|
|
52178
|
+
},
|
|
52179
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
52180
|
+
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
52181
|
+
method: "POST",
|
|
52182
|
+
headers: { "Content-Type": "application/json" },
|
|
52183
|
+
body: JSON.stringify({ event, payload })
|
|
52184
|
+
});
|
|
52185
|
+
return res.json();
|
|
52186
|
+
}
|
|
52187
|
+
};
|
|
52188
|
+
}
|
|
52157
52189
|
var ServerBridgeContext = createContext(null);
|
|
52158
52190
|
function useServerBridge() {
|
|
52159
52191
|
const ctx = useContext(ServerBridgeContext);
|
|
@@ -52166,40 +52198,34 @@ function useServerBridge() {
|
|
|
52166
52198
|
function ServerBridgeProvider({
|
|
52167
52199
|
schema,
|
|
52168
52200
|
serverUrl,
|
|
52201
|
+
transport: customTransport,
|
|
52169
52202
|
children
|
|
52170
52203
|
}) {
|
|
52204
|
+
if (!serverUrl && !customTransport) {
|
|
52205
|
+
throw new Error("ServerBridgeProvider requires either serverUrl or transport");
|
|
52206
|
+
}
|
|
52207
|
+
if (serverUrl && customTransport) {
|
|
52208
|
+
throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
|
|
52209
|
+
}
|
|
52171
52210
|
const eventBus = useEventBus();
|
|
52172
52211
|
const [connected, setConnected] = useState(false);
|
|
52173
|
-
const
|
|
52174
|
-
|
|
52175
|
-
|
|
52176
|
-
|
|
52177
|
-
|
|
52178
|
-
|
|
52179
|
-
|
|
52180
|
-
|
|
52181
|
-
|
|
52182
|
-
|
|
52183
|
-
|
|
52184
|
-
|
|
52185
|
-
}
|
|
52186
|
-
}, [schema, serverUrl]);
|
|
52187
|
-
const unregisterSchema = useCallback(async () => {
|
|
52188
|
-
try {
|
|
52189
|
-
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
52190
|
-
} catch {
|
|
52191
|
-
}
|
|
52192
|
-
}, [serverUrl]);
|
|
52212
|
+
const transport = useMemo(
|
|
52213
|
+
() => customTransport ?? createHttpTransport(serverUrl),
|
|
52214
|
+
[serverUrl, customTransport]
|
|
52215
|
+
);
|
|
52216
|
+
const registerSchema = useCallback(
|
|
52217
|
+
async () => transport.register(schema),
|
|
52218
|
+
[schema, transport]
|
|
52219
|
+
);
|
|
52220
|
+
const unregisterSchema = useCallback(
|
|
52221
|
+
async () => transport.unregister(),
|
|
52222
|
+
[transport]
|
|
52223
|
+
);
|
|
52193
52224
|
const sendEvent = useCallback(async (orbitalName, event, payload) => {
|
|
52194
52225
|
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
52195
52226
|
if (!connected) return { effects: [], meta: emptyMeta };
|
|
52196
52227
|
try {
|
|
52197
|
-
const
|
|
52198
|
-
method: "POST",
|
|
52199
|
-
headers: { "Content-Type": "application/json" },
|
|
52200
|
-
body: JSON.stringify({ event, payload })
|
|
52201
|
-
});
|
|
52202
|
-
const result = await res.json();
|
|
52228
|
+
const result = await transport.sendEvent(orbitalName, event, payload);
|
|
52203
52229
|
const effects = [];
|
|
52204
52230
|
const responseData = result.data || {};
|
|
52205
52231
|
const dataEntities = {};
|
|
@@ -52257,7 +52283,7 @@ function ServerBridgeProvider({
|
|
|
52257
52283
|
console.error("[ServerBridge] Event send failed:", err);
|
|
52258
52284
|
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
52259
52285
|
}
|
|
52260
|
-
}, [connected,
|
|
52286
|
+
}, [connected, transport, eventBus]);
|
|
52261
52287
|
useEffect(() => {
|
|
52262
52288
|
if (!schema) return;
|
|
52263
52289
|
let cancelled = false;
|
|
@@ -52533,7 +52559,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52533
52559
|
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
|
|
52534
52560
|
return null;
|
|
52535
52561
|
}
|
|
52536
|
-
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
52562
|
+
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
52537
52563
|
const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
|
|
52538
52564
|
const allPageTraits = useMemo(() => {
|
|
52539
52565
|
if (pageName && traits2.length > 0) return traits2;
|
|
@@ -52647,7 +52673,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
52647
52673
|
TraitInitializer,
|
|
52648
52674
|
{
|
|
52649
52675
|
traits: allPageTraits,
|
|
52650
|
-
orbitalNames: serverUrl ? pageOrbitalNames : void 0,
|
|
52676
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
52651
52677
|
traitConfigsByName,
|
|
52652
52678
|
orbitalsByTrait,
|
|
52653
52679
|
onNavigate,
|
|
@@ -52660,8 +52686,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
52660
52686
|
]
|
|
52661
52687
|
}
|
|
52662
52688
|
) }) });
|
|
52663
|
-
if (serverUrl) {
|
|
52664
|
-
return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
|
|
52689
|
+
if (serverUrl || transport) {
|
|
52690
|
+
return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
|
|
52665
52691
|
}
|
|
52666
52692
|
return inner;
|
|
52667
52693
|
}
|
|
@@ -52672,8 +52698,12 @@ function OrbPreview({
|
|
|
52672
52698
|
height = "400px",
|
|
52673
52699
|
className,
|
|
52674
52700
|
serverUrl,
|
|
52701
|
+
transport,
|
|
52675
52702
|
initialPagePath
|
|
52676
52703
|
}) {
|
|
52704
|
+
if (serverUrl && transport) {
|
|
52705
|
+
throw new Error("OrbPreview accepts serverUrl OR transport, not both");
|
|
52706
|
+
}
|
|
52677
52707
|
const [localFallback, setLocalFallback] = useState(false);
|
|
52678
52708
|
const eventBus = useEventBus();
|
|
52679
52709
|
const handleLocalFallback = useCallback(() => {
|
|
@@ -52695,21 +52725,21 @@ function OrbPreview({
|
|
|
52695
52725
|
} else {
|
|
52696
52726
|
parsed = schema;
|
|
52697
52727
|
}
|
|
52698
|
-
if (autoMock && !serverUrl) {
|
|
52728
|
+
if (autoMock && !serverUrl && !transport) {
|
|
52699
52729
|
const prepared = prepareSchemaForPreview(parsed);
|
|
52700
52730
|
return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
|
|
52701
52731
|
}
|
|
52702
52732
|
return { ok: true, schema: parsed, mockData: mockData ?? {} };
|
|
52703
|
-
}, [schema, autoMock, serverUrl, mockData]);
|
|
52733
|
+
}, [schema, autoMock, serverUrl, transport, mockData]);
|
|
52704
52734
|
const parsedSchema = parseResult.ok ? parseResult.schema : null;
|
|
52705
52735
|
const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
|
|
52706
52736
|
const persistence = useMemo(() => {
|
|
52707
|
-
if (!parsedSchema || serverUrl) return void 0;
|
|
52737
|
+
if (!parsedSchema || serverUrl || transport) return void 0;
|
|
52708
52738
|
if (!autoMock) return void 0;
|
|
52709
52739
|
const adapter = new InMemoryPersistence();
|
|
52710
52740
|
adapter.seed(effectiveMockData);
|
|
52711
52741
|
return adapter;
|
|
52712
|
-
}, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
|
|
52742
|
+
}, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
|
|
52713
52743
|
const pages = useMemo(() => {
|
|
52714
52744
|
if (!parsedSchema) return [];
|
|
52715
52745
|
try {
|
|
@@ -52771,6 +52801,7 @@ function OrbPreview({
|
|
|
52771
52801
|
{
|
|
52772
52802
|
schema: parsedSchema,
|
|
52773
52803
|
serverUrl,
|
|
52804
|
+
transport,
|
|
52774
52805
|
mockData: effectiveMockData,
|
|
52775
52806
|
pageName: currentPage,
|
|
52776
52807
|
onNavigate: handleNavigate,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BrowserPlayground — in-browser Almadar runtime mount.
|
|
3
|
+
*
|
|
4
|
+
* Runs `OrbitalServerRuntime` (mock mode) in-process and threads it through
|
|
5
|
+
* `<OrbPreview>` via the `ServerBridgeTransport` adapter. Equivalent to
|
|
6
|
+
* canonical playground-runtime's server-mode mount, but without Express,
|
|
7
|
+
* fork, or HTTP — invokes `runtime.processOrbitalEvent` directly.
|
|
8
|
+
*
|
|
9
|
+
* Same React tree as `runtime-verify` (and apps/builder server-mode) speak,
|
|
10
|
+
* so any `@almadar/runtime` fix flows in through one bump cycle.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <BrowserPlayground schema={schema} mode="mock" height="100%" />
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
import React from 'react';
|
|
20
|
+
import type { OrbitalSchema } from '@almadar/core';
|
|
21
|
+
export interface BrowserPlaygroundProps {
|
|
22
|
+
/** OrbitalSchema to render. */
|
|
23
|
+
schema: OrbitalSchema;
|
|
24
|
+
/** Persistence mode for the in-process runtime. Default: 'mock' (Faker-seeded MockPersistenceAdapter). */
|
|
25
|
+
mode?: 'mock';
|
|
26
|
+
/** Initial page path to render (forwarded to OrbPreview). */
|
|
27
|
+
initialPagePath?: string;
|
|
28
|
+
/** Preview container height. Default: '400px'. */
|
|
29
|
+
height?: string;
|
|
30
|
+
/** CSS class for the outer container. */
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function BrowserPlayground({ schema, mode, initialPagePath, height, className, }: BrowserPlaygroundProps): React.ReactElement;
|
|
34
|
+
export default BrowserPlayground;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import React from 'react';
|
|
15
15
|
import type { OrbitalSchema, EntityData } from '@almadar/core';
|
|
16
|
+
import { type ServerBridgeTransport } from './ServerBridge';
|
|
16
17
|
export interface OrbPreviewProps {
|
|
17
18
|
/**
|
|
18
19
|
* The orbital schema. Accepts a JSON string or an `OrbitalSchema` object
|
|
@@ -42,6 +43,12 @@ export interface OrbPreviewProps {
|
|
|
42
43
|
className?: string;
|
|
43
44
|
/** Server URL for dual execution (e.g. "/api/orbitals"). When set, events are forwarded to the server. */
|
|
44
45
|
serverUrl?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Custom transport for in-process execution. Mutually exclusive with
|
|
48
|
+
* `serverUrl`. Used by `<BrowserPlayground>` to invoke
|
|
49
|
+
* `OrbitalServerRuntime.processOrbitalEvent` directly without HTTP.
|
|
50
|
+
*/
|
|
51
|
+
transport?: ServerBridgeTransport;
|
|
45
52
|
/**
|
|
46
53
|
* Initial page path to render (e.g. `/deals`). Resolves against the
|
|
47
54
|
* schema's `pages[]` to seed `currentPage` so the right orbital's traits
|
|
@@ -64,7 +71,7 @@ export interface OrbPreviewProps {
|
|
|
64
71
|
* <OrbPreview schema={schema} serverUrl="/api/orbitals" />
|
|
65
72
|
* ```
|
|
66
73
|
*/
|
|
67
|
-
export declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, initialPagePath, }: OrbPreviewProps): React.ReactElement;
|
|
74
|
+
export declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, transport, initialPagePath, }: OrbPreviewProps): React.ReactElement;
|
|
68
75
|
export declare namespace OrbPreview {
|
|
69
76
|
var displayName: string;
|
|
70
77
|
}
|
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { BusEventSource, EventPayload } from '@almadar/core';
|
|
3
|
+
interface OrbitalEventResponse {
|
|
4
|
+
success: boolean;
|
|
5
|
+
transitioned: boolean;
|
|
6
|
+
states: Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Server-cascade events carried back in the response. Each entry has a
|
|
9
|
+
* `source: BusEventSource` stamped by the compiled handler (`emit ...
|
|
10
|
+
* { source: __ORBITAL_SOURCE }`) so the client can re-broadcast on the
|
|
11
|
+
* qualified `UI:Orbital.Trait.EVENT` bus key (gap #13).
|
|
12
|
+
*/
|
|
13
|
+
emittedEvents?: Array<{
|
|
14
|
+
event: string;
|
|
15
|
+
payload?: EventPayload;
|
|
16
|
+
source?: BusEventSource;
|
|
17
|
+
}>;
|
|
18
|
+
data?: Record<string, unknown[]>;
|
|
19
|
+
clientEffects?: unknown[];
|
|
20
|
+
/**
|
|
21
|
+
* Same effects as `clientEffects`, paired with the trait that produced
|
|
22
|
+
* each one. When present, prefer this for trait attribution. Falls back
|
|
23
|
+
* to legacy `clientEffects` parsing on older servers.
|
|
24
|
+
*/
|
|
25
|
+
clientEffectsByTrait?: Array<{
|
|
26
|
+
traitName: string;
|
|
27
|
+
effect: unknown[];
|
|
28
|
+
}>;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
2
31
|
export interface ServerClientEffect {
|
|
3
32
|
type: 'render-ui' | 'navigate' | 'notify';
|
|
4
33
|
slot?: string;
|
|
@@ -31,13 +60,40 @@ export interface ServerBridgeContextValue {
|
|
|
31
60
|
connected: boolean;
|
|
32
61
|
sendEvent: (orbitalName: string, event: string, payload?: Record<string, unknown>) => Promise<SendEventResult>;
|
|
33
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Transport adapter for ServerBridgeProvider. Decouples the bridge's
|
|
65
|
+
* cascade-rebroadcast / effect-parsing logic from its wire format.
|
|
66
|
+
*
|
|
67
|
+
* - The `serverUrl` mode (default) uses an HTTP transport that POSTs to
|
|
68
|
+
* `/register`, `/unregister`, `/:orbital/events`. This is what canonical
|
|
69
|
+
* playground-runtime (`tools/runtime-verify`) and apps/builder-server
|
|
70
|
+
* speak.
|
|
71
|
+
* - The `transport` mode lets a consumer plug in a direct function-call
|
|
72
|
+
* adapter — used by `<BrowserPlayground>` to invoke
|
|
73
|
+
* `OrbitalServerRuntime.processOrbitalEvent` in-process, no HTTP, no
|
|
74
|
+
* server. Both modes return the same `OrbitalEventResponse` shape so the
|
|
75
|
+
* cascade-rebroadcast logic is identical downstream.
|
|
76
|
+
*/
|
|
77
|
+
export interface ServerBridgeTransport {
|
|
78
|
+
register: (schema: unknown) => Promise<boolean>;
|
|
79
|
+
unregister: () => Promise<void>;
|
|
80
|
+
sendEvent: (orbitalName: string, event: string, payload?: Record<string, unknown>) => Promise<OrbitalEventResponse>;
|
|
81
|
+
}
|
|
34
82
|
/**
|
|
35
83
|
* Access the server bridge. Returns a no-op stub when outside the provider.
|
|
36
84
|
*/
|
|
37
85
|
export declare function useServerBridge(): ServerBridgeContextValue;
|
|
38
86
|
export interface ServerBridgeProviderProps {
|
|
39
87
|
schema: unknown;
|
|
40
|
-
|
|
88
|
+
/** HTTP server URL (canonical playground-runtime / apps/builder-server). */
|
|
89
|
+
serverUrl?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Custom transport adapter. Use this for in-process execution (e.g.
|
|
92
|
+
* `<BrowserPlayground>` invokes `OrbitalServerRuntime.processOrbitalEvent`
|
|
93
|
+
* directly). Mutually exclusive with `serverUrl`.
|
|
94
|
+
*/
|
|
95
|
+
transport?: ServerBridgeTransport;
|
|
41
96
|
children: ReactNode;
|
|
42
97
|
}
|
|
43
|
-
export declare function ServerBridgeProvider({ schema, serverUrl, children, }: ServerBridgeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
98
|
+
export declare function ServerBridgeProvider({ schema, serverUrl, transport: customTransport, children, }: ServerBridgeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
99
|
+
export {};
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ var langGraphql = require('react-syntax-highlighter/dist/esm/languages/prism/gra
|
|
|
37
37
|
var core = require('@almadar/core');
|
|
38
38
|
require('@tanstack/react-query');
|
|
39
39
|
var runtime = require('@almadar/runtime');
|
|
40
|
+
var OrbitalServerRuntime = require('@almadar/runtime/OrbitalServerRuntime');
|
|
40
41
|
|
|
41
42
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
42
43
|
|
|
@@ -8229,13 +8230,13 @@ var init_MapView = __esm({
|
|
|
8229
8230
|
shadowSize: [41, 41]
|
|
8230
8231
|
});
|
|
8231
8232
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
8232
|
-
const { useEffect:
|
|
8233
|
+
const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback110, useState: useState103 } = React115__namespace.default;
|
|
8233
8234
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
8234
8235
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
8235
8236
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
8236
8237
|
const map = useMap();
|
|
8237
8238
|
const prevRef = useRef65({ centerLat, centerLng, zoom });
|
|
8238
|
-
|
|
8239
|
+
useEffect69(() => {
|
|
8239
8240
|
const prev = prevRef.current;
|
|
8240
8241
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
8241
8242
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -8246,7 +8247,7 @@ var init_MapView = __esm({
|
|
|
8246
8247
|
}
|
|
8247
8248
|
function MapClickHandler({ onMapClick }) {
|
|
8248
8249
|
const map = useMap();
|
|
8249
|
-
|
|
8250
|
+
useEffect69(() => {
|
|
8250
8251
|
if (!onMapClick) return;
|
|
8251
8252
|
const handler = (e) => {
|
|
8252
8253
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -8273,7 +8274,7 @@ var init_MapView = __esm({
|
|
|
8273
8274
|
showAttribution = true
|
|
8274
8275
|
}) {
|
|
8275
8276
|
const eventBus = useEventBus2();
|
|
8276
|
-
const [clickedPosition, setClickedPosition] =
|
|
8277
|
+
const [clickedPosition, setClickedPosition] = useState103(null);
|
|
8277
8278
|
const handleMapClick = useCallback110((lat, lng) => {
|
|
8278
8279
|
if (showClickedPin) {
|
|
8279
8280
|
setClickedPosition({ lat, lng });
|
|
@@ -38980,6 +38981,38 @@ init_EntitySchemaContext();
|
|
|
38980
38981
|
init_useEventBus();
|
|
38981
38982
|
init_logger();
|
|
38982
38983
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
38984
|
+
function createHttpTransport(serverUrl) {
|
|
38985
|
+
return {
|
|
38986
|
+
register: async (schema) => {
|
|
38987
|
+
try {
|
|
38988
|
+
const res = await fetch(`${serverUrl}/register`, {
|
|
38989
|
+
method: "POST",
|
|
38990
|
+
headers: { "Content-Type": "application/json" },
|
|
38991
|
+
body: JSON.stringify({ schema })
|
|
38992
|
+
});
|
|
38993
|
+
const result = await res.json();
|
|
38994
|
+
return !!result.success;
|
|
38995
|
+
} catch (err) {
|
|
38996
|
+
console.error("[ServerBridge] Registration failed:", err);
|
|
38997
|
+
return false;
|
|
38998
|
+
}
|
|
38999
|
+
},
|
|
39000
|
+
unregister: async () => {
|
|
39001
|
+
try {
|
|
39002
|
+
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
39003
|
+
} catch {
|
|
39004
|
+
}
|
|
39005
|
+
},
|
|
39006
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
39007
|
+
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
39008
|
+
method: "POST",
|
|
39009
|
+
headers: { "Content-Type": "application/json" },
|
|
39010
|
+
body: JSON.stringify({ event, payload })
|
|
39011
|
+
});
|
|
39012
|
+
return res.json();
|
|
39013
|
+
}
|
|
39014
|
+
};
|
|
39015
|
+
}
|
|
38983
39016
|
var ServerBridgeContext = React115.createContext(null);
|
|
38984
39017
|
function useServerBridge() {
|
|
38985
39018
|
const ctx = React115.useContext(ServerBridgeContext);
|
|
@@ -38992,40 +39025,34 @@ function useServerBridge() {
|
|
|
38992
39025
|
function ServerBridgeProvider({
|
|
38993
39026
|
schema,
|
|
38994
39027
|
serverUrl,
|
|
39028
|
+
transport: customTransport,
|
|
38995
39029
|
children
|
|
38996
39030
|
}) {
|
|
39031
|
+
if (!serverUrl && !customTransport) {
|
|
39032
|
+
throw new Error("ServerBridgeProvider requires either serverUrl or transport");
|
|
39033
|
+
}
|
|
39034
|
+
if (serverUrl && customTransport) {
|
|
39035
|
+
throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
|
|
39036
|
+
}
|
|
38997
39037
|
const eventBus = useEventBus();
|
|
38998
39038
|
const [connected, setConnected] = React115.useState(false);
|
|
38999
|
-
const
|
|
39000
|
-
|
|
39001
|
-
|
|
39002
|
-
|
|
39003
|
-
|
|
39004
|
-
|
|
39005
|
-
|
|
39006
|
-
|
|
39007
|
-
|
|
39008
|
-
|
|
39009
|
-
|
|
39010
|
-
|
|
39011
|
-
}
|
|
39012
|
-
}, [schema, serverUrl]);
|
|
39013
|
-
const unregisterSchema = React115.useCallback(async () => {
|
|
39014
|
-
try {
|
|
39015
|
-
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
39016
|
-
} catch {
|
|
39017
|
-
}
|
|
39018
|
-
}, [serverUrl]);
|
|
39039
|
+
const transport = React115.useMemo(
|
|
39040
|
+
() => customTransport ?? createHttpTransport(serverUrl),
|
|
39041
|
+
[serverUrl, customTransport]
|
|
39042
|
+
);
|
|
39043
|
+
const registerSchema = React115.useCallback(
|
|
39044
|
+
async () => transport.register(schema),
|
|
39045
|
+
[schema, transport]
|
|
39046
|
+
);
|
|
39047
|
+
const unregisterSchema = React115.useCallback(
|
|
39048
|
+
async () => transport.unregister(),
|
|
39049
|
+
[transport]
|
|
39050
|
+
);
|
|
39019
39051
|
const sendEvent = React115.useCallback(async (orbitalName, event, payload) => {
|
|
39020
39052
|
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
39021
39053
|
if (!connected) return { effects: [], meta: emptyMeta };
|
|
39022
39054
|
try {
|
|
39023
|
-
const
|
|
39024
|
-
method: "POST",
|
|
39025
|
-
headers: { "Content-Type": "application/json" },
|
|
39026
|
-
body: JSON.stringify({ event, payload })
|
|
39027
|
-
});
|
|
39028
|
-
const result = await res.json();
|
|
39055
|
+
const result = await transport.sendEvent(orbitalName, event, payload);
|
|
39029
39056
|
const effects = [];
|
|
39030
39057
|
const responseData = result.data || {};
|
|
39031
39058
|
const dataEntities = {};
|
|
@@ -39083,7 +39110,7 @@ function ServerBridgeProvider({
|
|
|
39083
39110
|
console.error("[ServerBridge] Event send failed:", err);
|
|
39084
39111
|
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
39085
39112
|
}
|
|
39086
|
-
}, [connected,
|
|
39113
|
+
}, [connected, transport, eventBus]);
|
|
39087
39114
|
React115.useEffect(() => {
|
|
39088
39115
|
if (!schema) return;
|
|
39089
39116
|
let cancelled = false;
|
|
@@ -39359,7 +39386,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
39359
39386
|
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
|
|
39360
39387
|
return null;
|
|
39361
39388
|
}
|
|
39362
|
-
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
39389
|
+
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
39363
39390
|
const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
|
|
39364
39391
|
const allPageTraits = React115.useMemo(() => {
|
|
39365
39392
|
if (pageName && traits2.length > 0) return traits2;
|
|
@@ -39473,7 +39500,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39473
39500
|
TraitInitializer,
|
|
39474
39501
|
{
|
|
39475
39502
|
traits: allPageTraits,
|
|
39476
|
-
orbitalNames: serverUrl ? pageOrbitalNames : void 0,
|
|
39503
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
39477
39504
|
traitConfigsByName,
|
|
39478
39505
|
orbitalsByTrait,
|
|
39479
39506
|
onNavigate,
|
|
@@ -39486,8 +39513,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39486
39513
|
]
|
|
39487
39514
|
}
|
|
39488
39515
|
) }) });
|
|
39489
|
-
if (serverUrl) {
|
|
39490
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
|
|
39516
|
+
if (serverUrl || transport) {
|
|
39517
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
|
|
39491
39518
|
}
|
|
39492
39519
|
return inner;
|
|
39493
39520
|
}
|
|
@@ -39498,8 +39525,12 @@ function OrbPreview({
|
|
|
39498
39525
|
height = "400px",
|
|
39499
39526
|
className,
|
|
39500
39527
|
serverUrl,
|
|
39528
|
+
transport,
|
|
39501
39529
|
initialPagePath
|
|
39502
39530
|
}) {
|
|
39531
|
+
if (serverUrl && transport) {
|
|
39532
|
+
throw new Error("OrbPreview accepts serverUrl OR transport, not both");
|
|
39533
|
+
}
|
|
39503
39534
|
const [localFallback, setLocalFallback] = React115.useState(false);
|
|
39504
39535
|
const eventBus = useEventBus();
|
|
39505
39536
|
const handleLocalFallback = React115.useCallback(() => {
|
|
@@ -39521,21 +39552,21 @@ function OrbPreview({
|
|
|
39521
39552
|
} else {
|
|
39522
39553
|
parsed = schema;
|
|
39523
39554
|
}
|
|
39524
|
-
if (autoMock && !serverUrl) {
|
|
39555
|
+
if (autoMock && !serverUrl && !transport) {
|
|
39525
39556
|
const prepared = prepareSchemaForPreview(parsed);
|
|
39526
39557
|
return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
|
|
39527
39558
|
}
|
|
39528
39559
|
return { ok: true, schema: parsed, mockData: mockData ?? {} };
|
|
39529
|
-
}, [schema, autoMock, serverUrl, mockData]);
|
|
39560
|
+
}, [schema, autoMock, serverUrl, transport, mockData]);
|
|
39530
39561
|
const parsedSchema = parseResult.ok ? parseResult.schema : null;
|
|
39531
39562
|
const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
|
|
39532
39563
|
const persistence = React115.useMemo(() => {
|
|
39533
|
-
if (!parsedSchema || serverUrl) return void 0;
|
|
39564
|
+
if (!parsedSchema || serverUrl || transport) return void 0;
|
|
39534
39565
|
if (!autoMock) return void 0;
|
|
39535
39566
|
const adapter = new runtime.InMemoryPersistence();
|
|
39536
39567
|
adapter.seed(effectiveMockData);
|
|
39537
39568
|
return adapter;
|
|
39538
|
-
}, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
|
|
39569
|
+
}, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
|
|
39539
39570
|
const pages = React115.useMemo(() => {
|
|
39540
39571
|
if (!parsedSchema) return [];
|
|
39541
39572
|
try {
|
|
@@ -39597,6 +39628,7 @@ function OrbPreview({
|
|
|
39597
39628
|
{
|
|
39598
39629
|
schema: parsedSchema,
|
|
39599
39630
|
serverUrl,
|
|
39631
|
+
transport,
|
|
39600
39632
|
mockData: effectiveMockData,
|
|
39601
39633
|
pageName: currentPage,
|
|
39602
39634
|
onNavigate: handleNavigate,
|
|
@@ -39609,7 +39641,50 @@ function OrbPreview({
|
|
|
39609
39641
|
);
|
|
39610
39642
|
}
|
|
39611
39643
|
OrbPreview.displayName = "OrbPreview";
|
|
39644
|
+
function BrowserPlayground({
|
|
39645
|
+
schema,
|
|
39646
|
+
mode = "mock",
|
|
39647
|
+
initialPagePath,
|
|
39648
|
+
height,
|
|
39649
|
+
className
|
|
39650
|
+
}) {
|
|
39651
|
+
const [runtime] = React115.useState(
|
|
39652
|
+
() => new OrbitalServerRuntime.OrbitalServerRuntime({ mode, debug: false })
|
|
39653
|
+
);
|
|
39654
|
+
React115.useEffect(() => {
|
|
39655
|
+
void runtime.register(schema);
|
|
39656
|
+
return () => {
|
|
39657
|
+
runtime.unregisterAll();
|
|
39658
|
+
};
|
|
39659
|
+
}, [runtime, schema]);
|
|
39660
|
+
const transport = React115.useMemo(() => ({
|
|
39661
|
+
register: async (s) => {
|
|
39662
|
+
await runtime.register(s);
|
|
39663
|
+
return true;
|
|
39664
|
+
},
|
|
39665
|
+
unregister: async () => {
|
|
39666
|
+
runtime.unregisterAll();
|
|
39667
|
+
},
|
|
39668
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
39669
|
+
return runtime.processOrbitalEvent(orbitalName, {
|
|
39670
|
+
event,
|
|
39671
|
+
payload
|
|
39672
|
+
});
|
|
39673
|
+
}
|
|
39674
|
+
}), [runtime]);
|
|
39675
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39676
|
+
OrbPreview,
|
|
39677
|
+
{
|
|
39678
|
+
schema,
|
|
39679
|
+
transport,
|
|
39680
|
+
initialPagePath,
|
|
39681
|
+
height,
|
|
39682
|
+
className
|
|
39683
|
+
}
|
|
39684
|
+
);
|
|
39685
|
+
}
|
|
39612
39686
|
|
|
39687
|
+
exports.BrowserPlayground = BrowserPlayground;
|
|
39613
39688
|
exports.EntitySchemaProvider = EntitySchemaProvider;
|
|
39614
39689
|
exports.OrbPreview = OrbPreview;
|
|
39615
39690
|
exports.ServerBridgeProvider = ServerBridgeProvider;
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { TraitProvider, TraitContext, useTraitContext, useTrait, type TraitConte
|
|
|
13
13
|
export { SlotsProvider, useSlots, useSlotContent, useSlotsActions, type SlotsState, type SlotState, type SlotPatternEntry, type SlotSource, type SlotsActions, type SlotsProviderProps, } from './ui/SlotsContext';
|
|
14
14
|
export { createClientEffectHandlers, type ClientEventBus, type SlotSetter, type CreateClientEffectHandlersOptions, } from './createClientEffectHandlers';
|
|
15
15
|
export { OrbPreview, type OrbPreviewProps } from './OrbPreview';
|
|
16
|
+
export { BrowserPlayground, type BrowserPlaygroundProps } from './BrowserPlayground';
|
|
16
17
|
export { prepareSchemaForPreview, buildMockData, adjustSchemaForMockData, type PreparedPreviewSchema, } from './prepareSchemaForPreview';
|
|
17
|
-
export { ServerBridgeProvider, useServerBridge, type ServerBridgeContextValue, type ServerClientEffect } from './ServerBridge';
|
|
18
|
+
export { ServerBridgeProvider, useServerBridge, type ServerBridgeContextValue, type ServerBridgeTransport, type ServerClientEffect } from './ServerBridge';
|
|
18
19
|
export type { ResolvedTraitBinding, ResolvedTrait, ResolvedEntity, ResolvedPage, ResolvedIR, } from './types';
|
package/dist/runtime/index.js
CHANGED
|
@@ -37,6 +37,7 @@ import langGraphql from 'react-syntax-highlighter/dist/esm/languages/prism/graph
|
|
|
37
37
|
import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, isEntityCall, isInlineTrait } from '@almadar/core';
|
|
38
38
|
import '@tanstack/react-query';
|
|
39
39
|
import { StateMachineManager, createContextFromBindings, interpolateValue, createServerEffectHandlers, EffectExecutor, InMemoryPersistence } from '@almadar/runtime';
|
|
40
|
+
import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
|
|
40
41
|
|
|
41
42
|
var __defProp = Object.defineProperty;
|
|
42
43
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -8184,13 +8185,13 @@ var init_MapView = __esm({
|
|
|
8184
8185
|
shadowSize: [41, 41]
|
|
8185
8186
|
});
|
|
8186
8187
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
8187
|
-
const { useEffect:
|
|
8188
|
+
const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback110, useState: useState103 } = React115__default;
|
|
8188
8189
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
8189
8190
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
8190
8191
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
8191
8192
|
const map = useMap();
|
|
8192
8193
|
const prevRef = useRef65({ centerLat, centerLng, zoom });
|
|
8193
|
-
|
|
8194
|
+
useEffect69(() => {
|
|
8194
8195
|
const prev = prevRef.current;
|
|
8195
8196
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
8196
8197
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -8201,7 +8202,7 @@ var init_MapView = __esm({
|
|
|
8201
8202
|
}
|
|
8202
8203
|
function MapClickHandler({ onMapClick }) {
|
|
8203
8204
|
const map = useMap();
|
|
8204
|
-
|
|
8205
|
+
useEffect69(() => {
|
|
8205
8206
|
if (!onMapClick) return;
|
|
8206
8207
|
const handler = (e) => {
|
|
8207
8208
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -8228,7 +8229,7 @@ var init_MapView = __esm({
|
|
|
8228
8229
|
showAttribution = true
|
|
8229
8230
|
}) {
|
|
8230
8231
|
const eventBus = useEventBus2();
|
|
8231
|
-
const [clickedPosition, setClickedPosition] =
|
|
8232
|
+
const [clickedPosition, setClickedPosition] = useState103(null);
|
|
8232
8233
|
const handleMapClick = useCallback110((lat, lng) => {
|
|
8233
8234
|
if (showClickedPin) {
|
|
8234
8235
|
setClickedPosition({ lat, lng });
|
|
@@ -38935,6 +38936,38 @@ init_EntitySchemaContext();
|
|
|
38935
38936
|
init_useEventBus();
|
|
38936
38937
|
init_logger();
|
|
38937
38938
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
38939
|
+
function createHttpTransport(serverUrl) {
|
|
38940
|
+
return {
|
|
38941
|
+
register: async (schema) => {
|
|
38942
|
+
try {
|
|
38943
|
+
const res = await fetch(`${serverUrl}/register`, {
|
|
38944
|
+
method: "POST",
|
|
38945
|
+
headers: { "Content-Type": "application/json" },
|
|
38946
|
+
body: JSON.stringify({ schema })
|
|
38947
|
+
});
|
|
38948
|
+
const result = await res.json();
|
|
38949
|
+
return !!result.success;
|
|
38950
|
+
} catch (err) {
|
|
38951
|
+
console.error("[ServerBridge] Registration failed:", err);
|
|
38952
|
+
return false;
|
|
38953
|
+
}
|
|
38954
|
+
},
|
|
38955
|
+
unregister: async () => {
|
|
38956
|
+
try {
|
|
38957
|
+
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
38958
|
+
} catch {
|
|
38959
|
+
}
|
|
38960
|
+
},
|
|
38961
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
38962
|
+
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
38963
|
+
method: "POST",
|
|
38964
|
+
headers: { "Content-Type": "application/json" },
|
|
38965
|
+
body: JSON.stringify({ event, payload })
|
|
38966
|
+
});
|
|
38967
|
+
return res.json();
|
|
38968
|
+
}
|
|
38969
|
+
};
|
|
38970
|
+
}
|
|
38938
38971
|
var ServerBridgeContext = createContext(null);
|
|
38939
38972
|
function useServerBridge() {
|
|
38940
38973
|
const ctx = useContext(ServerBridgeContext);
|
|
@@ -38947,40 +38980,34 @@ function useServerBridge() {
|
|
|
38947
38980
|
function ServerBridgeProvider({
|
|
38948
38981
|
schema,
|
|
38949
38982
|
serverUrl,
|
|
38983
|
+
transport: customTransport,
|
|
38950
38984
|
children
|
|
38951
38985
|
}) {
|
|
38986
|
+
if (!serverUrl && !customTransport) {
|
|
38987
|
+
throw new Error("ServerBridgeProvider requires either serverUrl or transport");
|
|
38988
|
+
}
|
|
38989
|
+
if (serverUrl && customTransport) {
|
|
38990
|
+
throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
|
|
38991
|
+
}
|
|
38952
38992
|
const eventBus = useEventBus();
|
|
38953
38993
|
const [connected, setConnected] = useState(false);
|
|
38954
|
-
const
|
|
38955
|
-
|
|
38956
|
-
|
|
38957
|
-
|
|
38958
|
-
|
|
38959
|
-
|
|
38960
|
-
|
|
38961
|
-
|
|
38962
|
-
|
|
38963
|
-
|
|
38964
|
-
|
|
38965
|
-
|
|
38966
|
-
}
|
|
38967
|
-
}, [schema, serverUrl]);
|
|
38968
|
-
const unregisterSchema = useCallback(async () => {
|
|
38969
|
-
try {
|
|
38970
|
-
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
38971
|
-
} catch {
|
|
38972
|
-
}
|
|
38973
|
-
}, [serverUrl]);
|
|
38994
|
+
const transport = useMemo(
|
|
38995
|
+
() => customTransport ?? createHttpTransport(serverUrl),
|
|
38996
|
+
[serverUrl, customTransport]
|
|
38997
|
+
);
|
|
38998
|
+
const registerSchema = useCallback(
|
|
38999
|
+
async () => transport.register(schema),
|
|
39000
|
+
[schema, transport]
|
|
39001
|
+
);
|
|
39002
|
+
const unregisterSchema = useCallback(
|
|
39003
|
+
async () => transport.unregister(),
|
|
39004
|
+
[transport]
|
|
39005
|
+
);
|
|
38974
39006
|
const sendEvent = useCallback(async (orbitalName, event, payload) => {
|
|
38975
39007
|
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
38976
39008
|
if (!connected) return { effects: [], meta: emptyMeta };
|
|
38977
39009
|
try {
|
|
38978
|
-
const
|
|
38979
|
-
method: "POST",
|
|
38980
|
-
headers: { "Content-Type": "application/json" },
|
|
38981
|
-
body: JSON.stringify({ event, payload })
|
|
38982
|
-
});
|
|
38983
|
-
const result = await res.json();
|
|
39010
|
+
const result = await transport.sendEvent(orbitalName, event, payload);
|
|
38984
39011
|
const effects = [];
|
|
38985
39012
|
const responseData = result.data || {};
|
|
38986
39013
|
const dataEntities = {};
|
|
@@ -39038,7 +39065,7 @@ function ServerBridgeProvider({
|
|
|
39038
39065
|
console.error("[ServerBridge] Event send failed:", err);
|
|
39039
39066
|
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
39040
39067
|
}
|
|
39041
|
-
}, [connected,
|
|
39068
|
+
}, [connected, transport, eventBus]);
|
|
39042
39069
|
useEffect(() => {
|
|
39043
39070
|
if (!schema) return;
|
|
39044
39071
|
let cancelled = false;
|
|
@@ -39314,7 +39341,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
39314
39341
|
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
|
|
39315
39342
|
return null;
|
|
39316
39343
|
}
|
|
39317
|
-
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
39344
|
+
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
39318
39345
|
const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
|
|
39319
39346
|
const allPageTraits = useMemo(() => {
|
|
39320
39347
|
if (pageName && traits2.length > 0) return traits2;
|
|
@@ -39428,7 +39455,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39428
39455
|
TraitInitializer,
|
|
39429
39456
|
{
|
|
39430
39457
|
traits: allPageTraits,
|
|
39431
|
-
orbitalNames: serverUrl ? pageOrbitalNames : void 0,
|
|
39458
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
39432
39459
|
traitConfigsByName,
|
|
39433
39460
|
orbitalsByTrait,
|
|
39434
39461
|
onNavigate,
|
|
@@ -39441,8 +39468,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39441
39468
|
]
|
|
39442
39469
|
}
|
|
39443
39470
|
) }) });
|
|
39444
|
-
if (serverUrl) {
|
|
39445
|
-
return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
|
|
39471
|
+
if (serverUrl || transport) {
|
|
39472
|
+
return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
|
|
39446
39473
|
}
|
|
39447
39474
|
return inner;
|
|
39448
39475
|
}
|
|
@@ -39453,8 +39480,12 @@ function OrbPreview({
|
|
|
39453
39480
|
height = "400px",
|
|
39454
39481
|
className,
|
|
39455
39482
|
serverUrl,
|
|
39483
|
+
transport,
|
|
39456
39484
|
initialPagePath
|
|
39457
39485
|
}) {
|
|
39486
|
+
if (serverUrl && transport) {
|
|
39487
|
+
throw new Error("OrbPreview accepts serverUrl OR transport, not both");
|
|
39488
|
+
}
|
|
39458
39489
|
const [localFallback, setLocalFallback] = useState(false);
|
|
39459
39490
|
const eventBus = useEventBus();
|
|
39460
39491
|
const handleLocalFallback = useCallback(() => {
|
|
@@ -39476,21 +39507,21 @@ function OrbPreview({
|
|
|
39476
39507
|
} else {
|
|
39477
39508
|
parsed = schema;
|
|
39478
39509
|
}
|
|
39479
|
-
if (autoMock && !serverUrl) {
|
|
39510
|
+
if (autoMock && !serverUrl && !transport) {
|
|
39480
39511
|
const prepared = prepareSchemaForPreview(parsed);
|
|
39481
39512
|
return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
|
|
39482
39513
|
}
|
|
39483
39514
|
return { ok: true, schema: parsed, mockData: mockData ?? {} };
|
|
39484
|
-
}, [schema, autoMock, serverUrl, mockData]);
|
|
39515
|
+
}, [schema, autoMock, serverUrl, transport, mockData]);
|
|
39485
39516
|
const parsedSchema = parseResult.ok ? parseResult.schema : null;
|
|
39486
39517
|
const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
|
|
39487
39518
|
const persistence = useMemo(() => {
|
|
39488
|
-
if (!parsedSchema || serverUrl) return void 0;
|
|
39519
|
+
if (!parsedSchema || serverUrl || transport) return void 0;
|
|
39489
39520
|
if (!autoMock) return void 0;
|
|
39490
39521
|
const adapter = new InMemoryPersistence();
|
|
39491
39522
|
adapter.seed(effectiveMockData);
|
|
39492
39523
|
return adapter;
|
|
39493
|
-
}, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
|
|
39524
|
+
}, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
|
|
39494
39525
|
const pages = useMemo(() => {
|
|
39495
39526
|
if (!parsedSchema) return [];
|
|
39496
39527
|
try {
|
|
@@ -39552,6 +39583,7 @@ function OrbPreview({
|
|
|
39552
39583
|
{
|
|
39553
39584
|
schema: parsedSchema,
|
|
39554
39585
|
serverUrl,
|
|
39586
|
+
transport,
|
|
39555
39587
|
mockData: effectiveMockData,
|
|
39556
39588
|
pageName: currentPage,
|
|
39557
39589
|
onNavigate: handleNavigate,
|
|
@@ -39564,5 +39596,47 @@ function OrbPreview({
|
|
|
39564
39596
|
);
|
|
39565
39597
|
}
|
|
39566
39598
|
OrbPreview.displayName = "OrbPreview";
|
|
39599
|
+
function BrowserPlayground({
|
|
39600
|
+
schema,
|
|
39601
|
+
mode = "mock",
|
|
39602
|
+
initialPagePath,
|
|
39603
|
+
height,
|
|
39604
|
+
className
|
|
39605
|
+
}) {
|
|
39606
|
+
const [runtime] = useState(
|
|
39607
|
+
() => new OrbitalServerRuntime({ mode, debug: false })
|
|
39608
|
+
);
|
|
39609
|
+
useEffect(() => {
|
|
39610
|
+
void runtime.register(schema);
|
|
39611
|
+
return () => {
|
|
39612
|
+
runtime.unregisterAll();
|
|
39613
|
+
};
|
|
39614
|
+
}, [runtime, schema]);
|
|
39615
|
+
const transport = useMemo(() => ({
|
|
39616
|
+
register: async (s) => {
|
|
39617
|
+
await runtime.register(s);
|
|
39618
|
+
return true;
|
|
39619
|
+
},
|
|
39620
|
+
unregister: async () => {
|
|
39621
|
+
runtime.unregisterAll();
|
|
39622
|
+
},
|
|
39623
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
39624
|
+
return runtime.processOrbitalEvent(orbitalName, {
|
|
39625
|
+
event,
|
|
39626
|
+
payload
|
|
39627
|
+
});
|
|
39628
|
+
}
|
|
39629
|
+
}), [runtime]);
|
|
39630
|
+
return /* @__PURE__ */ jsx(
|
|
39631
|
+
OrbPreview,
|
|
39632
|
+
{
|
|
39633
|
+
schema,
|
|
39634
|
+
transport,
|
|
39635
|
+
initialPagePath,
|
|
39636
|
+
height,
|
|
39637
|
+
className
|
|
39638
|
+
}
|
|
39639
|
+
);
|
|
39640
|
+
}
|
|
39567
39641
|
|
|
39568
|
-
export { EntitySchemaProvider, OrbPreview, ServerBridgeProvider, SlotsProvider, TraitContext, TraitProvider, adjustSchemaForMockData, buildMockData, clearSchemaCache, createClientEffectHandlers, prepareSchemaForPreview, useEntityDefinition, useEntitySchema, useEntitySchemaOptional, useResolvedSchema, useServerBridge, useSlotContent, useSlots, useSlotsActions, useTrait, useTraitContext, useTraitStateMachine };
|
|
39642
|
+
export { BrowserPlayground, EntitySchemaProvider, OrbPreview, ServerBridgeProvider, SlotsProvider, TraitContext, TraitProvider, adjustSchemaForMockData, buildMockData, clearSchemaCache, createClientEffectHandlers, prepareSchemaForPreview, useEntityDefinition, useEntitySchema, useEntitySchemaOptional, useResolvedSchema, useServerBridge, useSlotContent, useSlots, useSlotsActions, useTrait, useTraitContext, useTraitStateMachine };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.0",
|
|
4
4
|
"description": "React UI components, hooks, and providers for Almadar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/components/index.js",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"@almadar/core": "^7.0.0",
|
|
122
122
|
"@almadar/evaluator": ">=2.9.2",
|
|
123
123
|
"@almadar/patterns": ">=2.17.1",
|
|
124
|
-
"@almadar/runtime": "^5.
|
|
124
|
+
"@almadar/runtime": "^5.7.0",
|
|
125
125
|
"@almadar/std": ">=6.4.1",
|
|
126
126
|
"@almadar/syntax": ">=1.3.1",
|
|
127
127
|
"@xyflow/react": "12.10.1",
|