@khester/create-dynamics-app 2.1.0 → 2.2.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 (121) hide show
  1. package/dist/artifacts/registry.d.ts +4 -3
  2. package/dist/artifacts/registry.d.ts.map +1 -1
  3. package/dist/artifacts/registry.js +121 -11
  4. package/dist/artifacts/registry.js.map +1 -1
  5. package/dist/artifacts/types.d.ts +1 -1
  6. package/dist/artifacts/types.d.ts.map +1 -1
  7. package/dist/index.js +2 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/injectDevTools.d.ts.map +1 -1
  10. package/dist/injectDevTools.js +4 -2
  11. package/dist/injectDevTools.js.map +1 -1
  12. package/dist/scaffold.d.ts +1 -0
  13. package/dist/scaffold.d.ts.map +1 -1
  14. package/dist/scaffold.js +3 -1
  15. package/dist/scaffold.js.map +1 -1
  16. package/package.json +3 -2
  17. package/templates/grid-starter/ARCHITECTURE.md +66 -0
  18. package/templates/grid-starter/README.md +122 -0
  19. package/templates/grid-starter/env.example +16 -0
  20. package/templates/grid-starter/gitignore +6 -0
  21. package/templates/grid-starter/index.html +16 -0
  22. package/templates/grid-starter/package.json +39 -0
  23. package/templates/grid-starter/src/App.tsx +23 -0
  24. package/templates/grid-starter/src/core/services/FetchApiService.ts +117 -0
  25. package/templates/grid-starter/src/core/services/IApiService.ts +37 -0
  26. package/templates/grid-starter/src/core/services/MockApiService.ts +72 -0
  27. package/templates/grid-starter/src/core/services/ServiceFactory.ts +58 -0
  28. package/templates/grid-starter/src/core/services/XrmApiService.ts +135 -0
  29. package/templates/grid-starter/src/core/services/crudLogging.ts +52 -0
  30. package/templates/grid-starter/src/dev-tools/DevPanel.tsx +239 -0
  31. package/templates/grid-starter/src/grid/GridPage.tsx +119 -0
  32. package/templates/grid-starter/src/index.tsx +18 -0
  33. package/templates/grid-starter/src/vite-env.d.ts +15 -0
  34. package/templates/grid-starter/tools/deploy/deploy-webresource.cjs +117 -0
  35. package/templates/grid-starter/tsconfig.json +19 -0
  36. package/templates/grid-starter/vite.config.ts +76 -0
  37. package/templates/pcf-field/_variants/ValueInput.boolean.tsx +2 -0
  38. package/templates/pcf-field/_variants/ValueInput.date.tsx +2 -0
  39. package/templates/pcf-field/_variants/ValueInput.number.tsx +2 -0
  40. package/templates/pcf-field/_variants/ValueInput.optionset.tsx +77 -0
  41. package/templates/pcf-field/_variants/ValueInput.text.tsx +2 -0
  42. package/templates/pcf-field/index.ts +1 -1
  43. package/templates/pcf-field/package.json +3 -1
  44. package/templates/pcf-field/{{componentName}}Component.tsx +2 -0
  45. package/templates/react-custom-page/ARCHITECTURE.md +75 -0
  46. package/templates/react-custom-page/README.md +74 -568
  47. package/templates/react-custom-page/env.example +16 -0
  48. package/templates/react-custom-page/gitignore +1 -0
  49. package/templates/react-custom-page/index.html +16 -0
  50. package/templates/react-custom-page/package.json +21 -49
  51. package/templates/react-custom-page/src/App.tsx +26 -0
  52. package/templates/react-custom-page/src/core/recordContext.test.ts +30 -0
  53. package/templates/react-custom-page/src/core/recordContext.ts +51 -0
  54. package/templates/react-custom-page/src/core/services/FetchApiService.ts +117 -0
  55. package/templates/react-custom-page/src/core/services/IApiService.ts +37 -0
  56. package/templates/react-custom-page/src/core/services/MockApiService.ts +73 -0
  57. package/templates/react-custom-page/src/core/services/ServiceFactory.ts +58 -0
  58. package/templates/react-custom-page/src/core/services/XrmApiService.ts +135 -0
  59. package/templates/react-custom-page/src/core/services/crudLogging.ts +52 -0
  60. package/templates/react-custom-page/src/dev-tools/DevPanel.tsx +238 -0
  61. package/templates/react-custom-page/src/domain/diff.test.ts +87 -0
  62. package/templates/react-custom-page/src/domain/diff.ts +38 -0
  63. package/templates/react-custom-page/src/example/ExamplePage.tsx +140 -0
  64. package/templates/react-custom-page/src/example/exampleError.ts +36 -0
  65. package/templates/react-custom-page/src/example/hooks/useExampleData.ts +40 -0
  66. package/templates/react-custom-page/src/example/hooks/useExampleForm.ts +99 -0
  67. package/templates/react-custom-page/src/example/mappers/accountMapper.test.ts +38 -0
  68. package/templates/react-custom-page/src/example/mappers/accountMapper.ts +55 -0
  69. package/templates/react-custom-page/src/example/models/Account.ts +74 -0
  70. package/templates/react-custom-page/src/index.tsx +18 -128
  71. package/templates/react-custom-page/src/vite-env.d.ts +15 -0
  72. package/templates/react-custom-page/tools/deploy/deploy-webresource.cjs +117 -0
  73. package/templates/react-custom-page/tsconfig.json +12 -22
  74. package/templates/react-custom-page/vite.config.ts +76 -0
  75. package/templates/starter-page/README.md +38 -0
  76. package/templates/starter-page/_variants/App.dashboard.v8.tsx +46 -0
  77. package/templates/starter-page/_variants/App.form.v8.tsx +59 -0
  78. package/templates/starter-page/_variants/App.master-detail.v8.tsx +61 -0
  79. package/templates/starter-page/_variants/App.panel.v8.tsx +99 -0
  80. package/templates/starter-page/gitignore +5 -0
  81. package/templates/starter-page/package.json +27 -0
  82. package/templates/starter-page/public/index.html +11 -0
  83. package/templates/starter-page/src/index.tsx +10 -0
  84. package/templates/starter-page/src/services/dataverse.ts +30 -0
  85. package/templates/starter-page/tsconfig.json +15 -0
  86. package/templates/starter-page/webpack.config.js +17 -0
  87. package/templates/react-custom-page/deployment/README.md +0 -484
  88. package/templates/react-custom-page/docs/ARCHITECTURE_OVERVIEW.md +0 -506
  89. package/templates/react-custom-page/docs/BEST_PRACTICES.md +0 -723
  90. package/templates/react-custom-page/docs/MIGRATION_GUIDE.md +0 -447
  91. package/templates/react-custom-page/public/index.html +0 -15
  92. package/templates/react-custom-page/scripts/custom-build.js +0 -255
  93. package/templates/react-custom-page/src/components/AccountForm.css +0 -71
  94. package/templates/react-custom-page/src/components/AccountForm.tsx +0 -541
  95. package/templates/react-custom-page/src/components/AccountManagement.css +0 -86
  96. package/templates/react-custom-page/src/components/AccountManagement.tsx +0 -370
  97. package/templates/react-custom-page/src/components/ContactForm.css +0 -48
  98. package/templates/react-custom-page/src/components/ContactForm.tsx +0 -327
  99. package/templates/react-custom-page/src/components/ContactManagement.css +0 -86
  100. package/templates/react-custom-page/src/components/ContactManagement.tsx +0 -357
  101. package/templates/react-custom-page/src/components/Logging/LogDialog.tsx +0 -291
  102. package/templates/react-custom-page/src/components/Logging/LoggingContext.tsx +0 -166
  103. package/templates/react-custom-page/src/components/Logging/LoggingDebugPanel.css +0 -192
  104. package/templates/react-custom-page/src/components/Logging/LoggingDebugPanel.tsx +0 -177
  105. package/templates/react-custom-page/src/components/Logging/LoggingProvider.tsx +0 -3
  106. package/templates/react-custom-page/src/components/Logging/logger.ts +0 -193
  107. package/templates/react-custom-page/src/constants/account.ts +0 -410
  108. package/templates/react-custom-page/src/constants/contact.ts +0 -362
  109. package/templates/react-custom-page/src/models/Account.ts +0 -480
  110. package/templates/react-custom-page/src/models/BaseEntity.ts +0 -204
  111. package/templates/react-custom-page/src/models/Contact.ts +0 -580
  112. package/templates/react-custom-page/src/pcf/ContactControlWrapper.tsx +0 -107
  113. package/templates/react-custom-page/src/pcf/MultiEntityControlWrapper.tsx +0 -205
  114. package/templates/react-custom-page/src/providers/DynamicsProvider.tsx +0 -353
  115. package/templates/react-custom-page/src/services/MockApiService.ts +0 -260
  116. package/templates/react-custom-page/src/services/ServiceFactory.ts +0 -65
  117. package/templates/react-custom-page/src/services/XrmApiService.ts +0 -213
  118. package/templates/react-custom-page/src/styles/index.css +0 -171
  119. package/templates/react-custom-page/tools/metadata-sync/index.js +0 -152
  120. package/templates/react-custom-page/webpack.config.js +0 -57
  121. /package/templates/_shared/dev-tools/auth/{get-token.js → get-token.cjs} +0 -0
@@ -1,166 +0,0 @@
1
- import React, {
2
- createContext,
3
- useContext,
4
- useState,
5
- useEffect,
6
- ReactNode,
7
- } from 'react';
8
- import { Logger } from './logger';
9
-
10
- /**
11
- * Log entry interface
12
- */
13
- export interface LogEntry {
14
- timestamp: string;
15
- message: string;
16
- source?: string;
17
- }
18
-
19
- /**
20
- * Logging context properties
21
- */
22
- interface LoggingContextProps {
23
- logs: LogEntry[];
24
- addLog: (message: string, source?: string) => void;
25
- clearLogs: () => void;
26
- }
27
-
28
- /**
29
- * Logging context
30
- */
31
- const LoggingContext = createContext<LoggingContextProps | undefined>(
32
- undefined
33
- );
34
-
35
- /**
36
- * Props for LoggingProvider
37
- */
38
- interface LoggingProviderProps {
39
- children: ReactNode;
40
- interceptConsole?: boolean;
41
- }
42
-
43
- /**
44
- * Logging provider component that manages logging state and provides context
45
- */
46
- export const LoggingProvider: React.FC<LoggingProviderProps> = ({
47
- children,
48
- interceptConsole = false,
49
- }) => {
50
- const [logs, setLogs] = useState<LogEntry[]>([]);
51
-
52
- /**
53
- * Add a new log entry
54
- */
55
- const addLog = (message: string, source?: string) => {
56
- const timestamp = new Date().toISOString();
57
- const newLog: LogEntry = {
58
- timestamp,
59
- message,
60
- source,
61
- };
62
-
63
- setLogs((prevLogs) => [...prevLogs, newLog]);
64
- };
65
-
66
- /**
67
- * Clear all logs
68
- */
69
- const clearLogs = () => {
70
- setLogs([]);
71
- };
72
-
73
- /**
74
- * Setup logger integration and optional console interception
75
- */
76
- useEffect(() => {
77
- // Set the logger function to use our addLog method
78
- Logger.setLoggerFunction(addLog);
79
-
80
- // Optional console interception
81
- if (interceptConsole) {
82
- const originalConsoleLog = console.log;
83
- const originalConsoleError = console.error;
84
- const originalConsoleWarn = console.warn;
85
-
86
- console.log = (...args: any[]) => {
87
- const message = args
88
- .map((arg) =>
89
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
90
- )
91
- .join(' ');
92
- addLog(message, 'console.log');
93
- originalConsoleLog(...args);
94
- };
95
-
96
- console.error = (...args: any[]) => {
97
- const message = args
98
- .map((arg) =>
99
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
100
- )
101
- .join(' ');
102
- addLog(`ERROR: ${message}`, 'console.error');
103
- originalConsoleError(...args);
104
- };
105
-
106
- console.warn = (...args: any[]) => {
107
- const message = args
108
- .map((arg) =>
109
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
110
- )
111
- .join(' ');
112
- addLog(`WARNING: ${message}`, 'console.warn');
113
- originalConsoleWarn(...args);
114
- };
115
-
116
- // Cleanup function to restore original console methods
117
- return () => {
118
- console.log = originalConsoleLog;
119
- console.error = originalConsoleError;
120
- console.warn = originalConsoleWarn;
121
- };
122
- }
123
- }, [interceptConsole]);
124
-
125
- const contextValue: LoggingContextProps = {
126
- logs,
127
- addLog,
128
- clearLogs,
129
- };
130
-
131
- return (
132
- <LoggingContext.Provider value={contextValue}>
133
- {children}
134
- </LoggingContext.Provider>
135
- );
136
- };
137
-
138
- /**
139
- * Hook to use logging context
140
- */
141
- export const useLogging = (): LoggingContextProps => {
142
- const context = useContext(LoggingContext);
143
- if (!context) {
144
- throw new Error('useLogging must be used within a LoggingProvider');
145
- }
146
- return context;
147
- };
148
-
149
- /**
150
- * Higher-order component to wrap components with logging
151
- */
152
- export const withLogging = <P extends object>(
153
- Component: React.ComponentType<P>
154
- ): React.FC<P & { enableConsoleInterception?: boolean }> => {
155
- const EnhancedComponent = ({
156
- enableConsoleInterception = false,
157
- ...props
158
- }) => (
159
- <LoggingProvider interceptConsole={enableConsoleInterception}>
160
- <Component {...(props as P)} />
161
- </LoggingProvider>
162
- );
163
-
164
- EnhancedComponent.displayName = `withLogging(${Component.displayName || Component.name})`;
165
- return EnhancedComponent;
166
- };
@@ -1,192 +0,0 @@
1
- .logging-debug-panel {
2
- background: white;
3
- border-radius: 8px;
4
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
5
- width: 90vw;
6
- height: 80vh;
7
- max-width: 1000px;
8
- max-height: 600px;
9
- display: flex;
10
- flex-direction: column;
11
- overflow: hidden;
12
- }
13
-
14
- .logging-debug-panel__header {
15
- display: flex;
16
- justify-content: space-between;
17
- align-items: center;
18
- padding: 16px 20px;
19
- border-bottom: 1px solid #edebe9;
20
- background: #f8f8f8;
21
- }
22
-
23
- .logging-debug-panel__header h3 {
24
- margin: 0;
25
- font-size: 18px;
26
- font-weight: 600;
27
- color: #323130;
28
- }
29
-
30
- .logging-debug-panel__controls {
31
- display: flex;
32
- justify-content: space-between;
33
- align-items: center;
34
- padding: 12px 20px;
35
- border-bottom: 1px solid #edebe9;
36
- gap: 16px;
37
- }
38
-
39
- .logging-debug-panel__filters {
40
- display: flex;
41
- gap: 12px;
42
- align-items: center;
43
- flex: 1;
44
- }
45
-
46
- .logging-debug-panel__filters .ms-TextField {
47
- min-width: 200px;
48
- }
49
-
50
- .level-filter {
51
- padding: 6px 12px;
52
- border: 1px solid #8a8886;
53
- border-radius: 2px;
54
- font-size: 14px;
55
- background: white;
56
- color: #323130;
57
- }
58
-
59
- .level-filter:focus {
60
- outline: none;
61
- border-color: #0078d4;
62
- }
63
-
64
- .logging-debug-panel__actions {
65
- display: flex;
66
- gap: 8px;
67
- }
68
-
69
- .logging-debug-panel__content {
70
- flex: 1;
71
- overflow: hidden;
72
- display: flex;
73
- flex-direction: column;
74
- }
75
-
76
- .logging-debug-panel__logs {
77
- flex: 1;
78
- overflow-y: auto;
79
- padding: 8px;
80
- }
81
-
82
- .no-logs {
83
- display: flex;
84
- justify-content: center;
85
- align-items: center;
86
- height: 200px;
87
- color: #605e5c;
88
- font-style: italic;
89
- }
90
-
91
- .log-entry {
92
- padding: 8px 12px;
93
- border-bottom: 1px solid #f3f2f1;
94
- font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
95
- font-size: 12px;
96
- }
97
-
98
- .log-entry:hover {
99
- background-color: #faf9f8;
100
- }
101
-
102
- .log-entry__header {
103
- display: flex;
104
- gap: 8px;
105
- align-items: center;
106
- margin-bottom: 4px;
107
- }
108
-
109
- .log-entry__timestamp {
110
- color: #605e5c;
111
- font-weight: 500;
112
- min-width: 80px;
113
- }
114
-
115
- .log-entry__level {
116
- font-weight: 600;
117
- min-width: 60px;
118
- }
119
-
120
- .log-entry__context {
121
- color: #0078d4;
122
- font-weight: 500;
123
- background: #deecf9;
124
- padding: 2px 6px;
125
- border-radius: 3px;
126
- font-size: 11px;
127
- }
128
-
129
- .log-entry__message {
130
- color: #323130;
131
- line-height: 1.4;
132
- margin-left: 96px;
133
- }
134
-
135
- .log-entry__data {
136
- margin-left: 96px;
137
- margin-top: 4px;
138
- }
139
-
140
- .log-entry__data pre {
141
- background: #f8f8f8;
142
- padding: 8px;
143
- border-radius: 4px;
144
- border-left: 3px solid #0078d4;
145
- font-size: 11px;
146
- overflow-x: auto;
147
- margin: 0;
148
- }
149
-
150
- .logging-debug-panel__footer {
151
- padding: 8px 20px;
152
- border-top: 1px solid #edebe9;
153
- background: #f8f8f8;
154
- text-align: center;
155
- }
156
-
157
- .logging-debug-panel__footer small {
158
- color: #605e5c;
159
- }
160
-
161
- /* Mobile responsiveness */
162
- @media (max-width: 768px) {
163
- .logging-debug-panel {
164
- width: 95vw;
165
- height: 90vh;
166
- }
167
-
168
- .logging-debug-panel__controls {
169
- flex-direction: column;
170
- align-items: stretch;
171
- gap: 8px;
172
- }
173
-
174
- .logging-debug-panel__filters {
175
- flex-direction: column;
176
- gap: 8px;
177
- }
178
-
179
- .logging-debug-panel__filters .ms-TextField {
180
- min-width: auto;
181
- }
182
-
183
- .log-entry__message,
184
- .log-entry__data {
185
- margin-left: 0;
186
- margin-top: 4px;
187
- }
188
-
189
- .log-entry__header {
190
- flex-wrap: wrap;
191
- }
192
- }
@@ -1,177 +0,0 @@
1
- import React, { useState, useCallback } from 'react';
2
- import { Button, TextField } from '@khester/dynamics-ui-components';
3
- import { Logger } from './logger';
4
- import './LoggingDebugPanel.css';
5
-
6
- interface LoggingDebugPanelProps {
7
- onClose: () => void;
8
- }
9
-
10
- interface LogEntry {
11
- timestamp: string;
12
- level: string;
13
- message: string;
14
- context?: string;
15
- data?: any;
16
- }
17
-
18
- /**
19
- * Debug panel component for viewing application logs
20
- */
21
- export const LoggingDebugPanel: React.FC<LoggingDebugPanelProps> = ({
22
- onClose,
23
- }) => {
24
- const [filter, setFilter] = useState('');
25
- const [selectedLevel, setSelectedLevel] = useState('all');
26
-
27
- // Get logs from the Logger (this is a simplified version)
28
- const [logs] = useState<LogEntry[]>(() => {
29
- // In a real implementation, you'd get logs from the Logger class
30
- // For now, create some sample logs to demonstrate the UI
31
- return [
32
- {
33
- timestamp: new Date().toISOString(),
34
- level: 'info',
35
- message: 'Application initialized',
36
- context: 'App',
37
- },
38
- {
39
- timestamp: new Date().toISOString(),
40
- level: 'debug',
41
- message: 'ServiceFactory: Running in mock environment',
42
- context: 'ServiceFactory',
43
- },
44
- {
45
- timestamp: new Date().toISOString(),
46
- level: 'user',
47
- message: 'Contact Management loaded',
48
- context: 'ContactManagement',
49
- },
50
- ];
51
- });
52
-
53
- const filteredLogs = logs.filter((log) => {
54
- const matchesFilter =
55
- !filter ||
56
- log.message.toLowerCase().includes(filter.toLowerCase()) ||
57
- log.context?.toLowerCase().includes(filter.toLowerCase());
58
-
59
- const matchesLevel = selectedLevel === 'all' || log.level === selectedLevel;
60
-
61
- return matchesFilter && matchesLevel;
62
- });
63
-
64
- const clearLogs = useCallback(() => {
65
- Logger.log('Debug panel: Logs cleared', 'LoggingDebugPanel');
66
- // In a real implementation, you'd clear the actual logs
67
- }, []);
68
-
69
- const exportLogs = useCallback(() => {
70
- const logData = JSON.stringify(logs, null, 2);
71
- const blob = new Blob([logData], { type: 'application/json' });
72
- const url = URL.createObjectURL(blob);
73
- const a = document.createElement('a');
74
- a.href = url;
75
- a.download = `dynamics-logs-${new Date().toISOString().split('T')[0]}.json`;
76
- a.click();
77
- URL.revokeObjectURL(url);
78
- Logger.log('Debug panel: Logs exported', 'LoggingDebugPanel');
79
- }, [logs]);
80
-
81
- const getLevelColor = (level: string) => {
82
- switch (level) {
83
- case 'error':
84
- return '#d13438';
85
- case 'warn':
86
- return '#ff8c00';
87
- case 'info':
88
- return '#0078d4';
89
- case 'debug':
90
- return '#605e5c';
91
- case 'user':
92
- return '#107c10';
93
- default:
94
- return '#323130';
95
- }
96
- };
97
-
98
- const formatTimestamp = (timestamp: string) => {
99
- return new Date(timestamp).toLocaleTimeString();
100
- };
101
-
102
- return (
103
- <div className="logging-debug-panel">
104
- <div className="logging-debug-panel__header">
105
- <h3>Debug Console</h3>
106
- <Button text="✕" onClick={onClose} variant="default" />
107
- </div>
108
-
109
- <div className="logging-debug-panel__controls">
110
- <div className="logging-debug-panel__filters">
111
- <TextField
112
- placeholder="Filter logs..."
113
- value={filter}
114
- onChange={(_, value) => setFilter(value || '')}
115
- />
116
-
117
- <select
118
- value={selectedLevel}
119
- onChange={(e) => setSelectedLevel(e.target.value)}
120
- className="level-filter"
121
- >
122
- <option value="all">All Levels</option>
123
- <option value="error">Error</option>
124
- <option value="warn">Warning</option>
125
- <option value="info">Info</option>
126
- <option value="debug">Debug</option>
127
- <option value="user">User Action</option>
128
- </select>
129
- </div>
130
-
131
- <div className="logging-debug-panel__actions">
132
- <Button text="Clear" onClick={clearLogs} variant="default" />
133
- <Button text="Export" onClick={exportLogs} variant="default" />
134
- </div>
135
- </div>
136
-
137
- <div className="logging-debug-panel__content">
138
- <div className="logging-debug-panel__logs">
139
- {filteredLogs.length === 0 ? (
140
- <div className="no-logs">No logs match the current filter</div>
141
- ) : (
142
- filteredLogs.map((log, index) => (
143
- <div key={index} className="log-entry">
144
- <div className="log-entry__header">
145
- <span className="log-entry__timestamp">
146
- {formatTimestamp(log.timestamp)}
147
- </span>
148
- <span
149
- className="log-entry__level"
150
- style={{ color: getLevelColor(log.level) }}
151
- >
152
- [{log.level.toUpperCase()}]
153
- </span>
154
- {log.context && (
155
- <span className="log-entry__context">{log.context}</span>
156
- )}
157
- </div>
158
- <div className="log-entry__message">{log.message}</div>
159
- {log.data && (
160
- <div className="log-entry__data">
161
- <pre>{JSON.stringify(log.data, null, 2)}</pre>
162
- </div>
163
- )}
164
- </div>
165
- ))
166
- )}
167
- </div>
168
- </div>
169
-
170
- <div className="logging-debug-panel__footer">
171
- <small>
172
- Showing {filteredLogs.length} of {logs.length} log entries
173
- </small>
174
- </div>
175
- </div>
176
- );
177
- };
@@ -1,3 +0,0 @@
1
- // Re-export the LoggingProvider and useLogging from LoggingContext
2
- // This provides a cleaner import path for the main application
3
- export { LoggingProvider, useLogging } from './LoggingContext';