@qlover/create-app 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/configs/_common/.github/workflows/general-check.yml +1 -1
  3. package/dist/configs/_common/.github/workflows/release.yml +2 -2
  4. package/dist/index.cjs +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/templates/next-app/.env.template +9 -10
  7. package/dist/templates/next-app/eslint.config.mjs +5 -0
  8. package/dist/templates/next-app/next.config.ts +1 -1
  9. package/dist/templates/next-app/src/app/[locale]/login/page.tsx +1 -1
  10. package/dist/templates/next-app/src/app/[locale]/page.tsx +1 -1
  11. package/dist/templates/next-app/src/app/[locale]/register/page.tsx +1 -1
  12. package/dist/templates/next-app/src/app/api/locales/json/route.ts +2 -1
  13. package/dist/templates/next-app/src/i18n/request.ts +2 -2
  14. package/dist/templates/react-app/__tests__/__mocks__/{MockAppConfit.ts → MockAppConfig.ts} +1 -1
  15. package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +10 -17
  16. package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +27 -8
  17. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +1 -1
  18. package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +110 -0
  19. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +3 -2
  20. package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +13 -0
  21. package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +3 -1
  22. package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +274 -0
  23. package/dist/templates/react-app/config/IOCIdentifier.ts +9 -3
  24. package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +56 -0
  25. package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +103 -0
  26. package/dist/templates/react-app/config/Identifier/pages/index.ts +1 -0
  27. package/dist/templates/react-app/config/Identifier/pages/page.message.ts +20 -0
  28. package/dist/templates/react-app/config/app.router.ts +23 -0
  29. package/dist/templates/react-app/config/common.ts +38 -0
  30. package/dist/templates/react-app/config/feapi.mock.json +5 -12
  31. package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +17 -0
  32. package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +22 -0
  33. package/dist/templates/react-app/config/i18n/messageI18n.ts +14 -0
  34. package/dist/templates/react-app/docs/en/components/chat-message-component.md +314 -0
  35. package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +270 -0
  36. package/dist/templates/react-app/docs/en/components/message-base-list-component.md +172 -0
  37. package/dist/templates/react-app/docs/zh/components/chat-message-component.md +314 -0
  38. package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +270 -0
  39. package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +172 -0
  40. package/dist/templates/react-app/eslint.config.mjs +6 -5
  41. package/dist/templates/react-app/package.json +1 -1
  42. package/dist/templates/react-app/playwright.config.ts +6 -6
  43. package/dist/templates/react-app/public/locales/en/common.json +44 -1
  44. package/dist/templates/react-app/public/locales/zh/common.json +44 -1
  45. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +22 -13
  46. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +3 -3
  47. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +17 -12
  48. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +19 -2
  49. package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +2 -4
  50. package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +15 -9
  51. package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +55 -0
  52. package/dist/templates/react-app/src/base/services/I18nService.ts +1 -0
  53. package/dist/templates/react-app/src/base/services/UserBootstrap.ts +43 -0
  54. package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +16 -0
  55. package/dist/templates/react-app/src/base/services/UserService.ts +51 -80
  56. package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +8 -3
  57. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +6 -6
  58. package/dist/templates/react-app/src/core/bootstraps/SaveAppInfo.ts +28 -0
  59. package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +24 -18
  60. package/dist/templates/react-app/src/core/globals.ts +10 -11
  61. package/dist/templates/react-app/src/main.tsx +1 -1
  62. package/dist/templates/react-app/src/pages/auth/Layout.tsx +4 -4
  63. package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +1 -1
  64. package/dist/templates/react-app/src/pages/base/Layout.tsx +3 -3
  65. package/dist/templates/react-app/src/pages/base/MessagePage.tsx +40 -0
  66. package/dist/templates/react-app/src/uikit/components/BaseLayoutProvider.tsx +44 -0
  67. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +1 -3
  68. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +240 -0
  69. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +176 -0
  70. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +21 -0
  71. package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +106 -0
  72. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +271 -0
  73. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +102 -0
  74. package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +86 -0
  75. package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +9 -0
  76. package/dist/templates/react-app/src/uikit/hooks/{useI18nGuard.ts → useRouterI18nGuard.ts} +7 -4
  77. package/dist/templates/react-app/tsconfig.app.json +4 -2
  78. package/dist/templates/react-app/tsconfig.node.json +4 -0
  79. package/dist/templates/react-app/tsconfig.test.json +3 -1
  80. package/package.json +3 -3
  81. package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +0 -102
  82. package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +0 -61
  83. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +0 -57
  84. package/dist/templates/react-app/src/uikit/components/ProcessExecutorProvider.tsx +0 -28
  85. package/dist/templates/react-app/src/uikit/components/UserAuthProvider.tsx +0 -16
@@ -0,0 +1,86 @@
1
+ import { useStore } from '@brain-toolkit/react-kit';
2
+ import { useCallback, type ComponentType } from 'react';
3
+ import type { ChatMessageI18nInterface } from '@config/i18n/chatMessageI18n';
4
+ import { MessageItem, type MessageItemProps } from './MessageItem';
5
+ import type {
6
+ ChatMessage,
7
+ ChatMessageBridgeInterface
8
+ } from '@qlover/corekit-bridge';
9
+
10
+ export type MessageComponentType<
11
+ T,
12
+ MessageType extends ChatMessage<T>
13
+ > = ComponentType<MessageItemProps<T, MessageType>>;
14
+
15
+ export type GetMessageComponent<T, MessageType extends ChatMessage<T>> = (
16
+ props: MessageItemProps<T, MessageType>
17
+ ) => MessageComponentType<T, MessageType>;
18
+
19
+ export interface MessagesListProps<T, MessageType extends ChatMessage<T>> {
20
+ bridge: ChatMessageBridgeInterface<T>;
21
+ tt: ChatMessageI18nInterface;
22
+
23
+ /**
24
+ * Get message component
25
+ *
26
+ * @default `MessageItem`
27
+ *
28
+ * @type `ComponentType<MessageItemProps<MessageType>>`
29
+ */
30
+ getMessageComponent?: GetMessageComponent<T, MessageType>;
31
+
32
+ /**
33
+ * Get message unique identifier
34
+ *
35
+ * @default `(message.id ?? '') + (message.startTime ?? 0) + index`
36
+ *
37
+ * @param message Message
38
+ * @param index Message index
39
+ * @returns Message unique identifier
40
+ */
41
+ getMessageKey?(message: MessageType, index: number): string;
42
+ }
43
+
44
+ export function MessagesList<T = string>({
45
+ bridge,
46
+ tt,
47
+ getMessageComponent,
48
+ getMessageKey
49
+ }: MessagesListProps<T, ChatMessage<T>>) {
50
+ const messagesStore = bridge.getMessageStore();
51
+ const messages = useStore(messagesStore, (state) => state.messages);
52
+
53
+ const _getMessageKey = useCallback(
54
+ (message: ChatMessage<T>, index: number): string => {
55
+ return (
56
+ getMessageKey?.(message, index) ||
57
+ String((message.id ?? '') + (message.startTime ?? 0) + index)
58
+ );
59
+ },
60
+ [getMessageKey]
61
+ );
62
+
63
+ return (
64
+ <div
65
+ data-testid="MessagesList"
66
+ className="flex-1 overflow-y-auto p-4 space-y-2"
67
+ >
68
+ {messages.length === 0 ? (
69
+ <div className="flex items-center justify-center h-full">
70
+ <div className="text-center text-text-secondary">
71
+ <p className="text-base mb-1">{tt.empty}</p>
72
+ <p className="text-sm">{tt.start}</p>
73
+ </div>
74
+ </div>
75
+ ) : (
76
+ messages.map((message, index) => {
77
+ const key = _getMessageKey(message, index);
78
+ const props = { message, index, bridge, tt };
79
+ const Component = getMessageComponent?.(props) || MessageItem;
80
+
81
+ return <Component data-testid="MessageItem" key={key} {...props} />;
82
+ })
83
+ )}
84
+ </div>
85
+ );
86
+ }
@@ -3,6 +3,15 @@ import { useNavigate } from 'react-router-dom';
3
3
  import { useIOC } from './useIOC';
4
4
  import { NavigateBridge } from '../bridges/NavigateBridge';
5
5
 
6
+ /**
7
+ * 使用 navigate 桥接
8
+ *
9
+ * 将 navigate 桥接到 NavigateBridge 中
10
+ *
11
+ * 这样就可以在服务层使用 navigate 了, 比如在某个service中需要跳转页面,就可以使用 navigateBridge.getUIBridge() 来跳转
12
+ *
13
+ * **但是它需要在 RouterProvider 中使用**
14
+ */
6
15
  export function useNavigateBridge() {
7
16
  const navigate = useNavigate();
8
17
  const navigateBridge = useIOC(NavigateBridge);
@@ -5,13 +5,16 @@ import type { LocaleType } from '@config/i18n/i18nConfig';
5
5
  import { useIOC } from './useIOC';
6
6
 
7
7
  /**
8
- * Language Guard
8
+ * 国际化路由国际化守卫
9
9
  *
10
- * if language not found, redirect to 404 page
10
+ * 比如: 开启了 `@config/common 中useLocaleRoutes` `true` 时,
11
+ *
12
+ * 访问 `/login` 则会自动重定向到 `/en/login`, 其中 en 为默认语言可配置
13
+ *
14
+ * 或者访问一个不支持的语言,则会自动重定向到 `/en/404`
11
15
  *
12
- * TODO: if language not found, use default language
13
16
  */
14
- export function useI18nGuard() {
17
+ export function useRouterI18nGuard() {
15
18
  const { lng } = useParams<{ lng: LocaleType }>();
16
19
  const { pathname } = useLocation();
17
20
  const navigate = useNavigate();
@@ -28,9 +28,11 @@
28
28
  "paths": {
29
29
  "@/*": ["./src/*"],
30
30
  "@config/*": ["./config/*"],
31
- "@lib/*": ["./lib/*"]
31
+ "@lib/*": ["./lib/*"],
32
+ "@qlover/corekit-bridge": ["../../../corekit-bridge"],
33
+ "@qlover/fe-corekit": ["../../../fe-corekit"]
32
34
  }
33
35
  },
34
36
  "include": ["src", "config"],
35
- "exclude": ["node_modules", "dist"]
37
+ "exclude": ["**/**/node_modules", "**/**dist"]
36
38
  }
@@ -12,6 +12,10 @@
12
12
  "isolatedModules": true,
13
13
  "moduleDetection": "force",
14
14
  "noEmit": true,
15
+ "paths": {
16
+ "@qlover/corekit-bridge": ["../../../corekit-bridge"],
17
+ "@qlover/fe-corekit": ["../../../fe-corekit"]
18
+ },
15
19
 
16
20
  /* Linting */
17
21
  "strict": true,
@@ -7,7 +7,9 @@
7
7
  "@/*": ["./src/*"],
8
8
  "@config/*": ["./config/*"],
9
9
  "@__tests__/*": ["./__tests__/*"],
10
- "@__mocks__/*": ["./__tests__/__mocks__/*"]
10
+ "@__mocks__/*": ["./__tests__/__mocks__/*"],
11
+ "@qlover/corekit-bridge": ["../../../corekit-bridge"],
12
+ "@qlover/fe-corekit": ["../../../fe-corekit"]
11
13
  }
12
14
  },
13
15
  "include": ["__tests__/**/*"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qlover/create-app",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Create a new app with a single command",
5
5
  "private": false,
6
6
  "type": "module",
@@ -33,12 +33,12 @@
33
33
  "ignore": "^7.0.3",
34
34
  "lodash": "^4.17.21",
35
35
  "ora": "^8.1.1",
36
- "@qlover/logger": "0.2.0"
36
+ "@qlover/logger": "0.3.0"
37
37
  },
38
38
  "dependencies": {
39
39
  "commander": "^13.1.0",
40
40
  "inquirer": "^12.3.2",
41
- "@qlover/scripts-context": "1.1.4"
41
+ "@qlover/scripts-context": "1.2.0"
42
42
  },
43
43
  "scripts": {
44
44
  "lint": "eslint src --fix",
@@ -1,102 +0,0 @@
1
- /**
2
- * AppError test suite
3
- *
4
- * Coverage:
5
- * 1. constructor - Constructor initialization with different source types
6
- * 2. inheritance - Verify inheritance from ExecutorError
7
- * 3. error properties - Verify error properties are set correctly
8
- */
9
-
10
- import { ExecutorError } from '@qlover/fe-corekit';
11
- import { describe, it, expect } from 'vitest';
12
- import { AppError } from '@/base/cases/AppError';
13
-
14
- describe('AppError', () => {
15
- describe('constructor', () => {
16
- it('should create instance with id only', () => {
17
- const error = new AppError('TEST_ERROR');
18
- expect(error).toBeInstanceOf(AppError);
19
- expect(error).toBeInstanceOf(ExecutorError);
20
- expect(error).toBeInstanceOf(Error);
21
- expect(error.id).toBe('TEST_ERROR');
22
- expect(error.message).toBe('TEST_ERROR');
23
- expect(error.source).toBeUndefined();
24
- });
25
-
26
- it('should create instance with string source', () => {
27
- const source = 'Test error message';
28
- const error = new AppError('TEST_ERROR', source);
29
- expect(error.id).toBe('TEST_ERROR');
30
- expect(error.message).toBe(source);
31
- expect(error.source).toBe(source);
32
- });
33
-
34
- it('should create instance with Error source', () => {
35
- const source = new Error('Original error');
36
- const error = new AppError('TEST_ERROR', source);
37
- expect(error.id).toBe('TEST_ERROR');
38
- expect(error.message).toBe('Original error');
39
- expect(error.source).toBe(source);
40
- });
41
- });
42
-
43
- describe('error properties', () => {
44
- it('should have correct error type', () => {
45
- const error = new AppError('TEST_ERROR');
46
- expect(error.id).toBe('TEST_ERROR');
47
- });
48
-
49
- it('should maintain id property', () => {
50
- const error = new AppError('TEST_ERROR');
51
- Object.defineProperty(error, 'id', { value: 'NEW_ID' });
52
- expect(error.id).toBe('NEW_ID');
53
- });
54
-
55
- it('should maintain source property', () => {
56
- const source = 'source';
57
- const error = new AppError('TEST_ERROR', source);
58
- Object.defineProperty(error, 'source', { value: 'new source' });
59
- expect(error.source).toBe('new source');
60
- });
61
- });
62
-
63
- describe('error handling', () => {
64
- it('should work in try-catch block', () => {
65
- expect(() => {
66
- throw new AppError('TEST_ERROR');
67
- }).toThrow(AppError);
68
- });
69
-
70
- it('should preserve stack trace', () => {
71
- const error = new AppError('TEST_ERROR');
72
- expect(error.stack).toBeDefined();
73
- expect(error.stack).toContain('AppError.test.ts');
74
- });
75
-
76
- it('should handle nested errors', () => {
77
- const originalError = new Error('Original error');
78
- const wrappedError = new AppError('WRAPPED_ERROR', originalError);
79
- expect(wrappedError.source).toBe(originalError);
80
- expect(wrappedError.message).toBe('Original error');
81
- });
82
- });
83
-
84
- describe('error message formatting', () => {
85
- it('should use id as message when source is undefined', () => {
86
- const error = new AppError('TEST_ERROR');
87
- expect(error.message).toBe('TEST_ERROR');
88
- });
89
-
90
- it('should use source message when source is Error', () => {
91
- const source = new Error('Source error message');
92
- const error = new AppError('TEST_ERROR', source);
93
- expect(error.message).toBe('Source error message');
94
- });
95
-
96
- it('should use source string when source is string', () => {
97
- const source = 'Source error message';
98
- const error = new AppError('TEST_ERROR', source);
99
- expect(error.message).toBe('Source error message');
100
- });
101
- });
102
- });
@@ -1,61 +0,0 @@
1
- import { readFileSync, existsSync } from 'fs';
2
- import { join } from 'path';
3
-
4
- describe('main.tsx Integration Tests', () => {
5
- beforeAll(() => {
6
- // Setup test environment
7
- if (!document.getElementById('root')) {
8
- const rootElement = document.createElement('div');
9
- rootElement.id = 'root';
10
- document.body.appendChild(rootElement);
11
- }
12
- });
13
-
14
- afterAll(() => {
15
- // Clean up DOM
16
- const rootElement = document.getElementById('root');
17
- if (rootElement) {
18
- rootElement.remove();
19
- }
20
- });
21
-
22
- beforeEach(() => {
23
- // Clean up root element content
24
- const rootElement = document.getElementById('root');
25
- if (rootElement) {
26
- rootElement.innerHTML = '';
27
- }
28
- });
29
-
30
- it('should have main.tsx file', () => {
31
- // Test if file exists
32
- const mainPath = join(process.cwd(), 'src/main.tsx');
33
- expect(existsSync(mainPath)).toBe(true);
34
- });
35
-
36
- it('should have main.tsx with correct structure', () => {
37
- // Test file content structure
38
- const mainPath = join(process.cwd(), 'src/main.tsx');
39
- const content = readFileSync(mainPath, 'utf-8');
40
-
41
- // Check if it contains necessary imports
42
- expect(content).toContain('import');
43
- expect(content).toContain('BootstrapClient');
44
- expect(content).toContain('createRoot');
45
- });
46
-
47
- it('should have App.tsx file', () => {
48
- // Test if App.tsx file exists
49
- const appPath = join(process.cwd(), 'src/App.tsx');
50
- expect(existsSync(appPath)).toBe(true);
51
- });
52
-
53
- it('should have BootstrapClient.ts file', () => {
54
- // Test if BootstrapClient.ts file exists
55
- const bootstrapPath = join(
56
- process.cwd(),
57
- 'src/core/bootstraps/BootstrapClient.ts'
58
- );
59
- expect(existsSync(bootstrapPath)).toBe(true);
60
- });
61
- });
@@ -1,57 +0,0 @@
1
- import { IOCIdentifier } from '@config/IOCIdentifier';
2
- import {
3
- AsyncExecutor,
4
- ExecutorContext,
5
- ExecutorPlugin
6
- } from '@qlover/fe-corekit';
7
- import { injectable, inject } from 'inversify';
8
- import type { ProcesserExecutorInterface } from '../port/ProcesserExecutorInterface';
9
- import type { RouteServiceInterface } from '../port/RouteServiceInterface';
10
- import type { BootstrapContextValue } from '@qlover/corekit-bridge';
11
- import type { LoggerInterface } from '@qlover/logger';
12
-
13
- @injectable()
14
- export class ProcesserExecutor implements ProcesserExecutorInterface {
15
- pluginName = 'ProcesserExecutor';
16
- protected executor: AsyncExecutor = new AsyncExecutor();
17
-
18
- constructor(
19
- @inject(IOCIdentifier.Logger) protected logger: LoggerInterface,
20
- @inject(IOCIdentifier.RouteServiceInterface)
21
- protected routeService: RouteServiceInterface
22
- ) {}
23
-
24
- /**
25
- * @override
26
- */
27
- onBefore({
28
- parameters: { ioc }
29
- }: ExecutorContext<BootstrapContextValue>): void | Promise<void> {
30
- this.use(ioc.get(IOCIdentifier.I18nKeyErrorPlugin));
31
- this.use(ioc.get(IOCIdentifier.UserServiceInterface));
32
- }
33
-
34
- use(plugin: ExecutorPlugin): this {
35
- this.executor.use(plugin);
36
- return this;
37
- }
38
-
39
- handler(): Promise<{ success: boolean }> {
40
- return Promise.resolve({
41
- success: true
42
- });
43
- }
44
-
45
- async starup(): Promise<unknown> {
46
- this.logger.info('PageProcesser startup');
47
-
48
- try {
49
- const result = await this.executor.exec(this.handler);
50
- return result;
51
- } catch (err) {
52
- this.logger.error('PageProcesser init failed', err);
53
-
54
- this.routeService.gotoLogin();
55
- }
56
- }
57
- }
@@ -1,28 +0,0 @@
1
- import { IOCIdentifier } from '@config/IOCIdentifier';
2
- import { UserAuthProvider } from './UserAuthProvider';
3
- import { useI18nGuard } from '../hooks/useI18nGuard';
4
- import { useIOC } from '../hooks/useIOC';
5
- import { useNavigateBridge } from '../hooks/useNavigateBridge';
6
- import { useStrictEffect } from '../hooks/useStrictEffect';
7
-
8
- export function ProcessExecutorProvider({
9
- children
10
- }: {
11
- children: React.ReactNode;
12
- }) {
13
- const processerExecutor = useIOC(IOCIdentifier.ProcesserExecutorInterface);
14
-
15
- useI18nGuard();
16
-
17
- useNavigateBridge();
18
-
19
- useStrictEffect(() => {
20
- processerExecutor.starup();
21
- }, []);
22
-
23
- return (
24
- <UserAuthProvider data-testid="ProcessExecutorProvider">
25
- {children}
26
- </UserAuthProvider>
27
- );
28
- }
@@ -1,16 +0,0 @@
1
- import { useStore } from '@brain-toolkit/react-kit/hooks/useStore';
2
- import { IOCIdentifier } from '@config/IOCIdentifier';
3
- import { Loading } from './Loading';
4
- import { useIOC } from '../hooks/useIOC';
5
-
6
- export function UserAuthProvider({ children }: { children: React.ReactNode }) {
7
- const userService = useIOC(IOCIdentifier.UserServiceInterface);
8
-
9
- useStore(userService.store);
10
-
11
- if (!userService.isAuthenticated()) {
12
- return <Loading data-testid="UserAuthProvider" fullscreen />;
13
- }
14
-
15
- return children;
16
- }