@gears-frontx/react 0.1.0 → 0.2.0-alpha.15

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.js CHANGED
@@ -1,16 +1,15 @@
1
- // src/HAI3Provider.tsx
2
- import { useMemo, useEffect } from "react";
1
+ // src/FrontXProvider.tsx
2
+ import { useEffect as useEffect3 } from "react";
3
3
  import { Provider as ReduxProvider } from "react-redux";
4
- import { createHAI3App } from "@gears-frontx/framework";
5
4
 
6
- // src/HAI3Context.tsx
5
+ // src/FrontXContext.tsx
7
6
  import { createContext, useContext } from "react";
8
- var HAI3Context = createContext(null);
9
- function useHAI3() {
10
- const context = useContext(HAI3Context);
7
+ var FrontXContext = createContext(null);
8
+ function useFrontX() {
9
+ const context = useContext(FrontXContext);
11
10
  if (!context) {
12
11
  throw new Error(
13
- "useHAI3 must be used within a HAI3Provider. Wrap your application with <HAI3Provider> to access HAI3 features."
12
+ "useFrontX must be used within a FrontXProvider. Wrap your application with <FrontXProvider> to access Gears FrontX features."
14
13
  );
15
14
  }
16
15
  return context;
@@ -35,34 +34,644 @@ var MfeProvider = ({ value, children }) => {
35
34
  return /* @__PURE__ */ jsx(MfeContext.Provider, { value, children });
36
35
  };
37
36
 
38
- // src/HAI3Provider.tsx
39
- import { jsx as jsx2 } from "react/jsx-runtime";
40
- var HAI3Provider = ({
41
- children,
42
- config,
43
- app: providedApp,
44
- mfeBridge
45
- }) => {
46
- const app = useMemo(() => {
47
- if (providedApp) {
48
- return providedApp;
37
+ // src/queryClient.tsx
38
+ import React, {
39
+ createContext as createContext3,
40
+ useContext as useContext3,
41
+ useEffect as useEffect2,
42
+ useLayoutEffect,
43
+ useMemo,
44
+ useState
45
+ } from "react";
46
+ import {
47
+ QueryClientContext,
48
+ QueryClientProvider,
49
+ useInfiniteQuery,
50
+ useMutation,
51
+ useQuery,
52
+ useSuspenseInfiniteQuery,
53
+ useSuspenseQuery
54
+ } from "@tanstack/react-query";
55
+ import {
56
+ readQueryCacheScopeGeneration,
57
+ recordQueryCacheScopeWriteDropped,
58
+ subscribeQueryCacheRuntimeChanged
59
+ } from "@gears-frontx/framework";
60
+
61
+ // src/hooks/QueryCache.ts
62
+ import { eventBus } from "@gears-frontx/framework";
63
+ var QUERY_CLIENT_BROADCAST_TARGET = /* @__PURE__ */ Symbol.for("frontx:query-cache:broadcast-target");
64
+ var QUERY_CLIENT_BROADCAST_COUNTER = /* @__PURE__ */ Symbol.for("frontx:query-cache:broadcast-counter");
65
+ function emitCacheEvent(event, payload) {
66
+ eventBus.emit(event, payload);
67
+ }
68
+ function ensureBroadcastSource(queryClient) {
69
+ const clientWithMetadata = queryClient;
70
+ const existingSource = clientWithMetadata[QUERY_CLIENT_BROADCAST_TARGET];
71
+ if (typeof existingSource === "string" && existingSource.length > 0) {
72
+ return existingSource;
73
+ }
74
+ const host = globalThis;
75
+ const nextCounter = (host[QUERY_CLIENT_BROADCAST_COUNTER] ?? 0) + 1;
76
+ host[QUERY_CLIENT_BROADCAST_COUNTER] = nextCounter;
77
+ const source = `query-cache-${nextCounter}`;
78
+ clientWithMetadata[QUERY_CLIENT_BROADCAST_TARGET] = source;
79
+ return source;
80
+ }
81
+ function resolveKey(target) {
82
+ if (target !== null && typeof target === "object" && !Array.isArray(target) && "key" in target && "fetch" in target && Array.isArray(target.key) && typeof target.fetch === "function") {
83
+ return target.key;
84
+ }
85
+ return target;
86
+ }
87
+ function toQueryUpdater(dataOrUpdater) {
88
+ if (typeof dataOrUpdater === "function") {
89
+ return dataOrUpdater;
90
+ }
91
+ return () => dataOrUpdater;
92
+ }
93
+ function mapQueryState(state) {
94
+ return {
95
+ data: state.data,
96
+ dataUpdatedAt: state.dataUpdatedAt,
97
+ error: state.error,
98
+ errorUpdatedAt: state.errorUpdatedAt,
99
+ fetchFailureCount: state.fetchFailureCount,
100
+ fetchFailureReason: state.fetchFailureReason,
101
+ fetchStatus: state.fetchStatus,
102
+ isInvalidated: state.isInvalidated,
103
+ status: state.status
104
+ };
105
+ }
106
+ function createQueryCache(queryClient) {
107
+ return {
108
+ get: (key) => {
109
+ return queryClient.getQueryData(resolveKey(key));
110
+ },
111
+ getState: (key) => {
112
+ const state = queryClient.getQueryState(resolveKey(key));
113
+ return state ? mapQueryState(state) : void 0;
114
+ },
115
+ set: (key, dataOrUpdater) => {
116
+ const resolvedKey = resolveKey(key);
117
+ queryClient.setQueryData(resolvedKey, toQueryUpdater(dataOrUpdater));
118
+ emitCacheEvent("cache/set", {
119
+ queryKey: resolvedKey,
120
+ dataOrUpdater,
121
+ source: ensureBroadcastSource(queryClient)
122
+ });
123
+ },
124
+ cancel: (key) => {
125
+ return queryClient.cancelQueries({ queryKey: resolveKey(key) });
126
+ },
127
+ invalidate: (key) => {
128
+ const resolvedKey = resolveKey(key);
129
+ const result = queryClient.invalidateQueries({ queryKey: resolvedKey });
130
+ emitCacheEvent("cache/invalidate", {
131
+ queryKey: resolvedKey,
132
+ source: ensureBroadcastSource(queryClient)
133
+ });
134
+ return result;
135
+ },
136
+ invalidateMany: (filters) => {
137
+ if (filters?.queryKey == null) {
138
+ return Promise.resolve();
139
+ }
140
+ const resolvedKey = resolveKey(filters.queryKey);
141
+ if (!Array.isArray(resolvedKey) || resolvedKey.length === 0) {
142
+ return Promise.resolve();
143
+ }
144
+ const payload = {
145
+ ...filters,
146
+ queryKey: resolvedKey
147
+ };
148
+ const result = queryClient.invalidateQueries(payload);
149
+ emitCacheEvent("cache/invalidate", {
150
+ ...payload,
151
+ source: ensureBroadcastSource(queryClient)
152
+ });
153
+ return result;
154
+ },
155
+ remove: (key) => {
156
+ const resolvedKey = resolveKey(key);
157
+ queryClient.removeQueries({ queryKey: resolvedKey });
158
+ emitCacheEvent("cache/remove", {
159
+ queryKey: resolvedKey,
160
+ source: ensureBroadcastSource(queryClient)
161
+ });
49
162
  }
50
- return createHAI3App(config);
51
- }, [providedApp, config]);
163
+ };
164
+ }
165
+
166
+ // src/hooks/useLatest.ts
167
+ import { useEffect, useRef } from "react";
168
+ function useLatest(value) {
169
+ const ref = useRef(value);
52
170
  useEffect(() => {
171
+ ref.current = value;
172
+ });
173
+ return ref;
174
+ }
175
+
176
+ // src/queryClient.tsx
177
+ import { jsx as jsx2 } from "react/jsx-runtime";
178
+ var APP_QUERY_CLIENT_SYMBOL = /* @__PURE__ */ Symbol.for("frontx:query-cache:app-client");
179
+ var APP_QUERY_CLIENT_RESOLVER_SYMBOL = /* @__PURE__ */ Symbol.for("frontx:query-cache:app-client-resolver");
180
+ var APP_QUERY_CLIENT_ACTIVATOR_SYMBOL = /* @__PURE__ */ Symbol.for("frontx:query-cache:app-client-activator");
181
+ var FrontXQueryClientContext = createContext3(void 0);
182
+ var useCommitEffect = typeof globalThis.window === "undefined" ? useEffect2 : useLayoutEffect;
183
+ function resolveFrontXQueryClient(app) {
184
+ const clientApp = app;
185
+ return clientApp[APP_QUERY_CLIENT_SYMBOL] ?? clientApp[APP_QUERY_CLIENT_RESOLVER_SYMBOL]?.();
186
+ }
187
+ function hasFrontXQueryClientActivator(app) {
188
+ return typeof app[APP_QUERY_CLIENT_ACTIVATOR_SYMBOL] === "function";
189
+ }
190
+ function activateFrontXQueryClient(app) {
191
+ const clientApp = app;
192
+ return clientApp[APP_QUERY_CLIENT_SYMBOL] ?? clientApp[APP_QUERY_CLIENT_ACTIVATOR_SYMBOL]?.();
193
+ }
194
+ async function invalidateQueryCacheForApp(app, target) {
195
+ const queryClient = resolveFrontXQueryClient(app) ?? activateFrontXQueryClient(app);
196
+ if (!queryClient) {
197
+ throw new Error(
198
+ "[invalidateQueryCacheForApp] No QueryClient on app. Ensure queryCache() or queryCacheShared() is in the plugin chain."
199
+ );
200
+ }
201
+ await createQueryCache(queryClient).invalidate(target);
202
+ }
203
+ function bootstrapFrontXQueryClient(app) {
204
+ return resolveFrontXQueryClient(app);
205
+ }
206
+ function useBootstrappedFrontXQueryClient(app) {
207
+ const fromApp = useMemo(() => bootstrapFrontXQueryClient(app), [app]);
208
+ const [eventResolvedClient, setEventResolvedClient] = useState(
209
+ void 0
210
+ );
211
+ const queryClient = fromApp ?? (eventResolvedClient?.app === app ? eventResolvedClient.queryClient : void 0);
212
+ useCommitEffect(() => {
213
+ if (fromApp || !hasFrontXQueryClientActivator(app)) {
214
+ return;
215
+ }
216
+ const tryResolveQueryClient = () => {
217
+ const nextQueryClient = resolveFrontXQueryClient(app) ?? activateFrontXQueryClient(app);
218
+ if (nextQueryClient) {
219
+ setEventResolvedClient((current) => {
220
+ if (current?.app === app && current.queryClient === nextQueryClient) {
221
+ return current;
222
+ }
223
+ return {
224
+ app,
225
+ queryClient: nextQueryClient
226
+ };
227
+ });
228
+ }
229
+ };
230
+ tryResolveQueryClient();
231
+ const subscription = subscribeQueryCacheRuntimeChanged(() => {
232
+ tryResolveQueryClient();
233
+ });
234
+ return () => {
235
+ subscription.unsubscribe();
236
+ };
237
+ }, [app, fromApp]);
238
+ return queryClient;
239
+ }
240
+ function FrontXQueryClientProvider({
241
+ queryClient,
242
+ children
243
+ }) {
244
+ if (!queryClient) {
245
+ return /* @__PURE__ */ jsx2(FrontXQueryClientContext.Provider, { value: void 0, children: /* @__PURE__ */ jsx2(QueryClientContext.Provider, { value: void 0, children }) });
246
+ }
247
+ return /* @__PURE__ */ jsx2(FrontXQueryClientContext.Provider, { value: queryClient, children: /* @__PURE__ */ jsx2(QueryClientProvider, { client: queryClient, children }) });
248
+ }
249
+ function useOptionalFrontXQueryClient() {
250
+ return useContext3(FrontXQueryClientContext);
251
+ }
252
+ function useRequiredFrontXQueryClient() {
253
+ const queryClient = useOptionalFrontXQueryClient();
254
+ if (!queryClient) {
255
+ throw new Error(
256
+ "[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition."
257
+ );
258
+ }
259
+ return queryClient;
260
+ }
261
+ function buildPageContext(page, pages, descriptor, descriptors) {
262
+ return {
263
+ page,
264
+ pages,
265
+ descriptor,
266
+ descriptors
267
+ };
268
+ }
269
+ function normalizeFetchStaleTime(staleTime) {
270
+ if (staleTime === "static") {
271
+ return Number.POSITIVE_INFINITY;
272
+ }
273
+ if (typeof staleTime === "function") {
274
+ return 0;
275
+ }
276
+ return typeof staleTime === "number" ? staleTime : void 0;
277
+ }
278
+ function resolveFetchStaleTime(queryClient, queryKey, descriptor, overrideStaleTime) {
279
+ const clientDefaults = {
280
+ ...queryClient.getDefaultOptions().queries,
281
+ ...queryClient.getQueryDefaults(queryKey)
282
+ };
283
+ return normalizeFetchStaleTime(
284
+ overrideStaleTime ?? descriptor.staleTime ?? clientDefaults.staleTime
285
+ );
286
+ }
287
+ function cacheTimeOptions(staleTime, gcTime) {
288
+ return {
289
+ ...staleTime === void 0 ? {} : { staleTime },
290
+ ...gcTime === void 0 ? {} : { gcTime }
291
+ };
292
+ }
293
+ function fetchDescriptor(descriptor, options) {
294
+ return descriptor.fetch(options);
295
+ }
296
+ function useFrontXQuery(descriptor, overrides) {
297
+ const queryClient = useRequiredFrontXQueryClient();
298
+ const staleTime = resolveFetchStaleTime(
299
+ queryClient,
300
+ descriptor.key,
301
+ descriptor,
302
+ overrides?.staleTime
303
+ );
304
+ const result = useQuery({
305
+ queryKey: descriptor.key,
306
+ queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),
307
+ ...cacheTimeOptions(
308
+ overrides?.staleTime ?? descriptor.staleTime,
309
+ overrides?.gcTime ?? descriptor.gcTime
310
+ ),
311
+ ...overrides?.enabled === void 0 ? {} : { enabled: overrides.enabled }
312
+ });
313
+ return {
314
+ data: result.data,
315
+ error: result.error,
316
+ isLoading: result.isLoading,
317
+ isFetching: result.isFetching,
318
+ isError: result.isError,
319
+ refetch: result.refetch
320
+ };
321
+ }
322
+ function useFrontXSuspenseQuery(descriptor, overrides) {
323
+ const queryClient = useRequiredFrontXQueryClient();
324
+ const staleTime = resolveFetchStaleTime(
325
+ queryClient,
326
+ descriptor.key,
327
+ descriptor,
328
+ overrides?.staleTime
329
+ );
330
+ const result = useSuspenseQuery({
331
+ queryKey: descriptor.key,
332
+ queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),
333
+ ...cacheTimeOptions(
334
+ overrides?.staleTime ?? descriptor.staleTime,
335
+ overrides?.gcTime ?? descriptor.gcTime
336
+ )
337
+ });
338
+ return {
339
+ data: result.data,
340
+ error: result.error,
341
+ isFetching: result.isFetching,
342
+ refetch: async () => {
343
+ await result.refetch();
344
+ }
345
+ };
346
+ }
347
+ function useFrontXInfiniteQuery(options) {
348
+ const queryClient = useRequiredFrontXQueryClient();
349
+ const result = useInfiniteQuery({
350
+ queryKey: options.initialPage.key,
351
+ initialPageParam: options.initialPage,
352
+ queryFn: ({ pageParam, signal }) => fetchDescriptor(pageParam, {
353
+ signal,
354
+ staleTime: resolveFetchStaleTime(
355
+ queryClient,
356
+ options.initialPage.key,
357
+ pageParam,
358
+ options.staleTime
359
+ )
360
+ }),
361
+ getNextPageParam: (lastPage, allPages, lastPageDescriptor, allPageDescriptors) => options.getNextPage(
362
+ buildPageContext(
363
+ lastPage,
364
+ allPages,
365
+ lastPageDescriptor,
366
+ allPageDescriptors
367
+ )
368
+ ),
369
+ getPreviousPageParam: options.getPreviousPage ? (firstPage, allPages, firstPageDescriptor, allPageDescriptors) => options.getPreviousPage?.(
370
+ buildPageContext(
371
+ firstPage,
372
+ allPages,
373
+ firstPageDescriptor,
374
+ allPageDescriptors
375
+ )
376
+ ) : void 0,
377
+ select: (data) => data.pages,
378
+ ...cacheTimeOptions(
379
+ options.staleTime ?? options.initialPage.staleTime,
380
+ options.gcTime ?? options.initialPage.gcTime
381
+ ),
382
+ maxPages: options.maxPages,
383
+ ...options.enabled === void 0 ? {} : { enabled: options.enabled }
384
+ });
385
+ return {
386
+ data: result.data,
387
+ error: result.error,
388
+ isLoading: result.isLoading,
389
+ isFetching: result.isFetching,
390
+ isError: result.isError,
391
+ hasNextPage: result.hasNextPage ?? false,
392
+ hasPreviousPage: result.hasPreviousPage ?? false,
393
+ isFetchingNextPage: result.isFetchingNextPage,
394
+ isFetchingPreviousPage: result.isFetchingPreviousPage,
395
+ fetchNextPage: async () => {
396
+ await result.fetchNextPage();
397
+ },
398
+ fetchPreviousPage: async () => {
399
+ await result.fetchPreviousPage();
400
+ },
401
+ refetch: async () => {
402
+ await result.refetch();
403
+ }
404
+ };
405
+ }
406
+ function useFrontXSuspenseInfiniteQuery(options) {
407
+ const queryClient = useRequiredFrontXQueryClient();
408
+ const result = useSuspenseInfiniteQuery({
409
+ queryKey: options.initialPage.key,
410
+ initialPageParam: options.initialPage,
411
+ queryFn: ({ pageParam, signal }) => fetchDescriptor(pageParam, {
412
+ signal,
413
+ staleTime: resolveFetchStaleTime(
414
+ queryClient,
415
+ options.initialPage.key,
416
+ pageParam,
417
+ options.staleTime
418
+ )
419
+ }),
420
+ getNextPageParam: (lastPage, allPages, lastPageDescriptor, allPageDescriptors) => options.getNextPage(
421
+ buildPageContext(
422
+ lastPage,
423
+ allPages,
424
+ lastPageDescriptor,
425
+ allPageDescriptors
426
+ )
427
+ ),
428
+ getPreviousPageParam: options.getPreviousPage ? (firstPage, allPages, firstPageDescriptor, allPageDescriptors) => options.getPreviousPage?.(
429
+ buildPageContext(
430
+ firstPage,
431
+ allPages,
432
+ firstPageDescriptor,
433
+ allPageDescriptors
434
+ )
435
+ ) : void 0,
436
+ select: (data) => data.pages,
437
+ ...cacheTimeOptions(
438
+ options.staleTime ?? options.initialPage.staleTime,
439
+ options.gcTime ?? options.initialPage.gcTime
440
+ ),
441
+ maxPages: options.maxPages
442
+ });
443
+ return {
444
+ data: result.data,
445
+ error: result.error,
446
+ isFetching: result.isFetching,
447
+ hasNextPage: result.hasNextPage ?? false,
448
+ hasPreviousPage: result.hasPreviousPage ?? false,
449
+ isFetchingNextPage: result.isFetchingNextPage,
450
+ isFetchingPreviousPage: result.isFetchingPreviousPage,
451
+ fetchNextPage: async () => {
452
+ await result.fetchNextPage();
453
+ },
454
+ fetchPreviousPage: async () => {
455
+ await result.fetchPreviousPage();
456
+ },
457
+ refetch: async () => {
458
+ await result.refetch();
459
+ }
460
+ };
461
+ }
462
+ var mutationScopes = /* @__PURE__ */ new WeakMap();
463
+ function scopeBoundQueryCache(queryCache2, scope) {
464
+ const scopeChanged = () => readQueryCacheScopeGeneration(scope.queryClient) !== scope.generation;
465
+ const dropped = () => {
466
+ if (!scopeChanged()) return false;
467
+ recordQueryCacheScopeWriteDropped(scope.queryClient, scope.generation);
468
+ return true;
469
+ };
470
+ return {
471
+ get: queryCache2.get,
472
+ getState: queryCache2.getState,
473
+ set: (key, dataOrUpdater) => {
474
+ if (!dropped()) queryCache2.set(key, dataOrUpdater);
475
+ },
476
+ cancel: (key) => scopeChanged() ? Promise.resolve() : queryCache2.cancel(key),
477
+ invalidate: (key) => dropped() ? Promise.resolve() : queryCache2.invalidate(key),
478
+ invalidateMany: (filters) => dropped() ? Promise.resolve() : queryCache2.invalidateMany(filters),
479
+ remove: (key) => {
480
+ if (!dropped()) queryCache2.remove(key);
481
+ }
482
+ };
483
+ }
484
+ function scopeBoundCallbackCtx(callbackCtx, scope) {
485
+ return scope ? { queryCache: scopeBoundQueryCache(createQueryCache(scope.queryClient), scope) } : callbackCtx;
486
+ }
487
+ function useFrontXMutation(options, callbackCtx) {
488
+ const queryClient = useRequiredFrontXQueryClient();
489
+ const latestRef = useLatest({ options, callbackCtx, queryClient });
490
+ const fetchAbortControllersRef = React.useRef(/* @__PURE__ */ new Set());
491
+ const abortFetchesOnUnmount = React.useEffectEvent(() => {
492
+ if (options.abortOnUnmount) {
493
+ for (const controller of fetchAbortControllersRef.current) {
494
+ controller.abort();
495
+ }
496
+ fetchAbortControllersRef.current.clear();
497
+ }
498
+ });
499
+ React.useEffect(() => {
53
500
  return () => {
54
- if (!providedApp) {
55
- app.destroy();
501
+ abortFetchesOnUnmount();
502
+ };
503
+ }, []);
504
+ const mutationFn = React.useCallback((variables, context) => {
505
+ const cancelOnSupersede = latestRef.current.options.cancelOnSupersede;
506
+ if (cancelOnSupersede) {
507
+ for (const controller2 of fetchAbortControllersRef.current) {
508
+ controller2.abort();
509
+ }
510
+ fetchAbortControllersRef.current.clear();
511
+ }
512
+ const controller = new AbortController();
513
+ fetchAbortControllersRef.current.add(controller);
514
+ const librarySignal = context.signal;
515
+ if (cancelOnSupersede && librarySignal) {
516
+ if (librarySignal.aborted) {
517
+ controller.abort();
518
+ } else {
519
+ librarySignal.addEventListener("abort", () => controller.abort(), { once: true });
56
520
  }
521
+ }
522
+ return latestRef.current.options.endpoint.fetch(variables, { signal: controller.signal }).finally(() => {
523
+ fetchAbortControllersRef.current.delete(controller);
524
+ });
525
+ }, [latestRef]);
526
+ const onMutate = React.useCallback(async (variables, mutationFnContext) => {
527
+ const current = latestRef.current;
528
+ const scope = {
529
+ queryClient: current.queryClient,
530
+ generation: readQueryCacheScopeGeneration(current.queryClient)
57
531
  };
58
- }, [app, providedApp]);
59
- const content = /* @__PURE__ */ jsx2(HAI3Context.Provider, { value: app, children: /* @__PURE__ */ jsx2(ReduxProvider, { store: app.store, children }) });
532
+ mutationScopes.set(mutationFnContext, scope);
533
+ return current.options.onMutate?.(
534
+ variables,
535
+ scopeBoundCallbackCtx(current.callbackCtx, scope)
536
+ );
537
+ }, [latestRef]);
538
+ const onSuccess = React.useCallback((data, variables, context, mutationFnContext) => {
539
+ const current = latestRef.current;
540
+ return current.options.onSuccess?.(
541
+ data,
542
+ variables,
543
+ context,
544
+ scopeBoundCallbackCtx(current.callbackCtx, mutationScopes.get(mutationFnContext))
545
+ );
546
+ }, [latestRef]);
547
+ const onError = React.useCallback((error, variables, context, mutationFnContext) => {
548
+ const current = latestRef.current;
549
+ return current.options.onError?.(
550
+ error,
551
+ variables,
552
+ context,
553
+ scopeBoundCallbackCtx(current.callbackCtx, mutationScopes.get(mutationFnContext))
554
+ );
555
+ }, [latestRef]);
556
+ const onSettled = React.useCallback((data, error, variables, context, mutationFnContext) => {
557
+ const current = latestRef.current;
558
+ return current.options.onSettled?.(
559
+ data,
560
+ error,
561
+ variables,
562
+ context,
563
+ scopeBoundCallbackCtx(current.callbackCtx, mutationScopes.get(mutationFnContext))
564
+ );
565
+ }, [latestRef]);
566
+ const mutation = useMutation({
567
+ mutationFn,
568
+ onMutate,
569
+ onSuccess: options.onSuccess ? onSuccess : void 0,
570
+ onError: options.onError ? onError : void 0,
571
+ onSettled: options.onSettled ? onSettled : void 0
572
+ });
573
+ return {
574
+ mutate: mutation.mutate,
575
+ mutateAsync: mutation.mutateAsync,
576
+ isPending: mutation.isPending,
577
+ error: mutation.error,
578
+ data: mutation.data,
579
+ reset: mutation.reset
580
+ };
581
+ }
582
+
583
+ // src/FrontXProvider.tsx
584
+ import { jsx as jsx3 } from "react/jsx-runtime";
585
+ var FrontXProvider = ({
586
+ children,
587
+ app,
588
+ mfeBridge
589
+ }) => {
590
+ const queryClient = useBootstrappedFrontXQueryClient(app);
591
+ const deferQuerySubtree = hasFrontXQueryClientActivator(app) && queryClient === void 0;
592
+ useEffect3(() => {
593
+ if (queryClient || hasFrontXQueryClientActivator(app) || process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test" || process.env.VITEST === "true") {
594
+ return;
595
+ }
596
+ console.warn(
597
+ "[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition. useApiQuery/useApiMutation will fail without it."
598
+ );
599
+ }, [app, queryClient]);
600
+ const content = /* @__PURE__ */ jsx3(FrontXContext.Provider, { value: app, children: /* @__PURE__ */ jsx3(ReduxProvider, { store: app.store, children: /* @__PURE__ */ jsx3(FrontXQueryClientProvider, { queryClient, children: deferQuerySubtree ? null : children }) }) });
60
601
  if (mfeBridge) {
61
- return /* @__PURE__ */ jsx2(MfeProvider, { value: mfeBridge, children: content });
602
+ return /* @__PURE__ */ jsx3(MfeProvider, { value: mfeBridge, children: content });
62
603
  }
63
604
  return content;
64
605
  };
65
606
 
607
+ // src/hooks/useCanAccess.ts
608
+ import { useEffect as useEffect4, useState as useState2 } from "react";
609
+ function serializeRecordValue(value) {
610
+ if (value === null) return "n:";
611
+ if (typeof value === "string") return `s:${value}`;
612
+ if (typeof value === "number") {
613
+ return `d:${Object.is(value, -0) ? "-0" : String(value)}`;
614
+ }
615
+ return value ? "b:1" : "b:0";
616
+ }
617
+ function accessQueryKey(query) {
618
+ const { action, resource, record } = query;
619
+ const normalizedRecord = record ? Object.entries(record).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => [k, serializeRecordValue(v)]) : null;
620
+ return JSON.stringify([action, resource, normalizedRecord]);
621
+ }
622
+ function getAuthRuntime(app) {
623
+ return app.auth ?? null;
624
+ }
625
+ var DENIED_NO_AUTH = { allow: false, isResolving: false };
626
+ function useCanAccess(query) {
627
+ const app = useFrontX();
628
+ const auth2 = getAuthRuntime(app);
629
+ const stableKey = accessQueryKey(query);
630
+ const [stableQuery, setStableQuery] = useState2(() => query);
631
+ const [runState, setRunState] = useState2({ auth: auth2, stableKey });
632
+ const [result, setResult] = useState2({ allow: false, isResolving: true });
633
+ if (runState.auth !== auth2 || runState.stableKey !== stableKey) {
634
+ setRunState({ auth: auth2, stableKey });
635
+ setStableQuery(query);
636
+ setResult({ allow: false, isResolving: true });
637
+ }
638
+ useEffect4(() => {
639
+ if (!auth2) {
640
+ return;
641
+ }
642
+ let alive = true;
643
+ const controller = new AbortController();
644
+ void auth2.canAccess(stableQuery, { signal: controller.signal }).then((decision) => {
645
+ if (alive) {
646
+ setResult({ allow: decision === "allow", isResolving: false });
647
+ }
648
+ }).catch(() => {
649
+ if (alive) {
650
+ setResult({ allow: false, isResolving: false });
651
+ }
652
+ });
653
+ return () => {
654
+ alive = false;
655
+ controller.abort();
656
+ };
657
+ }, [auth2, stableQuery]);
658
+ return auth2 ? result : DENIED_NO_AUTH;
659
+ }
660
+
661
+ // src/components/CanAccess.tsx
662
+ function CanAccess({
663
+ query,
664
+ allowed,
665
+ denied = null,
666
+ loading
667
+ }) {
668
+ const { allow, isResolving } = useCanAccess(query);
669
+ if (isResolving) {
670
+ return loading !== void 0 ? loading : denied;
671
+ }
672
+ return allow ? allowed : denied;
673
+ }
674
+
66
675
  // src/hooks/useAppDispatch.ts
67
676
  import { useDispatch } from "react-redux";
68
677
  function useAppDispatch() {
@@ -76,7 +685,7 @@ var useAppSelector = useSelector;
76
685
  // src/hooks/useTranslation.ts
77
686
  import { useMemo as useMemo2, useCallback, useSyncExternalStore } from "react";
78
687
  function useTranslation() {
79
- const app = useHAI3();
688
+ const app = useFrontX();
80
689
  const { i18nRegistry: i18nRegistry2 } = app;
81
690
  const version = useSyncExternalStore(
82
691
  useCallback(
@@ -119,16 +728,15 @@ function useTranslation() {
119
728
  }
120
729
 
121
730
  // src/hooks/useScreenTranslations.ts
122
- import { useState, useEffect as useEffect2, useMemo as useMemo3, useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore2 } from "react";
731
+ import { useState as useState3, useEffect as useEffect5, useMemo as useMemo3, useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore2 } from "react";
123
732
  function isTranslationLoader(input) {
124
733
  return typeof input === "function";
125
734
  }
126
735
  function useScreenTranslations(screensetId, screenId, translations) {
127
- const app = useHAI3();
736
+ const app = useFrontX();
128
737
  const { i18nRegistry: i18nRegistry2 } = app;
129
- const [loadedLanguage, setLoadedLanguage] = useState(null);
130
- const [isLoading, setIsLoading] = useState(false);
131
- const [error, setError] = useState(null);
738
+ const [loadedLanguage, setLoadedLanguage] = useState3(null);
739
+ const [error, setError] = useState3(null);
132
740
  const version = useSyncExternalStore2(
133
741
  useCallback2(
134
742
  (callback) => i18nRegistry2.subscribe(callback),
@@ -154,12 +762,11 @@ function useScreenTranslations(screensetId, screenId, translations) {
154
762
  return module.default;
155
763
  };
156
764
  }, [translations]);
157
- useEffect2(() => {
765
+ useEffect5(() => {
158
766
  if (!currentLanguage || currentLanguage === loadedLanguage) {
159
767
  return;
160
768
  }
161
769
  let cancelled = false;
162
- setIsLoading(true);
163
770
  const loadTranslations = async () => {
164
771
  try {
165
772
  const namespace = `screen.${screensetId}.${screenId}`;
@@ -168,13 +775,11 @@ function useScreenTranslations(screensetId, screenId, translations) {
168
775
  i18nRegistry2.register(namespace, currentLanguage, loadedTranslations);
169
776
  if (!cancelled) {
170
777
  setLoadedLanguage(currentLanguage);
171
- setIsLoading(false);
172
778
  setError(null);
173
779
  }
174
780
  } catch (err) {
175
781
  if (!cancelled) {
176
782
  setError(err instanceof Error ? err : new Error(String(err)));
177
- setIsLoading(false);
178
783
  }
179
784
  }
180
785
  };
@@ -183,7 +788,7 @@ function useScreenTranslations(screensetId, screenId, translations) {
183
788
  cancelled = true;
184
789
  };
185
790
  }, [screensetId, screenId, loader, i18nRegistry2, currentLanguage, loadedLanguage]);
186
- const isLoaded = currentLanguage !== null && currentLanguage === loadedLanguage && !isLoading;
791
+ const isLoaded = currentLanguage !== null && currentLanguage === loadedLanguage;
187
792
  return { isLoaded, error };
188
793
  }
189
794
 
@@ -226,7 +831,7 @@ function useFormatters() {
226
831
  // src/hooks/useTheme.ts
227
832
  import { useCallback as useCallback3, useMemo as useMemo5, useSyncExternalStore as useSyncExternalStore3 } from "react";
228
833
  function useTheme() {
229
- const app = useHAI3();
834
+ const app = useFrontX();
230
835
  const { themeRegistry } = app;
231
836
  const version = useSyncExternalStore3(
232
837
  useCallback3(
@@ -264,6 +869,145 @@ function useTheme() {
264
869
  };
265
870
  }
266
871
 
872
+ // src/hooks/useApiQuery.ts
873
+ function useApiQuery(descriptor, overrides) {
874
+ return useFrontXQuery(descriptor, overrides);
875
+ }
876
+
877
+ // src/hooks/useApiSuspenseQuery.ts
878
+ function useApiSuspenseQuery(descriptor, overrides) {
879
+ return useFrontXSuspenseQuery(descriptor, overrides);
880
+ }
881
+
882
+ // src/hooks/useApiInfiniteQuery.ts
883
+ function useApiInfiniteQuery(options) {
884
+ return useFrontXInfiniteQuery(options);
885
+ }
886
+
887
+ // src/hooks/useApiSuspenseInfiniteQuery.ts
888
+ function useApiSuspenseInfiniteQuery(options) {
889
+ return useFrontXSuspenseInfiniteQuery(options);
890
+ }
891
+
892
+ // src/hooks/useApiMutation.ts
893
+ import { useMemo as useMemo6 } from "react";
894
+ function useApiMutation(options) {
895
+ const queryClient = useRequiredFrontXQueryClient();
896
+ const queryCache2 = useMemo6(() => createQueryCache(queryClient), [queryClient]);
897
+ const callbackCtx = useMemo6(() => ({ queryCache: queryCache2 }), [queryCache2]);
898
+ return useFrontXMutation(options, callbackCtx);
899
+ }
900
+
901
+ // src/hooks/useApiStream.ts
902
+ import { useEffect as useEffect6, useMemo as useMemo7, useRef as useRef2, useState as useState4, useCallback as useCallback4 } from "react";
903
+ function useApiStream(descriptor, options) {
904
+ const mode = options?.mode ?? "latest";
905
+ const enabled = options?.enabled ?? true;
906
+ const [data, setData] = useState4(void 0);
907
+ const [events, setEvents] = useState4([]);
908
+ const [status, setStatus] = useState4(() => enabled ? "connecting" : "idle");
909
+ const [error, setError] = useState4(null);
910
+ const connectPromiseRef = useRef2(null);
911
+ const connectionIdRef = useRef2(null);
912
+ const disconnectRequestedRef = useRef2(false);
913
+ const descriptorRef = useLatest(descriptor);
914
+ const descriptorKey = useMemo7(() => JSON.stringify(descriptor.key), [descriptor.key]);
915
+ const resetKey = `${descriptorKey}:${mode}`;
916
+ const [prevResetKey, setPrevResetKey] = useState4(resetKey);
917
+ if (resetKey !== prevResetKey) {
918
+ setPrevResetKey(resetKey);
919
+ setData(void 0);
920
+ setEvents([]);
921
+ setError(null);
922
+ }
923
+ const connectKey = `${resetKey}:${enabled}`;
924
+ const [prevConnectKey, setPrevConnectKey] = useState4(connectKey);
925
+ if (connectKey !== prevConnectKey) {
926
+ setPrevConnectKey(connectKey);
927
+ if (enabled) {
928
+ setData(void 0);
929
+ setEvents([]);
930
+ setStatus("connecting");
931
+ setError(null);
932
+ }
933
+ }
934
+ const disconnect = useCallback4(() => {
935
+ disconnectRequestedRef.current = true;
936
+ if (connectionIdRef.current) {
937
+ descriptorRef.current.disconnect(connectionIdRef.current);
938
+ connectionIdRef.current = null;
939
+ disconnectRequestedRef.current = false;
940
+ }
941
+ setStatus("disconnected");
942
+ }, [descriptorRef]);
943
+ useEffect6(() => {
944
+ if (!enabled) {
945
+ return;
946
+ }
947
+ let cancelled = false;
948
+ disconnectRequestedRef.current = false;
949
+ const d = descriptorRef.current;
950
+ const connectPromise = d.connect(
951
+ (event) => {
952
+ if (cancelled) return;
953
+ setData(event);
954
+ setStatus("connected");
955
+ if (mode === "accumulate") {
956
+ setEvents((prev) => [...prev, event]);
957
+ }
958
+ },
959
+ () => {
960
+ if (cancelled) return;
961
+ setStatus("disconnected");
962
+ connectionIdRef.current = null;
963
+ }
964
+ );
965
+ connectPromiseRef.current = connectPromise;
966
+ connectPromise.then((id) => {
967
+ if (cancelled) return;
968
+ if (disconnectRequestedRef.current) {
969
+ d.disconnect(id);
970
+ disconnectRequestedRef.current = false;
971
+ return;
972
+ }
973
+ connectionIdRef.current = id;
974
+ setStatus("connected");
975
+ }).catch((err) => {
976
+ if (cancelled) return;
977
+ if (disconnectRequestedRef.current) {
978
+ disconnectRequestedRef.current = false;
979
+ setStatus("disconnected");
980
+ return;
981
+ }
982
+ setError(err instanceof Error ? err : new Error(String(err)));
983
+ setStatus("error");
984
+ });
985
+ return () => {
986
+ cancelled = true;
987
+ connectPromise.then(
988
+ (id) => d.disconnect(id),
989
+ () => {
990
+ }
991
+ );
992
+ connectPromiseRef.current = null;
993
+ connectionIdRef.current = null;
994
+ };
995
+ }, [descriptorKey, enabled, mode, descriptorRef]);
996
+ return { data, events, status: enabled ? status : "idle", error, disconnect };
997
+ }
998
+
999
+ // src/hooks/useQueryCache.ts
1000
+ import { useMemo as useMemo8 } from "react";
1001
+ function useQueryCache() {
1002
+ const queryClient = useOptionalFrontXQueryClient();
1003
+ if (!queryClient) {
1004
+ throw new Error(
1005
+ "[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition."
1006
+ );
1007
+ }
1008
+ return useMemo8(() => createQueryCache(queryClient), [queryClient]);
1009
+ }
1010
+
267
1011
  // src/mfe/hooks/useMfeBridge.ts
268
1012
  function useMfeBridge() {
269
1013
  const { bridge } = useMfeContext();
@@ -271,61 +1015,73 @@ function useMfeBridge() {
271
1015
  }
272
1016
 
273
1017
  // src/mfe/hooks/useSharedProperty.ts
274
- import { useSyncExternalStore as useSyncExternalStore4, useCallback as useCallback4 } from "react";
275
- function useSharedProperty(propertyTypeId) {
276
- const { bridge } = useMfeContext();
277
- const subscribe = useCallback4((callback) => {
278
- return bridge.subscribeToProperty(propertyTypeId, () => {
279
- callback();
280
- });
281
- }, [bridge, propertyTypeId]);
282
- const getSnapshot = useCallback4(() => {
283
- const property = bridge.getProperty(propertyTypeId);
284
- return property?.value;
285
- }, [bridge, propertyTypeId]);
286
- const value = useSyncExternalStore4(subscribe, getSnapshot, getSnapshot);
287
- return value;
1018
+ import { useCallback as useCallback5, useContext as useContext4, useSyncExternalStore as useSyncExternalStore4 } from "react";
1019
+ function useSharedProperty(propertyTypeId, options) {
1020
+ const contextValue = useContext4(MfeContext);
1021
+ const bridge = options?.bridge ?? contextValue?.bridge;
1022
+ const fallback = options?.fallback;
1023
+ if (!bridge) {
1024
+ throw new Error(
1025
+ "useSharedProperty must be used within a MfeProvider, or given an explicit `bridge` option, for components that never mount MfeProvider."
1026
+ );
1027
+ }
1028
+ const subscribe = useCallback5(
1029
+ (onStoreChange) => bridge.subscribeToProperty(propertyTypeId, () => {
1030
+ onStoreChange();
1031
+ }),
1032
+ [bridge, propertyTypeId]
1033
+ );
1034
+ const getSnapshot = useCallback5(() => {
1035
+ const raw = bridge.getProperty(propertyTypeId)?.value;
1036
+ return raw === void 0 ? fallback : raw;
1037
+ }, [bridge, propertyTypeId, fallback]);
1038
+ return useSyncExternalStore4(subscribe, getSnapshot, getSnapshot);
288
1039
  }
289
1040
 
290
1041
  // src/mfe/hooks/useHostAction.ts
291
- import { useCallback as useCallback5 } from "react";
1042
+ import { useCallback as useCallback6 } from "react";
292
1043
  function useHostAction(actionTypeId) {
293
1044
  const { bridge } = useMfeContext();
294
- return useCallback5((payload) => {
1045
+ return useCallback6((payload) => {
295
1046
  const chain = {
296
1047
  action: {
297
1048
  type: actionTypeId,
298
- target: bridge.domainId,
1049
+ target: bridge.extDomainId,
299
1050
  payload
300
1051
  }
301
1052
  };
302
- bridge.executeActionsChain(chain).catch((error) => {
303
- console.error(
304
- `[useHostAction] Failed to send action '${actionTypeId}':`,
305
- error
306
- );
307
- });
1053
+ bridge.executeActionsChain(chain);
308
1054
  }, [actionTypeId, bridge]);
309
1055
  }
310
1056
 
311
- // src/mfe/hooks/useDomainExtensions.ts
312
- import { useSyncExternalStore as useSyncExternalStore5, useCallback as useCallback6, useRef } from "react";
313
- function useDomainExtensions(domainId) {
314
- const app = useHAI3();
315
- const registry = app.screensetsRegistry;
1057
+ // src/mfe/hooks/useMfeRegistry.ts
1058
+ function resolveMfeRegistry(app, callerName) {
1059
+ const registry = app.mfeRegistry;
316
1060
  if (!registry) {
317
1061
  throw new Error(
318
- "useDomainExtensions requires the microfrontends plugin. Add microfrontends() to your HAI3 app configuration."
1062
+ `${callerName} requires the microfrontends plugin. Add microfrontends() to your Gears FrontX app configuration.`
319
1063
  );
320
1064
  }
321
- const subscribe = useCallback6(
1065
+ return registry;
1066
+ }
1067
+ function useMfeRegistry() {
1068
+ const app = useFrontX();
1069
+ return resolveMfeRegistry(app, "useMfeRegistry");
1070
+ }
1071
+
1072
+ // src/mfe/hooks/useDomainExtensions.ts
1073
+ import { useSyncExternalStore as useSyncExternalStore5, useCallback as useCallback7, useRef as useRef3 } from "react";
1074
+ function useDomainExtensions(domainId) {
1075
+ const app = useFrontX();
1076
+ const registry = resolveMfeRegistry(app, "useDomainExtensions");
1077
+ const subscribe = useCallback7(
322
1078
  (onStoreChange) => {
323
1079
  return app.store.subscribe(onStoreChange);
324
1080
  },
325
1081
  [app.store]
326
1082
  );
327
- const cacheRef = useRef({ ids: "", extensions: [] });
328
- const getSnapshot = useCallback6(() => {
1083
+ const cacheRef = useRef3({ ids: "", extensions: [] });
1084
+ const getSnapshot = useCallback7(() => {
329
1085
  const extensions = registry.getExtensionsForDomain(domainId);
330
1086
  const ids = extensions.map((e) => e.id).join(",");
331
1087
  if (ids !== cacheRef.current.ids) {
@@ -337,23 +1093,18 @@ function useDomainExtensions(domainId) {
337
1093
  }
338
1094
 
339
1095
  // src/mfe/hooks/useRegisteredPackages.ts
340
- import { useSyncExternalStore as useSyncExternalStore6, useCallback as useCallback7, useRef as useRef2 } from "react";
1096
+ import { useSyncExternalStore as useSyncExternalStore6, useCallback as useCallback8, useRef as useRef4 } from "react";
341
1097
  function useRegisteredPackages() {
342
- const app = useHAI3();
343
- const registry = app.screensetsRegistry;
344
- if (!registry) {
345
- throw new Error(
346
- "useRegisteredPackages requires the microfrontends plugin. Add microfrontends() to your HAI3 app configuration."
347
- );
348
- }
349
- const subscribe = useCallback7(
1098
+ const app = useFrontX();
1099
+ const registry = resolveMfeRegistry(app, "useRegisteredPackages");
1100
+ const subscribe = useCallback8(
350
1101
  (onStoreChange) => {
351
1102
  return app.store.subscribe(onStoreChange);
352
1103
  },
353
1104
  [app.store]
354
1105
  );
355
- const cacheRef = useRef2({ packages: "", list: [] });
356
- const getSnapshot = useCallback7(() => {
1106
+ const cacheRef = useRef4({ packages: "", list: [] });
1107
+ const getSnapshot = useCallback8(() => {
357
1108
  const list = registry.getRegisteredPackages();
358
1109
  const packages = list.join(",");
359
1110
  if (packages !== cacheRef.current.packages) {
@@ -364,195 +1115,331 @@ function useRegisteredPackages() {
364
1115
  return useSyncExternalStore6(subscribe, getSnapshot, getSnapshot);
365
1116
  }
366
1117
 
367
- // src/mfe/hooks/useActivePackage.ts
368
- import { useSyncExternalStore as useSyncExternalStore7, useCallback as useCallback8, useRef as useRef3 } from "react";
369
- import { extractGtsPackage, FRONTX_SCREEN_DOMAIN } from "@gears-frontx/framework";
370
- function useActivePackage() {
371
- const app = useHAI3();
372
- const registry = app.screensetsRegistry;
373
- if (!registry) {
1118
+ // src/mfe/ThemeAwareReactLifecycle.tsx
1119
+ import { createRoot } from "react-dom/client";
1120
+
1121
+ // src/mfe/domainTeardownCollector.ts
1122
+ var activeCollector;
1123
+ function collectDomainTeardowns(fn) {
1124
+ const previousCollector = activeCollector;
1125
+ const collector = [];
1126
+ activeCollector = collector;
1127
+ try {
1128
+ fn();
1129
+ } finally {
1130
+ activeCollector = previousCollector;
1131
+ }
1132
+ return collector;
1133
+ }
1134
+ function registerDomainTeardown(promise) {
1135
+ activeCollector?.push(promise);
1136
+ }
1137
+
1138
+ // src/mfe/ThemeAwareReactLifecycle.tsx
1139
+ import { jsx as jsx4 } from "react/jsx-runtime";
1140
+ var ADOPTED_HOST_STYLE_ATTR = "data-frontx-adopted-host-style";
1141
+ var BASE_RESETS_STYLE_ID = "__frontx-base-resets__";
1142
+ var SHELL_OWNED_SHADOW_STYLE_IDS = ["__frontx-shadow-isolation__", "__frontx-css-variables__"];
1143
+ function cssToCopy(style) {
1144
+ const text = style.textContent ?? "";
1145
+ const sheet = style.sheet;
1146
+ if (text.trim() || !sheet) return text;
1147
+ return Array.from(sheet.cssRules, (rule) => rule.cssText).join("\n");
1148
+ }
1149
+ function resolveProviderMountOptions(app, bridge, mountContext) {
1150
+ const extensionId = mountContext?.extensionId;
1151
+ const domainId = mountContext?.domainId;
1152
+ const isMountedMfe = typeof extensionId === "string" && typeof domainId === "string";
1153
+ if (isMountedMfe && !resolveFrontXQueryClient(app) && !hasFrontXQueryClientActivator(app)) {
374
1154
  throw new Error(
375
- "useActivePackage requires the microfrontends plugin. Add microfrontends() to your HAI3 app configuration."
1155
+ "[FrontXProvider] Mounted MFEs require queryCacheShared() in the child app and queryCache() in the host app before loading the MFE app."
376
1156
  );
377
1157
  }
378
- const subscribe = useCallback8(
379
- (onStoreChange) => {
380
- return app.store.subscribe(onStoreChange);
381
- },
382
- [app.store]
383
- );
384
- const cacheRef = useRef3({ activePackage: void 0 });
385
- const getSnapshot = useCallback8(() => {
386
- const mountedExtensionId = registry.getMountedExtension(FRONTX_SCREEN_DOMAIN);
387
- if (!mountedExtensionId) {
388
- const result = void 0;
389
- if (result !== cacheRef.current.activePackage) {
390
- cacheRef.current = { activePackage: result };
391
- }
392
- return cacheRef.current.activePackage;
393
- }
394
- const activePackage = extractGtsPackage(mountedExtensionId);
395
- if (activePackage !== cacheRef.current.activePackage) {
396
- cacheRef.current = { activePackage };
397
- }
398
- return cacheRef.current.activePackage;
399
- }, [registry]);
400
- return useSyncExternalStore7(subscribe, getSnapshot, getSnapshot);
1158
+ return {
1159
+ mfeBridge: isMountedMfe ? { bridge, extensionId, domainId } : void 0
1160
+ };
401
1161
  }
402
-
403
- // src/mfe/components/RefContainerProvider.ts
404
- import { ContainerProvider } from "@gears-frontx/framework";
405
- var RefContainerProvider = class extends ContainerProvider {
406
- constructor(containerRef) {
407
- super();
408
- this.containerRef = containerRef;
1162
+ function MountRuntimeAwareProvider({
1163
+ app,
1164
+ mfeBridge,
1165
+ children
1166
+ }) {
1167
+ return /* @__PURE__ */ jsx4(FrontXProvider, { app, mfeBridge, children });
1168
+ }
1169
+ var ThemeAwareReactLifecycle = class {
1170
+ constructor(app) {
1171
+ this.app = app;
409
1172
  }
410
- getContainer(_extensionId) {
411
- if (!this.containerRef.current) {
412
- throw new Error("Container ref is not attached -- component may not be mounted yet");
1173
+ app;
1174
+ root = null;
1175
+ mount(container, bridge, mountContext) {
1176
+ void this.app.mfeRegistry;
1177
+ if (container instanceof ShadowRoot) {
1178
+ this.adoptHostStylesIntoShadowRoot(container);
413
1179
  }
414
- return this.containerRef.current;
1180
+ this.injectBaseResets(container);
1181
+ this.initializeStyles(container);
1182
+ const providerMountOptions = resolveProviderMountOptions(this.app, bridge, mountContext);
1183
+ this.root = createRoot(container);
1184
+ this.root.render(
1185
+ /* @__PURE__ */ jsx4(
1186
+ MountRuntimeAwareProvider,
1187
+ {
1188
+ app: this.app,
1189
+ mfeBridge: providerMountOptions.mfeBridge,
1190
+ children: this.renderContent(bridge)
1191
+ }
1192
+ )
1193
+ );
415
1194
  }
416
- releaseContainer(_extensionId) {
1195
+ /**
1196
+ * `Root.unmount()` itself is synchronous, but a nested `ExtensionDomainSlot`
1197
+ * mounted anywhere in this root's own tree cannot make ITS cleanup
1198
+ * synchronous too — its mounter's own `detach()` awaits per-extension
1199
+ * unmounts. Collecting whatever that cleanup fire-and-forgets (through
1200
+ * `domainTeardownCollector`, scoped to this one `Root.unmount()` call) and
1201
+ * awaiting it here is what makes this method's own returned promise settle
1202
+ * only once every nested domain this root owns has actually finished
1203
+ * tearing down — never before. A root with no routed nested domain
1204
+ * collects nothing, and this resolves exactly as before (a microtask after
1205
+ * the synchronous unmount, same observable timing `void | Promise<void>`
1206
+ * already allows).
1207
+ */
1208
+ async unmount(_container) {
1209
+ if (!this.root) return;
1210
+ const root = this.root;
1211
+ this.root = null;
1212
+ const pendingTeardowns = collectDomainTeardowns(() => root.unmount());
1213
+ const settled = await Promise.allSettled(pendingTeardowns);
1214
+ const failed = settled.find((result) => result.status === "rejected");
1215
+ if (failed) throw failed.reason;
1216
+ }
1217
+ /**
1218
+ * Copy all inline <style> and <link rel="stylesheet"> from the host document
1219
+ * into the shadow root so that Tailwind and component styles apply inside the MFE.
1220
+ *
1221
+ * The clones are inserted ahead of everything already in the shadow root, never
1222
+ * appended, because adopted host styles are context rather than authority: where
1223
+ * they and the MFE's own CSS declare the same property at equal specificity, the
1224
+ * MFE has to win. Appending inverted that. `MfeHandlerMF` injects the MFE's
1225
+ * compiled stylesheet into the shadow root before it calls mount, so an appended
1226
+ * clone of the shell's Tailwind preflight - whose
1227
+ * `button, [type='button'], [type='reset'], [type='submit']` rule sets
1228
+ * `background-color: transparent` at specificity (0,1,0) - tied with
1229
+ * `@gears-frontx/ui-kit`'s single-class button rule and won on document order,
1230
+ * leaving every kit Button transparent until it was hovered.
1231
+ *
1232
+ * Inserting at the front rather than pushing MFE styles to the back is what makes
1233
+ * the invariant hold for stylesheets that appear after mount too - a lazily
1234
+ * imported component's CSS module, or whatever initializeStyles() adds - since
1235
+ * those land behind the adopted block by construction.
1236
+ *
1237
+ * A cascade layer around the adopted CSS was the alternative and is rejected:
1238
+ * layered rules lose to unlayered ones at *any* specificity, so a host utility
1239
+ * class would stop overriding an MFE element selector. Document order keeps
1240
+ * specificity in charge and only settles the ties.
1241
+ *
1242
+ * The block replaces its predecessor instead of stacking on it, the same
1243
+ * upsert shape `injectStylesheet` and `injectCssVariables` use in
1244
+ * `@gears-frontx/mfes`' shadow utilities, widened from one id-keyed node to a
1245
+ * marked block. Replacement is required rather than tidy: `createShadowRoot`
1246
+ * hands back an existing `element.shadowRoot` instead of attaching a new one,
1247
+ * so remounting the same container runs this method again on a shadow root
1248
+ * that already holds a full adopted block, and appending would grow it once
1249
+ * per mount with no bound. It does not save re-resolving the cloned `<link>`s -
1250
+ * every mount clones them afresh and the browser resolves each clone; what
1251
+ * replacement buys is that the count stays at one block instead of one per
1252
+ * mount.
1253
+ *
1254
+ * The block is rebuilt from the host head rather than left in place, because
1255
+ * the head is not fixed: a lazily imported chunk adds stylesheets to it after
1256
+ * the first mount, and the second mount has to pick those up.
1257
+ *
1258
+ * A `<style>` is copied into a new element that holds the host's CSS - see
1259
+ * `cssToCopy` - and takes three things from the host element: `media`,
1260
+ * without which a print-only host style applies on screen inside the MFE;
1261
+ * `type`, which keeps the copy of a non-CSS element as inert as the original;
1262
+ * and the nonce, without which a nonce-based CSP blocks the copy. The nonce is read from the `nonce` property, because
1263
+ * browsers blank the attribute in a document served with a CSP header.
1264
+ * Nothing else is carried over, because libraries look for their own
1265
+ * attributes inside the shadow root: styled-components, rendering into it,
1266
+ * puts its tag right after the last `style[data-styled]` there, so a copy of
1267
+ * the host's tag would pull the MFE's rules ahead of the base resets and the
1268
+ * MFE's own CSS. A `<link>` is a deep clone and is loaded from its `href`
1269
+ * again.
1270
+ *
1271
+ * The fresh block goes in before the previous one comes out. Removing first
1272
+ * leaves the shadow root with no host CSS at all, and everything between that
1273
+ * removal and the insertion is synchronous work in this same task - so the gap
1274
+ * never reaches a paint, but any code that reads computed styles from the tree
1275
+ * in between sees an unstyled one. Inserting first costs one moment with two
1276
+ * blocks present, which changes nothing: the old block is a clone of the same
1277
+ * host head and loses every tie to the new one on document order anyway.
1278
+ */
1279
+ adoptHostStylesIntoShadowRoot(shadowRoot) {
1280
+ const supersededStyles = Array.from(shadowRoot.querySelectorAll(`[${ADOPTED_HOST_STYLE_ATTR}]`));
1281
+ const adoptedStyles = document.createDocumentFragment();
1282
+ const hostStyleNodes = document.head.querySelectorAll('style, link[rel="stylesheet"]');
1283
+ hostStyleNodes.forEach((el) => {
1284
+ if (el instanceof HTMLStyleElement) {
1285
+ const copy = document.createElement("style");
1286
+ if (el.media) copy.media = el.media;
1287
+ if (el.type) copy.type = el.type;
1288
+ if (el.nonce) copy.nonce = el.nonce;
1289
+ copy.textContent = cssToCopy(el);
1290
+ copy.setAttribute(ADOPTED_HOST_STYLE_ATTR, "");
1291
+ adoptedStyles.appendChild(copy);
1292
+ return;
1293
+ }
1294
+ const linkClone = el.cloneNode(true);
1295
+ linkClone.setAttribute(ADOPTED_HOST_STYLE_ATTR, "");
1296
+ adoptedStyles.appendChild(linkClone);
1297
+ });
1298
+ shadowRoot.insertBefore(adoptedStyles, shadowRoot.firstChild);
1299
+ supersededStyles.forEach((el) => el.remove());
1300
+ }
1301
+ /**
1302
+ * Box-model resets and :host defaults needed inside every shadow root.
1303
+ * These aren't part of Tailwind's compiled output but are required for
1304
+ * consistent rendering across browsers.
1305
+ *
1306
+ * Reuses the node a previous mount left behind, exactly as `injectStylesheet`
1307
+ * does in `@gears-frontx/mfes`' shadow utilities: a remount runs against a
1308
+ * shadow root that `createShadowRoot` handed back intact, and appending a
1309
+ * second copy would add one node per mount forever.
1310
+ *
1311
+ * Reuse alone is not enough, which is why the node is also positioned on every
1312
+ * mount rather than left where the previous one sat. These resets are context
1313
+ * like the adopted block is - `border-color: currentColor` on `*` is a 0-0-0
1314
+ * declaration that beats an MFE preflight's own 0-0-0 reset purely on document
1315
+ * order - so they have to stay ahead of the MFE's CSS, and where they land is
1316
+ * not stable on its own. `MfeHandlerMF.wrapLifecycleWithStylesheets` removes the
1317
+ * MFE's stylesheet on unmount and appends a fresh one before the next mount, so
1318
+ * a node merely left in place ends up ahead of that stylesheet on a remount and
1319
+ * behind it on the first mount: two different cascades for one component.
1320
+ * Anchoring it to the end of the shell-owned head gives every mount the same
1321
+ * order - adopted block, isolation, resets, MFE - which is also the order the
1322
+ * adoption method's invariant is written against.
1323
+ *
1324
+ * With no shell-owned node to anchor to, the resets go to the front. That is the
1325
+ * plain-`Element` container: no adopted block, no isolation style, and the MFE
1326
+ * stylesheet already appended by the handler, so the front is again the only
1327
+ * position that leaves the MFE winning ties.
1328
+ *
1329
+ * Looked up by attribute-selector form rather than `getElementById`, which
1330
+ * `ShadowRoot` has but `Element` does not, and this hook takes either.
1331
+ */
1332
+ injectBaseResets(container) {
1333
+ const existing = container.querySelector(
1334
+ `style[id="${BASE_RESETS_STYLE_ID}"]`
1335
+ );
1336
+ const style = existing ?? document.createElement("style");
1337
+ style.id = BASE_RESETS_STYLE_ID;
1338
+ style.textContent = `
1339
+ *, *::before, *::after {
1340
+ box-sizing: border-box;
1341
+ border-width: 0;
1342
+ border-style: solid;
1343
+ border-color: currentColor;
1344
+ }
1345
+ * { margin: 0; padding: 0; }
1346
+ :host {
1347
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
1348
+ line-height: 1.5;
1349
+ -webkit-font-smoothing: antialiased;
1350
+ -moz-osx-font-smoothing: grayscale;
1351
+ color: var(--foreground);
1352
+ background-color: var(--background);
1353
+ }
1354
+ `;
1355
+ const shellOwnedHead = container.querySelectorAll(
1356
+ [
1357
+ `[${ADOPTED_HOST_STYLE_ATTR}]`,
1358
+ ...SHELL_OWNED_SHADOW_STYLE_IDS.map((id) => `[id="${id}"]`)
1359
+ ].join(", ")
1360
+ );
1361
+ const lastShellOwnedNode = shellOwnedHead[shellOwnedHead.length - 1];
1362
+ container.insertBefore(
1363
+ style,
1364
+ lastShellOwnedNode ? lastShellOwnedNode.nextSibling : container.firstChild
1365
+ );
1366
+ }
1367
+ /**
1368
+ * Hook for subclasses to inject additional CSS not covered by the adopted host
1369
+ * stylesheet (e.g., MFE-specific @font-face rules or custom animations).
1370
+ * No-op by default: host styles adopted in adoptHostStylesIntoShadowRoot()
1371
+ * already include all Tailwind utilities compiled from MFE source files.
1372
+ */
1373
+ initializeStyles(_container) {
417
1374
  }
418
1375
  };
419
1376
 
420
1377
  // src/mfe/components/ExtensionDomainSlot.tsx
421
- import { useEffect as useEffect3, useRef as useRef4, useState as useState2 } from "react";
422
- import {
423
- FRONTX_ACTION_MOUNT_EXT,
424
- FRONTX_ACTION_UNMOUNT_EXT
425
- } from "@gears-frontx/framework";
426
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
1378
+ import { useEffect as useEffect7, useEffectEvent, useRef as useRef5, useState as useState5 } from "react";
1379
+ import { jsx as jsx5 } from "react/jsx-runtime";
427
1380
  function ExtensionDomainSlot(props) {
428
1381
  const {
429
1382
  registry,
430
1383
  domainId,
431
- extensionId,
432
1384
  className,
433
- onMounted,
434
- onUnmounted,
435
- onError,
436
- loadingComponent,
437
- errorComponent
1385
+ onAttached,
1386
+ onDetached,
1387
+ loadingComponent = null
438
1388
  } = props;
439
- const containerRef = useRef4(null);
440
- const [isLoading, setIsLoading] = useState2(true);
441
- const [error, setError] = useState2(null);
442
- const [bridge, setBridge] = useState2(null);
443
- useEffect3(() => {
444
- let mounted = true;
445
- let currentBridge = null;
446
- async function mountExtension2() {
447
- if (!containerRef.current) {
448
- return;
449
- }
450
- try {
451
- setIsLoading(true);
452
- setError(null);
453
- await registry.executeActionsChain({
454
- action: {
455
- type: FRONTX_ACTION_MOUNT_EXT,
456
- target: domainId,
457
- payload: {
458
- extensionId
459
- }
460
- }
461
- });
462
- if (!mounted) {
463
- await registry.executeActionsChain({
464
- action: {
465
- type: FRONTX_ACTION_UNMOUNT_EXT,
466
- target: domainId,
467
- payload: {
468
- extensionId
469
- }
470
- }
471
- });
472
- return;
473
- }
474
- const newBridge = registry.getParentBridge(extensionId);
475
- if (!newBridge) {
476
- throw new Error(`Failed to obtain bridge for extension ${extensionId} after mount`);
477
- }
478
- currentBridge = newBridge;
479
- setBridge(newBridge);
480
- setIsLoading(false);
481
- if (onMounted) {
482
- onMounted(newBridge);
483
- }
484
- } catch (err) {
485
- if (!mounted) {
486
- return;
487
- }
488
- const errorObj = err instanceof Error ? err : new Error(String(err));
489
- setError(errorObj);
490
- setIsLoading(false);
491
- if (onError) {
492
- onError(errorObj);
493
- }
494
- }
1389
+ const rootRef = useRef5(null);
1390
+ const emitAttached = useEffectEvent((root) => {
1391
+ onAttached?.(root);
1392
+ });
1393
+ const emitDetached = useEffectEvent(() => {
1394
+ onDetached?.();
1395
+ });
1396
+ const [attached, setAttached] = useState5(false);
1397
+ useEffect7(() => {
1398
+ const root = rootRef.current;
1399
+ if (!root) {
1400
+ return;
495
1401
  }
496
- void mountExtension2();
1402
+ const mounter = registry.getMounter(domainId);
1403
+ mounter.attach(root);
1404
+ setAttached(true);
1405
+ emitAttached(root);
497
1406
  return () => {
498
- mounted = false;
499
- if (currentBridge) {
500
- void registry.executeActionsChain({
501
- action: {
502
- type: FRONTX_ACTION_UNMOUNT_EXT,
503
- target: domainId,
504
- payload: {
505
- extensionId
506
- }
507
- }
508
- }).then(() => {
509
- if (onUnmounted) {
510
- onUnmounted();
511
- }
512
- });
513
- }
1407
+ const detachPromise = mounter.detach();
1408
+ registerDomainTeardown(detachPromise);
1409
+ setAttached(false);
1410
+ emitDetached();
514
1411
  };
515
- }, [registry, domainId, extensionId, onMounted, onUnmounted, onError]);
516
- if (isLoading) {
517
- return /* @__PURE__ */ jsx3("div", { className, "data-domain-id": domainId, "data-extension-id": extensionId, children: loadingComponent ?? /* @__PURE__ */ jsx3("div", { children: "Loading extension..." }) });
518
- }
519
- if (error) {
520
- return /* @__PURE__ */ jsx3("div", { className, "data-domain-id": domainId, "data-extension-id": extensionId, children: errorComponent ? errorComponent(error) : /* @__PURE__ */ jsxs("div", { children: [
521
- /* @__PURE__ */ jsx3("strong", { children: "Error loading extension:" }),
522
- /* @__PURE__ */ jsx3("pre", { children: error.message })
523
- ] }) });
524
- }
525
- return /* @__PURE__ */ jsx3(
1412
+ }, [registry, domainId]);
1413
+ return /* @__PURE__ */ jsx5(
526
1414
  "div",
527
1415
  {
528
- ref: containerRef,
1416
+ ref: rootRef,
529
1417
  className,
530
1418
  "data-domain-id": domainId,
531
- "data-extension-id": extensionId,
532
- "data-bridge-active": bridge !== null
1419
+ children: !attached ? loadingComponent : null
533
1420
  }
534
1421
  );
535
1422
  }
536
1423
 
537
1424
  // src/index.ts
538
1425
  import {
539
- createHAI3,
540
- createHAI3App as createHAI3App2,
1426
+ createFrontX,
541
1427
  presets,
542
1428
  ACCOUNTS_DOMAIN,
543
1429
  I18nRegistry,
544
- screensets,
545
1430
  themes,
546
1431
  layout,
547
1432
  i18n,
548
1433
  effects,
1434
+ queryCache,
1435
+ queryCacheShared,
1436
+ subscribeQueryCacheRuntimeChanged as subscribeQueryCacheRuntimeChanged2,
549
1437
  createThemeRegistry,
550
1438
  createStore,
551
1439
  getStore,
552
1440
  registerSlice,
553
1441
  hasSlice,
554
1442
  createSlice,
555
- LayoutDomain,
556
1443
  layoutReducer,
557
1444
  layoutDomainReducers,
558
1445
  LAYOUT_SLICE_NAME,
@@ -560,14 +1447,12 @@ import {
560
1447
  footerSlice,
561
1448
  menuSlice,
562
1449
  sidebarSlice,
563
- screenSlice,
564
1450
  popupSlice,
565
1451
  overlaySlice,
566
1452
  headerActions,
567
1453
  footerActions,
568
1454
  menuActions,
569
1455
  sidebarActions,
570
- screenActions,
571
1456
  popupActions,
572
1457
  overlayActions,
573
1458
  setUser,
@@ -588,10 +1473,6 @@ import {
588
1473
  setSidebarVisible,
589
1474
  setSidebarWidth,
590
1475
  setSidebarConfig,
591
- setActiveScreen,
592
- setScreenLoading,
593
- navigateTo,
594
- clearActiveScreen,
595
1476
  openPopup,
596
1477
  closePopup,
597
1478
  closeTopPopup,
@@ -617,13 +1498,15 @@ import {
617
1498
  initMockEffects,
618
1499
  toggleMockMode,
619
1500
  MockEvents,
1501
+ auth,
1502
+ AuthEvents,
1503
+ frontxApiTransport,
620
1504
  apiRegistry,
621
1505
  BaseApiService,
622
1506
  RestProtocol,
1507
+ RestEndpointProtocol,
623
1508
  SseProtocol,
624
- RestMockPlugin,
625
- SseMockPlugin,
626
- MockEventSource,
1509
+ SseStreamProtocol,
627
1510
  ApiPluginBase,
628
1511
  ApiPlugin,
629
1512
  ApiProtocol,
@@ -662,7 +1545,7 @@ import {
662
1545
  import {
663
1546
  FRONTX_POPUP_DOMAIN,
664
1547
  FRONTX_SIDEBAR_DOMAIN,
665
- FRONTX_SCREEN_DOMAIN as FRONTX_SCREEN_DOMAIN2,
1548
+ FRONTX_SCREEN_DOMAIN,
666
1549
  FRONTX_OVERLAY_DOMAIN,
667
1550
  screenDomain,
668
1551
  sidebarDomain,
@@ -675,102 +1558,118 @@ import {
675
1558
  } from "@gears-frontx/framework";
676
1559
  import {
677
1560
  FRONTX_ACTION_LOAD_EXT,
678
- FRONTX_ACTION_MOUNT_EXT as FRONTX_ACTION_MOUNT_EXT2,
679
- FRONTX_ACTION_UNMOUNT_EXT as FRONTX_ACTION_UNMOUNT_EXT2
1561
+ FRONTX_ACTION_MOUNT_EXT,
1562
+ FRONTX_ACTION_UNMOUNT_EXT
680
1563
  } from "@gears-frontx/framework";
681
1564
  import {
682
1565
  FRONTX_SHARED_PROPERTY_THEME,
683
1566
  FRONTX_SHARED_PROPERTY_LANGUAGE
684
1567
  } from "@gears-frontx/framework";
685
1568
  import {
1569
+ ChildMfeBridge,
1570
+ ParentMfeBridge,
686
1571
  MfeHandler,
687
1572
  MfeBridgeFactory,
688
- ScreensetsRegistry,
689
- ScreensetsRegistryFactory,
690
- screensetsRegistryFactory,
691
- ContainerProvider as ContainerProvider2
1573
+ MfeRegistry,
1574
+ MfeRegistryFactory,
1575
+ mfeRegistryFactory,
1576
+ ActionHandler,
1577
+ ExtensionDomainImplementation,
1578
+ ExtensionDomainImplementationFactory,
1579
+ ExtensionMounter,
1580
+ MountStrategy,
1581
+ ConcurrentMountStrategy,
1582
+ OptionalMountStrategy,
1583
+ ExclusiveMountStrategy
692
1584
  } from "@gears-frontx/framework";
693
1585
  import { MfeHandlerMF, gtsPlugin } from "@gears-frontx/framework";
694
- import { themeSchema, languageSchema, extensionScreenSchema } from "@gears-frontx/framework";
695
1586
  import {
696
1587
  createShadowRoot,
697
1588
  injectCssVariables,
698
- extractGtsPackage as extractGtsPackage2
1589
+ extractGtsPackage
699
1590
  } from "@gears-frontx/framework";
700
1591
  import { eventBus as frameworkEventBus } from "@gears-frontx/framework";
701
- var eventBus = frameworkEventBus;
1592
+ var eventBus2 = frameworkEventBus;
702
1593
  export {
703
1594
  ACCOUNTS_DOMAIN,
1595
+ ActionHandler,
704
1596
  ApiPlugin,
705
1597
  ApiPluginBase,
706
1598
  ApiProtocol,
1599
+ AuthEvents,
707
1600
  BaseApiService,
708
- ContainerProvider2 as ContainerProvider,
1601
+ CanAccess,
1602
+ ChildMfeBridge,
1603
+ ConcurrentMountStrategy,
1604
+ ExclusiveMountStrategy,
1605
+ ExtensionDomainImplementation,
1606
+ ExtensionDomainImplementationFactory,
709
1607
  ExtensionDomainSlot,
1608
+ ExtensionMounter,
710
1609
  FRONTX_ACTION_LOAD_EXT,
711
- FRONTX_ACTION_MOUNT_EXT2 as FRONTX_ACTION_MOUNT_EXT,
712
- FRONTX_ACTION_UNMOUNT_EXT2 as FRONTX_ACTION_UNMOUNT_EXT,
1610
+ FRONTX_ACTION_MOUNT_EXT,
1611
+ FRONTX_ACTION_UNMOUNT_EXT,
713
1612
  FRONTX_MFE_ENTRY_MF,
714
1613
  FRONTX_OVERLAY_DOMAIN,
715
1614
  FRONTX_POPUP_DOMAIN,
716
- FRONTX_SCREEN_DOMAIN2 as FRONTX_SCREEN_DOMAIN,
1615
+ FRONTX_SCREEN_DOMAIN,
717
1616
  FRONTX_SCREEN_EXTENSION_TYPE,
718
1617
  FRONTX_SHARED_PROPERTY_LANGUAGE,
719
1618
  FRONTX_SHARED_PROPERTY_THEME,
720
1619
  FRONTX_SIDEBAR_DOMAIN,
721
- HAI3Context,
722
- HAI3Provider,
1620
+ FrontXContext,
1621
+ FrontXProvider,
723
1622
  I18nRegistry,
724
1623
  I18nRegistryImpl,
725
1624
  LAYOUT_SLICE_NAME,
726
1625
  Language,
727
1626
  LanguageDisplayMode,
728
- LayoutDomain,
729
1627
  MOCK_PLUGIN,
730
1628
  MfeBridgeFactory,
731
1629
  MfeContext,
732
1630
  MfeHandler,
733
1631
  MfeHandlerMF,
734
1632
  MfeProvider,
735
- MockEventSource,
1633
+ MfeRegistry,
1634
+ MfeRegistryFactory,
736
1635
  MockEvents,
737
- RefContainerProvider,
738
- RestMockPlugin,
1636
+ MountStrategy,
1637
+ OptionalMountStrategy,
1638
+ ParentMfeBridge,
1639
+ RestEndpointProtocol,
739
1640
  RestPlugin,
740
1641
  RestPluginWithConfig,
741
1642
  RestProtocol,
742
1643
  SUPPORTED_LANGUAGES,
743
- ScreensetsRegistry,
744
- ScreensetsRegistryFactory,
745
- SseMockPlugin,
746
1644
  SsePlugin,
747
1645
  SsePluginWithConfig,
748
1646
  SseProtocol,
1647
+ SseStreamProtocol,
749
1648
  TENANT_SLICE_NAME,
750
1649
  TenantEvents,
751
1650
  TextDirection,
1651
+ ThemeAwareReactLifecycle,
752
1652
  apiRegistry,
1653
+ auth,
753
1654
  changeTenant,
754
- clearActiveScreen,
755
1655
  clearTenant,
756
1656
  clearTenantAction,
757
1657
  clearUser,
758
1658
  closeAllPopups,
759
1659
  closePopup,
760
1660
  closeTopPopup,
761
- createHAI3,
762
- createHAI3App2 as createHAI3App,
1661
+ createFrontX,
763
1662
  createI18nRegistry,
764
1663
  createShadowRoot,
765
1664
  createSlice,
766
1665
  createStore,
767
1666
  createThemeRegistry,
768
1667
  effects,
769
- eventBus,
770
- extensionScreenSchema,
771
- extractGtsPackage2 as extractGtsPackage,
1668
+ eventBus2 as eventBus,
1669
+ extractGtsPackage,
772
1670
  footerActions,
773
1671
  footerSlice,
1672
+ frontxApiTransport,
774
1673
  getLanguageMetadata,
775
1674
  getStore,
776
1675
  gtsPlugin,
@@ -783,23 +1682,23 @@ export {
783
1682
  initMockEffects,
784
1683
  initTenantEffects,
785
1684
  injectCssVariables,
1685
+ invalidateQueryCacheForApp,
786
1686
  isMockPlugin,
787
1687
  isRestShortCircuit,
788
1688
  isShortCircuit,
789
1689
  isSseShortCircuit,
790
- languageSchema,
791
1690
  layout,
792
1691
  layoutDomainReducers,
793
1692
  layoutReducer,
794
1693
  loadExtension,
795
1694
  menuActions,
796
1695
  menuSlice,
1696
+ mfeRegistryFactory,
797
1697
  microfrontends,
798
1698
  mock,
799
1699
  mockActions,
800
1700
  mockSlice,
801
1701
  mountExtension,
802
- navigateTo,
803
1702
  openPopup,
804
1703
  overlayActions,
805
1704
  overlayDomain,
@@ -808,17 +1707,14 @@ export {
808
1707
  popupDomain,
809
1708
  popupSlice,
810
1709
  presets,
1710
+ queryCache,
1711
+ queryCacheShared,
811
1712
  registerExtension,
812
1713
  registerSlice,
813
- screenActions,
814
1714
  screenDomain,
815
- screenSlice,
816
- screensets,
817
- screensetsRegistryFactory,
818
1715
  selectExtensionError,
819
1716
  selectExtensionState,
820
1717
  selectRegisteredExtensions,
821
- setActiveScreen,
822
1718
  setFooterConfig,
823
1719
  setFooterVisible,
824
1720
  setHeaderLoading,
@@ -828,7 +1724,6 @@ export {
828
1724
  setMenuVisible,
829
1725
  setMockEnabled,
830
1726
  setOverlayVisible,
831
- setScreenLoading,
832
1727
  setSidebarCollapsed,
833
1728
  setSidebarConfig,
834
1729
  setSidebarContent,
@@ -844,25 +1739,33 @@ export {
844
1739
  sidebarActions,
845
1740
  sidebarDomain,
846
1741
  sidebarSlice,
1742
+ subscribeQueryCacheRuntimeChanged2 as subscribeQueryCacheRuntimeChanged,
847
1743
  tenantActions,
848
1744
  tenantReducer,
849
1745
  tenantSlice,
850
- themeSchema,
851
1746
  themes,
852
1747
  toggleMenu,
853
1748
  toggleMockMode,
854
1749
  toggleSidebar,
855
1750
  unmountExtension,
856
1751
  unregisterExtension,
857
- useActivePackage,
1752
+ useApiInfiniteQuery,
1753
+ useApiMutation,
1754
+ useApiQuery,
1755
+ useApiStream,
1756
+ useApiSuspenseInfiniteQuery,
1757
+ useApiSuspenseQuery,
858
1758
  useAppDispatch,
859
1759
  useAppSelector,
1760
+ useCanAccess,
860
1761
  useDomainExtensions,
861
1762
  useFormatters,
862
- useHAI3,
1763
+ useFrontX,
863
1764
  useHostAction,
864
1765
  useMfeBridge,
865
1766
  useMfeContext,
1767
+ useMfeRegistry,
1768
+ useQueryCache,
866
1769
  useRegisteredPackages,
867
1770
  useScreenTranslations,
868
1771
  useSharedProperty,