@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,410 @@
1
+ import React from 'react';
2
+ import type { IModule } from '@linyjs/client-module-interface';
3
+
4
+ const API_BASE = '/api/analytics';
5
+
6
+ /**
7
+ * 实时统计卡片组件
8
+ */
9
+ function StatsCard({ title, value, unit = '', description }: {
10
+ title: string;
11
+ value: React.ReactNode;
12
+ unit?: string;
13
+ description?: string;
14
+ }) {
15
+ return (
16
+ <div className="bg-white p-6 rounded-lg shadow-md">
17
+ <h3 className="text-sm font-medium text-gray-500 mb-2">{title}</h3>
18
+ <div className="flex items-baseline mb-2">
19
+ <span className="text-3xl font-bold text-gray-900">{value}</span>
20
+ {unit && <span className="text-lg text-gray-500 ml-1">{unit}</span>}
21
+ </div>
22
+ {description && <p className="text-sm text-gray-600">{description}</p>}
23
+ </div>
24
+ );
25
+ }
26
+
27
+ /**
28
+ * 图表组件 (简化版)
29
+ */
30
+ function SimpleChart({ data, title, type = 'line' }: {
31
+ data: any[];
32
+ title: string;
33
+ type?: 'line' | 'bar';
34
+ }) {
35
+ return (
36
+ <div className="bg-white p-6 rounded-lg shadow-md">
37
+ <h3 className="text-lg font-semibold mb-4">{title}</h3>
38
+ <div className="space-y-2 max-h-64 overflow-y-auto">
39
+ {data.map((item, index) => {
40
+ if (typeof item === 'object' && item.name && typeof item.count === 'number') {
41
+ const maxCount = Math.max(...data.map(d => d.count || 1));
42
+ const widthPercent = (item.count / maxCount) * 100;
43
+
44
+ return (
45
+ <div key={index} className="flex items-center space-x-2">
46
+ <div className="w-24 text-sm text-gray-600 truncate">
47
+ {item.name}
48
+ </div>
49
+ <div className="flex-1 bg-gray-200 rounded-full h-4">
50
+ <div
51
+ className="bg-blue-600 h-4 rounded-full"
52
+ style={{ width: `${widthPercent}%` }}
53
+ ></div>
54
+ </div>
55
+ <div className="w-12 text-sm text-gray-900 font-medium">
56
+ {item.count}
57
+ </div>
58
+ </div>
59
+ );
60
+ }
61
+ return null;
62
+ })}
63
+ </div>
64
+ </div>
65
+ );
66
+ }
67
+
68
+ /**
69
+ * 留存分析组件
70
+ */
71
+ function RetentionChart({ data }: { data: any }) {
72
+ return (
73
+ <div className="bg-white p-6 rounded-lg shadow-md">
74
+ <h3 className="text-lg font-semibold mb-4">用户留存分析</h3>
75
+
76
+ <div className="grid grid-cols-2 gap-4 mb-4">
77
+ <div>
78
+ <h4 className="font-medium text-gray-900 mb-2">新用户</h4>
79
+ <div className="space-y-1">
80
+ {data.newUsers?.map((count: number, index: number) => (
81
+ <div key={index} className="flex justify-between text-sm">
82
+ <span>{data.dayIntervals[index]}</span>
83
+ <span className="font-medium">{count}</span>
84
+ </div>
85
+ ))}
86
+ </div>
87
+ </div>
88
+
89
+ <div>
90
+ <h4 className="font-medium text-gray-900 mb-2">回访用户</h4>
91
+ <div className="space-y-1">
92
+ {data.returningUsers?.map((count: number, index: number) => (
93
+ <div key={index} className="flex justify-between text-sm">
94
+ <span>{data.dayIntervals[index]}</span>
95
+ <span className="font-medium">{count}</span>
96
+ </div>
97
+ ))}
98
+ </div>
99
+ </div>
100
+ </div>
101
+
102
+ <div>
103
+ <h4 className="font-medium text-gray-900 mb-2">留存率</h4>
104
+ <div className="space-y-1">
105
+ {data.retentionRates?.map((rate: string, index: number) => (
106
+ <div key={index} className="flex justify-between text-sm">
107
+ <span>{data.dayIntervals[index]}</span>
108
+ <span className={parseFloat(rate) > 60 ? 'text-green-600' : parseFloat(rate) > 30 ? 'text-yellow-600' : 'text-red-500'}>
109
+ {rate}%
110
+ </span>
111
+ </div>
112
+ ))}
113
+ </div>
114
+ </div>
115
+ </div>
116
+ );
117
+ }
118
+
119
+ /**
120
+ * 分析仪表盘主组件
121
+ */
122
+ function AnalyticsDashboard() {
123
+ const [stats, setStats] = React.useState<any>(null);
124
+ const [realtimeStats, setRealtimeStats] = React.useState<any>(null);
125
+ const [retentionData, setRetentionData] = React.useState<any>(null);
126
+ const [loading, setLoading] = React.useState(true);
127
+ const [activeTab, setActiveTab] = React.useState<'overview' | 'retention'>('overview');
128
+
129
+ React.useEffect(() => {
130
+ loadAnalytics();
131
+
132
+ // 实时数据每30秒更新一次
133
+ const interval = setInterval(loadRealTimeStats, 30000);
134
+ loadRealTimeStats();
135
+
136
+ return () => clearInterval(interval);
137
+ }, []);
138
+
139
+ const loadAnalytics = async () => {
140
+ try {
141
+ setLoading(true);
142
+ const response = await fetch(`${API_BASE}/summary`);
143
+ const data = await response.json();
144
+ setStats(data);
145
+ } catch (error) {
146
+ console.error('加载分析数据失败:', error);
147
+ } finally {
148
+ setLoading(false);
149
+ }
150
+ };
151
+
152
+ const loadRealTimeStats = async () => {
153
+ try {
154
+ const response = await fetch(`${API_BASE}/realtime`);
155
+ const data = await response.json();
156
+ setRealtimeStats(data);
157
+ } catch (error) {
158
+ console.error('加载实时数据失败:', error);
159
+ }
160
+ };
161
+
162
+ const loadRetentionData = async () => {
163
+ try {
164
+ const response = await fetch(`${API_BASE}/retention`);
165
+ const data = await response.json();
166
+ setRetentionData(data);
167
+ } catch (error) {
168
+ console.error('加载留存数据失败:', error);
169
+ }
170
+ };
171
+
172
+ React.useEffect(() => {
173
+ if (activeTab === 'retention' && !retentionData) {
174
+ loadRetentionData();
175
+ }
176
+ }, [activeTab, retentionData]);
177
+
178
+ if (loading) {
179
+ return (
180
+ <div className="min-h-screen bg-gray-50 flex items-center justify-center">
181
+ <div className="text-center">
182
+ <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
183
+ <p className="text-gray-600">加载分析数据中...</p>
184
+ </div>
185
+ </div>
186
+ );
187
+ }
188
+
189
+ return (
190
+ <div className="min-h-screen bg-gray-50">
191
+ {/* 导航栏 */}
192
+ <nav className="bg-white shadow-sm border-b">
193
+ <div className="max-w-7xl mx-auto px-4">
194
+ <div className="flex justify-between items-center py-4">
195
+ <h1 className="text-2xl font-bold text-gray-900">分析仪表盘</h1>
196
+ <button
197
+ onClick={loadAnalytics}
198
+ className="px-4 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50"
199
+ >
200
+ 刷新数据
201
+ </button>
202
+ </div>
203
+ </div>
204
+ </nav>
205
+
206
+ {/* 标签页导航 */}
207
+ <div className="max-w-7xl mx-auto px-4 py-6">
208
+ <div className="flex space-x-1 mb-6">
209
+ <button
210
+ onClick={() => setActiveTab('overview')}
211
+ className={`px-4 py-2 text-sm font-medium rounded-md ${
212
+ activeTab === 'overview'
213
+ ? 'bg-blue-600 text-white'
214
+ : 'text-gray-500 hover:text-gray-700'
215
+ }`}
216
+ >
217
+ 概览
218
+ </button>
219
+ <button
220
+ onClick={() => setActiveTab('retention')}
221
+ className={`px-4 py-2 text-sm font-medium rounded-md ${
222
+ activeTab === 'retention'
223
+ ? 'bg-blue-600 text-white'
224
+ : 'text-gray-500 hover:text-gray-700'
225
+ }`}
226
+ >
227
+ 留存分析
228
+ </button>
229
+ </div>
230
+
231
+ {activeTab === 'overview' ? (
232
+ /* 概览页面 */
233
+ <div className="space-y-6">
234
+ {/* 实时统计卡片 */}
235
+ {realtimeStats && (
236
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
237
+ <StatsCard
238
+ title="当前在线用户"
239
+ value={realtimeStats.onlineUsers || 0}
240
+ description="实时活跃用户数"
241
+ />
242
+ <StatsCard
243
+ title="当前事件数"
244
+ value={realtimeStats.currentEvents || 0}
245
+ description="每分钟处理的事件"
246
+ />
247
+ <StatsCard
248
+ title="服务器时间"
249
+ value={new Date(realtimeStats.serverTime).toLocaleTimeString()}
250
+ description="数据更新时间"
251
+ />
252
+ </div>
253
+ )}
254
+
255
+ {/* 统计摘要卡片 */}
256
+ {stats && (
257
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
258
+ <StatsCard
259
+ title="总事件数"
260
+ value={stats.totalEvents || 0}
261
+ description="过去7天事件总数"
262
+ />
263
+ <StatsCard
264
+ title="活跃用户数"
265
+ value={stats.activeUsers || 0}
266
+ description="过去7天活跃用户"
267
+ />
268
+ <StatsCard
269
+ title="事件类型数"
270
+ value={Object.keys(stats.eventTypes || {}).length}
271
+ description="不同类型的事件"
272
+ />
273
+ </div>
274
+ )}
275
+
276
+ {/* 图表展示 */}
277
+ {stats && stats.topEvents && (
278
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
279
+ <SimpleChart
280
+ data={stats.topEvents}
281
+ title="热门事件分析"
282
+ />
283
+
284
+ <div className="bg-white p-6 rounded-lg shadow-md">
285
+ <h3 className="text-lg font-semibold mb-4">事件类型分布</h3>
286
+ <div className="space-y-2">
287
+ {Object.entries(stats.eventTypes || {}).map(([name, count]) => (
288
+ <div key={name} className="flex justify-between items-center">
289
+ <span className="text-sm text-gray-600">{name}</span>
290
+ <span className="font-medium">{count as number}</span>
291
+ </div>
292
+ ))}
293
+ </div>
294
+ </div>
295
+ </div>
296
+ )}
297
+ </div>
298
+ ) : (
299
+ /* 留存分析页面 */
300
+ retentionData ? (
301
+ <div className="grid grid-cols-1 gap-6">
302
+ <RetentionChart data={retentionData} />
303
+ </div>
304
+ ) : (
305
+ <div className="text-center py-12">
306
+ <button
307
+ onClick={loadRetentionData}
308
+ className="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
309
+ >
310
+ 加载留存数据
311
+ </button>
312
+ </div>
313
+ )
314
+ )}
315
+
316
+ {/* 无数据提示 */}
317
+ {!loading && !stats && (
318
+ <div className="text-center py-12">
319
+ <p className="text-gray-500 mb-4">暂无分析数据</p>
320
+ <p className="text-sm text-gray-400">开始收集应用使用数据后,这里将显示详细的分析报告</p>
321
+ </div>
322
+ )}
323
+ </div>
324
+ </div>
325
+ );
326
+ }
327
+
328
+ /**
329
+ * 分析事件追踪组件(可嵌入其他页面)
330
+ */
331
+ function AnalyticsTracker({ eventName, userId, children }: {
332
+ eventName: string;
333
+ userId?: string;
334
+ children: React.ReactNode;
335
+ }) {
336
+ const trackEvent = async () => {
337
+ try {
338
+ await fetch(`${API_BASE}/track`, {
339
+ method: 'POST',
340
+ headers: { 'Content-Type': 'application/json' },
341
+ body: JSON.stringify({
342
+ eventName,
343
+ userId: userId || 'anonymous-' + Date.now(),
344
+ data: { timestamp: new Date().toISOString() }
345
+ })
346
+ });
347
+ } catch (error) {
348
+ console.error('追踪事件失败:', error);
349
+ }
350
+ };
351
+
352
+ return (
353
+ <div onClick={trackEvent}>
354
+ {children}
355
+ </div>
356
+ );
357
+ }
358
+
359
+ /**
360
+ * 客户端模块
361
+ */
362
+ export const analyticsClientModule: IModule = {
363
+ name: 'analyticsClient',
364
+ serviceDefs: [
365
+ {
366
+ serviceTag: 'analyticsRoute',
367
+ serviceImpl: class AnalyticsRouteService {
368
+ basePath = '/analytics';
369
+
370
+ getRoutes() {
371
+ return [
372
+ {
373
+ path: '/',
374
+ component: AnalyticsDashboard,
375
+ key: 'analytics-dashboard',
376
+ meta: {
377
+ title: '分析仪表盘 - linyjs分析插件',
378
+ description: '查看应用使用统计和用户行为分析'
379
+ }
380
+ }
381
+ ];
382
+ }
383
+ },
384
+ meta: { usageType: 'route' }
385
+ },
386
+
387
+ {
388
+ serviceTag: 'analyticsComponent',
389
+ serviceImpl: class AnalyticsComponentService {
390
+ getComponents() {
391
+ return {
392
+ AnalyticsDashboard,
393
+ AnalyticsTracker,
394
+ StatsCard,
395
+ SimpleChart
396
+ };
397
+ }
398
+ },
399
+ meta: { usageType: 'component' }
400
+ }
401
+ ]
402
+ };
403
+
404
+ // 导出组件
405
+ export {
406
+ AnalyticsDashboard,
407
+ AnalyticsTracker,
408
+ StatsCard,
409
+ SimpleChart
410
+ };
@@ -0,0 +1,71 @@
1
+ import { analyticsServerModule } from './server';
2
+ import { analyticsClientModule } from './client';
3
+
4
+ export { analyticsServerModule } from './server';
5
+ export { analyticsClientModule } from './client';
6
+
7
+ // 默认导出两个模块(同时适用于服务端和客户端)
8
+ const analyticsPlugin = {
9
+ server: analyticsServerModule,
10
+ client: analyticsClientModule
11
+ };
12
+
13
+ export default analyticsPlugin;
14
+
15
+ /**
16
+ * @module @linyjs/example-analytics-plugin
17
+ *
18
+ * Analytics Plugin Example
19
+ * ===============
20
+ *
21
+ * Features:
22
+ * - 📊 Real-time analytics dashboard
23
+ * - 📈 User behavior tracking
24
+ * - 🔄 Hourly data aggregation (cron job)
25
+ * - 📈 User retention analysis
26
+ * - 🌊 Live metrics monitoring
27
+ * - 📱 Responsive web interface
28
+ *
29
+ * Server-side:
30
+ * - AnalyticsService: Core analytics logic
31
+ * - AnalyticsController: REST API endpoints
32
+ * - AnalyticsCronService: Background aggregation task
33
+ *
34
+ * Client-side:
35
+ * - AnalyticsDashboard: Main dashboard UI
36
+ * - AnalyticsTracker: Event tracking utility
37
+ * - Visual charts and metrics display
38
+ *
39
+ * API Endpoints:
40
+ * - POST /api/analytics/track - Track events
41
+ * - GET /api/analytics/summary - Get analytics summary
42
+ * - GET /api/analytics/realtime - Get real-time stats
43
+ * - GET /api/analytics/retention - Get user retention
44
+ * - POST /api/analytics/aggregate - Manual aggregation
45
+ *
46
+ * Usage:
47
+ *
48
+ * 1. Include in your Linyjs app:
49
+ * ```typescript
50
+ * import { analyticsServerModule } from '@linyjs/example-analytics-plugin';
51
+ *
52
+ * // In server config
53
+ * plugins: [analyticsServerModule]
54
+ * ```
55
+ *
56
+ * 2. Track events from client:
57
+ * ```javascript
58
+ * fetch('/api/analytics/track', {
59
+ * method: 'POST',
60
+ * headers: { 'Content-Type': 'application/json' },
61
+ * body: JSON.stringify({
62
+ * eventName: 'page_view',
63
+ * userId: 'user123',
64
+ * data: { page: '/home' }
65
+ * })
66
+ * });
67
+ * ```
68
+ *
69
+ * 3. View analytics dashboard:
70
+ * Access at `/analytics` route in your app
71
+ */