@gears-frontx/react 0.2.0-alpha.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/CLAUDE.md +118 -61
- package/dist/index.cjs +607 -426
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +365 -100
- package/dist/index.d.ts +365 -100
- package/dist/index.js +437 -253
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +7 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +7 -2
- package/dist/testing.js.map +1 -1
- package/dist/{types-Cjd20AT-.d.cts → types-JtpziA_B.d.cts} +5 -12
- package/dist/{types-Cjd20AT-.d.ts → types-JtpziA_B.d.ts} +5 -12
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/llms.txt +38 -12
- package/package.json +20 -15
- package/commands/frontx-duplicate-screenset.md +0 -58
- package/commands/frontx-new-component.md +0 -57
- package/commands/frontx-new-mfe.md +0 -153
- package/commands/frontx-new-screen.md +0 -45
- package/commands/frontx-new-screenset.md +0 -57
package/dist/index.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
// src/FrontXProvider.tsx
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect as useEffect3 } from "react";
|
|
3
3
|
import { Provider as ReduxProvider } from "react-redux";
|
|
4
|
-
import {
|
|
5
|
-
createFrontXApp
|
|
6
|
-
} from "@gears-frontx/framework";
|
|
7
4
|
|
|
8
5
|
// src/FrontXContext.tsx
|
|
9
6
|
import { createContext, useContext } from "react";
|
|
@@ -41,7 +38,7 @@ var MfeProvider = ({ value, children }) => {
|
|
|
41
38
|
import React, {
|
|
42
39
|
createContext as createContext3,
|
|
43
40
|
useContext as useContext3,
|
|
44
|
-
useEffect,
|
|
41
|
+
useEffect as useEffect2,
|
|
45
42
|
useLayoutEffect,
|
|
46
43
|
useMemo,
|
|
47
44
|
useState
|
|
@@ -56,6 +53,8 @@ import {
|
|
|
56
53
|
useSuspenseQuery
|
|
57
54
|
} from "@tanstack/react-query";
|
|
58
55
|
import {
|
|
56
|
+
readQueryCacheScopeGeneration,
|
|
57
|
+
recordQueryCacheScopeWriteDropped,
|
|
59
58
|
subscribeQueryCacheRuntimeChanged
|
|
60
59
|
} from "@gears-frontx/framework";
|
|
61
60
|
|
|
@@ -164,13 +163,23 @@ function createQueryCache(queryClient) {
|
|
|
164
163
|
};
|
|
165
164
|
}
|
|
166
165
|
|
|
166
|
+
// src/hooks/useLatest.ts
|
|
167
|
+
import { useEffect, useRef } from "react";
|
|
168
|
+
function useLatest(value) {
|
|
169
|
+
const ref = useRef(value);
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
ref.current = value;
|
|
172
|
+
});
|
|
173
|
+
return ref;
|
|
174
|
+
}
|
|
175
|
+
|
|
167
176
|
// src/queryClient.tsx
|
|
168
177
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
169
178
|
var APP_QUERY_CLIENT_SYMBOL = /* @__PURE__ */ Symbol.for("frontx:query-cache:app-client");
|
|
170
179
|
var APP_QUERY_CLIENT_RESOLVER_SYMBOL = /* @__PURE__ */ Symbol.for("frontx:query-cache:app-client-resolver");
|
|
171
180
|
var APP_QUERY_CLIENT_ACTIVATOR_SYMBOL = /* @__PURE__ */ Symbol.for("frontx:query-cache:app-client-activator");
|
|
172
181
|
var FrontXQueryClientContext = createContext3(void 0);
|
|
173
|
-
var useCommitEffect = typeof globalThis.window === "undefined" ?
|
|
182
|
+
var useCommitEffect = typeof globalThis.window === "undefined" ? useEffect2 : useLayoutEffect;
|
|
174
183
|
function resolveFrontXQueryClient(app) {
|
|
175
184
|
const clientApp = app;
|
|
176
185
|
return clientApp[APP_QUERY_CLIENT_SYMBOL] ?? clientApp[APP_QUERY_CLIENT_RESOLVER_SYMBOL]?.();
|
|
@@ -261,24 +270,45 @@ function normalizeFetchStaleTime(staleTime) {
|
|
|
261
270
|
if (staleTime === "static") {
|
|
262
271
|
return Number.POSITIVE_INFINITY;
|
|
263
272
|
}
|
|
273
|
+
if (typeof staleTime === "function") {
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
264
276
|
return typeof staleTime === "number" ? staleTime : void 0;
|
|
265
277
|
}
|
|
266
|
-
function resolveFetchStaleTime(queryClient, descriptor, overrideStaleTime) {
|
|
278
|
+
function resolveFetchStaleTime(queryClient, queryKey, descriptor, overrideStaleTime) {
|
|
279
|
+
const clientDefaults = {
|
|
280
|
+
...queryClient.getDefaultOptions().queries,
|
|
281
|
+
...queryClient.getQueryDefaults(queryKey)
|
|
282
|
+
};
|
|
267
283
|
return normalizeFetchStaleTime(
|
|
268
|
-
overrideStaleTime ?? descriptor.staleTime ??
|
|
284
|
+
overrideStaleTime ?? descriptor.staleTime ?? clientDefaults.staleTime
|
|
269
285
|
);
|
|
270
286
|
}
|
|
287
|
+
function cacheTimeOptions(staleTime, gcTime) {
|
|
288
|
+
return {
|
|
289
|
+
...staleTime === void 0 ? {} : { staleTime },
|
|
290
|
+
...gcTime === void 0 ? {} : { gcTime }
|
|
291
|
+
};
|
|
292
|
+
}
|
|
271
293
|
function fetchDescriptor(descriptor, options) {
|
|
272
294
|
return descriptor.fetch(options);
|
|
273
295
|
}
|
|
274
296
|
function useFrontXQuery(descriptor, overrides) {
|
|
275
297
|
const queryClient = useRequiredFrontXQueryClient();
|
|
276
|
-
const staleTime = resolveFetchStaleTime(
|
|
298
|
+
const staleTime = resolveFetchStaleTime(
|
|
299
|
+
queryClient,
|
|
300
|
+
descriptor.key,
|
|
301
|
+
descriptor,
|
|
302
|
+
overrides?.staleTime
|
|
303
|
+
);
|
|
277
304
|
const result = useQuery({
|
|
278
305
|
queryKey: descriptor.key,
|
|
279
306
|
queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),
|
|
280
|
-
|
|
281
|
-
|
|
307
|
+
...cacheTimeOptions(
|
|
308
|
+
overrides?.staleTime ?? descriptor.staleTime,
|
|
309
|
+
overrides?.gcTime ?? descriptor.gcTime
|
|
310
|
+
),
|
|
311
|
+
...overrides?.enabled === void 0 ? {} : { enabled: overrides.enabled }
|
|
282
312
|
});
|
|
283
313
|
return {
|
|
284
314
|
data: result.data,
|
|
@@ -291,12 +321,19 @@ function useFrontXQuery(descriptor, overrides) {
|
|
|
291
321
|
}
|
|
292
322
|
function useFrontXSuspenseQuery(descriptor, overrides) {
|
|
293
323
|
const queryClient = useRequiredFrontXQueryClient();
|
|
294
|
-
const staleTime = resolveFetchStaleTime(
|
|
324
|
+
const staleTime = resolveFetchStaleTime(
|
|
325
|
+
queryClient,
|
|
326
|
+
descriptor.key,
|
|
327
|
+
descriptor,
|
|
328
|
+
overrides?.staleTime
|
|
329
|
+
);
|
|
295
330
|
const result = useSuspenseQuery({
|
|
296
331
|
queryKey: descriptor.key,
|
|
297
332
|
queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),
|
|
298
|
-
|
|
299
|
-
|
|
333
|
+
...cacheTimeOptions(
|
|
334
|
+
overrides?.staleTime ?? descriptor.staleTime,
|
|
335
|
+
overrides?.gcTime ?? descriptor.gcTime
|
|
336
|
+
)
|
|
300
337
|
});
|
|
301
338
|
return {
|
|
302
339
|
data: result.data,
|
|
@@ -314,7 +351,12 @@ function useFrontXInfiniteQuery(options) {
|
|
|
314
351
|
initialPageParam: options.initialPage,
|
|
315
352
|
queryFn: ({ pageParam, signal }) => fetchDescriptor(pageParam, {
|
|
316
353
|
signal,
|
|
317
|
-
staleTime: resolveFetchStaleTime(
|
|
354
|
+
staleTime: resolveFetchStaleTime(
|
|
355
|
+
queryClient,
|
|
356
|
+
options.initialPage.key,
|
|
357
|
+
pageParam,
|
|
358
|
+
options.staleTime
|
|
359
|
+
)
|
|
318
360
|
}),
|
|
319
361
|
getNextPageParam: (lastPage, allPages, lastPageDescriptor, allPageDescriptors) => options.getNextPage(
|
|
320
362
|
buildPageContext(
|
|
@@ -333,9 +375,12 @@ function useFrontXInfiniteQuery(options) {
|
|
|
333
375
|
)
|
|
334
376
|
) : void 0,
|
|
335
377
|
select: (data) => data.pages,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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 }
|
|
339
384
|
});
|
|
340
385
|
return {
|
|
341
386
|
data: result.data,
|
|
@@ -365,7 +410,12 @@ function useFrontXSuspenseInfiniteQuery(options) {
|
|
|
365
410
|
initialPageParam: options.initialPage,
|
|
366
411
|
queryFn: ({ pageParam, signal }) => fetchDescriptor(pageParam, {
|
|
367
412
|
signal,
|
|
368
|
-
staleTime: resolveFetchStaleTime(
|
|
413
|
+
staleTime: resolveFetchStaleTime(
|
|
414
|
+
queryClient,
|
|
415
|
+
options.initialPage.key,
|
|
416
|
+
pageParam,
|
|
417
|
+
options.staleTime
|
|
418
|
+
)
|
|
369
419
|
}),
|
|
370
420
|
getNextPageParam: (lastPage, allPages, lastPageDescriptor, allPageDescriptors) => options.getNextPage(
|
|
371
421
|
buildPageContext(
|
|
@@ -384,8 +434,10 @@ function useFrontXSuspenseInfiniteQuery(options) {
|
|
|
384
434
|
)
|
|
385
435
|
) : void 0,
|
|
386
436
|
select: (data) => data.pages,
|
|
387
|
-
|
|
388
|
-
|
|
437
|
+
...cacheTimeOptions(
|
|
438
|
+
options.staleTime ?? options.initialPage.staleTime,
|
|
439
|
+
options.gcTime ?? options.initialPage.gcTime
|
|
440
|
+
),
|
|
389
441
|
maxPages: options.maxPages
|
|
390
442
|
});
|
|
391
443
|
return {
|
|
@@ -407,20 +459,46 @@ function useFrontXSuspenseInfiniteQuery(options) {
|
|
|
407
459
|
}
|
|
408
460
|
};
|
|
409
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
|
+
}
|
|
410
487
|
function useFrontXMutation(options, callbackCtx) {
|
|
411
|
-
useRequiredFrontXQueryClient();
|
|
412
|
-
const latestRef =
|
|
413
|
-
latestRef.current = { options, callbackCtx };
|
|
488
|
+
const queryClient = useRequiredFrontXQueryClient();
|
|
489
|
+
const latestRef = useLatest({ options, callbackCtx, queryClient });
|
|
414
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
|
+
});
|
|
415
499
|
React.useEffect(() => {
|
|
416
|
-
const fetchAbortControllers = fetchAbortControllersRef.current;
|
|
417
500
|
return () => {
|
|
418
|
-
|
|
419
|
-
for (const controller of fetchAbortControllers) {
|
|
420
|
-
controller.abort();
|
|
421
|
-
}
|
|
422
|
-
fetchAbortControllers.clear();
|
|
423
|
-
}
|
|
501
|
+
abortFetchesOnUnmount();
|
|
424
502
|
};
|
|
425
503
|
}, []);
|
|
426
504
|
const mutationFn = React.useCallback((variables, context) => {
|
|
@@ -444,35 +522,50 @@ function useFrontXMutation(options, callbackCtx) {
|
|
|
444
522
|
return latestRef.current.options.endpoint.fetch(variables, { signal: controller.signal }).finally(() => {
|
|
445
523
|
fetchAbortControllersRef.current.delete(controller);
|
|
446
524
|
});
|
|
447
|
-
}, []);
|
|
448
|
-
const onMutate = React.useCallback((variables,
|
|
525
|
+
}, [latestRef]);
|
|
526
|
+
const onMutate = React.useCallback(async (variables, mutationFnContext) => {
|
|
449
527
|
const current = latestRef.current;
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
528
|
+
const scope = {
|
|
529
|
+
queryClient: current.queryClient,
|
|
530
|
+
generation: readQueryCacheScopeGeneration(current.queryClient)
|
|
531
|
+
};
|
|
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) => {
|
|
456
539
|
const current = latestRef.current;
|
|
457
|
-
return current.options.onSuccess?.(
|
|
458
|
-
|
|
459
|
-
|
|
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) => {
|
|
460
548
|
const current = latestRef.current;
|
|
461
|
-
return current.options.onError?.(
|
|
462
|
-
|
|
463
|
-
|
|
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) => {
|
|
464
557
|
const current = latestRef.current;
|
|
465
558
|
return current.options.onSettled?.(
|
|
466
559
|
data,
|
|
467
560
|
error,
|
|
468
561
|
variables,
|
|
469
562
|
context,
|
|
470
|
-
current.callbackCtx
|
|
563
|
+
scopeBoundCallbackCtx(current.callbackCtx, mutationScopes.get(mutationFnContext))
|
|
471
564
|
);
|
|
472
|
-
}, []);
|
|
565
|
+
}, [latestRef]);
|
|
473
566
|
const mutation = useMutation({
|
|
474
567
|
mutationFn,
|
|
475
|
-
onMutate
|
|
568
|
+
onMutate,
|
|
476
569
|
onSuccess: options.onSuccess ? onSuccess : void 0,
|
|
477
570
|
onError: options.onError ? onError : void 0,
|
|
478
571
|
onSettled: options.onSettled ? onSettled : void 0
|
|
@@ -489,38 +582,14 @@ function useFrontXMutation(options, callbackCtx) {
|
|
|
489
582
|
|
|
490
583
|
// src/FrontXProvider.tsx
|
|
491
584
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
492
|
-
function shallowEqual(a, b) {
|
|
493
|
-
if (a === b) return true;
|
|
494
|
-
if (!a || !b) return false;
|
|
495
|
-
const keysA = Object.keys(a);
|
|
496
|
-
if (keysA.length !== Object.keys(b).length) return false;
|
|
497
|
-
return keysA.every((k) => Object.is(a[k], b[k]));
|
|
498
|
-
}
|
|
499
|
-
function createProviderOwnedApp(config) {
|
|
500
|
-
return createFrontXApp(config);
|
|
501
|
-
}
|
|
502
585
|
var FrontXProvider = ({
|
|
503
586
|
children,
|
|
504
|
-
|
|
505
|
-
app: providedApp,
|
|
587
|
+
app,
|
|
506
588
|
mfeBridge
|
|
507
589
|
}) => {
|
|
508
|
-
const [stableConfig, setStableConfig] = useState2(config);
|
|
509
|
-
if (!shallowEqual(
|
|
510
|
-
stableConfig,
|
|
511
|
-
config
|
|
512
|
-
)) {
|
|
513
|
-
setStableConfig(config);
|
|
514
|
-
}
|
|
515
|
-
const app = useMemo2(() => {
|
|
516
|
-
if (providedApp) {
|
|
517
|
-
return providedApp;
|
|
518
|
-
}
|
|
519
|
-
return createProviderOwnedApp(stableConfig);
|
|
520
|
-
}, [providedApp, stableConfig]);
|
|
521
590
|
const queryClient = useBootstrappedFrontXQueryClient(app);
|
|
522
591
|
const deferQuerySubtree = hasFrontXQueryClientActivator(app) && queryClient === void 0;
|
|
523
|
-
|
|
592
|
+
useEffect3(() => {
|
|
524
593
|
if (queryClient || hasFrontXQueryClientActivator(app) || process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test" || process.env.VITEST === "true") {
|
|
525
594
|
return;
|
|
526
595
|
}
|
|
@@ -528,13 +597,6 @@ var FrontXProvider = ({
|
|
|
528
597
|
"[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition. useApiQuery/useApiMutation will fail without it."
|
|
529
598
|
);
|
|
530
599
|
}, [app, queryClient]);
|
|
531
|
-
useEffect2(() => {
|
|
532
|
-
return () => {
|
|
533
|
-
if (!providedApp) {
|
|
534
|
-
app.destroy();
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
}, [app, providedApp]);
|
|
538
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 }) }) });
|
|
539
601
|
if (mfeBridge) {
|
|
540
602
|
return /* @__PURE__ */ jsx3(MfeProvider, { value: mfeBridge, children: content });
|
|
@@ -543,7 +605,7 @@ var FrontXProvider = ({
|
|
|
543
605
|
};
|
|
544
606
|
|
|
545
607
|
// src/hooks/useCanAccess.ts
|
|
546
|
-
import { useEffect as
|
|
608
|
+
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
547
609
|
function serializeRecordValue(value) {
|
|
548
610
|
if (value === null) return "n:";
|
|
549
611
|
if (typeof value === "string") return `s:${value}`;
|
|
@@ -560,24 +622,23 @@ function accessQueryKey(query) {
|
|
|
560
622
|
function getAuthRuntime(app) {
|
|
561
623
|
return app.auth ?? null;
|
|
562
624
|
}
|
|
625
|
+
var DENIED_NO_AUTH = { allow: false, isResolving: false };
|
|
563
626
|
function useCanAccess(query) {
|
|
564
627
|
const app = useFrontX();
|
|
628
|
+
const auth2 = getAuthRuntime(app);
|
|
565
629
|
const stableKey = accessQueryKey(query);
|
|
566
|
-
const [stableQuery, setStableQuery] =
|
|
567
|
-
const [
|
|
568
|
-
const [result, setResult] =
|
|
569
|
-
if (
|
|
570
|
-
|
|
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 });
|
|
571
635
|
setStableQuery(query);
|
|
572
636
|
setResult({ allow: false, isResolving: true });
|
|
573
637
|
}
|
|
574
|
-
|
|
575
|
-
const auth2 = getAuthRuntime(app);
|
|
638
|
+
useEffect4(() => {
|
|
576
639
|
if (!auth2) {
|
|
577
|
-
setResult({ allow: false, isResolving: false });
|
|
578
640
|
return;
|
|
579
641
|
}
|
|
580
|
-
setResult({ allow: false, isResolving: true });
|
|
581
642
|
let alive = true;
|
|
582
643
|
const controller = new AbortController();
|
|
583
644
|
void auth2.canAccess(stableQuery, { signal: controller.signal }).then((decision) => {
|
|
@@ -593,8 +654,8 @@ function useCanAccess(query) {
|
|
|
593
654
|
alive = false;
|
|
594
655
|
controller.abort();
|
|
595
656
|
};
|
|
596
|
-
}, [
|
|
597
|
-
return result;
|
|
657
|
+
}, [auth2, stableQuery]);
|
|
658
|
+
return auth2 ? result : DENIED_NO_AUTH;
|
|
598
659
|
}
|
|
599
660
|
|
|
600
661
|
// src/components/CanAccess.tsx
|
|
@@ -622,7 +683,7 @@ import { useSelector } from "react-redux";
|
|
|
622
683
|
var useAppSelector = useSelector;
|
|
623
684
|
|
|
624
685
|
// src/hooks/useTranslation.ts
|
|
625
|
-
import { useMemo as
|
|
686
|
+
import { useMemo as useMemo2, useCallback, useSyncExternalStore } from "react";
|
|
626
687
|
function useTranslation() {
|
|
627
688
|
const app = useFrontX();
|
|
628
689
|
const { i18nRegistry: i18nRegistry2 } = app;
|
|
@@ -636,7 +697,7 @@ function useTranslation() {
|
|
|
636
697
|
() => i18nRegistry2.getVersion(),
|
|
637
698
|
() => i18nRegistry2.getVersion()
|
|
638
699
|
);
|
|
639
|
-
const language =
|
|
700
|
+
const language = useMemo2(() => {
|
|
640
701
|
void version;
|
|
641
702
|
return i18nRegistry2.getLanguage();
|
|
642
703
|
}, [i18nRegistry2, version]);
|
|
@@ -654,7 +715,7 @@ function useTranslation() {
|
|
|
654
715
|
},
|
|
655
716
|
[app.actions]
|
|
656
717
|
);
|
|
657
|
-
const isRTL =
|
|
718
|
+
const isRTL = useMemo2(() => {
|
|
658
719
|
void language;
|
|
659
720
|
return i18nRegistry2.isRTL();
|
|
660
721
|
}, [i18nRegistry2, language]);
|
|
@@ -667,16 +728,15 @@ function useTranslation() {
|
|
|
667
728
|
}
|
|
668
729
|
|
|
669
730
|
// src/hooks/useScreenTranslations.ts
|
|
670
|
-
import { useState as
|
|
731
|
+
import { useState as useState3, useEffect as useEffect5, useMemo as useMemo3, useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
671
732
|
function isTranslationLoader(input) {
|
|
672
733
|
return typeof input === "function";
|
|
673
734
|
}
|
|
674
735
|
function useScreenTranslations(screensetId, screenId, translations) {
|
|
675
736
|
const app = useFrontX();
|
|
676
737
|
const { i18nRegistry: i18nRegistry2 } = app;
|
|
677
|
-
const [loadedLanguage, setLoadedLanguage] =
|
|
678
|
-
const [
|
|
679
|
-
const [error, setError] = useState4(null);
|
|
738
|
+
const [loadedLanguage, setLoadedLanguage] = useState3(null);
|
|
739
|
+
const [error, setError] = useState3(null);
|
|
680
740
|
const version = useSyncExternalStore2(
|
|
681
741
|
useCallback2(
|
|
682
742
|
(callback) => i18nRegistry2.subscribe(callback),
|
|
@@ -685,11 +745,11 @@ function useScreenTranslations(screensetId, screenId, translations) {
|
|
|
685
745
|
() => i18nRegistry2.getVersion(),
|
|
686
746
|
() => i18nRegistry2.getVersion()
|
|
687
747
|
);
|
|
688
|
-
const currentLanguage =
|
|
748
|
+
const currentLanguage = useMemo3(() => {
|
|
689
749
|
void version;
|
|
690
750
|
return i18nRegistry2.getLanguage();
|
|
691
751
|
}, [i18nRegistry2, version]);
|
|
692
|
-
const loader =
|
|
752
|
+
const loader = useMemo3(() => {
|
|
693
753
|
if (isTranslationLoader(translations)) {
|
|
694
754
|
return translations;
|
|
695
755
|
}
|
|
@@ -702,12 +762,11 @@ function useScreenTranslations(screensetId, screenId, translations) {
|
|
|
702
762
|
return module.default;
|
|
703
763
|
};
|
|
704
764
|
}, [translations]);
|
|
705
|
-
|
|
765
|
+
useEffect5(() => {
|
|
706
766
|
if (!currentLanguage || currentLanguage === loadedLanguage) {
|
|
707
767
|
return;
|
|
708
768
|
}
|
|
709
769
|
let cancelled = false;
|
|
710
|
-
setIsLoading(true);
|
|
711
770
|
const loadTranslations = async () => {
|
|
712
771
|
try {
|
|
713
772
|
const namespace = `screen.${screensetId}.${screenId}`;
|
|
@@ -716,13 +775,11 @@ function useScreenTranslations(screensetId, screenId, translations) {
|
|
|
716
775
|
i18nRegistry2.register(namespace, currentLanguage, loadedTranslations);
|
|
717
776
|
if (!cancelled) {
|
|
718
777
|
setLoadedLanguage(currentLanguage);
|
|
719
|
-
setIsLoading(false);
|
|
720
778
|
setError(null);
|
|
721
779
|
}
|
|
722
780
|
} catch (err) {
|
|
723
781
|
if (!cancelled) {
|
|
724
782
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
725
|
-
setIsLoading(false);
|
|
726
783
|
}
|
|
727
784
|
}
|
|
728
785
|
};
|
|
@@ -731,12 +788,12 @@ function useScreenTranslations(screensetId, screenId, translations) {
|
|
|
731
788
|
cancelled = true;
|
|
732
789
|
};
|
|
733
790
|
}, [screensetId, screenId, loader, i18nRegistry2, currentLanguage, loadedLanguage]);
|
|
734
|
-
const isLoaded = currentLanguage !== null && currentLanguage === loadedLanguage
|
|
791
|
+
const isLoaded = currentLanguage !== null && currentLanguage === loadedLanguage;
|
|
735
792
|
return { isLoaded, error };
|
|
736
793
|
}
|
|
737
794
|
|
|
738
795
|
// src/hooks/useFormatters.ts
|
|
739
|
-
import { useMemo as
|
|
796
|
+
import { useMemo as useMemo4 } from "react";
|
|
740
797
|
import {
|
|
741
798
|
formatDate as formatDateFn,
|
|
742
799
|
formatTime as formatTimeFn,
|
|
@@ -751,7 +808,7 @@ import {
|
|
|
751
808
|
} from "@gears-frontx/framework";
|
|
752
809
|
function useFormatters() {
|
|
753
810
|
const { language } = useTranslation();
|
|
754
|
-
return
|
|
811
|
+
return useMemo4(
|
|
755
812
|
() => {
|
|
756
813
|
void language;
|
|
757
814
|
return {
|
|
@@ -772,7 +829,7 @@ function useFormatters() {
|
|
|
772
829
|
}
|
|
773
830
|
|
|
774
831
|
// src/hooks/useTheme.ts
|
|
775
|
-
import { useCallback as useCallback3, useMemo as
|
|
832
|
+
import { useCallback as useCallback3, useMemo as useMemo5, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
776
833
|
function useTheme() {
|
|
777
834
|
const app = useFrontX();
|
|
778
835
|
const { themeRegistry } = app;
|
|
@@ -786,12 +843,12 @@ function useTheme() {
|
|
|
786
843
|
() => themeRegistry.getVersion(),
|
|
787
844
|
() => themeRegistry.getVersion()
|
|
788
845
|
);
|
|
789
|
-
const currentTheme =
|
|
846
|
+
const currentTheme = useMemo5(() => {
|
|
790
847
|
void version;
|
|
791
848
|
const theme = themeRegistry.getCurrent();
|
|
792
849
|
return theme?.id;
|
|
793
850
|
}, [themeRegistry, version]);
|
|
794
|
-
const themes2 =
|
|
851
|
+
const themes2 = useMemo5(() => {
|
|
795
852
|
return themeRegistry.getAll().map((theme) => ({
|
|
796
853
|
id: theme.id,
|
|
797
854
|
name: theme.name
|
|
@@ -833,34 +890,47 @@ function useApiSuspenseInfiniteQuery(options) {
|
|
|
833
890
|
}
|
|
834
891
|
|
|
835
892
|
// src/hooks/useApiMutation.ts
|
|
836
|
-
import { useMemo as
|
|
893
|
+
import { useMemo as useMemo6 } from "react";
|
|
837
894
|
function useApiMutation(options) {
|
|
838
895
|
const queryClient = useRequiredFrontXQueryClient();
|
|
839
|
-
const queryCache2 =
|
|
840
|
-
const callbackCtx =
|
|
896
|
+
const queryCache2 = useMemo6(() => createQueryCache(queryClient), [queryClient]);
|
|
897
|
+
const callbackCtx = useMemo6(() => ({ queryCache: queryCache2 }), [queryCache2]);
|
|
841
898
|
return useFrontXMutation(options, callbackCtx);
|
|
842
899
|
}
|
|
843
900
|
|
|
844
901
|
// src/hooks/useApiStream.ts
|
|
845
|
-
import { useEffect as
|
|
902
|
+
import { useEffect as useEffect6, useMemo as useMemo7, useRef as useRef2, useState as useState4, useCallback as useCallback4 } from "react";
|
|
846
903
|
function useApiStream(descriptor, options) {
|
|
847
904
|
const mode = options?.mode ?? "latest";
|
|
848
905
|
const enabled = options?.enabled ?? true;
|
|
849
|
-
const [data, setData] =
|
|
850
|
-
const [events, setEvents] =
|
|
851
|
-
const [status, setStatus] =
|
|
852
|
-
const [error, setError] =
|
|
853
|
-
const connectPromiseRef =
|
|
854
|
-
const connectionIdRef =
|
|
855
|
-
const disconnectRequestedRef =
|
|
856
|
-
const descriptorRef =
|
|
857
|
-
|
|
858
|
-
const
|
|
859
|
-
|
|
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);
|
|
860
919
|
setData(void 0);
|
|
861
920
|
setEvents([]);
|
|
862
921
|
setError(null);
|
|
863
|
-
}
|
|
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
|
+
}
|
|
864
934
|
const disconnect = useCallback4(() => {
|
|
865
935
|
disconnectRequestedRef.current = true;
|
|
866
936
|
if (connectionIdRef.current) {
|
|
@@ -869,19 +939,14 @@ function useApiStream(descriptor, options) {
|
|
|
869
939
|
disconnectRequestedRef.current = false;
|
|
870
940
|
}
|
|
871
941
|
setStatus("disconnected");
|
|
872
|
-
}, []);
|
|
873
|
-
|
|
942
|
+
}, [descriptorRef]);
|
|
943
|
+
useEffect6(() => {
|
|
874
944
|
if (!enabled) {
|
|
875
|
-
setStatus("idle");
|
|
876
945
|
return;
|
|
877
946
|
}
|
|
878
947
|
let cancelled = false;
|
|
879
948
|
disconnectRequestedRef.current = false;
|
|
880
949
|
const d = descriptorRef.current;
|
|
881
|
-
setData(void 0);
|
|
882
|
-
setEvents([]);
|
|
883
|
-
setStatus("connecting");
|
|
884
|
-
setError(null);
|
|
885
950
|
const connectPromise = d.connect(
|
|
886
951
|
(event) => {
|
|
887
952
|
if (cancelled) return;
|
|
@@ -927,12 +992,12 @@ function useApiStream(descriptor, options) {
|
|
|
927
992
|
connectPromiseRef.current = null;
|
|
928
993
|
connectionIdRef.current = null;
|
|
929
994
|
};
|
|
930
|
-
}, [descriptorKey, enabled, mode]);
|
|
931
|
-
return { data, events, status, error, disconnect };
|
|
995
|
+
}, [descriptorKey, enabled, mode, descriptorRef]);
|
|
996
|
+
return { data, events, status: enabled ? status : "idle", error, disconnect };
|
|
932
997
|
}
|
|
933
998
|
|
|
934
999
|
// src/hooks/useQueryCache.ts
|
|
935
|
-
import { useMemo as
|
|
1000
|
+
import { useMemo as useMemo8 } from "react";
|
|
936
1001
|
function useQueryCache() {
|
|
937
1002
|
const queryClient = useOptionalFrontXQueryClient();
|
|
938
1003
|
if (!queryClient) {
|
|
@@ -940,7 +1005,7 @@ function useQueryCache() {
|
|
|
940
1005
|
"[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition."
|
|
941
1006
|
);
|
|
942
1007
|
}
|
|
943
|
-
return
|
|
1008
|
+
return useMemo8(() => createQueryCache(queryClient), [queryClient]);
|
|
944
1009
|
}
|
|
945
1010
|
|
|
946
1011
|
// src/mfe/hooks/useMfeBridge.ts
|
|
@@ -950,20 +1015,27 @@ function useMfeBridge() {
|
|
|
950
1015
|
}
|
|
951
1016
|
|
|
952
1017
|
// src/mfe/hooks/useSharedProperty.ts
|
|
953
|
-
import {
|
|
954
|
-
function useSharedProperty(propertyTypeId) {
|
|
955
|
-
const
|
|
956
|
-
const
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
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
|
+
);
|
|
961
1034
|
const getSnapshot = useCallback5(() => {
|
|
962
|
-
const
|
|
963
|
-
return
|
|
964
|
-
}, [bridge, propertyTypeId]);
|
|
965
|
-
|
|
966
|
-
return value;
|
|
1035
|
+
const raw = bridge.getProperty(propertyTypeId)?.value;
|
|
1036
|
+
return raw === void 0 ? fallback : raw;
|
|
1037
|
+
}, [bridge, propertyTypeId, fallback]);
|
|
1038
|
+
return useSyncExternalStore4(subscribe, getSnapshot, getSnapshot);
|
|
967
1039
|
}
|
|
968
1040
|
|
|
969
1041
|
// src/mfe/hooks/useHostAction.ts
|
|
@@ -974,36 +1046,41 @@ function useHostAction(actionTypeId) {
|
|
|
974
1046
|
const chain = {
|
|
975
1047
|
action: {
|
|
976
1048
|
type: actionTypeId,
|
|
977
|
-
target: bridge.
|
|
1049
|
+
target: bridge.extDomainId,
|
|
978
1050
|
payload
|
|
979
1051
|
}
|
|
980
1052
|
};
|
|
981
|
-
bridge.executeActionsChain(chain)
|
|
982
|
-
console.error(
|
|
983
|
-
`[useHostAction] Failed to send action '${actionTypeId}':`,
|
|
984
|
-
error
|
|
985
|
-
);
|
|
986
|
-
});
|
|
1053
|
+
bridge.executeActionsChain(chain);
|
|
987
1054
|
}, [actionTypeId, bridge]);
|
|
988
1055
|
}
|
|
989
1056
|
|
|
990
|
-
// src/mfe/hooks/
|
|
991
|
-
|
|
992
|
-
function useDomainExtensions(domainId) {
|
|
993
|
-
const app = useFrontX();
|
|
1057
|
+
// src/mfe/hooks/useMfeRegistry.ts
|
|
1058
|
+
function resolveMfeRegistry(app, callerName) {
|
|
994
1059
|
const registry = app.mfeRegistry;
|
|
995
1060
|
if (!registry) {
|
|
996
1061
|
throw new Error(
|
|
997
|
-
|
|
1062
|
+
`${callerName} requires the microfrontends plugin. Add microfrontends() to your Gears FrontX app configuration.`
|
|
998
1063
|
);
|
|
999
1064
|
}
|
|
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");
|
|
1000
1077
|
const subscribe = useCallback7(
|
|
1001
1078
|
(onStoreChange) => {
|
|
1002
1079
|
return app.store.subscribe(onStoreChange);
|
|
1003
1080
|
},
|
|
1004
1081
|
[app.store]
|
|
1005
1082
|
);
|
|
1006
|
-
const cacheRef =
|
|
1083
|
+
const cacheRef = useRef3({ ids: "", extensions: [] });
|
|
1007
1084
|
const getSnapshot = useCallback7(() => {
|
|
1008
1085
|
const extensions = registry.getExtensionsForDomain(domainId);
|
|
1009
1086
|
const ids = extensions.map((e) => e.id).join(",");
|
|
@@ -1015,53 +1092,19 @@ function useDomainExtensions(domainId) {
|
|
|
1015
1092
|
return useSyncExternalStore5(subscribe, getSnapshot, getSnapshot);
|
|
1016
1093
|
}
|
|
1017
1094
|
|
|
1018
|
-
// src/mfe/hooks/useMountedExtensions.ts
|
|
1019
|
-
import { useSyncExternalStore as useSyncExternalStore6, useCallback as useCallback8, useRef as useRef3 } from "react";
|
|
1020
|
-
function useMountedExtensions(domainId) {
|
|
1021
|
-
const app = useFrontX();
|
|
1022
|
-
const registry = app.mfeRegistry;
|
|
1023
|
-
if (!registry) {
|
|
1024
|
-
throw new Error(
|
|
1025
|
-
"useMountedExtensions requires the microfrontends plugin. Add microfrontends() to your Gears FrontX app configuration."
|
|
1026
|
-
);
|
|
1027
|
-
}
|
|
1028
|
-
const subscribe = useCallback8(
|
|
1029
|
-
(onStoreChange) => {
|
|
1030
|
-
return app.store.subscribe(onStoreChange);
|
|
1031
|
-
},
|
|
1032
|
-
[app.store]
|
|
1033
|
-
);
|
|
1034
|
-
const cacheRef = useRef3({ key: "", extensions: [] });
|
|
1035
|
-
const getSnapshot = useCallback8(() => {
|
|
1036
|
-
const ids = registry.getMountedExtensions(domainId);
|
|
1037
|
-
const resolved = ids.map((id) => registry.getExtension(id)).filter((ext) => ext !== void 0);
|
|
1038
|
-
const key = ids.join(",");
|
|
1039
|
-
if (key !== cacheRef.current.key) {
|
|
1040
|
-
cacheRef.current = { key, extensions: resolved };
|
|
1041
|
-
}
|
|
1042
|
-
return cacheRef.current.extensions;
|
|
1043
|
-
}, [registry, domainId]);
|
|
1044
|
-
return useSyncExternalStore6(subscribe, getSnapshot, getSnapshot);
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
1095
|
// src/mfe/hooks/useRegisteredPackages.ts
|
|
1048
|
-
import { useSyncExternalStore as
|
|
1096
|
+
import { useSyncExternalStore as useSyncExternalStore6, useCallback as useCallback8, useRef as useRef4 } from "react";
|
|
1049
1097
|
function useRegisteredPackages() {
|
|
1050
1098
|
const app = useFrontX();
|
|
1051
|
-
const registry = app
|
|
1052
|
-
|
|
1053
|
-
throw new Error(
|
|
1054
|
-
"useRegisteredPackages requires the microfrontends plugin. Add microfrontends() to your Gears FrontX app configuration."
|
|
1055
|
-
);
|
|
1056
|
-
}
|
|
1057
|
-
const subscribe = useCallback9(
|
|
1099
|
+
const registry = resolveMfeRegistry(app, "useRegisteredPackages");
|
|
1100
|
+
const subscribe = useCallback8(
|
|
1058
1101
|
(onStoreChange) => {
|
|
1059
1102
|
return app.store.subscribe(onStoreChange);
|
|
1060
1103
|
},
|
|
1061
1104
|
[app.store]
|
|
1062
1105
|
);
|
|
1063
1106
|
const cacheRef = useRef4({ packages: "", list: [] });
|
|
1064
|
-
const getSnapshot =
|
|
1107
|
+
const getSnapshot = useCallback8(() => {
|
|
1065
1108
|
const list = registry.getRegisteredPackages();
|
|
1066
1109
|
const packages = list.join(",");
|
|
1067
1110
|
if (packages !== cacheRef.current.packages) {
|
|
@@ -1069,12 +1112,40 @@ function useRegisteredPackages() {
|
|
|
1069
1112
|
}
|
|
1070
1113
|
return cacheRef.current.list;
|
|
1071
1114
|
}, [registry]);
|
|
1072
|
-
return
|
|
1115
|
+
return useSyncExternalStore6(subscribe, getSnapshot, getSnapshot);
|
|
1073
1116
|
}
|
|
1074
1117
|
|
|
1075
1118
|
// src/mfe/ThemeAwareReactLifecycle.tsx
|
|
1076
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
|
|
1077
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
|
+
}
|
|
1078
1149
|
function resolveProviderMountOptions(app, bridge, mountContext) {
|
|
1079
1150
|
const extensionId = mountContext?.extensionId;
|
|
1080
1151
|
const domainId = mountContext?.domainId;
|
|
@@ -1102,6 +1173,7 @@ var ThemeAwareReactLifecycle = class {
|
|
|
1102
1173
|
app;
|
|
1103
1174
|
root = null;
|
|
1104
1175
|
mount(container, bridge, mountContext) {
|
|
1176
|
+
void this.app.mfeRegistry;
|
|
1105
1177
|
if (container instanceof ShadowRoot) {
|
|
1106
1178
|
this.adoptHostStylesIntoShadowRoot(container);
|
|
1107
1179
|
}
|
|
@@ -1120,36 +1192,149 @@ var ThemeAwareReactLifecycle = class {
|
|
|
1120
1192
|
)
|
|
1121
1193
|
);
|
|
1122
1194
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
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;
|
|
1128
1216
|
}
|
|
1129
1217
|
/**
|
|
1130
1218
|
* Copy all inline <style> and <link rel="stylesheet"> from the host document
|
|
1131
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.
|
|
1132
1278
|
*/
|
|
1133
1279
|
adoptHostStylesIntoShadowRoot(shadowRoot) {
|
|
1134
|
-
const
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
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);
|
|
1144
1297
|
});
|
|
1298
|
+
shadowRoot.insertBefore(adoptedStyles, shadowRoot.firstChild);
|
|
1299
|
+
supersededStyles.forEach((el) => el.remove());
|
|
1145
1300
|
}
|
|
1146
1301
|
/**
|
|
1147
1302
|
* Box-model resets and :host defaults needed inside every shadow root.
|
|
1148
1303
|
* These aren't part of Tailwind's compiled output but are required for
|
|
1149
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.
|
|
1150
1331
|
*/
|
|
1151
1332
|
injectBaseResets(container) {
|
|
1152
|
-
const
|
|
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;
|
|
1153
1338
|
style.textContent = `
|
|
1154
1339
|
*, *::before, *::after {
|
|
1155
1340
|
box-sizing: border-box;
|
|
@@ -1163,11 +1348,21 @@ var ThemeAwareReactLifecycle = class {
|
|
|
1163
1348
|
line-height: 1.5;
|
|
1164
1349
|
-webkit-font-smoothing: antialiased;
|
|
1165
1350
|
-moz-osx-font-smoothing: grayscale;
|
|
1166
|
-
color:
|
|
1167
|
-
background-color:
|
|
1351
|
+
color: var(--foreground);
|
|
1352
|
+
background-color: var(--background);
|
|
1168
1353
|
}
|
|
1169
1354
|
`;
|
|
1170
|
-
container.
|
|
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
|
+
);
|
|
1171
1366
|
}
|
|
1172
1367
|
/**
|
|
1173
1368
|
* Hook for subclasses to inject additional CSS not covered by the adopted host
|
|
@@ -1180,7 +1375,7 @@ var ThemeAwareReactLifecycle = class {
|
|
|
1180
1375
|
};
|
|
1181
1376
|
|
|
1182
1377
|
// src/mfe/components/ExtensionDomainSlot.tsx
|
|
1183
|
-
import { useEffect as
|
|
1378
|
+
import { useEffect as useEffect7, useEffectEvent, useRef as useRef5, useState as useState5 } from "react";
|
|
1184
1379
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1185
1380
|
function ExtensionDomainSlot(props) {
|
|
1186
1381
|
const {
|
|
@@ -1192,12 +1387,14 @@ function ExtensionDomainSlot(props) {
|
|
|
1192
1387
|
loadingComponent = null
|
|
1193
1388
|
} = props;
|
|
1194
1389
|
const rootRef = useRef5(null);
|
|
1195
|
-
const
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1390
|
+
const emitAttached = useEffectEvent((root) => {
|
|
1391
|
+
onAttached?.(root);
|
|
1392
|
+
});
|
|
1393
|
+
const emitDetached = useEffectEvent(() => {
|
|
1394
|
+
onDetached?.();
|
|
1395
|
+
});
|
|
1396
|
+
const [attached, setAttached] = useState5(false);
|
|
1397
|
+
useEffect7(() => {
|
|
1201
1398
|
const root = rootRef.current;
|
|
1202
1399
|
if (!root) {
|
|
1203
1400
|
return;
|
|
@@ -1205,11 +1402,12 @@ function ExtensionDomainSlot(props) {
|
|
|
1205
1402
|
const mounter = registry.getMounter(domainId);
|
|
1206
1403
|
mounter.attach(root);
|
|
1207
1404
|
setAttached(true);
|
|
1208
|
-
|
|
1405
|
+
emitAttached(root);
|
|
1209
1406
|
return () => {
|
|
1210
|
-
|
|
1407
|
+
const detachPromise = mounter.detach();
|
|
1408
|
+
registerDomainTeardown(detachPromise);
|
|
1211
1409
|
setAttached(false);
|
|
1212
|
-
|
|
1410
|
+
emitDetached();
|
|
1213
1411
|
};
|
|
1214
1412
|
}, [registry, domainId]);
|
|
1215
1413
|
return /* @__PURE__ */ jsx5(
|
|
@@ -1226,7 +1424,6 @@ function ExtensionDomainSlot(props) {
|
|
|
1226
1424
|
// src/index.ts
|
|
1227
1425
|
import {
|
|
1228
1426
|
createFrontX,
|
|
1229
|
-
createFrontXApp as createFrontXApp2,
|
|
1230
1427
|
presets,
|
|
1231
1428
|
ACCOUNTS_DOMAIN,
|
|
1232
1429
|
I18nRegistry,
|
|
@@ -1243,7 +1440,6 @@ import {
|
|
|
1243
1440
|
registerSlice,
|
|
1244
1441
|
hasSlice,
|
|
1245
1442
|
createSlice,
|
|
1246
|
-
LayoutDomain,
|
|
1247
1443
|
layoutReducer,
|
|
1248
1444
|
layoutDomainReducers,
|
|
1249
1445
|
LAYOUT_SLICE_NAME,
|
|
@@ -1303,6 +1499,7 @@ import {
|
|
|
1303
1499
|
toggleMockMode,
|
|
1304
1500
|
MockEvents,
|
|
1305
1501
|
auth,
|
|
1502
|
+
AuthEvents,
|
|
1306
1503
|
frontxApiTransport,
|
|
1307
1504
|
apiRegistry,
|
|
1308
1505
|
BaseApiService,
|
|
@@ -1310,9 +1507,6 @@ import {
|
|
|
1310
1507
|
RestEndpointProtocol,
|
|
1311
1508
|
SseProtocol,
|
|
1312
1509
|
SseStreamProtocol,
|
|
1313
|
-
RestMockPlugin,
|
|
1314
|
-
SseMockPlugin,
|
|
1315
|
-
MockEventSource,
|
|
1316
1510
|
ApiPluginBase,
|
|
1317
1511
|
ApiPlugin,
|
|
1318
1512
|
ApiProtocol,
|
|
@@ -1333,7 +1527,7 @@ import {
|
|
|
1333
1527
|
} from "@gears-frontx/framework";
|
|
1334
1528
|
import { Language, TextDirection, LanguageDisplayMode } from "@gears-frontx/framework";
|
|
1335
1529
|
import {
|
|
1336
|
-
microfrontends
|
|
1530
|
+
microfrontends,
|
|
1337
1531
|
mock
|
|
1338
1532
|
} from "@gears-frontx/framework";
|
|
1339
1533
|
import {
|
|
@@ -1346,8 +1540,7 @@ import {
|
|
|
1346
1540
|
import {
|
|
1347
1541
|
selectExtensionState,
|
|
1348
1542
|
selectRegisteredExtensions,
|
|
1349
|
-
selectExtensionError
|
|
1350
|
-
selectMountedExtensions
|
|
1543
|
+
selectExtensionError
|
|
1351
1544
|
} from "@gears-frontx/framework";
|
|
1352
1545
|
import {
|
|
1353
1546
|
FRONTX_POPUP_DOMAIN,
|
|
@@ -1390,7 +1583,6 @@ import {
|
|
|
1390
1583
|
ExclusiveMountStrategy
|
|
1391
1584
|
} from "@gears-frontx/framework";
|
|
1392
1585
|
import { MfeHandlerMF, gtsPlugin } from "@gears-frontx/framework";
|
|
1393
|
-
import { themeSchema, languageSchema, extensionScreenSchema } from "@gears-frontx/framework";
|
|
1394
1586
|
import {
|
|
1395
1587
|
createShadowRoot,
|
|
1396
1588
|
injectCssVariables,
|
|
@@ -1404,6 +1596,7 @@ export {
|
|
|
1404
1596
|
ApiPlugin,
|
|
1405
1597
|
ApiPluginBase,
|
|
1406
1598
|
ApiProtocol,
|
|
1599
|
+
AuthEvents,
|
|
1407
1600
|
BaseApiService,
|
|
1408
1601
|
CanAccess,
|
|
1409
1602
|
ChildMfeBridge,
|
|
@@ -1431,7 +1624,6 @@ export {
|
|
|
1431
1624
|
LAYOUT_SLICE_NAME,
|
|
1432
1625
|
Language,
|
|
1433
1626
|
LanguageDisplayMode,
|
|
1434
|
-
LayoutDomain,
|
|
1435
1627
|
MOCK_PLUGIN,
|
|
1436
1628
|
MfeBridgeFactory,
|
|
1437
1629
|
MfeContext,
|
|
@@ -1440,18 +1632,15 @@ export {
|
|
|
1440
1632
|
MfeProvider,
|
|
1441
1633
|
MfeRegistry,
|
|
1442
1634
|
MfeRegistryFactory,
|
|
1443
|
-
MockEventSource,
|
|
1444
1635
|
MockEvents,
|
|
1445
1636
|
MountStrategy,
|
|
1446
1637
|
OptionalMountStrategy,
|
|
1447
1638
|
ParentMfeBridge,
|
|
1448
1639
|
RestEndpointProtocol,
|
|
1449
|
-
RestMockPlugin,
|
|
1450
1640
|
RestPlugin,
|
|
1451
1641
|
RestPluginWithConfig,
|
|
1452
1642
|
RestProtocol,
|
|
1453
1643
|
SUPPORTED_LANGUAGES,
|
|
1454
|
-
SseMockPlugin,
|
|
1455
1644
|
SsePlugin,
|
|
1456
1645
|
SsePluginWithConfig,
|
|
1457
1646
|
SseProtocol,
|
|
@@ -1470,7 +1659,6 @@ export {
|
|
|
1470
1659
|
closePopup,
|
|
1471
1660
|
closeTopPopup,
|
|
1472
1661
|
createFrontX,
|
|
1473
|
-
createFrontXApp2 as createFrontXApp,
|
|
1474
1662
|
createI18nRegistry,
|
|
1475
1663
|
createShadowRoot,
|
|
1476
1664
|
createSlice,
|
|
@@ -1478,7 +1666,6 @@ export {
|
|
|
1478
1666
|
createThemeRegistry,
|
|
1479
1667
|
effects,
|
|
1480
1668
|
eventBus2 as eventBus,
|
|
1481
|
-
extensionScreenSchema,
|
|
1482
1669
|
extractGtsPackage,
|
|
1483
1670
|
footerActions,
|
|
1484
1671
|
footerSlice,
|
|
@@ -1500,7 +1687,6 @@ export {
|
|
|
1500
1687
|
isRestShortCircuit,
|
|
1501
1688
|
isShortCircuit,
|
|
1502
1689
|
isSseShortCircuit,
|
|
1503
|
-
languageSchema,
|
|
1504
1690
|
layout,
|
|
1505
1691
|
layoutDomainReducers,
|
|
1506
1692
|
layoutReducer,
|
|
@@ -1508,7 +1694,7 @@ export {
|
|
|
1508
1694
|
menuActions,
|
|
1509
1695
|
menuSlice,
|
|
1510
1696
|
mfeRegistryFactory,
|
|
1511
|
-
|
|
1697
|
+
microfrontends,
|
|
1512
1698
|
mock,
|
|
1513
1699
|
mockActions,
|
|
1514
1700
|
mockSlice,
|
|
@@ -1528,7 +1714,6 @@ export {
|
|
|
1528
1714
|
screenDomain,
|
|
1529
1715
|
selectExtensionError,
|
|
1530
1716
|
selectExtensionState,
|
|
1531
|
-
selectMountedExtensions,
|
|
1532
1717
|
selectRegisteredExtensions,
|
|
1533
1718
|
setFooterConfig,
|
|
1534
1719
|
setFooterVisible,
|
|
@@ -1558,7 +1743,6 @@ export {
|
|
|
1558
1743
|
tenantActions,
|
|
1559
1744
|
tenantReducer,
|
|
1560
1745
|
tenantSlice,
|
|
1561
|
-
themeSchema,
|
|
1562
1746
|
themes,
|
|
1563
1747
|
toggleMenu,
|
|
1564
1748
|
toggleMockMode,
|
|
@@ -1580,7 +1764,7 @@ export {
|
|
|
1580
1764
|
useHostAction,
|
|
1581
1765
|
useMfeBridge,
|
|
1582
1766
|
useMfeContext,
|
|
1583
|
-
|
|
1767
|
+
useMfeRegistry,
|
|
1584
1768
|
useQueryCache,
|
|
1585
1769
|
useRegisteredPackages,
|
|
1586
1770
|
useScreenTranslations,
|