@linyjs/plugin-docs 0.1.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.
- package/README.md +97 -0
- package/docs/api-reference/index.md +341 -0
- package/docs/best-practices/error-handling.md +462 -0
- package/docs/best-practices/naming-conventions.md +495 -0
- package/docs/best-practices/performance.md +532 -0
- package/docs/best-practices/security.md +620 -0
- package/docs/faq.md +323 -0
- package/docs/getting-started/first-plugin.md +358 -0
- package/docs/getting-started/installation.md +244 -0
- package/docs/getting-started/quick-start.md +174 -0
- package/docs/guides/client-module.md +598 -0
- package/docs/guides/data-persistence.md +536 -0
- package/docs/guides/permissions.md +440 -0
- package/docs/guides/server-module.md +371 -0
- package/docs/guides/ui-slots.md +475 -0
- package/docs/migration/v0-to-v1.md +354 -0
- package/examples/analytics-plugin/README.md +416 -0
- package/examples/analytics-plugin/dist/client/index.d.ts +36 -0
- package/examples/analytics-plugin/dist/client/index.js +173 -0
- package/examples/analytics-plugin/dist/index.d.ts +64 -0
- package/examples/analytics-plugin/dist/index.js +72 -0
- package/examples/analytics-plugin/dist/server/index.d.ts +119 -0
- package/examples/analytics-plugin/dist/server/index.js +313 -0
- package/examples/analytics-plugin/package.json +28 -0
- package/examples/analytics-plugin/src/client/index.tsx +410 -0
- package/examples/analytics-plugin/src/index.ts +71 -0
- package/examples/analytics-plugin/src/server/index.ts +348 -0
- package/examples/analytics-plugin/tsconfig.json +21 -0
- package/examples/blog-plugin/README.md +316 -0
- package/examples/blog-plugin/dist/client/index.d.ts +22 -0
- package/examples/blog-plugin/dist/client/index.js +197 -0
- package/examples/blog-plugin/dist/server/index.d.ts +5 -0
- package/examples/blog-plugin/dist/server/index.js +220 -0
- package/examples/blog-plugin/package.json +24 -0
- package/examples/blog-plugin/src/client/index.tsx +405 -0
- package/examples/blog-plugin/src/server/index.ts +240 -0
- package/examples/blog-plugin/tsconfig.json +16 -0
- package/examples/hello-world/README.md +101 -0
- package/examples/hello-world/dist/client/index.d.ts +5 -0
- package/examples/hello-world/dist/client/index.js +80 -0
- package/examples/hello-world/dist/server/index.d.ts +5 -0
- package/examples/hello-world/dist/server/index.js +38 -0
- package/examples/hello-world/node_modules/.package-lock.json +61 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/HOOKS_USAGE.md +281 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/IMPLEMENTATION_SUMMARY.md +166 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/QUICK_REFERENCE.md +130 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/README.md +214 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/package.json +26 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/application.ts +50 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/comparison-example.tsx +229 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/di.ts +127 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/domain.ts +52 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/hooks-example.tsx +275 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/hooks.ts +175 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/index.ts +87 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/interfaces.ts +117 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/router.ts +49 -0
- package/examples/hello-world/node_modules/@linyjs/client-module-interface/tsconfig.json +10 -0
- package/examples/hello-world/node_modules/@linyjs/server-module-interface/package.json +21 -0
- package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/application.ts +21 -0
- package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/di.ts +127 -0
- package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/domain.ts +75 -0
- package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/index.ts +55 -0
- package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/interfaces.ts +58 -0
- package/examples/hello-world/node_modules/@linyjs/server-module-interface/tsconfig.json +8 -0
- package/examples/hello-world/node_modules/@types/react/LICENSE +21 -0
- package/examples/hello-world/node_modules/@types/react/README.md +15 -0
- package/examples/hello-world/node_modules/@types/react/canary.d.ts +129 -0
- package/examples/hello-world/node_modules/@types/react/compiler-runtime.d.ts +4 -0
- package/examples/hello-world/node_modules/@types/react/experimental.d.ts +184 -0
- package/examples/hello-world/node_modules/@types/react/global.d.ts +166 -0
- package/examples/hello-world/node_modules/@types/react/index.d.ts +4369 -0
- package/examples/hello-world/node_modules/@types/react/jsx-dev-runtime.d.ts +33 -0
- package/examples/hello-world/node_modules/@types/react/jsx-runtime.d.ts +24 -0
- package/examples/hello-world/node_modules/@types/react/package.json +210 -0
- package/examples/hello-world/node_modules/@types/react/ts5.0/canary.d.ts +129 -0
- package/examples/hello-world/node_modules/@types/react/ts5.0/experimental.d.ts +184 -0
- package/examples/hello-world/node_modules/@types/react/ts5.0/global.d.ts +166 -0
- package/examples/hello-world/node_modules/@types/react/ts5.0/index.d.ts +4356 -0
- package/examples/hello-world/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +33 -0
- package/examples/hello-world/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +24 -0
- package/examples/hello-world/node_modules/csstype/LICENSE +19 -0
- package/examples/hello-world/node_modules/csstype/README.md +291 -0
- package/examples/hello-world/node_modules/csstype/index.d.ts +22569 -0
- package/examples/hello-world/node_modules/csstype/index.js.flow +6863 -0
- package/examples/hello-world/node_modules/csstype/package.json +70 -0
- package/examples/hello-world/node_modules/react/LICENSE +21 -0
- package/examples/hello-world/node_modules/react/README.md +37 -0
- package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.development.js +24 -0
- package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.production.js +16 -0
- package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.profiling.js +16 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.development.js +338 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.production.js +14 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.profiling.js +14 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.react-server.development.js +370 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.react-server.production.js +40 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.development.js +352 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.production.js +34 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.profiling.js +34 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.react-server.development.js +370 -0
- package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.react-server.production.js +40 -0
- package/examples/hello-world/node_modules/react/cjs/react.development.js +1284 -0
- package/examples/hello-world/node_modules/react/cjs/react.production.js +542 -0
- package/examples/hello-world/node_modules/react/cjs/react.react-server.development.js +848 -0
- package/examples/hello-world/node_modules/react/cjs/react.react-server.production.js +423 -0
- package/examples/hello-world/node_modules/react/compiler-runtime.js +14 -0
- package/examples/hello-world/node_modules/react/index.js +7 -0
- package/examples/hello-world/node_modules/react/jsx-dev-runtime.js +7 -0
- package/examples/hello-world/node_modules/react/jsx-dev-runtime.react-server.js +7 -0
- package/examples/hello-world/node_modules/react/jsx-runtime.js +7 -0
- package/examples/hello-world/node_modules/react/jsx-runtime.react-server.js +7 -0
- package/examples/hello-world/node_modules/react/package.json +51 -0
- package/examples/hello-world/node_modules/react/react.react-server.js +7 -0
- package/examples/hello-world/node_modules/typescript/LICENSE.txt +55 -0
- package/examples/hello-world/node_modules/typescript/README.md +50 -0
- package/examples/hello-world/node_modules/typescript/SECURITY.md +41 -0
- package/examples/hello-world/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
- package/examples/hello-world/node_modules/typescript/bin/tsc +2 -0
- package/examples/hello-world/node_modules/typescript/bin/tsserver +2 -0
- package/examples/hello-world/node_modules/typescript/lib/_tsc.js +133818 -0
- package/examples/hello-world/node_modules/typescript/lib/_tsserver.js +659 -0
- package/examples/hello-world/node_modules/typescript/lib/_typingsInstaller.js +222 -0
- package/examples/hello-world/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.d.ts +22 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.es6.d.ts +23 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
- package/examples/hello-world/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
- package/examples/hello-world/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/tsc.js +8 -0
- package/examples/hello-world/node_modules/typescript/lib/tsserver.js +8 -0
- package/examples/hello-world/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
- package/examples/hello-world/node_modules/typescript/lib/tsserverlibrary.js +21 -0
- package/examples/hello-world/node_modules/typescript/lib/typesMap.json +497 -0
- package/examples/hello-world/node_modules/typescript/lib/typescript.d.ts +11437 -0
- package/examples/hello-world/node_modules/typescript/lib/typescript.js +200276 -0
- package/examples/hello-world/node_modules/typescript/lib/typingsInstaller.js +8 -0
- package/examples/hello-world/node_modules/typescript/lib/watchGuard.js +53 -0
- package/examples/hello-world/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
- package/examples/hello-world/node_modules/typescript/package.json +120 -0
- package/examples/hello-world/package-lock.json +74 -0
- package/examples/hello-world/package.json +23 -0
- package/examples/hello-world/src/client/index.tsx +110 -0
- package/examples/hello-world/src/server/index.ts +42 -0
- package/examples/hello-world/tsconfig.json +16 -0
- package/package.json +42 -0
- package/src/cli.ts +321 -0
package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/comparison-example.tsx
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook 使用对比示例
|
|
3
|
+
*
|
|
4
|
+
* 展示 useContext 方式 vs useClient* Hook 方式的对比
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useContext } from 'react'
|
|
8
|
+
import type { IComponent } from '@linyjs/client-module-interface'
|
|
9
|
+
import { ClientComponentsContext, ClientServicesContext, ClientHooksContext } from '@linyjs/client-module-interface'
|
|
10
|
+
import { useClientComponent, useClientHook, useClientService } from '../src/hooks.js'
|
|
11
|
+
|
|
12
|
+
// ==================== 方式1: 传统 useContext 方式 ====================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 使用 useContext 获取组件(旧方式)
|
|
16
|
+
*/
|
|
17
|
+
function OldWayComponent() {
|
|
18
|
+
const components = useContext(ClientComponentsContext)
|
|
19
|
+
|
|
20
|
+
// 需要手动从 Context 中提取组件
|
|
21
|
+
const Avatar = components['userModule.userComponents.Avatar'] as IComponent<{ userId: string }> | undefined
|
|
22
|
+
const Button = components['uiModule.uiComponents.Button'] as IComponent<any> | undefined
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
<h2>旧方式 - useContext</h2>
|
|
27
|
+
{Avatar && <Avatar userId="123" />}
|
|
28
|
+
{Button && <Button text="点击" variant="primary" onClick={() => {}} />}
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 使用 useContext 获取服务(旧方式)
|
|
35
|
+
*/
|
|
36
|
+
interface IUserService {
|
|
37
|
+
getUser(id: string): Promise<{ id: string; name: string }>
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function OldWayService() {
|
|
41
|
+
const services = useContext(ClientServicesContext)
|
|
42
|
+
|
|
43
|
+
// 需要手动类型断言
|
|
44
|
+
const userService = services['userModule.userService'] as IUserService | undefined
|
|
45
|
+
|
|
46
|
+
const handleLoad = async () => {
|
|
47
|
+
if (userService) {
|
|
48
|
+
const user = await userService.getUser('123')
|
|
49
|
+
console.log(user)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return <button onClick={handleLoad}>加载用户</button>
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ==================== 方式2: 新 Hook 方式 ====================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 使用 useClientComponent 获取组件(新方式)
|
|
60
|
+
*/
|
|
61
|
+
function NewWayComponent() {
|
|
62
|
+
// 更简洁的 API,自动处理类型
|
|
63
|
+
const Avatar = useClientComponent<{ userId: string }>('userModule.userComponents.Avatar')
|
|
64
|
+
const Button = useClientComponent('uiModule.uiComponents.Button')
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div>
|
|
68
|
+
<h2>新方式 - useClientComponent</h2>
|
|
69
|
+
{Avatar && <Avatar userId="123" />}
|
|
70
|
+
{Button && <Button text="点击" variant="primary" onClick={() => {}} />}
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 使用 useClientService 获取服务(新方式)
|
|
77
|
+
*/
|
|
78
|
+
function NewWayService() {
|
|
79
|
+
// 泛型提供类型安全,无需手动断言
|
|
80
|
+
const userService = useClientService<IUserService>('userModule.userService')
|
|
81
|
+
|
|
82
|
+
const handleLoad = async () => {
|
|
83
|
+
if (userService) {
|
|
84
|
+
const user = await userService.getUser('123')
|
|
85
|
+
console.log(user)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return <button onClick={handleLoad}>加载用户</button>
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 使用 useClientHook 获取 Hook(新方式)
|
|
94
|
+
*/
|
|
95
|
+
function NewWayHook() {
|
|
96
|
+
// 定义 Hook 类型
|
|
97
|
+
type UseAuthHook = () => { isAuthenticated: boolean; user: any }
|
|
98
|
+
|
|
99
|
+
// 使用 Hook
|
|
100
|
+
const useAuth = useClientHook<UseAuthHook>('authModule.authHooks.useAuth')
|
|
101
|
+
const authState = useAuth ? useAuth() : null
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div>
|
|
105
|
+
<h2>新方式 - useClientHook</h2>
|
|
106
|
+
<p>认证状态: {authState?.isAuthenticated ? '已登录' : '未登录'}</p>
|
|
107
|
+
</div>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ==================== 对比总结 ====================
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 两种方式对比
|
|
115
|
+
*/
|
|
116
|
+
export function ComparisonExample() {
|
|
117
|
+
return (
|
|
118
|
+
<div>
|
|
119
|
+
<h1>Hook 使用方式对比</h1>
|
|
120
|
+
|
|
121
|
+
<section>
|
|
122
|
+
<h2>❌ 旧方式 - useContext</h2>
|
|
123
|
+
<pre>{`
|
|
124
|
+
// 需要导入 Context
|
|
125
|
+
import { useContext } from 'react'
|
|
126
|
+
import { ClientComponentsContext } from '@linyjs/client-module-interface'
|
|
127
|
+
|
|
128
|
+
function MyComponent() {
|
|
129
|
+
// 1. 获取整个 Context
|
|
130
|
+
const components = useContext(ClientComponentsContext)
|
|
131
|
+
|
|
132
|
+
// 2. 手动提取需要的组件
|
|
133
|
+
const Avatar = components['userModule.userComponents.Avatar']
|
|
134
|
+
|
|
135
|
+
// 3. 需要手动类型断言
|
|
136
|
+
const TypedAvatar = Avatar as IComponent<Props>
|
|
137
|
+
|
|
138
|
+
return <TypedAvatar userId="123" />
|
|
139
|
+
}
|
|
140
|
+
`}</pre>
|
|
141
|
+
|
|
142
|
+
<strong>缺点:</strong>
|
|
143
|
+
<ul>
|
|
144
|
+
<li>需要手动从 Context 中提取资源</li>
|
|
145
|
+
<li>需要手动类型断言</li>
|
|
146
|
+
<li>代码冗长</li>
|
|
147
|
+
<li>容易出错</li>
|
|
148
|
+
</ul>
|
|
149
|
+
</section>
|
|
150
|
+
|
|
151
|
+
<section>
|
|
152
|
+
<h2>✅ 新方式 - useClient* Hooks</h2>
|
|
153
|
+
<pre>{`
|
|
154
|
+
// 直接导入 Hook
|
|
155
|
+
import { useClientComponent } from '@linyjs/client-module-interface'
|
|
156
|
+
|
|
157
|
+
function MyComponent() {
|
|
158
|
+
// 一行代码搞定,类型安全
|
|
159
|
+
const Avatar = useClientComponent<Props>('userModule.userComponents.Avatar')
|
|
160
|
+
|
|
161
|
+
return <Avatar userId="123" />
|
|
162
|
+
}
|
|
163
|
+
`}</pre>
|
|
164
|
+
|
|
165
|
+
<strong>优点:</strong>
|
|
166
|
+
<ul>
|
|
167
|
+
<li>API 简洁直观</li>
|
|
168
|
+
<li>自动类型推断(通过泛型)</li>
|
|
169
|
+
<li>代码更短</li>
|
|
170
|
+
<li>更易维护</li>
|
|
171
|
+
<li>统一的错误处理</li>
|
|
172
|
+
</ul>
|
|
173
|
+
</section>
|
|
174
|
+
|
|
175
|
+
<section>
|
|
176
|
+
<h2>📊 代码对比</h2>
|
|
177
|
+
<table border={1} cellPadding={8}>
|
|
178
|
+
<thead>
|
|
179
|
+
<tr>
|
|
180
|
+
<th>特性</th>
|
|
181
|
+
<th>useContext</th>
|
|
182
|
+
<th>useClient* Hooks</th>
|
|
183
|
+
</tr>
|
|
184
|
+
</thead>
|
|
185
|
+
<tbody>
|
|
186
|
+
<tr>
|
|
187
|
+
<td>代码行数</td>
|
|
188
|
+
<td>~5 行</td>
|
|
189
|
+
<td>~1 行</td>
|
|
190
|
+
</tr>
|
|
191
|
+
<tr>
|
|
192
|
+
<td>类型安全</td>
|
|
193
|
+
<td>需要手动断言</td>
|
|
194
|
+
<td>自动推断</td>
|
|
195
|
+
</tr>
|
|
196
|
+
<tr>
|
|
197
|
+
<td>错误处理</td>
|
|
198
|
+
<td>需要手动检查</td>
|
|
199
|
+
<td>内置警告</td>
|
|
200
|
+
</tr>
|
|
201
|
+
<tr>
|
|
202
|
+
<td>可读性</td>
|
|
203
|
+
<td>一般</td>
|
|
204
|
+
<td>优秀</td>
|
|
205
|
+
</tr>
|
|
206
|
+
<tr>
|
|
207
|
+
<td>学习成本</td>
|
|
208
|
+
<td>需要了解 Context</td>
|
|
209
|
+
<td>简单直观</td>
|
|
210
|
+
</tr>
|
|
211
|
+
</tbody>
|
|
212
|
+
</table>
|
|
213
|
+
</section>
|
|
214
|
+
</div>
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ==================== 推荐使用 ====================
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* 推荐始终使用新的 Hook 方式
|
|
222
|
+
*
|
|
223
|
+
* 原因:
|
|
224
|
+
* 1. 更简洁的 API
|
|
225
|
+
* 2. 更好的类型安全
|
|
226
|
+
* 3. 统一的错误处理
|
|
227
|
+
* 4. 更符合 React Hooks 的使用习惯
|
|
228
|
+
* 5. 更容易维护和重构
|
|
229
|
+
*/
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 基础依赖注入类型定义
|
|
3
|
+
* 详见 [依赖注入机制设计](../../spec/依赖注入机制设计.md)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** 所有服务的基础类型 */
|
|
7
|
+
export type IService = object
|
|
8
|
+
|
|
9
|
+
/** 服务类构造器类型 */
|
|
10
|
+
export interface IServiceConstructor<S extends IService> {
|
|
11
|
+
new (...args: any[]): S
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** 服务工厂函数类型 */
|
|
15
|
+
export type IServiceFactory<S extends IService> = (...args: any[]) => S
|
|
16
|
+
|
|
17
|
+
/** 服务实现类型(类或工厂函数) */
|
|
18
|
+
export type IServiceMaker<S extends IService> =
|
|
19
|
+
| IServiceConstructor<S>
|
|
20
|
+
| IServiceFactory<S>
|
|
21
|
+
|
|
22
|
+
/** 服务元数据基础类型 */
|
|
23
|
+
export type IServiceMetadata = Record<string, any>
|
|
24
|
+
|
|
25
|
+
/** 服务定义 */
|
|
26
|
+
export interface IServiceDef<
|
|
27
|
+
S extends IService = IService,
|
|
28
|
+
M extends IServiceMetadata = IServiceMetadata
|
|
29
|
+
> {
|
|
30
|
+
/** 服务唯一标识(模块内唯一) */
|
|
31
|
+
serviceTag: string
|
|
32
|
+
/** 服务实现,可以是类或工厂函数 */
|
|
33
|
+
serviceImpl: IServiceMaker<S>
|
|
34
|
+
/** 依赖的其他服务列表,支持 'serviceTag' 或 'moduleName.serviceTag' 格式 */
|
|
35
|
+
dependencies?: string[]
|
|
36
|
+
/** 元数据 */
|
|
37
|
+
meta?: M
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** 模块定义 */
|
|
41
|
+
export interface IModule {
|
|
42
|
+
/** 模块名称 */
|
|
43
|
+
name: string
|
|
44
|
+
/** 依赖的其他模块名称 */
|
|
45
|
+
moduleDependencies?: string[]
|
|
46
|
+
/** 服务定义列表 */
|
|
47
|
+
serviceDefs: IServiceDef[]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ==================== 模块状态与事件 ====================
|
|
51
|
+
|
|
52
|
+
/** 模块状态枚举 */
|
|
53
|
+
export enum ModuleState {
|
|
54
|
+
Unloaded = 'unloaded',
|
|
55
|
+
Loading = 'loading',
|
|
56
|
+
Loaded = 'loaded',
|
|
57
|
+
Error = 'error',
|
|
58
|
+
Unloading = 'unloading',
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** 模块事件类型 */
|
|
62
|
+
export type ModuleEventType =
|
|
63
|
+
| 'module_loaded'
|
|
64
|
+
| 'module_unloaded'
|
|
65
|
+
| 'module_error'
|
|
66
|
+
| 'module_state_changed'
|
|
67
|
+
|
|
68
|
+
/** 模块事件 */
|
|
69
|
+
export interface IModuleEvent {
|
|
70
|
+
type: ModuleEventType
|
|
71
|
+
moduleName: string
|
|
72
|
+
module?: ILoadedModule
|
|
73
|
+
error?: Error
|
|
74
|
+
timestamp: number
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** 已加载模块的运行时表示 */
|
|
78
|
+
export interface ILoadedModule {
|
|
79
|
+
/** 模块名称 */
|
|
80
|
+
name: string
|
|
81
|
+
/** 模块状态 */
|
|
82
|
+
state: ModuleState
|
|
83
|
+
/** 服务实例映射表 */
|
|
84
|
+
services: Map<string, IService>
|
|
85
|
+
/** 源模块定义 */
|
|
86
|
+
sourceModule?: IModule
|
|
87
|
+
/** 加载时间戳 */
|
|
88
|
+
loadedAt?: number
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** 模块生命周期处理器 */
|
|
92
|
+
export interface IModuleHandler {
|
|
93
|
+
/** 模块加载完成后执行 */
|
|
94
|
+
onModuleLoaded?(module: ILoadedModule): void | Promise<void>
|
|
95
|
+
/** 模块卸载后执行 */
|
|
96
|
+
onModuleUnloaded?(module: ILoadedModule): void | Promise<void>
|
|
97
|
+
/** 模块加载错误时执行 */
|
|
98
|
+
onModuleError?(moduleName: string, error: Error): void | Promise<void>
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** 模块容器接口 */
|
|
102
|
+
export interface IModuleContainer {
|
|
103
|
+
/** 设置模块生命周期处理器 */
|
|
104
|
+
setModuleHandler(handler: IModuleHandler): void
|
|
105
|
+
|
|
106
|
+
/** 加载模块 */
|
|
107
|
+
loadModules(modules: IModule[]): Promise<void>
|
|
108
|
+
|
|
109
|
+
/** 卸载模块 */
|
|
110
|
+
unloadModule(moduleName: string): Promise<void>
|
|
111
|
+
/** 重新加载模块 */
|
|
112
|
+
reloadModule(moduleName: string, newModule?: IModule): Promise<void>
|
|
113
|
+
|
|
114
|
+
/** 检查模块是否已加载 */
|
|
115
|
+
isModuleLoaded(moduleName: string): boolean
|
|
116
|
+
/** 获取已加载模块 */
|
|
117
|
+
getLoadedModule(moduleName: string): ILoadedModule | undefined
|
|
118
|
+
/** 获取模块状态 */
|
|
119
|
+
getModuleState(moduleName: string): ModuleState
|
|
120
|
+
/** 获取服务实例 */
|
|
121
|
+
getService<T>(moduleName: string, serviceTag: string): T
|
|
122
|
+
|
|
123
|
+
/** 监听模块事件 */
|
|
124
|
+
on(event: ModuleEventType, listener: (event: IModuleEvent) => void): void
|
|
125
|
+
/** 取消监听模块事件 */
|
|
126
|
+
off(event: ModuleEventType, listener: (event: IModuleEvent) => void): void
|
|
127
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 前端领域类型
|
|
3
|
+
* 详见 [前端模块接口设计](../../spec/前端模块接口设计.md)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ComponentType } from 'react'
|
|
7
|
+
|
|
8
|
+
/** React 组件类型 */
|
|
9
|
+
export type IComponent<P = any> = ComponentType<P>
|
|
10
|
+
|
|
11
|
+
/** 路由守卫 */
|
|
12
|
+
export interface IRouteGuard {
|
|
13
|
+
/** 进入前校验,返回 false 阻止进入,返回 string 重定向到该路径 */
|
|
14
|
+
canEnter?(params: { location: Location }): boolean | string | Promise<boolean | string>
|
|
15
|
+
/** 离开前校验 */
|
|
16
|
+
canLeave?(params: { location: Location }): boolean | Promise<boolean>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 路由 loader — 页面数据预加载 */
|
|
20
|
+
export type IRouteLoader = (params: {
|
|
21
|
+
request?: Request
|
|
22
|
+
params: Record<string, string>
|
|
23
|
+
location: Location
|
|
24
|
+
}) => Promise<any> | any
|
|
25
|
+
|
|
26
|
+
/** 页面路由 */
|
|
27
|
+
export interface IRoute {
|
|
28
|
+
path: string
|
|
29
|
+
component: IComponent
|
|
30
|
+
key?: string
|
|
31
|
+
children?: IRoute[]
|
|
32
|
+
guard?: IRouteGuard
|
|
33
|
+
loader?: IRouteLoader
|
|
34
|
+
meta?: {
|
|
35
|
+
title?: string
|
|
36
|
+
requiresAuth?: boolean
|
|
37
|
+
[key: string]: any
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 全局注册标识
|
|
43
|
+
*
|
|
44
|
+
* Handler 在 onModuleLoaded 中将组件/Hook/服务注册到全局注册表时,
|
|
45
|
+
* 使用 "moduleName.serviceTag.name" 格式作为 key,确保跨模块唯一。
|
|
46
|
+
*
|
|
47
|
+
* 示例:
|
|
48
|
+
* - 'userModule.userComponents.Avatar' → userModule 模块中 userComponents 服务的 Avatar 组件
|
|
49
|
+
* - 'authModule.authHooks.useAuth' → authModule 模块中 authHooks 服务的 useAuth hook
|
|
50
|
+
* - 'userModule.userService' → userModule 模块中 userService 服务
|
|
51
|
+
*/
|
|
52
|
+
export type RegistryKey = string // 格式:"{moduleName}.{serviceTag}.{name}"
|
package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/hooks-example.tsx
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 资源消费 Hooks 使用示例
|
|
3
|
+
*
|
|
4
|
+
* 本文件展示如何在模块中使用 useClientComponent、useClientHook、useClientService
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useContext } from 'react'
|
|
8
|
+
import type { IModule, IRouteService, IRoute, IComponentListService, IHooksService, INormalServiceDef } from '@linyjs/client-module-interface'
|
|
9
|
+
import { useClientComponent, useClientHook, useClientService } from '@linyjs/client-module-interface'
|
|
10
|
+
|
|
11
|
+
// ==================== 示例1: 在组件中使用共享组件 ====================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 用户资料页 - 展示如何使用跨模块的共享组件
|
|
15
|
+
*/
|
|
16
|
+
function UserProfilePage() {
|
|
17
|
+
// 方式1: 跨模块引用(显式指定 moduleName)
|
|
18
|
+
const Avatar = useClientComponent('userModule.userComponents.Avatar')
|
|
19
|
+
const Button = useClientComponent('uiModule.uiComponents.Button')
|
|
20
|
+
|
|
21
|
+
// 方式2: 模块内引用(省略 moduleName,需要当前模块上下文支持)
|
|
22
|
+
// const ProfileCard = useClientComponent('userComponents.ProfileCard')
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
<h1>用户资料</h1>
|
|
27
|
+
|
|
28
|
+
{/* 使用从 userModule 引用的 Avatar 组件 */}
|
|
29
|
+
{Avatar && <Avatar userId="123" size="large" />}
|
|
30
|
+
|
|
31
|
+
{/* 使用从 uiModule 引用的 Button 组件 */}
|
|
32
|
+
{Button && (
|
|
33
|
+
<Button
|
|
34
|
+
text="编辑资料"
|
|
35
|
+
variant="primary"
|
|
36
|
+
onClick={() => console.log('Edit clicked')}
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ==================== 示例2: 在组件中使用共享 Hook ====================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 认证状态显示组件 - 展示如何使用跨模块的 Hook
|
|
47
|
+
*/
|
|
48
|
+
function AuthStatusDisplay() {
|
|
49
|
+
// 跨模块引用 authModule 的 useAuth Hook
|
|
50
|
+
type UseAuthHook = () => { isAuthenticated: boolean; user: { id: string; name: string } | null }
|
|
51
|
+
const useAuth = useClientHook<UseAuthHook>('authModule.authHooks.useAuth')
|
|
52
|
+
|
|
53
|
+
// 如果 Hook 存在,调用它获取认证状态
|
|
54
|
+
const authState = useAuth ? useAuth() : null
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div>
|
|
58
|
+
{authState?.isAuthenticated ? (
|
|
59
|
+
<p>✅ 已登录: {authState.user?.name}</p>
|
|
60
|
+
) : (
|
|
61
|
+
<p>❌ 未登录</p>
|
|
62
|
+
)}
|
|
63
|
+
</div>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ==================== 示例3: 在组件中使用服务 ====================
|
|
68
|
+
|
|
69
|
+
interface IUserService {
|
|
70
|
+
getUser(id: string): Promise<{ id: string; name: string; email: string }>
|
|
71
|
+
updateUser(id: string, data: Partial<{ name: string; email: string }>): Promise<void>
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 用户管理组件 - 展示如何使用跨模块的服务
|
|
76
|
+
*/
|
|
77
|
+
function UserManagement() {
|
|
78
|
+
// 跨模块引用 userModule 的 userService
|
|
79
|
+
const userService = useClientService<IUserService>('userModule.userService')
|
|
80
|
+
|
|
81
|
+
const handleLoadUser = async () => {
|
|
82
|
+
if (userService) {
|
|
83
|
+
try {
|
|
84
|
+
const user = await userService.getUser('123')
|
|
85
|
+
console.log('User loaded:', user)
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('Failed to load user:', error)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div>
|
|
94
|
+
<h2>用户管理</h2>
|
|
95
|
+
<button onClick={handleLoadUser}>加载用户</button>
|
|
96
|
+
</div>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ==================== 示例4: 混合使用多种资源 ====================
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 综合示例 - 同时使用组件、Hook 和服务
|
|
104
|
+
*/
|
|
105
|
+
function ComprehensiveExample() {
|
|
106
|
+
// 引用组件
|
|
107
|
+
const Avatar = useClientComponent('userModule.userComponents.Avatar')
|
|
108
|
+
const Card = useClientComponent('uiModule.uiComponents.Card')
|
|
109
|
+
|
|
110
|
+
// 引用 Hook
|
|
111
|
+
type UseAuthHook = () => { isAuthenticated: boolean; user: { id: string; name: string } | null }
|
|
112
|
+
const useAuth = useClientHook<UseAuthHook>('authModule.authHooks.useAuth')
|
|
113
|
+
const authState = useAuth ? useAuth() : null
|
|
114
|
+
|
|
115
|
+
// 引用服务
|
|
116
|
+
const userService = useClientService<IUserService>('userModule.userService')
|
|
117
|
+
|
|
118
|
+
const handleUpdateProfile = async () => {
|
|
119
|
+
if (userService && authState?.user) {
|
|
120
|
+
await userService.updateUser(authState.user.id, { name: 'New Name' })
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<div>
|
|
126
|
+
{Card && (
|
|
127
|
+
<Card title="用户信息">
|
|
128
|
+
{Avatar && authState?.user && (
|
|
129
|
+
<Avatar userId={authState.user.id} size="medium" />
|
|
130
|
+
)}
|
|
131
|
+
|
|
132
|
+
<p>用户名: {authState?.user?.name ?? '未知'}</p>
|
|
133
|
+
|
|
134
|
+
<button onClick={handleUpdateProfile}>更新资料</button>
|
|
135
|
+
</Card>
|
|
136
|
+
)}
|
|
137
|
+
</div>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ==================== 示例5: 定义提供资源的模块 ====================
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 示例 Hook - 在实际项目中应该由 authModule 提供
|
|
145
|
+
*/
|
|
146
|
+
export function useAuth() {
|
|
147
|
+
// 这里只是示例,实际应该从 Context 或状态管理中获取
|
|
148
|
+
return {
|
|
149
|
+
isAuthenticated: true,
|
|
150
|
+
user: { id: '123', name: '张三' },
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* UI 组件服务 - 提供可复用的 UI 组件
|
|
156
|
+
*/
|
|
157
|
+
class UIComponentService implements IComponentListService {
|
|
158
|
+
components = {
|
|
159
|
+
Button: ({ text, variant, onClick }: any) => (
|
|
160
|
+
<button
|
|
161
|
+
onClick={onClick}
|
|
162
|
+
style={{
|
|
163
|
+
padding: '8px 16px',
|
|
164
|
+
backgroundColor: variant === 'primary' ? '#007bff' : '#6c757d',
|
|
165
|
+
color: 'white',
|
|
166
|
+
border: 'none',
|
|
167
|
+
borderRadius: '4px',
|
|
168
|
+
cursor: 'pointer'
|
|
169
|
+
}}
|
|
170
|
+
>
|
|
171
|
+
{text}
|
|
172
|
+
</button>
|
|
173
|
+
),
|
|
174
|
+
Card: ({ title, children }: any) => (
|
|
175
|
+
<div style={{ border: '1px solid #ddd', borderRadius: '8px', padding: '16px' }}>
|
|
176
|
+
{title && <h3>{title}</h3>}
|
|
177
|
+
{children}
|
|
178
|
+
</div>
|
|
179
|
+
),
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const uiComponentsDef = {
|
|
184
|
+
serviceTag: 'uiComponents',
|
|
185
|
+
serviceImpl: UIComponentService,
|
|
186
|
+
meta: { usageType: 'component' as const },
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Hooks 服务 - 提供可复用的 Hooks
|
|
191
|
+
*/
|
|
192
|
+
class AuthHooksService implements IHooksService {
|
|
193
|
+
hooks = {
|
|
194
|
+
useAuth,
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const authHooksDef = {
|
|
199
|
+
serviceTag: 'authHooks',
|
|
200
|
+
serviceImpl: AuthHooksService,
|
|
201
|
+
meta: { usageType: 'hook' as const },
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 普通服务 - 提供业务逻辑
|
|
206
|
+
*/
|
|
207
|
+
class UserServiceImpl implements IUserService {
|
|
208
|
+
async getUser(id: string) {
|
|
209
|
+
return { id, name: '张三', email: 'zhangsan@example.com' }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async updateUser(id: string, data: Partial<{ name: string; email: string }>) {
|
|
213
|
+
console.log('Updating user:', id, data)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const userServiceDef: INormalServiceDef = {
|
|
218
|
+
serviceTag: 'userService',
|
|
219
|
+
serviceImpl: UserServiceImpl,
|
|
220
|
+
meta: { usageType: 'normal_service' },
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* 用户模块 - 提供组件、Hook 和服务
|
|
225
|
+
*/
|
|
226
|
+
export const userModule: IModule = {
|
|
227
|
+
name: 'userModule',
|
|
228
|
+
serviceDefs: [
|
|
229
|
+
// 这里可以添加路由服务等
|
|
230
|
+
],
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* UI 模块 - 提供共享 UI 组件
|
|
235
|
+
*/
|
|
236
|
+
export const uiModule: IModule = {
|
|
237
|
+
name: 'uiModule',
|
|
238
|
+
serviceDefs: [uiComponentsDef],
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* 认证模块 - 提供认证相关的 Hook
|
|
243
|
+
*/
|
|
244
|
+
export const authModule: IModule = {
|
|
245
|
+
name: 'authModule',
|
|
246
|
+
serviceDefs: [authHooksDef, userServiceDef],
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ==================== 使用建议 ====================
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* 最佳实践:
|
|
253
|
+
*
|
|
254
|
+
* 1. 模块内引用 vs 跨模块引用
|
|
255
|
+
* - 同一模块内的资源可以使用短路径(省略 moduleName)
|
|
256
|
+
* - 跨模块引用必须使用完整路径(moduleName.serviceTag.name)
|
|
257
|
+
*
|
|
258
|
+
* 2. 类型安全
|
|
259
|
+
* - 使用泛型参数为服务和 Hook 提供类型约束
|
|
260
|
+
* - 例如:useClientService<IUserService>('...')
|
|
261
|
+
*
|
|
262
|
+
* 3. 空值检查
|
|
263
|
+
* - 所有 Hook 都可能返回 undefined(资源未找到时)
|
|
264
|
+
* - 使用前应该进行空值检查
|
|
265
|
+
*
|
|
266
|
+
* 4. 命名规范
|
|
267
|
+
* - 组件:PascalCase,如 Avatar、UserProfile
|
|
268
|
+
* - Hook:camelCase 且以 use 开头,如 useAuth、useUser
|
|
269
|
+
* - 服务:camelCase,如 userService、apiService
|
|
270
|
+
*
|
|
271
|
+
* 5. RegistryKey 格式
|
|
272
|
+
* - 组件:moduleName.serviceTag.componentName
|
|
273
|
+
* - Hook:moduleName.serviceTag.hookName
|
|
274
|
+
* - 服务:moduleName.serviceTag
|
|
275
|
+
*/
|