@qlover/create-app 0.6.1 → 0.6.3
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/CHANGELOG.md +61 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/react-app/README.en.md +257 -0
- package/dist/templates/react-app/README.md +29 -231
- package/dist/templates/react-app/config/IOCIdentifier.ts +13 -0
- package/dist/templates/react-app/docs/en/bootstrap.md +562 -0
- package/dist/templates/react-app/docs/en/development-guide.md +523 -0
- package/dist/templates/react-app/docs/en/env.md +482 -0
- package/dist/templates/react-app/docs/en/global.md +509 -0
- package/dist/templates/react-app/docs/en/i18n.md +268 -0
- package/dist/templates/react-app/docs/en/index.md +173 -0
- package/dist/templates/react-app/docs/en/ioc.md +424 -0
- package/dist/templates/react-app/docs/en/project-structure.md +434 -0
- package/dist/templates/react-app/docs/en/request.md +425 -0
- package/dist/templates/react-app/docs/en/router.md +404 -0
- package/dist/templates/react-app/docs/en/store.md +321 -0
- package/dist/templates/react-app/docs/en/theme.md +424 -0
- package/dist/templates/react-app/docs/en/typescript-guide.md +473 -0
- package/dist/templates/react-app/docs/zh/bootstrap.md +562 -0
- package/dist/templates/react-app/docs/zh/development-guide.md +523 -0
- package/dist/templates/react-app/docs/zh/env.md +479 -0
- package/dist/templates/react-app/docs/zh/global.md +511 -0
- package/dist/templates/react-app/docs/zh/i18n.md +268 -0
- package/dist/templates/react-app/docs/zh/index.md +173 -0
- package/dist/templates/react-app/docs/zh/ioc.md +422 -0
- package/dist/templates/react-app/docs/zh/project-structure.md +434 -0
- package/dist/templates/react-app/docs/zh/request.md +429 -0
- package/dist/templates/react-app/docs/zh/router.md +408 -0
- package/dist/templates/react-app/docs/zh/store.md +321 -0
- package/dist/templates/react-app/docs/zh/theme.md +424 -0
- package/dist/templates/react-app/docs/zh/typescript-guide.md +473 -0
- package/dist/templates/react-app/package.json +2 -2
- package/dist/templates/react-app/src/base/apis/AiApi.ts +10 -5
- package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +1 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +10 -17
- package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +2 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +7 -5
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -2
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +33 -0
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +1 -1
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
- package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +1 -1
- package/dist/templates/react-app/src/base/services/RouteService.ts +5 -2
- package/dist/templates/react-app/src/base/services/UserService.ts +8 -10
- package/dist/templates/react-app/src/core/IOC.ts +73 -83
- package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +52 -4
- package/dist/templates/react-app/src/core/bootstraps/{index.ts → BootstrapsRegistry.ts} +2 -3
- package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +25 -0
- package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +11 -17
- package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +10 -4
- package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +6 -15
- package/dist/templates/react-app/src/main.tsx +2 -5
- package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +3 -1
- package/dist/templates/react-app/src/styles/css/antd-themes/index.css +1 -1
- package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +6 -1
- package/dist/templates/react-app/src/styles/css/page.css +1 -1
- package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +1 -1
- package/dist/templates/react-app/tsconfig.app.json +2 -1
- package/dist/templates/react-app/tsconfig.node.json +2 -1
- package/package.json +2 -2
- package/dist/templates/react-app/src/base/port/ApiTransactionInterface.ts +0 -7
- package/dist/templates/react-app/src/base/port/RequestCatcherInterface.ts +0 -12
- package/dist/templates/react-app/src/core/bootstrap.ts +0 -58
- package/dist/templates/react-app/src/core/registers/RegisterApi.ts +0 -5
- package/dist/templates/react-app/src/core/registers/index.ts +0 -32
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# Browser Global Variable Injection
|
|
2
|
+
|
|
3
|
+
## What is Global Variable Injection?
|
|
4
|
+
|
|
5
|
+
Global variable injection is a crucial feature of Bootstrap that allows us to inject core services and utilities into the browser's global environment, making them accessible from anywhere.
|
|
6
|
+
|
|
7
|
+
**In simple terms**: Just like putting commonly used tools in a toolbox, we place the application's core functionalities (logging, storage, configuration, etc.) into the browser's global environment, making them easily accessible from anywhere.
|
|
8
|
+
|
|
9
|
+
## How It Works
|
|
10
|
+
|
|
11
|
+
### 1. Global Variable Injection Process
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
App Start → Bootstrap Initialization → InjectGlobal Plugin → Inject into window Object → Globally Accessible
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 2. Core Technology Stack
|
|
18
|
+
|
|
19
|
+
- **@qlover/corekit-bridge**: Provides InjectGlobal plugin
|
|
20
|
+
- **TypeScript**: Provides type safety
|
|
21
|
+
- **Browser Global Object**: window or globalThis
|
|
22
|
+
|
|
23
|
+
### 3. File Structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
config/
|
|
27
|
+
├── common.ts # Global variable name configuration
|
|
28
|
+
src/
|
|
29
|
+
├── core/
|
|
30
|
+
│ ├── globals.ts # Global variable definitions
|
|
31
|
+
│ └── bootstraps/
|
|
32
|
+
│ └── BootstrapApp.ts # Bootstrap configuration
|
|
33
|
+
├── base/
|
|
34
|
+
│ └── types/
|
|
35
|
+
│ └── global.d.ts # Global type declarations
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Implementation in Project
|
|
39
|
+
|
|
40
|
+
### 1. Global Variable Definition
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
// src/core/globals.ts
|
|
44
|
+
import { Logger, ConsoleHandler, ColorFormatter } from '@qlover/corekit-bridge';
|
|
45
|
+
import { AppConfig } from '@/base/cases/AppConfig';
|
|
46
|
+
import { DialogHandler } from '@/base/cases/DialogHandler';
|
|
47
|
+
|
|
48
|
+
// Application configuration
|
|
49
|
+
export const appConfig = new AppConfig();
|
|
50
|
+
|
|
51
|
+
// Dialog handler
|
|
52
|
+
export const dialogHandler = new DialogHandler();
|
|
53
|
+
|
|
54
|
+
// Global logger
|
|
55
|
+
export const logger = new Logger({
|
|
56
|
+
handlers: new ConsoleHandler(new ColorFormatter(loggerStyles)),
|
|
57
|
+
silent: isProduction,
|
|
58
|
+
level: 'debug'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// JSON serializer
|
|
62
|
+
export const JSON = new JSONSerializer();
|
|
63
|
+
|
|
64
|
+
// Local storage
|
|
65
|
+
export const localStorage = new SyncStorage(new ObjectStorage(), [
|
|
66
|
+
JSON,
|
|
67
|
+
new Base64Serializer(),
|
|
68
|
+
window.localStorage
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
// Encrypted storage
|
|
72
|
+
export const localStorageEncrypt = localStorage;
|
|
73
|
+
|
|
74
|
+
// Cookie storage
|
|
75
|
+
export const cookieStorage = new CookieStorage();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Global Type Declaration
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
// src/base/types/global.d.ts
|
|
82
|
+
import * as feGlobals from '@/core/globals';
|
|
83
|
+
import type { browserGlobalsName } from '@config/common';
|
|
84
|
+
|
|
85
|
+
declare global {
|
|
86
|
+
interface Window {
|
|
87
|
+
[browserGlobalsName]: Readonly<typeof feGlobals>;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 3. Injection Configuration in Bootstrap
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
// src/core/bootstraps/BootstrapApp.ts
|
|
96
|
+
import { Bootstrap } from '@qlover/corekit-bridge';
|
|
97
|
+
import { browserGlobalsName } from '@config/common';
|
|
98
|
+
import * as globals from '../globals';
|
|
99
|
+
|
|
100
|
+
const bootstrap = new Bootstrap({
|
|
101
|
+
root: window,
|
|
102
|
+
logger,
|
|
103
|
+
ioc: {
|
|
104
|
+
manager: IOC,
|
|
105
|
+
register: new IocRegisterImpl({ pathname, appConfig })
|
|
106
|
+
},
|
|
107
|
+
globalOptions: {
|
|
108
|
+
sources: globals, // Global variable source
|
|
109
|
+
target: browserGlobalsName // Injection target name
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 4. Global Variable Name Configuration
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
// config/common.ts
|
|
118
|
+
export const browserGlobalsName = 'feGlobals';
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## InjectGlobal Plugin Working Principle
|
|
122
|
+
|
|
123
|
+
### 1. Plugin Implementation
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
// corekit-bridge/src/core/bootstrap/plugins/InjectGlobal.ts
|
|
127
|
+
export class InjectGlobal implements BootstrapExecutorPlugin {
|
|
128
|
+
readonly pluginName = 'InjectGlobal';
|
|
129
|
+
|
|
130
|
+
constructor(protected config: InjectGlobalConfig) {}
|
|
131
|
+
|
|
132
|
+
onBefore(context: BootstrapContext): void {
|
|
133
|
+
const { sources, target } = this.config;
|
|
134
|
+
|
|
135
|
+
// If target is string, inject into root object
|
|
136
|
+
if (typeof target === 'string') {
|
|
137
|
+
Object.assign(context.parameters.root!, {
|
|
138
|
+
[target]: Object.freeze(Object.assign({}, sources))
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// If target is object, inject directly into target object
|
|
144
|
+
const _target = target || context.parameters.root;
|
|
145
|
+
|
|
146
|
+
if (typeof _target !== 'object' || _target === null) {
|
|
147
|
+
throw new Error('target must be an object');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Inject global variables into target object
|
|
151
|
+
for (const key in sources) {
|
|
152
|
+
const element = sources[key];
|
|
153
|
+
Object.assign(_target, { [key]: element });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 2. Injection Process
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
// Before injection
|
|
163
|
+
window = {
|
|
164
|
+
// Browser native properties
|
|
165
|
+
location: {...},
|
|
166
|
+
document: {...},
|
|
167
|
+
// Other browser properties
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// After injection
|
|
171
|
+
window = {
|
|
172
|
+
// Browser native properties
|
|
173
|
+
location: {...},
|
|
174
|
+
document: {...},
|
|
175
|
+
// Injected global variables
|
|
176
|
+
feGlobals: {
|
|
177
|
+
appConfig: AppConfig,
|
|
178
|
+
logger: Logger,
|
|
179
|
+
localStorage: SyncStorage,
|
|
180
|
+
dialogHandler: DialogHandler,
|
|
181
|
+
// ... other global variables
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Usage in Code
|
|
187
|
+
|
|
188
|
+
### 1. Direct Access to Global Variables
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
// Accessible from anywhere
|
|
192
|
+
function someFunction() {
|
|
193
|
+
// Access global logger
|
|
194
|
+
window.feGlobals.logger.info('This is a log message');
|
|
195
|
+
|
|
196
|
+
// Access application configuration
|
|
197
|
+
const appName = window.feGlobals.appConfig.appName;
|
|
198
|
+
|
|
199
|
+
// Access local storage
|
|
200
|
+
window.feGlobals.localStorage.set('key', 'value');
|
|
201
|
+
|
|
202
|
+
// Access dialog handler
|
|
203
|
+
window.feGlobals.dialogHandler.showMessage('Hello World');
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 2. Using in Components
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
import React from 'react';
|
|
211
|
+
|
|
212
|
+
function MyComponent() {
|
|
213
|
+
const handleClick = () => {
|
|
214
|
+
// Use global logger
|
|
215
|
+
window.feGlobals.logger.info('User clicked button');
|
|
216
|
+
|
|
217
|
+
// Use global dialog
|
|
218
|
+
window.feGlobals.dialogHandler.showMessage('Operation successful');
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
return <button onClick={handleClick}>Click me</button>;
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 3. Using in Services
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
@injectable()
|
|
229
|
+
export class SomeService {
|
|
230
|
+
async doSomething() {
|
|
231
|
+
// Use global logger to record operation
|
|
232
|
+
window.feGlobals.logger.info('Starting operation');
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
// Business logic
|
|
236
|
+
const result = await this.performOperation();
|
|
237
|
+
|
|
238
|
+
// Use global dialog to show result
|
|
239
|
+
window.feGlobals.dialogHandler.showMessage('Operation complete');
|
|
240
|
+
|
|
241
|
+
return result;
|
|
242
|
+
} catch (error) {
|
|
243
|
+
// Use global logger to record error
|
|
244
|
+
window.feGlobals.logger.error('Operation failed:', error);
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### 4. Using in Utility Functions
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
// utils/helper.ts
|
|
255
|
+
export function saveUserData(data: any) {
|
|
256
|
+
try {
|
|
257
|
+
// Use global storage
|
|
258
|
+
window.feGlobals.localStorage.set('userData', data);
|
|
259
|
+
|
|
260
|
+
// Use global logger
|
|
261
|
+
window.feGlobals.logger.info('User data saved');
|
|
262
|
+
|
|
263
|
+
return true;
|
|
264
|
+
} catch (error) {
|
|
265
|
+
window.feGlobals.logger.error('Failed to save user data:', error);
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Practical Application Scenarios
|
|
272
|
+
|
|
273
|
+
### 1. Debugging and Development
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
// Debug in browser console
|
|
277
|
+
console.log('App config:', window.feGlobals.appConfig);
|
|
278
|
+
console.log('Current user:', window.feGlobals.localStorage.get('userData'));
|
|
279
|
+
|
|
280
|
+
// Manually trigger logs
|
|
281
|
+
window.feGlobals.logger.debug('Debug information');
|
|
282
|
+
|
|
283
|
+
// Manually show dialog
|
|
284
|
+
window.feGlobals.dialogHandler.showMessage('Test message');
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 2. Error Handling and Monitoring
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
// Global error handling
|
|
291
|
+
window.addEventListener('error', (event) => {
|
|
292
|
+
window.feGlobals.logger.error('Global error:', event.error);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// Unhandled Promise rejection
|
|
296
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
297
|
+
window.feGlobals.logger.error('Unhandled Promise rejection:', event.reason);
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### 3. Third-party Library Integration
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
// Integrate with third-party library
|
|
305
|
+
import thirdPartyLib from 'third-party-lib';
|
|
306
|
+
|
|
307
|
+
// Configure third-party library to use our global services
|
|
308
|
+
thirdPartyLib.configure({
|
|
309
|
+
logger: window.feGlobals.logger,
|
|
310
|
+
storage: window.feGlobals.localStorage,
|
|
311
|
+
dialog: window.feGlobals.dialogHandler
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### 4. Browser Extension Development
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
// Use in browser extension
|
|
319
|
+
if (window.feGlobals) {
|
|
320
|
+
// Extension can access application's global services
|
|
321
|
+
const appConfig = window.feGlobals.appConfig;
|
|
322
|
+
const logger = window.feGlobals.logger;
|
|
323
|
+
|
|
324
|
+
// Execute extension logic
|
|
325
|
+
logger.info('Browser extension loaded');
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Best Practices
|
|
330
|
+
|
|
331
|
+
### 1. Global Variable Design Principles
|
|
332
|
+
|
|
333
|
+
```tsx
|
|
334
|
+
// ✅ Good design: only expose core services
|
|
335
|
+
export const globals = {
|
|
336
|
+
appConfig, // Application configuration
|
|
337
|
+
logger, // Logging service
|
|
338
|
+
localStorage, // Storage service
|
|
339
|
+
dialogHandler // Dialog service
|
|
340
|
+
// Other core services...
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// ❌ Bad design: exposing too many details
|
|
344
|
+
export const globals = {
|
|
345
|
+
appConfig,
|
|
346
|
+
logger,
|
|
347
|
+
localStorage,
|
|
348
|
+
dialogHandler,
|
|
349
|
+
// Implementation details that shouldn't be exposed
|
|
350
|
+
internalService,
|
|
351
|
+
privateHelper,
|
|
352
|
+
implementationDetail
|
|
353
|
+
};
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 2. Type Safety
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
// Ensure global variables have correct types
|
|
360
|
+
declare global {
|
|
361
|
+
interface Window {
|
|
362
|
+
feGlobals: {
|
|
363
|
+
appConfig: AppConfig;
|
|
364
|
+
logger: LoggerInterface;
|
|
365
|
+
localStorage: SyncStorageInterface<string, string>;
|
|
366
|
+
dialogHandler: DialogHandler;
|
|
367
|
+
// Types for other global variables...
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### 3. Read-only Access
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
// Use Object.freeze to ensure global variables can't be modified
|
|
377
|
+
Object.assign(context.parameters.root!, {
|
|
378
|
+
[target]: Object.freeze(Object.assign({}, sources))
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 4. Namespace Isolation
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
// Use namespace to avoid conflicts
|
|
386
|
+
export const browserGlobalsName = 'feGlobals'; // instead of 'globals'
|
|
387
|
+
|
|
388
|
+
// Create namespace on window
|
|
389
|
+
window.feGlobals = {
|
|
390
|
+
// Our global variables
|
|
391
|
+
};
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Debugging and Troubleshooting
|
|
395
|
+
|
|
396
|
+
### 1. Check Global Variable Injection
|
|
397
|
+
|
|
398
|
+
```tsx
|
|
399
|
+
// Check in browser console
|
|
400
|
+
console.log('Global variables:', window.feGlobals);
|
|
401
|
+
console.log('App config:', window.feGlobals?.appConfig);
|
|
402
|
+
console.log('Logger:', window.feGlobals?.logger);
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### 2. Common Issues
|
|
406
|
+
|
|
407
|
+
**Issue 1: Global Variables Not Injected**
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
// Check Bootstrap configuration
|
|
411
|
+
const bootstrap = new Bootstrap({
|
|
412
|
+
globalOptions: {
|
|
413
|
+
sources: globals, // Ensure sources is correct
|
|
414
|
+
target: browserGlobalsName // Ensure target is correct
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Issue 2: Type Errors**
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
// Check type declarations
|
|
423
|
+
declare global {
|
|
424
|
+
interface Window {
|
|
425
|
+
[browserGlobalsName]: Readonly<typeof feGlobals>;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Issue 3: Global Variables Modified**
|
|
431
|
+
|
|
432
|
+
```tsx
|
|
433
|
+
// Ensure using Object.freeze
|
|
434
|
+
Object.freeze(Object.assign({}, sources));
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 3. Debugging Tools
|
|
438
|
+
|
|
439
|
+
```tsx
|
|
440
|
+
// Create debugging tool
|
|
441
|
+
export class GlobalDebugger {
|
|
442
|
+
static logGlobals(): void {
|
|
443
|
+
console.group('Global Variables Debug');
|
|
444
|
+
console.log('feGlobals:', window.feGlobals);
|
|
445
|
+
console.log('AppConfig:', window.feGlobals?.appConfig);
|
|
446
|
+
console.log('Logger:', window.feGlobals?.logger);
|
|
447
|
+
console.log('LocalStorage:', window.feGlobals?.localStorage);
|
|
448
|
+
console.groupEnd();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Use in development environment
|
|
453
|
+
if (import.meta.env.DEV) {
|
|
454
|
+
GlobalDebugger.logGlobals();
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## Security Considerations
|
|
459
|
+
|
|
460
|
+
### 1. Avoid Sensitive Information
|
|
461
|
+
|
|
462
|
+
```tsx
|
|
463
|
+
// ❌ Don't expose sensitive information
|
|
464
|
+
export const globals = {
|
|
465
|
+
appConfig,
|
|
466
|
+
logger,
|
|
467
|
+
// Don't expose API keys, passwords, or other sensitive information
|
|
468
|
+
apiKey: 'secret_key', // Dangerous!
|
|
469
|
+
password: 'password' // Dangerous!
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// ✅ Only expose necessary services
|
|
473
|
+
export const globals = {
|
|
474
|
+
appConfig,
|
|
475
|
+
logger,
|
|
476
|
+
localStorage,
|
|
477
|
+
dialogHandler
|
|
478
|
+
// No sensitive information
|
|
479
|
+
};
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### 2. Access Control
|
|
483
|
+
|
|
484
|
+
```tsx
|
|
485
|
+
// Restrict certain features in production
|
|
486
|
+
if (import.meta.env.PROD) {
|
|
487
|
+
// Disable debug features
|
|
488
|
+
window.feGlobals.logger.setLevel('warn');
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### 3. Namespace Isolation
|
|
493
|
+
|
|
494
|
+
```tsx
|
|
495
|
+
// Use specific namespace to avoid conflicts
|
|
496
|
+
export const browserGlobalsName = 'feGlobals'; // instead of generic 'globals'
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
## Summary
|
|
500
|
+
|
|
501
|
+
The global variable injection system provides:
|
|
502
|
+
|
|
503
|
+
1. **Global Access**: Core services accessible from anywhere
|
|
504
|
+
2. **Type Safety**: Type checking through TypeScript
|
|
505
|
+
3. **Debugging Convenience**: Direct debugging in browser console
|
|
506
|
+
4. **Third-party Integration**: Easy integration with third-party libraries
|
|
507
|
+
5. **Development Experience**: Improved development efficiency and debugging experience
|
|
508
|
+
|
|
509
|
+
Through proper use of global variable injection, core application services can be conveniently accessed from anywhere while maintaining code cleanliness and type safety.
|