@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.
Files changed (68) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/react-app/README.en.md +257 -0
  5. package/dist/templates/react-app/README.md +29 -231
  6. package/dist/templates/react-app/config/IOCIdentifier.ts +13 -0
  7. package/dist/templates/react-app/docs/en/bootstrap.md +562 -0
  8. package/dist/templates/react-app/docs/en/development-guide.md +523 -0
  9. package/dist/templates/react-app/docs/en/env.md +482 -0
  10. package/dist/templates/react-app/docs/en/global.md +509 -0
  11. package/dist/templates/react-app/docs/en/i18n.md +268 -0
  12. package/dist/templates/react-app/docs/en/index.md +173 -0
  13. package/dist/templates/react-app/docs/en/ioc.md +424 -0
  14. package/dist/templates/react-app/docs/en/project-structure.md +434 -0
  15. package/dist/templates/react-app/docs/en/request.md +425 -0
  16. package/dist/templates/react-app/docs/en/router.md +404 -0
  17. package/dist/templates/react-app/docs/en/store.md +321 -0
  18. package/dist/templates/react-app/docs/en/theme.md +424 -0
  19. package/dist/templates/react-app/docs/en/typescript-guide.md +473 -0
  20. package/dist/templates/react-app/docs/zh/bootstrap.md +562 -0
  21. package/dist/templates/react-app/docs/zh/development-guide.md +523 -0
  22. package/dist/templates/react-app/docs/zh/env.md +479 -0
  23. package/dist/templates/react-app/docs/zh/global.md +511 -0
  24. package/dist/templates/react-app/docs/zh/i18n.md +268 -0
  25. package/dist/templates/react-app/docs/zh/index.md +173 -0
  26. package/dist/templates/react-app/docs/zh/ioc.md +422 -0
  27. package/dist/templates/react-app/docs/zh/project-structure.md +434 -0
  28. package/dist/templates/react-app/docs/zh/request.md +429 -0
  29. package/dist/templates/react-app/docs/zh/router.md +408 -0
  30. package/dist/templates/react-app/docs/zh/store.md +321 -0
  31. package/dist/templates/react-app/docs/zh/theme.md +424 -0
  32. package/dist/templates/react-app/docs/zh/typescript-guide.md +473 -0
  33. package/dist/templates/react-app/package.json +2 -2
  34. package/dist/templates/react-app/src/base/apis/AiApi.ts +10 -5
  35. package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
  36. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +1 -1
  37. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +10 -17
  38. package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
  39. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +2 -1
  40. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +7 -5
  41. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -2
  42. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +33 -0
  43. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +1 -1
  44. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
  45. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +1 -1
  46. package/dist/templates/react-app/src/base/services/RouteService.ts +5 -2
  47. package/dist/templates/react-app/src/base/services/UserService.ts +8 -10
  48. package/dist/templates/react-app/src/core/IOC.ts +73 -83
  49. package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +52 -4
  50. package/dist/templates/react-app/src/core/bootstraps/{index.ts → BootstrapsRegistry.ts} +2 -3
  51. package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +25 -0
  52. package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +11 -17
  53. package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +10 -4
  54. package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +6 -15
  55. package/dist/templates/react-app/src/main.tsx +2 -5
  56. package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +3 -1
  57. package/dist/templates/react-app/src/styles/css/antd-themes/index.css +1 -1
  58. package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +6 -1
  59. package/dist/templates/react-app/src/styles/css/page.css +1 -1
  60. package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +1 -1
  61. package/dist/templates/react-app/tsconfig.app.json +2 -1
  62. package/dist/templates/react-app/tsconfig.node.json +2 -1
  63. package/package.json +2 -2
  64. package/dist/templates/react-app/src/base/port/ApiTransactionInterface.ts +0 -7
  65. package/dist/templates/react-app/src/base/port/RequestCatcherInterface.ts +0 -12
  66. package/dist/templates/react-app/src/core/bootstrap.ts +0 -58
  67. package/dist/templates/react-app/src/core/registers/RegisterApi.ts +0 -5
  68. package/dist/templates/react-app/src/core/registers/index.ts +0 -32
@@ -0,0 +1,511 @@
1
+ # 浏览器全局变量注入
2
+
3
+ ## 什么是全局变量注入?
4
+
5
+ 全局变量注入是 Bootstrap 的一个重要功能,它允许我们将应用的核心服务和工具注入到浏览器的全局环境中,方便在任何地方访问。
6
+
7
+ **简单来说**:就像把常用的工具放在工具箱里一样,我们把应用的核心功能(日志、存储、配置等)放到浏览器的全局环境中,这样在任何地方都能方便地使用。
8
+
9
+ ## 工作原理
10
+
11
+ ### 1. 全局变量注入流程
12
+
13
+ ```
14
+ 应用启动 → Bootstrap 初始化 → InjectGlobal 插件 → 注入到 window 对象 → 全局可访问
15
+ ```
16
+
17
+ ### 2. 核心技术栈
18
+
19
+ - **@qlover/corekit-bridge**:提供 InjectGlobal 插件
20
+ - **TypeScript**:提供类型安全
21
+ - **浏览器全局对象**:window 或 globalThis
22
+
23
+ ### 3. 文件结构
24
+
25
+ ```
26
+ config/
27
+ ├── common.ts # 全局变量名称配置
28
+ src/
29
+ ├── core/
30
+ │ ├── globals.ts # 全局变量定义
31
+ │ └── bootstraps/
32
+ │ └── BootstrapApp.ts # Bootstrap 配置
33
+ ├── base/
34
+ │ └── types/
35
+ │ └── global.d.ts # 全局类型声明
36
+ └── config/
37
+ └── common.ts # 全局变量名称配置
38
+ ```
39
+
40
+ ## 项目中的实现
41
+
42
+ ### 1. 全局变量定义
43
+
44
+ ```tsx
45
+ // src/core/globals.ts
46
+ import { Logger, ConsoleHandler, ColorFormatter } from '@qlover/corekit-bridge';
47
+ import { AppConfig } from '@/base/cases/AppConfig';
48
+ import { DialogHandler } from '@/base/cases/DialogHandler';
49
+
50
+ // 应用配置
51
+ export const appConfig = new AppConfig();
52
+
53
+ // 对话框处理器
54
+ export const dialogHandler = new DialogHandler();
55
+
56
+ // 全局日志器
57
+ export const logger = new Logger({
58
+ handlers: new ConsoleHandler(new ColorFormatter(loggerStyles)),
59
+ silent: isProduction,
60
+ level: 'debug'
61
+ });
62
+
63
+ // JSON 序列化器
64
+ export const JSON = new JSONSerializer();
65
+
66
+ // 本地存储
67
+ export const localStorage = new SyncStorage(new ObjectStorage(), [
68
+ JSON,
69
+ new Base64Serializer(),
70
+ window.localStorage
71
+ ]);
72
+
73
+ // 加密存储
74
+ export const localStorageEncrypt = localStorage;
75
+
76
+ // Cookie 存储
77
+ export const cookieStorage = new CookieStorage();
78
+ ```
79
+
80
+ ### 2. 全局类型声明
81
+
82
+ ```tsx
83
+ // src/base/types/global.d.ts
84
+ import * as feGlobals from '@/core/globals';
85
+ import type { browserGlobalsName } from '@config/common';
86
+
87
+ declare global {
88
+ interface Window {
89
+ [browserGlobalsName]: Readonly<typeof feGlobals>;
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### 3. Bootstrap 中的注入配置
95
+
96
+ ```tsx
97
+ // src/core/bootstraps/BootstrapApp.ts
98
+ import { Bootstrap } from '@qlover/corekit-bridge';
99
+ import { browserGlobalsName } from '@config/common';
100
+ import * as globals from '../globals';
101
+
102
+ const bootstrap = new Bootstrap({
103
+ root: window,
104
+ logger,
105
+ ioc: {
106
+ manager: IOC,
107
+ register: new IocRegisterImpl({ pathname, appConfig })
108
+ },
109
+ globalOptions: {
110
+ sources: globals, // 全局变量源
111
+ target: browserGlobalsName // 注入目标名称
112
+ }
113
+ });
114
+ ```
115
+
116
+ ### 4. 全局变量名称配置
117
+
118
+ ```tsx
119
+ // config/common.ts
120
+ export const browserGlobalsName = 'feGlobals';
121
+ ```
122
+
123
+ ## InjectGlobal 插件工作原理
124
+
125
+ ### 1. 插件实现
126
+
127
+ ```tsx
128
+ // corekit-bridge/src/core/bootstrap/plugins/InjectGlobal.ts
129
+ export class InjectGlobal implements BootstrapExecutorPlugin {
130
+ readonly pluginName = 'InjectGlobal';
131
+
132
+ constructor(protected config: InjectGlobalConfig) {}
133
+
134
+ onBefore(context: BootstrapContext): void {
135
+ const { sources, target } = this.config;
136
+
137
+ // 如果 target 是字符串,注入到 root 对象
138
+ if (typeof target === 'string') {
139
+ Object.assign(context.parameters.root!, {
140
+ [target]: Object.freeze(Object.assign({}, sources))
141
+ });
142
+ return;
143
+ }
144
+
145
+ // 如果 target 是对象,直接注入到目标对象
146
+ const _target = target || context.parameters.root;
147
+
148
+ if (typeof _target !== 'object' || _target === null) {
149
+ throw new Error('target must be an object');
150
+ }
151
+
152
+ // 注入全局变量到目标对象
153
+ for (const key in sources) {
154
+ const element = sources[key];
155
+ Object.assign(_target, { [key]: element });
156
+ }
157
+ }
158
+ }
159
+ ```
160
+
161
+ ### 2. 注入过程
162
+
163
+ ```tsx
164
+ // 注入前
165
+ window = {
166
+ // 浏览器原生属性
167
+ location: {...},
168
+ document: {...},
169
+ // 其他浏览器属性
170
+ }
171
+
172
+ // 注入后
173
+ window = {
174
+ // 浏览器原生属性
175
+ location: {...},
176
+ document: {...},
177
+ // 注入的全局变量
178
+ feGlobals: {
179
+ appConfig: AppConfig,
180
+ logger: Logger,
181
+ localStorage: SyncStorage,
182
+ dialogHandler: DialogHandler,
183
+ // ... 其他全局变量
184
+ }
185
+ }
186
+ ```
187
+
188
+ ## 在代码中使用
189
+
190
+ ### 1. 直接访问全局变量
191
+
192
+ ```tsx
193
+ // 在任何地方都可以直接访问
194
+ function someFunction() {
195
+ // 访问全局日志器
196
+ window.feGlobals.logger.info('这是一条日志');
197
+
198
+ // 访问应用配置
199
+ const appName = window.feGlobals.appConfig.appName;
200
+
201
+ // 访问本地存储
202
+ window.feGlobals.localStorage.set('key', 'value');
203
+
204
+ // 访问对话框处理器
205
+ window.feGlobals.dialogHandler.showMessage('Hello World');
206
+ }
207
+ ```
208
+
209
+ ### 2. 在组件中使用
210
+
211
+ ```tsx
212
+ import React from 'react';
213
+
214
+ function MyComponent() {
215
+ const handleClick = () => {
216
+ // 使用全局日志器
217
+ window.feGlobals.logger.info('用户点击了按钮');
218
+
219
+ // 使用全局对话框
220
+ window.feGlobals.dialogHandler.showMessage('操作成功');
221
+ };
222
+
223
+ return <button onClick={handleClick}>点击我</button>;
224
+ }
225
+ ```
226
+
227
+ ### 3. 在服务中使用
228
+
229
+ ```tsx
230
+ @injectable()
231
+ export class SomeService {
232
+ async doSomething() {
233
+ // 使用全局日志器记录操作
234
+ window.feGlobals.logger.info('开始执行操作');
235
+
236
+ try {
237
+ // 业务逻辑
238
+ const result = await this.performOperation();
239
+
240
+ // 使用全局对话框显示结果
241
+ window.feGlobals.dialogHandler.showMessage('操作完成');
242
+
243
+ return result;
244
+ } catch (error) {
245
+ // 使用全局日志器记录错误
246
+ window.feGlobals.logger.error('操作失败:', error);
247
+ throw error;
248
+ }
249
+ }
250
+ }
251
+ ```
252
+
253
+ ### 4. 在工具函数中使用
254
+
255
+ ```tsx
256
+ // utils/helper.ts
257
+ export function saveUserData(data: any) {
258
+ try {
259
+ // 使用全局存储
260
+ window.feGlobals.localStorage.set('userData', data);
261
+
262
+ // 使用全局日志器
263
+ window.feGlobals.logger.info('用户数据已保存');
264
+
265
+ return true;
266
+ } catch (error) {
267
+ window.feGlobals.logger.error('保存用户数据失败:', error);
268
+ return false;
269
+ }
270
+ }
271
+ ```
272
+
273
+ ## 实际应用场景
274
+
275
+ ### 1. 调试和开发
276
+
277
+ ```tsx
278
+ // 在浏览器控制台中调试
279
+ console.log('应用配置:', window.feGlobals.appConfig);
280
+ console.log('当前用户:', window.feGlobals.localStorage.get('userData'));
281
+
282
+ // 手动触发日志
283
+ window.feGlobals.logger.debug('调试信息');
284
+
285
+ // 手动显示对话框
286
+ window.feGlobals.dialogHandler.showMessage('测试消息');
287
+ ```
288
+
289
+ ### 2. 错误处理和监控
290
+
291
+ ```tsx
292
+ // 全局错误处理
293
+ window.addEventListener('error', (event) => {
294
+ window.feGlobals.logger.error('全局错误:', event.error);
295
+ });
296
+
297
+ // 未处理的 Promise 拒绝
298
+ window.addEventListener('unhandledrejection', (event) => {
299
+ window.feGlobals.logger.error('未处理的 Promise 拒绝:', event.reason);
300
+ });
301
+ ```
302
+
303
+ ### 3. 第三方库集成
304
+
305
+ ```tsx
306
+ // 与第三方库集成
307
+ import thirdPartyLib from 'third-party-lib';
308
+
309
+ // 配置第三方库使用我们的全局服务
310
+ thirdPartyLib.configure({
311
+ logger: window.feGlobals.logger,
312
+ storage: window.feGlobals.localStorage,
313
+ dialog: window.feGlobals.dialogHandler
314
+ });
315
+ ```
316
+
317
+ ### 4. 浏览器扩展开发
318
+
319
+ ```tsx
320
+ // 在浏览器扩展中使用
321
+ if (window.feGlobals) {
322
+ // 扩展可以访问应用的全局服务
323
+ const appConfig = window.feGlobals.appConfig;
324
+ const logger = window.feGlobals.logger;
325
+
326
+ // 执行扩展逻辑
327
+ logger.info('浏览器扩展已加载');
328
+ }
329
+ ```
330
+
331
+ ## 最佳实践
332
+
333
+ ### 1. 全局变量设计原则
334
+
335
+ ```tsx
336
+ // ✅ 好的设计:只暴露核心服务
337
+ export const globals = {
338
+ appConfig, // 应用配置
339
+ logger, // 日志服务
340
+ localStorage, // 存储服务
341
+ dialogHandler // 对话框服务
342
+ // 其他核心服务...
343
+ };
344
+
345
+ // ❌ 不好的设计:暴露太多细节
346
+ export const globals = {
347
+ appConfig,
348
+ logger,
349
+ localStorage,
350
+ dialogHandler,
351
+ // 不应该暴露的实现细节
352
+ internalService,
353
+ privateHelper,
354
+ implementationDetail
355
+ };
356
+ ```
357
+
358
+ ### 2. 类型安全
359
+
360
+ ```tsx
361
+ // 确保全局变量有正确的类型
362
+ declare global {
363
+ interface Window {
364
+ feGlobals: {
365
+ appConfig: AppConfig;
366
+ logger: LoggerInterface;
367
+ localStorage: SyncStorageInterface<string, string>;
368
+ dialogHandler: DialogHandler;
369
+ // 其他全局变量的类型...
370
+ };
371
+ }
372
+ }
373
+ ```
374
+
375
+ ### 3. 只读访问
376
+
377
+ ```tsx
378
+ // 使用 Object.freeze 确保全局变量不被修改
379
+ Object.assign(context.parameters.root!, {
380
+ [target]: Object.freeze(Object.assign({}, sources))
381
+ });
382
+ ```
383
+
384
+ ### 4. 命名空间隔离
385
+
386
+ ```tsx
387
+ // 使用命名空间避免冲突
388
+ export const browserGlobalsName = 'feGlobals'; // 而不是 'globals'
389
+
390
+ // 在 window 上创建命名空间
391
+ window.feGlobals = {
392
+ // 我们的全局变量
393
+ };
394
+ ```
395
+
396
+ ## 调试和故障排除
397
+
398
+ ### 1. 检查全局变量注入
399
+
400
+ ```tsx
401
+ // 在浏览器控制台中检查
402
+ console.log('全局变量:', window.feGlobals);
403
+ console.log('应用配置:', window.feGlobals?.appConfig);
404
+ console.log('日志器:', window.feGlobals?.logger);
405
+ ```
406
+
407
+ ### 2. 常见问题
408
+
409
+ **问题 1:全局变量未注入**
410
+
411
+ ```tsx
412
+ // 检查 Bootstrap 配置
413
+ const bootstrap = new Bootstrap({
414
+ globalOptions: {
415
+ sources: globals, // 确保 sources 正确
416
+ target: browserGlobalsName // 确保 target 正确
417
+ }
418
+ });
419
+ ```
420
+
421
+ **问题 2:类型错误**
422
+
423
+ ```tsx
424
+ // 检查类型声明
425
+ declare global {
426
+ interface Window {
427
+ [browserGlobalsName]: Readonly<typeof feGlobals>;
428
+ }
429
+ }
430
+ ```
431
+
432
+ **问题 3:全局变量被修改**
433
+
434
+ ```tsx
435
+ // 确保使用 Object.freeze
436
+ Object.freeze(Object.assign({}, sources));
437
+ ```
438
+
439
+ ### 3. 调试工具
440
+
441
+ ```tsx
442
+ // 创建调试工具
443
+ export class GlobalDebugger {
444
+ static logGlobals(): void {
445
+ console.group('Global Variables Debug');
446
+ console.log('feGlobals:', window.feGlobals);
447
+ console.log('AppConfig:', window.feGlobals?.appConfig);
448
+ console.log('Logger:', window.feGlobals?.logger);
449
+ console.log('LocalStorage:', window.feGlobals?.localStorage);
450
+ console.groupEnd();
451
+ }
452
+ }
453
+
454
+ // 在开发环境中使用
455
+ if (import.meta.env.DEV) {
456
+ GlobalDebugger.logGlobals();
457
+ }
458
+ ```
459
+
460
+ ## 安全考虑
461
+
462
+ ### 1. 避免敏感信息
463
+
464
+ ```tsx
465
+ // ❌ 不要暴露敏感信息
466
+ export const globals = {
467
+ appConfig,
468
+ logger,
469
+ // 不要暴露 API 密钥、密码等敏感信息
470
+ apiKey: 'secret_key', // 危险!
471
+ password: 'password' // 危险!
472
+ };
473
+
474
+ // ✅ 只暴露必要的服务
475
+ export const globals = {
476
+ appConfig,
477
+ logger,
478
+ localStorage,
479
+ dialogHandler
480
+ // 不包含敏感信息
481
+ };
482
+ ```
483
+
484
+ ### 2. 权限控制
485
+
486
+ ```tsx
487
+ // 在生产环境中限制某些功能
488
+ if (import.meta.env.PROD) {
489
+ // 禁用调试功能
490
+ window.feGlobals.logger.setLevel('warn');
491
+ }
492
+ ```
493
+
494
+ ### 3. 命名空间隔离
495
+
496
+ ```tsx
497
+ // 使用特定的命名空间避免冲突
498
+ export const browserGlobalsName = 'feGlobals'; // 而不是通用的 'globals'
499
+ ```
500
+
501
+ ## 总结
502
+
503
+ 全局变量注入系统提供了:
504
+
505
+ 1. **全局访问**:在任何地方都能访问核心服务
506
+ 2. **类型安全**:通过 TypeScript 提供类型检查
507
+ 3. **调试便利**:在浏览器控制台中直接调试
508
+ 4. **第三方集成**:便于与第三方库集成
509
+ 5. **开发体验**:提升开发效率和调试体验
510
+
511
+ 通过合理使用全局变量注入,可以让应用的核心服务在任何地方都能方便地访问,同时保持代码的整洁和类型安全。