@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.
Files changed (252) hide show
  1. package/README.md +97 -0
  2. package/docs/api-reference/index.md +341 -0
  3. package/docs/best-practices/error-handling.md +462 -0
  4. package/docs/best-practices/naming-conventions.md +495 -0
  5. package/docs/best-practices/performance.md +532 -0
  6. package/docs/best-practices/security.md +620 -0
  7. package/docs/faq.md +323 -0
  8. package/docs/getting-started/first-plugin.md +358 -0
  9. package/docs/getting-started/installation.md +244 -0
  10. package/docs/getting-started/quick-start.md +174 -0
  11. package/docs/guides/client-module.md +598 -0
  12. package/docs/guides/data-persistence.md +536 -0
  13. package/docs/guides/permissions.md +440 -0
  14. package/docs/guides/server-module.md +371 -0
  15. package/docs/guides/ui-slots.md +475 -0
  16. package/docs/migration/v0-to-v1.md +354 -0
  17. package/examples/analytics-plugin/README.md +416 -0
  18. package/examples/analytics-plugin/dist/client/index.d.ts +36 -0
  19. package/examples/analytics-plugin/dist/client/index.js +173 -0
  20. package/examples/analytics-plugin/dist/index.d.ts +64 -0
  21. package/examples/analytics-plugin/dist/index.js +72 -0
  22. package/examples/analytics-plugin/dist/server/index.d.ts +119 -0
  23. package/examples/analytics-plugin/dist/server/index.js +313 -0
  24. package/examples/analytics-plugin/package.json +28 -0
  25. package/examples/analytics-plugin/src/client/index.tsx +410 -0
  26. package/examples/analytics-plugin/src/index.ts +71 -0
  27. package/examples/analytics-plugin/src/server/index.ts +348 -0
  28. package/examples/analytics-plugin/tsconfig.json +21 -0
  29. package/examples/blog-plugin/README.md +316 -0
  30. package/examples/blog-plugin/dist/client/index.d.ts +22 -0
  31. package/examples/blog-plugin/dist/client/index.js +197 -0
  32. package/examples/blog-plugin/dist/server/index.d.ts +5 -0
  33. package/examples/blog-plugin/dist/server/index.js +220 -0
  34. package/examples/blog-plugin/package.json +24 -0
  35. package/examples/blog-plugin/src/client/index.tsx +405 -0
  36. package/examples/blog-plugin/src/server/index.ts +240 -0
  37. package/examples/blog-plugin/tsconfig.json +16 -0
  38. package/examples/hello-world/README.md +101 -0
  39. package/examples/hello-world/dist/client/index.d.ts +5 -0
  40. package/examples/hello-world/dist/client/index.js +80 -0
  41. package/examples/hello-world/dist/server/index.d.ts +5 -0
  42. package/examples/hello-world/dist/server/index.js +38 -0
  43. package/examples/hello-world/node_modules/.package-lock.json +61 -0
  44. package/examples/hello-world/node_modules/@linyjs/client-module-interface/HOOKS_USAGE.md +281 -0
  45. package/examples/hello-world/node_modules/@linyjs/client-module-interface/IMPLEMENTATION_SUMMARY.md +166 -0
  46. package/examples/hello-world/node_modules/@linyjs/client-module-interface/QUICK_REFERENCE.md +130 -0
  47. package/examples/hello-world/node_modules/@linyjs/client-module-interface/README.md +214 -0
  48. package/examples/hello-world/node_modules/@linyjs/client-module-interface/package.json +26 -0
  49. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/application.ts +50 -0
  50. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/comparison-example.tsx +229 -0
  51. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/di.ts +127 -0
  52. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/domain.ts +52 -0
  53. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/hooks-example.tsx +275 -0
  54. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/hooks.ts +175 -0
  55. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/index.ts +87 -0
  56. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/interfaces.ts +117 -0
  57. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/router.ts +49 -0
  58. package/examples/hello-world/node_modules/@linyjs/client-module-interface/tsconfig.json +10 -0
  59. package/examples/hello-world/node_modules/@linyjs/server-module-interface/package.json +21 -0
  60. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/application.ts +21 -0
  61. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/di.ts +127 -0
  62. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/domain.ts +75 -0
  63. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/index.ts +55 -0
  64. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/interfaces.ts +58 -0
  65. package/examples/hello-world/node_modules/@linyjs/server-module-interface/tsconfig.json +8 -0
  66. package/examples/hello-world/node_modules/@types/react/LICENSE +21 -0
  67. package/examples/hello-world/node_modules/@types/react/README.md +15 -0
  68. package/examples/hello-world/node_modules/@types/react/canary.d.ts +129 -0
  69. package/examples/hello-world/node_modules/@types/react/compiler-runtime.d.ts +4 -0
  70. package/examples/hello-world/node_modules/@types/react/experimental.d.ts +184 -0
  71. package/examples/hello-world/node_modules/@types/react/global.d.ts +166 -0
  72. package/examples/hello-world/node_modules/@types/react/index.d.ts +4369 -0
  73. package/examples/hello-world/node_modules/@types/react/jsx-dev-runtime.d.ts +33 -0
  74. package/examples/hello-world/node_modules/@types/react/jsx-runtime.d.ts +24 -0
  75. package/examples/hello-world/node_modules/@types/react/package.json +210 -0
  76. package/examples/hello-world/node_modules/@types/react/ts5.0/canary.d.ts +129 -0
  77. package/examples/hello-world/node_modules/@types/react/ts5.0/experimental.d.ts +184 -0
  78. package/examples/hello-world/node_modules/@types/react/ts5.0/global.d.ts +166 -0
  79. package/examples/hello-world/node_modules/@types/react/ts5.0/index.d.ts +4356 -0
  80. package/examples/hello-world/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +33 -0
  81. package/examples/hello-world/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +24 -0
  82. package/examples/hello-world/node_modules/csstype/LICENSE +19 -0
  83. package/examples/hello-world/node_modules/csstype/README.md +291 -0
  84. package/examples/hello-world/node_modules/csstype/index.d.ts +22569 -0
  85. package/examples/hello-world/node_modules/csstype/index.js.flow +6863 -0
  86. package/examples/hello-world/node_modules/csstype/package.json +70 -0
  87. package/examples/hello-world/node_modules/react/LICENSE +21 -0
  88. package/examples/hello-world/node_modules/react/README.md +37 -0
  89. package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.development.js +24 -0
  90. package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.production.js +16 -0
  91. package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.profiling.js +16 -0
  92. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.development.js +338 -0
  93. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.production.js +14 -0
  94. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.profiling.js +14 -0
  95. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.react-server.development.js +370 -0
  96. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.react-server.production.js +40 -0
  97. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.development.js +352 -0
  98. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.production.js +34 -0
  99. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.profiling.js +34 -0
  100. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.react-server.development.js +370 -0
  101. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.react-server.production.js +40 -0
  102. package/examples/hello-world/node_modules/react/cjs/react.development.js +1284 -0
  103. package/examples/hello-world/node_modules/react/cjs/react.production.js +542 -0
  104. package/examples/hello-world/node_modules/react/cjs/react.react-server.development.js +848 -0
  105. package/examples/hello-world/node_modules/react/cjs/react.react-server.production.js +423 -0
  106. package/examples/hello-world/node_modules/react/compiler-runtime.js +14 -0
  107. package/examples/hello-world/node_modules/react/index.js +7 -0
  108. package/examples/hello-world/node_modules/react/jsx-dev-runtime.js +7 -0
  109. package/examples/hello-world/node_modules/react/jsx-dev-runtime.react-server.js +7 -0
  110. package/examples/hello-world/node_modules/react/jsx-runtime.js +7 -0
  111. package/examples/hello-world/node_modules/react/jsx-runtime.react-server.js +7 -0
  112. package/examples/hello-world/node_modules/react/package.json +51 -0
  113. package/examples/hello-world/node_modules/react/react.react-server.js +7 -0
  114. package/examples/hello-world/node_modules/typescript/LICENSE.txt +55 -0
  115. package/examples/hello-world/node_modules/typescript/README.md +50 -0
  116. package/examples/hello-world/node_modules/typescript/SECURITY.md +41 -0
  117. package/examples/hello-world/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  118. package/examples/hello-world/node_modules/typescript/bin/tsc +2 -0
  119. package/examples/hello-world/node_modules/typescript/bin/tsserver +2 -0
  120. package/examples/hello-world/node_modules/typescript/lib/_tsc.js +133818 -0
  121. package/examples/hello-world/node_modules/typescript/lib/_tsserver.js +659 -0
  122. package/examples/hello-world/node_modules/typescript/lib/_typingsInstaller.js +222 -0
  123. package/examples/hello-world/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
  124. package/examples/hello-world/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
  125. package/examples/hello-world/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
  126. package/examples/hello-world/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
  127. package/examples/hello-world/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
  128. package/examples/hello-world/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
  129. package/examples/hello-world/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
  130. package/examples/hello-world/node_modules/typescript/lib/lib.d.ts +22 -0
  131. package/examples/hello-world/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  132. package/examples/hello-world/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  133. package/examples/hello-world/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  134. package/examples/hello-world/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  135. package/examples/hello-world/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  136. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  137. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  138. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  139. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  140. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  141. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  142. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  143. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  144. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  145. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  146. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  147. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  148. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  149. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  150. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  151. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  152. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  153. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  154. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  155. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  156. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  157. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  158. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  159. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  160. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  161. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  162. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  163. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  164. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  165. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  166. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  167. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  168. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  169. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  170. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  171. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  172. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  173. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  174. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  175. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  176. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  177. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  178. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  179. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  180. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  181. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  182. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  183. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  184. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  185. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  186. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  187. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  188. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  189. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  190. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  191. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  192. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  193. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  194. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  195. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  196. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  197. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  198. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  199. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  200. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  201. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  202. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  203. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  204. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  205. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  206. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  207. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  208. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  209. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  210. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  211. package/examples/hello-world/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  212. package/examples/hello-world/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  213. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  214. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  215. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  216. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  217. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  218. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  219. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  220. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  221. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  222. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  223. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  224. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  225. package/examples/hello-world/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  226. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  227. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  228. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  229. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  230. package/examples/hello-world/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
  231. package/examples/hello-world/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
  232. package/examples/hello-world/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
  233. package/examples/hello-world/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
  234. package/examples/hello-world/node_modules/typescript/lib/tsc.js +8 -0
  235. package/examples/hello-world/node_modules/typescript/lib/tsserver.js +8 -0
  236. package/examples/hello-world/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
  237. package/examples/hello-world/node_modules/typescript/lib/tsserverlibrary.js +21 -0
  238. package/examples/hello-world/node_modules/typescript/lib/typesMap.json +497 -0
  239. package/examples/hello-world/node_modules/typescript/lib/typescript.d.ts +11437 -0
  240. package/examples/hello-world/node_modules/typescript/lib/typescript.js +200276 -0
  241. package/examples/hello-world/node_modules/typescript/lib/typingsInstaller.js +8 -0
  242. package/examples/hello-world/node_modules/typescript/lib/watchGuard.js +53 -0
  243. package/examples/hello-world/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
  244. package/examples/hello-world/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
  245. package/examples/hello-world/node_modules/typescript/package.json +120 -0
  246. package/examples/hello-world/package-lock.json +74 -0
  247. package/examples/hello-world/package.json +23 -0
  248. package/examples/hello-world/src/client/index.tsx +110 -0
  249. package/examples/hello-world/src/server/index.ts +42 -0
  250. package/examples/hello-world/tsconfig.json +16 -0
  251. package/package.json +42 -0
  252. package/src/cli.ts +321 -0
@@ -0,0 +1,598 @@
1
+ # 客户端模块开发
2
+
3
+ 本指南详细介绍如何开发 linyjs 插件的客户端模块。
4
+
5
+ ## 概述
6
+
7
+ 客户端模块负责:
8
+
9
+ - 🎨 定义页面路由和组件
10
+ - 📊 管理全局状态
11
+ - 🔗 提供可复用的组件和 Hooks
12
+ - 💫 实现用户交互和 UI 逻辑
13
+
14
+ ## 模块结构
15
+
16
+ 一个完整的客户端模块包含:
17
+
18
+ ```typescript
19
+ import type { IModule } from '@linyjs/client-module-interface';
20
+
21
+ export const myClientModule: IModule = {
22
+ name: 'myClient',
23
+ serviceDefs: [
24
+ routeDef, // 路由
25
+ stateDef, // 全局状态
26
+ componentDef, // 组件注册
27
+ hookDef, // Hooks 注册
28
+ serviceDef // 普通服务
29
+ ]
30
+ };
31
+ ```
32
+
33
+ ## 路由(Route)
34
+
35
+ 路由用于定义页面的 URL 和组件映射。
36
+
37
+ ### 基本示例
38
+
39
+ ```typescript
40
+ import type { IRouteService } from '@linyjs/client-module-interface';
41
+ import React from 'react';
42
+
43
+ function MyPage() {
44
+ return <div>My Page</div>;
45
+ }
46
+
47
+ class MyRouteService implements IRouteService {
48
+ basePath = '/my'; // 路由前缀
49
+
50
+ getRoutes() {
51
+ return [
52
+ {
53
+ path: '/',
54
+ component: MyPage,
55
+ key: 'my-page',
56
+ meta: {
57
+ title: 'My Page',
58
+ requiresAuth: true // 需要登录
59
+ }
60
+ }
61
+ ];
62
+ }
63
+ }
64
+
65
+ export const routeDef = {
66
+ serviceTag: 'myRoute',
67
+ serviceImpl: MyRouteService,
68
+ meta: { usageType: 'route' }
69
+ };
70
+ ```
71
+
72
+ ### 路由参数
73
+
74
+ ```typescript
75
+ // 动态路由: /blog/:id
76
+ {
77
+ path: '/:id',
78
+ component: BlogDetail,
79
+ key: 'blog-detail',
80
+ meta: { title: 'Blog Detail' }
81
+ }
82
+
83
+ // 在组件中获取参数
84
+ import { useParams } from 'react-router-dom';
85
+
86
+ function BlogDetail() {
87
+ const { id } = useParams();
88
+ return <div>Blog ID: {id}</div>;
89
+ }
90
+ ```
91
+
92
+ ### 路由守卫
93
+
94
+ ```typescript
95
+ {
96
+ path: '/admin',
97
+ component: AdminPanel,
98
+ key: 'admin',
99
+ guard: {
100
+ canEnter: async ({ location }) => {
101
+ // 检查权限
102
+ const hasPermission = checkAdminPermission();
103
+ if (!hasPermission) {
104
+ return '/forbidden'; // 重定向到禁止访问页面
105
+ }
106
+ return true; // 允许访问
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ ### 数据预加载(Loader)
113
+
114
+ ```typescript
115
+ {
116
+ path: '/articles',
117
+ component: ArticleList,
118
+ key: 'article-list',
119
+ loader: async ({ params }) => {
120
+ // 在渲染组件前预加载数据(SSR 友好)
121
+ const res = await fetch('/api/articles');
122
+ return { articles: await res.json() };
123
+ }
124
+ }
125
+
126
+ // 在组件中使用 loader 数据
127
+ import { useLoaderData } from 'react-router-dom';
128
+
129
+ function ArticleList() {
130
+ const { articles } = useLoaderData();
131
+ return <div>{/* 渲染文章列表 */}</div>;
132
+ }
133
+ ```
134
+
135
+ ### 嵌套路由
136
+
137
+ ```typescript
138
+ class BlogRouteService implements IRouteService {
139
+ basePath = '/blog';
140
+
141
+ getRoutes() {
142
+ return [
143
+ {
144
+ path: '/',
145
+ component: BlogLayout, // 布局组件
146
+ key: 'blog-layout',
147
+ children: [
148
+ {
149
+ path: '',
150
+ component: ArticleList,
151
+ key: 'article-list'
152
+ },
153
+ {
154
+ path: ':id',
155
+ component: ArticleDetail,
156
+ key: 'article-detail'
157
+ }
158
+ ]
159
+ }
160
+ ];
161
+ }
162
+ }
163
+ ```
164
+
165
+ ## 全局状态(Global State)
166
+
167
+ 使用 Jotai 进行状态管理。
168
+
169
+ ### 定义状态
170
+
171
+ ```typescript
172
+ import type { IGlobalStateService } from '@linyjs/client-module-interface';
173
+ import { atom } from 'jotai';
174
+
175
+ interface UserState {
176
+ id: number;
177
+ name: string;
178
+ email: string;
179
+ }
180
+
181
+ interface AppState {
182
+ user: UserState | null;
183
+ loading: boolean;
184
+ theme: 'light' | 'dark';
185
+ }
186
+
187
+ class MyStateService implements IGlobalStateService {
188
+ atoms = {
189
+ // 应用状态
190
+ appState: atom<AppState>({
191
+ user: null,
192
+ loading: false,
193
+ theme: 'light'
194
+ }),
195
+
196
+ // 派生状态
197
+ isLoggedIn: atom((get) => {
198
+ const state = get(this.atoms.appState);
199
+ return state.user !== null;
200
+ }),
201
+
202
+ // 可写状态
203
+ userName: atom(
204
+ (get) => get(this.atoms.appState).user?.name || '',
205
+ (get, set, newName: string) => {
206
+ const state = get(this.atoms.appState);
207
+ set(this.atoms.appState, {
208
+ ...state,
209
+ user: state.user ? { ...state.user, name: newName } : null
210
+ });
211
+ }
212
+ )
213
+ };
214
+ }
215
+
216
+ export const stateDef = {
217
+ serviceTag: 'myState',
218
+ serviceImpl: MyStateService,
219
+ meta: { usageType: 'global_state' }
220
+ };
221
+ ```
222
+
223
+ ### 使用状态
224
+
225
+ ```typescript
226
+ import { useAtom } from 'jotai';
227
+
228
+ function UserProfile() {
229
+ const [appState, setAppState] = useAtom('myState.appState');
230
+ const [isLoggedIn] = useAtom('myState.isLoggedIn');
231
+ const [userName, setUserName] = useAtom('myState.userName');
232
+
233
+ if (!isLoggedIn) {
234
+ return <div>Please login</div>;
235
+ }
236
+
237
+ return (
238
+ <div>
239
+ <h1>Welcome, {userName}!</h1>
240
+ <button onClick={() => setUserName('New Name')}>
241
+ Change Name
242
+ </button>
243
+ </div>
244
+ );
245
+ }
246
+ ```
247
+
248
+ ### 异步状态
249
+
250
+ ```typescript
251
+ import { atom } from 'jotai';
252
+
253
+ const userDataAtom = atom(async () => {
254
+ const res = await fetch('/api/user');
255
+ return res.json();
256
+ });
257
+
258
+ function UserDashboard() {
259
+ const [user] = useAtom(userDataAtom);
260
+
261
+ if (!user) {
262
+ return <div>Loading...</div>;
263
+ }
264
+
265
+ return <div>{user.name}</div>;
266
+ }
267
+ ```
268
+
269
+ ## 组件注册(Component)
270
+
271
+ 注册可跨模块复用的组件。
272
+
273
+ ### 定义组件
274
+
275
+ ```typescript
276
+ import type { IComponentListService } from '@linyjs/client-module-interface';
277
+ import React from 'react';
278
+
279
+ // 按钮组件
280
+ function MyButton({
281
+ onClick,
282
+ children
283
+ }: {
284
+ onClick: () => void;
285
+ children: React.ReactNode
286
+ }) {
287
+ return (
288
+ <button
289
+ onClick={onClick}
290
+ style={{ padding: '8px 16px' }}
291
+ >
292
+ {children}
293
+ </button>
294
+ );
295
+ }
296
+
297
+ // 卡片组件
298
+ function MyCard({
299
+ title,
300
+ children
301
+ }: {
302
+ title: string;
303
+ children: React.ReactNode
304
+ }) {
305
+ return (
306
+ <div className="card">
307
+ <h3>{title}</h3>
308
+ {children}
309
+ </div>
310
+ );
311
+ }
312
+
313
+ class MyComponentService implements IComponentListService {
314
+ components = {
315
+ MyButton,
316
+ MyCard
317
+ };
318
+ }
319
+
320
+ export const componentDef = {
321
+ serviceTag: 'myComponents',
322
+ serviceImpl: MyComponentService,
323
+ meta: { usageType: 'component' }
324
+ };
325
+ ```
326
+
327
+ ### 跨模块使用组件
328
+
329
+ ```typescript
330
+ import { useClientComponent } from '@linyjs/client-module-interface';
331
+
332
+ function MyPage() {
333
+ // 从其他模块获取组件
334
+ const MyButton = useClientComponent('otherModule.myComponents.MyButton');
335
+
336
+ return (
337
+ <MyButton onClick={() => alert('Clicked!')}>
338
+ Click Me
339
+ </MyButton>
340
+ );
341
+ }
342
+ ```
343
+
344
+ ## Hooks 注册
345
+
346
+ 注册可跨模块复用的自定义 Hooks。
347
+
348
+ ### 定义 Hooks
349
+
350
+ ```typescript
351
+ import type { IHooksService } from '@linyjs/client-module-interface';
352
+ import { useState, useEffect } from 'react';
353
+
354
+ // 获取数据的 Hook
355
+ function useFetchData<T>(url: string) {
356
+ const [data, setData] = useState<T | null>(null);
357
+ const [loading, setLoading] = useState(true);
358
+ const [error, setError] = useState<string | null>(null);
359
+
360
+ useEffect(() => {
361
+ fetch(url)
362
+ .then(res => res.json())
363
+ .then(setData)
364
+ .catch(err => setError(err.message))
365
+ .finally(() => setLoading(false));
366
+ }, [url]);
367
+
368
+ return { data, loading, error };
369
+ }
370
+
371
+ // 本地存储 Hook
372
+ function useLocalStorage(key: string, initialValue: any) {
373
+ const [value, setValue] = useState(() => {
374
+ const stored = localStorage.getItem(key);
375
+ return stored ? JSON.parse(stored) : initialValue;
376
+ });
377
+
378
+ useEffect(() => {
379
+ localStorage.setItem(key, JSON.stringify(value));
380
+ }, [key, value]);
381
+
382
+ return [value, setValue];
383
+ }
384
+
385
+ class MyHooksService implements IHooksService {
386
+ hooks = {
387
+ useFetchData,
388
+ useLocalStorage
389
+ };
390
+ }
391
+
392
+ export const hookDef = {
393
+ serviceTag: 'myHooks',
394
+ serviceImpl: MyHooksService,
395
+ meta: { usageType: 'hook' }
396
+ };
397
+ ```
398
+
399
+ ### 跨模块使用 Hooks
400
+
401
+ ```typescript
402
+ import { useClientHook } from '@linyjs/client-module-interface';
403
+
404
+ function MyComponent() {
405
+ const useFetchData = useClientHook('otherModule.myHooks.useFetchData');
406
+ const { data, loading } = useFetchData('/api/data');
407
+
408
+ if (loading) return <div>Loading...</div>;
409
+
410
+ return <div>{JSON.stringify(data)}</div>;
411
+ }
412
+ ```
413
+
414
+ ## 样式处理
415
+
416
+ ### CSS Modules
417
+
418
+ ```typescript
419
+ import styles from './MyComponent.module.css';
420
+
421
+ function MyComponent() {
422
+ return <div className={styles.container}>Hello</div>;
423
+ }
424
+ ```
425
+
426
+ ### 内联样式
427
+
428
+ ```typescript
429
+ function MyComponent() {
430
+ return (
431
+ <div style={{
432
+ padding: '20px',
433
+ backgroundColor: '#f5f5f5'
434
+ }}>
435
+ Hello
436
+ </div>
437
+ );
438
+ }
439
+ ```
440
+
441
+ ### Tailwind CSS
442
+
443
+ ```typescript
444
+ function MyComponent() {
445
+ return (
446
+ <div className="p-4 bg-gray-100 rounded-lg">
447
+ Hello
448
+ </div>
449
+ );
450
+ }
451
+ ```
452
+
453
+ ## 错误边界
454
+
455
+ ```typescript
456
+ import React, { Component } from 'react';
457
+
458
+ class ErrorBoundary extends Component {
459
+ state = { hasError: false };
460
+
461
+ static getDerivedStateFromError(error: Error) {
462
+ return { hasError: true };
463
+ }
464
+
465
+ render() {
466
+ if (this.state.hasError) {
467
+ return <div>Something went wrong.</div>;
468
+ }
469
+ return this.props.children;
470
+ }
471
+ }
472
+
473
+ // 使用
474
+ function MyApp() {
475
+ return (
476
+ <ErrorBoundary>
477
+ <MyComponent />
478
+ </ErrorBoundary>
479
+ );
480
+ }
481
+ ```
482
+
483
+ ## 性能优化
484
+
485
+ ### React.memo
486
+
487
+ ```typescript
488
+ import { memo } from 'react';
489
+
490
+ const ExpensiveComponent = memo(({ data }) => {
491
+ // 复杂计算...
492
+ return <div>{/* ... */}</div>;
493
+ });
494
+ ```
495
+
496
+ ### useMemo
497
+
498
+ ```typescript
499
+ import { useMemo } from 'react';
500
+
501
+ function MyComponent({ items }) {
502
+ const sortedItems = useMemo(() => {
503
+ return [...items].sort((a, b) => a.name.localeCompare(b.name));
504
+ }, [items]);
505
+
506
+ return <div>{/* ... */}</div>;
507
+ }
508
+ ```
509
+
510
+ ### useCallback
511
+
512
+ ```typescript
513
+ import { useCallback } from 'react';
514
+
515
+ function MyComponent() {
516
+ const handleClick = useCallback(() => {
517
+ console.log('Clicked');
518
+ }, []);
519
+
520
+ return <button onClick={handleClick}>Click</button>;
521
+ }
522
+ ```
523
+
524
+ ### 懒加载
525
+
526
+ ```typescript
527
+ import { lazy, Suspense } from 'react';
528
+
529
+ const HeavyComponent = lazy(() => import('./HeavyComponent'));
530
+
531
+ function MyPage() {
532
+ return (
533
+ <Suspense fallback={<div>Loading...</div>}>
534
+ <HeavyComponent />
535
+ </Suspense>
536
+ );
537
+ }
538
+ ```
539
+
540
+ ## 完整示例
541
+
542
+ 查看完整示例:
543
+
544
+ - 📁 [Hello World 示例](../../examples/hello-world/src/client/index.tsx)
545
+
546
+ ## 最佳实践
547
+
548
+ ### 1. 组件拆分
549
+
550
+ ```
551
+ src/client/
552
+ ├── pages/ # 页面组件
553
+ ├── components/ # 可复用组件
554
+ ├── hooks/ # 自定义 Hooks
555
+ └── services/ # 服务类
556
+ ```
557
+
558
+ ### 2. 类型安全
559
+
560
+ ```typescript
561
+ interface MyComponentProps {
562
+ title: string;
563
+ onClick?: () => void;
564
+ }
565
+
566
+ function MyComponent({ title, onClick }: MyComponentProps) {
567
+ return <button onClick={onClick}>{title}</button>;
568
+ }
569
+ ```
570
+
571
+ ### 3. 错误处理
572
+
573
+ ```typescript
574
+ function SafeComponent() {
575
+ const [error, setError] = useState<string | null>(null);
576
+
577
+ useEffect(() => {
578
+ fetchData()
579
+ .catch(err => setError(err.message));
580
+ }, []);
581
+
582
+ if (error) {
583
+ return <div>Error: {error}</div>;
584
+ }
585
+
586
+ return <div>Content</div>;
587
+ }
588
+ ```
589
+
590
+ ## 下一步
591
+
592
+ - 🎨 阅读 [UI 扩展插槽](./ui-slots.md)
593
+ - 🔒 阅读 [权限管理](./permissions.md)
594
+ - 💾 阅读 [数据持久化](./data-persistence.md)
595
+
596
+ ---
597
+
598
+ **上一篇**: [服务端模块开发](./server-module.md) | **下一篇**: [UI 扩展插槽](./ui-slots.md)