@linyjs/plugin-docs 0.0.13

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 (254) hide show
  1. package/README.md +137 -0
  2. package/docs/api-reference/index.md +361 -0
  3. package/docs/best-practices/error-handling.md +462 -0
  4. package/docs/best-practices/naming-conventions.md +496 -0
  5. package/docs/best-practices/performance.md +532 -0
  6. package/docs/best-practices/security.md +620 -0
  7. package/docs/best-practices/service-definition.md +332 -0
  8. package/docs/faq.md +322 -0
  9. package/docs/getting-started/first-plugin.md +358 -0
  10. package/docs/getting-started/installation.md +244 -0
  11. package/docs/getting-started/quick-start.md +235 -0
  12. package/docs/guides/authentication.md +428 -0
  13. package/docs/guides/client-module.md +604 -0
  14. package/docs/guides/data-persistence.md +640 -0
  15. package/docs/guides/permissions.md +440 -0
  16. package/docs/guides/server-module.md +377 -0
  17. package/docs/guides/ui-slots.md +475 -0
  18. package/docs/migration/v0-to-v1.md +354 -0
  19. package/examples/analytics-plugin/README.md +416 -0
  20. package/examples/analytics-plugin/dist/client/index.d.ts +36 -0
  21. package/examples/analytics-plugin/dist/client/index.js +173 -0
  22. package/examples/analytics-plugin/dist/index.d.ts +64 -0
  23. package/examples/analytics-plugin/dist/index.js +72 -0
  24. package/examples/analytics-plugin/dist/server/index.d.ts +119 -0
  25. package/examples/analytics-plugin/dist/server/index.js +313 -0
  26. package/examples/analytics-plugin/package.json +28 -0
  27. package/examples/analytics-plugin/src/client/index.tsx +414 -0
  28. package/examples/analytics-plugin/src/index.ts +71 -0
  29. package/examples/analytics-plugin/src/server/index.ts +349 -0
  30. package/examples/analytics-plugin/tsconfig.json +21 -0
  31. package/examples/blog-plugin/README.md +319 -0
  32. package/examples/blog-plugin/dist/client/index.d.ts +22 -0
  33. package/examples/blog-plugin/dist/client/index.js +197 -0
  34. package/examples/blog-plugin/dist/server/index.d.ts +5 -0
  35. package/examples/blog-plugin/dist/server/index.js +220 -0
  36. package/examples/blog-plugin/package.json +24 -0
  37. package/examples/blog-plugin/src/client/index.tsx +409 -0
  38. package/examples/blog-plugin/src/server/index.ts +240 -0
  39. package/examples/blog-plugin/tsconfig.json +16 -0
  40. package/examples/hello-world/README.md +101 -0
  41. package/examples/hello-world/dist/client/index.d.ts +5 -0
  42. package/examples/hello-world/dist/client/index.js +80 -0
  43. package/examples/hello-world/dist/server/index.d.ts +5 -0
  44. package/examples/hello-world/dist/server/index.js +38 -0
  45. package/examples/hello-world/node_modules/.package-lock.json +61 -0
  46. package/examples/hello-world/node_modules/@linyjs/client-module-interface/HOOKS_USAGE.md +281 -0
  47. package/examples/hello-world/node_modules/@linyjs/client-module-interface/IMPLEMENTATION_SUMMARY.md +166 -0
  48. package/examples/hello-world/node_modules/@linyjs/client-module-interface/QUICK_REFERENCE.md +130 -0
  49. package/examples/hello-world/node_modules/@linyjs/client-module-interface/README.md +214 -0
  50. package/examples/hello-world/node_modules/@linyjs/client-module-interface/package.json +26 -0
  51. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/application.ts +50 -0
  52. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/comparison-example.tsx +229 -0
  53. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/di.ts +127 -0
  54. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/domain.ts +52 -0
  55. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/hooks-example.tsx +275 -0
  56. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/hooks.ts +175 -0
  57. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/index.ts +87 -0
  58. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/interfaces.ts +117 -0
  59. package/examples/hello-world/node_modules/@linyjs/client-module-interface/src/router.ts +49 -0
  60. package/examples/hello-world/node_modules/@linyjs/client-module-interface/tsconfig.json +10 -0
  61. package/examples/hello-world/node_modules/@linyjs/server-module-interface/package.json +21 -0
  62. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/application.ts +21 -0
  63. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/di.ts +127 -0
  64. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/domain.ts +75 -0
  65. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/index.ts +55 -0
  66. package/examples/hello-world/node_modules/@linyjs/server-module-interface/src/interfaces.ts +58 -0
  67. package/examples/hello-world/node_modules/@linyjs/server-module-interface/tsconfig.json +8 -0
  68. package/examples/hello-world/node_modules/@types/react/LICENSE +21 -0
  69. package/examples/hello-world/node_modules/@types/react/README.md +15 -0
  70. package/examples/hello-world/node_modules/@types/react/canary.d.ts +129 -0
  71. package/examples/hello-world/node_modules/@types/react/compiler-runtime.d.ts +4 -0
  72. package/examples/hello-world/node_modules/@types/react/experimental.d.ts +184 -0
  73. package/examples/hello-world/node_modules/@types/react/global.d.ts +166 -0
  74. package/examples/hello-world/node_modules/@types/react/index.d.ts +4369 -0
  75. package/examples/hello-world/node_modules/@types/react/jsx-dev-runtime.d.ts +33 -0
  76. package/examples/hello-world/node_modules/@types/react/jsx-runtime.d.ts +24 -0
  77. package/examples/hello-world/node_modules/@types/react/package.json +210 -0
  78. package/examples/hello-world/node_modules/@types/react/ts5.0/canary.d.ts +129 -0
  79. package/examples/hello-world/node_modules/@types/react/ts5.0/experimental.d.ts +184 -0
  80. package/examples/hello-world/node_modules/@types/react/ts5.0/global.d.ts +166 -0
  81. package/examples/hello-world/node_modules/@types/react/ts5.0/index.d.ts +4356 -0
  82. package/examples/hello-world/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +33 -0
  83. package/examples/hello-world/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +24 -0
  84. package/examples/hello-world/node_modules/csstype/LICENSE +19 -0
  85. package/examples/hello-world/node_modules/csstype/README.md +291 -0
  86. package/examples/hello-world/node_modules/csstype/index.d.ts +22569 -0
  87. package/examples/hello-world/node_modules/csstype/index.js.flow +6863 -0
  88. package/examples/hello-world/node_modules/csstype/package.json +70 -0
  89. package/examples/hello-world/node_modules/react/LICENSE +21 -0
  90. package/examples/hello-world/node_modules/react/README.md +37 -0
  91. package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.development.js +24 -0
  92. package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.production.js +16 -0
  93. package/examples/hello-world/node_modules/react/cjs/react-compiler-runtime.profiling.js +16 -0
  94. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.development.js +338 -0
  95. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.production.js +14 -0
  96. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.profiling.js +14 -0
  97. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.react-server.development.js +370 -0
  98. package/examples/hello-world/node_modules/react/cjs/react-jsx-dev-runtime.react-server.production.js +40 -0
  99. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.development.js +352 -0
  100. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.production.js +34 -0
  101. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.profiling.js +34 -0
  102. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.react-server.development.js +370 -0
  103. package/examples/hello-world/node_modules/react/cjs/react-jsx-runtime.react-server.production.js +40 -0
  104. package/examples/hello-world/node_modules/react/cjs/react.development.js +1284 -0
  105. package/examples/hello-world/node_modules/react/cjs/react.production.js +542 -0
  106. package/examples/hello-world/node_modules/react/cjs/react.react-server.development.js +848 -0
  107. package/examples/hello-world/node_modules/react/cjs/react.react-server.production.js +423 -0
  108. package/examples/hello-world/node_modules/react/compiler-runtime.js +14 -0
  109. package/examples/hello-world/node_modules/react/index.js +7 -0
  110. package/examples/hello-world/node_modules/react/jsx-dev-runtime.js +7 -0
  111. package/examples/hello-world/node_modules/react/jsx-dev-runtime.react-server.js +7 -0
  112. package/examples/hello-world/node_modules/react/jsx-runtime.js +7 -0
  113. package/examples/hello-world/node_modules/react/jsx-runtime.react-server.js +7 -0
  114. package/examples/hello-world/node_modules/react/package.json +51 -0
  115. package/examples/hello-world/node_modules/react/react.react-server.js +7 -0
  116. package/examples/hello-world/node_modules/typescript/LICENSE.txt +55 -0
  117. package/examples/hello-world/node_modules/typescript/README.md +50 -0
  118. package/examples/hello-world/node_modules/typescript/SECURITY.md +41 -0
  119. package/examples/hello-world/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  120. package/examples/hello-world/node_modules/typescript/bin/tsc +2 -0
  121. package/examples/hello-world/node_modules/typescript/bin/tsserver +2 -0
  122. package/examples/hello-world/node_modules/typescript/lib/_tsc.js +133818 -0
  123. package/examples/hello-world/node_modules/typescript/lib/_tsserver.js +659 -0
  124. package/examples/hello-world/node_modules/typescript/lib/_typingsInstaller.js +222 -0
  125. package/examples/hello-world/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
  126. package/examples/hello-world/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
  127. package/examples/hello-world/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
  128. package/examples/hello-world/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
  129. package/examples/hello-world/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
  130. package/examples/hello-world/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
  131. package/examples/hello-world/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
  132. package/examples/hello-world/node_modules/typescript/lib/lib.d.ts +22 -0
  133. package/examples/hello-world/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  134. package/examples/hello-world/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  135. package/examples/hello-world/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  136. package/examples/hello-world/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  137. package/examples/hello-world/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  138. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  139. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  140. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  141. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  142. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  143. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  144. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  145. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  146. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  147. package/examples/hello-world/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  148. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  149. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  150. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  151. package/examples/hello-world/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  152. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  153. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  154. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  155. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  156. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  157. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  158. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  159. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  160. package/examples/hello-world/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  161. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  162. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  163. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  164. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  165. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  166. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  167. package/examples/hello-world/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  168. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  169. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  170. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  171. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  172. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  173. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  174. package/examples/hello-world/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  175. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  176. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  177. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  178. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  179. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  180. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  181. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  182. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  183. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  184. package/examples/hello-world/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  185. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  186. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  187. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  188. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  189. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  190. package/examples/hello-world/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  191. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  192. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  193. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  194. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  195. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  196. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  197. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  198. package/examples/hello-world/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  199. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  200. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  201. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  202. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  203. package/examples/hello-world/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  204. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  205. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  206. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  207. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  208. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  209. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  210. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  211. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  212. package/examples/hello-world/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  213. package/examples/hello-world/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  214. package/examples/hello-world/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  215. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  216. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  217. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  218. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  219. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  220. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  221. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  222. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  223. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  224. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  225. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  226. package/examples/hello-world/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  227. package/examples/hello-world/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  228. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  229. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  230. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  231. package/examples/hello-world/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  232. package/examples/hello-world/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
  233. package/examples/hello-world/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
  234. package/examples/hello-world/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
  235. package/examples/hello-world/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
  236. package/examples/hello-world/node_modules/typescript/lib/tsc.js +8 -0
  237. package/examples/hello-world/node_modules/typescript/lib/tsserver.js +8 -0
  238. package/examples/hello-world/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
  239. package/examples/hello-world/node_modules/typescript/lib/tsserverlibrary.js +21 -0
  240. package/examples/hello-world/node_modules/typescript/lib/typesMap.json +497 -0
  241. package/examples/hello-world/node_modules/typescript/lib/typescript.d.ts +11437 -0
  242. package/examples/hello-world/node_modules/typescript/lib/typescript.js +200276 -0
  243. package/examples/hello-world/node_modules/typescript/lib/typingsInstaller.js +8 -0
  244. package/examples/hello-world/node_modules/typescript/lib/watchGuard.js +53 -0
  245. package/examples/hello-world/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
  246. package/examples/hello-world/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
  247. package/examples/hello-world/node_modules/typescript/package.json +120 -0
  248. package/examples/hello-world/package-lock.json +74 -0
  249. package/examples/hello-world/package.json +23 -0
  250. package/examples/hello-world/src/client/index.tsx +110 -0
  251. package/examples/hello-world/src/server/index.ts +42 -0
  252. package/examples/hello-world/tsconfig.json +16 -0
  253. package/package.json +46 -0
  254. package/src/cli.ts +321 -0
@@ -0,0 +1,640 @@
1
+ # 数据持久化
2
+
3
+ 本指南介绍如何在 linyjs 插件中使用 MongoDB 进行数据持久化。
4
+
5
+ ## 概述
6
+
7
+ linyjs 提供 MongoDB 服务,支持:
8
+
9
+ - 💾 CRUD 操作(创建、读取、更新、删除)
10
+ - 🔍 复杂查询和聚合
11
+ - 📊 索引优化
12
+ - 🔗 数据关联
13
+
14
+ ## 配置 MongoDB 服务
15
+
16
+ ### 在服务端模块中注入依赖
17
+
18
+ ```typescript
19
+ import type { IModule, IServiceDef } from '@linyjs/server-module-interface';
20
+ import type { IMongoDBService } from '@linyjs/shared-module-interface';
21
+
22
+ class ArticleService {
23
+ constructor({ mongoDBService }: { mongoDBService: IMongoDBService }) {
24
+ this.mongoDBService = mongoDBService;
25
+ }
26
+
27
+ // ... 服务方法
28
+ }
29
+
30
+ const articleServiceDef: IServiceDef = {
31
+ serviceTag: 'articleService',
32
+ serviceImpl: ArticleService,
33
+ dependencies: ['mdb.mongoDBService'], // 注入 MongoDB 服务
34
+ meta: { usageType: 'normal_service' }
35
+ };
36
+
37
+ export const myServerModule: IModule = {
38
+ name: 'myServer',
39
+ moduleDependencies: ['mdb'], // 依赖 MongoDB 模块
40
+ serviceDefs: [articleServiceDef]
41
+ };
42
+ ```
43
+
44
+ ## 使用 @linyjs/shared-module-interface 获取类型提示
45
+
46
+ linyjs 插件通常作为独立的 npm 包或 git 仓库开发。通过依赖注入机制,插件可以获取 `IMongoDBService` 等服务实例,但 TypeScript 需要类型声明才能提供完整的类型提示。
47
+
48
+ ### 安装
49
+
50
+ 在插件的 `package.json` 中添加 `@linyjs/shared-module-interface` 作为开发依赖:
51
+
52
+ ```json
53
+ {
54
+ "devDependencies": {
55
+ "@linyjs/shared-module-interface": "^0.0.1"
56
+ }
57
+ }
58
+ ```
59
+
60
+ 此包是**纯类型包**,包含了所有公共模块(mdb、auth、permission)的服务接口和类型定义,并重新导出了 `mongodb` 包的全部类型(`ObjectId`、`Db`、`Collection`、`Document`、`Filter` 等),使插件无需单独安装 `mongodb`、`@linyjs/mdb`、`@linyjs/auth`、`@linyjs/permission` 等包。
61
+
62
+ > ⚠️ **纯类型包**:此包只导出 TypeScript 类型(`export type`),不包含任何运行时代码。无法通过 `import { ObjectId }` 导入运行时值,运行时请通过依赖注入获取的 `mongoDBService.ObjectId` 使用。
63
+
64
+ ### 可用类型一览
65
+
66
+ | 类型 | 说明 | 来源模块 |
67
+ |------|------|----------|
68
+ | `IMongoDBService` | MongoDB 服务接口 | @linyjs/mdb |
69
+ | `ObjectId`, `Db`, `Collection`, `Document`, `Filter` ... | mongodb 全部类型 | mongodb |
70
+ | `IUserService` | 用户管理服务接口 | @linyjs/auth |
71
+ | `IAuthUser`, `ISafeUser`, `IAuthResult`, `IJwtPayload` | 认证相关类型 | @linyjs/auth |
72
+ | `IPermissionService` | 权限服务接口 | @linyjs/permission |
73
+ | `IPermissionPolicy`, `IPermissionCheckResult`, `Role` | 权限相关类型 | @linyjs/permission |
74
+
75
+ ## 使用 ObjectId
76
+
77
+ 在 MongoDB 中,文档的主键 `_id` 默认是 `ObjectId` 类型。在查询、更新、删除等操作中经常需要用 `ObjectId` 构造器将字符串 ID 转换为 `ObjectId` 实例。
78
+
79
+ ### 为什么不从 mongodb 包直接导入?
80
+
81
+ 如果每个插件都直接依赖 `mongodb` npm 包,会带来以下问题:
82
+
83
+ - 📦 **包体积增大** — 插件单独安装一份 mongodb 驱动
84
+ - ⚠️ **版本冲突** — 插件与框架使用的 mongodb 版本不一致
85
+ - 🔧 **配置冗余** — 每个插件都需要在 `package.json` 中声明 mongodb 依赖
86
+
87
+ ### 通过 IMongoDBService 使用
88
+
89
+ `@linyjs/shared-module-interface` 是纯类型包,不导出运行时值。`ObjectId` 构造器通过 `IMongoDBService` 接口的 `ObjectId` 属性暴露,插件通过注入的 `mongoDBService` 在运行时获取:
90
+
91
+ ```typescript
92
+ import type { IMongoDBService } from '@linyjs/shared-module-interface';
93
+
94
+ class ArticleService {
95
+ constructor(private mongoDBService: IMongoDBService) {}
96
+
97
+ async getArticleById(id: string) {
98
+ const collection = this.mongoDBService.getCollection('articles');
99
+ // ✅ 通过 mongoDBService.ObjectId 获取运行时构造器
100
+ const article = await collection.findOne({
101
+ _id: new this.mongoDBService.ObjectId(id)
102
+ });
103
+ return article;
104
+ }
105
+ }
106
+ ```
107
+
108
+ 如果需要在服务类外部(如工具函数)创建 `ObjectId`,可以通过一个辅助函数转发:
109
+
110
+ ```typescript
111
+ // db.ts - 在模块内部保存 mongoDBService 引用
112
+ import type { IMongoDBService } from '@linyjs/shared-module-interface';
113
+
114
+ let mongoDBService: IMongoDBService | null = null;
115
+
116
+ export function setMongoDBService(service: IMongoDBService) {
117
+ mongoDBService = service;
118
+ }
119
+
120
+ /** 通过注入的 MongoDB 服务创建 ObjectId */
121
+ export function createObjectId(id: string) {
122
+ if (!mongoDBService) throw new Error('MongoDB service not initialized');
123
+ return new mongoDBService.ObjectId(id);
124
+ }
125
+
126
+ // 在 service.ts 中使用
127
+ import { createObjectId } from './db.js';
128
+ const objectId = createObjectId(userId);
129
+ ```
130
+
131
+ > 💡 **类型使用**:如果仅需在类型注解中使用 `ObjectId`(如 `_id?: ObjectId`),可以用 `import type { ObjectId } from '@linyjs/shared-module-interface'`,这是纯类型导入,编译后会被完全擦除。
132
+
133
+ ## 基本 CRUD 操作
134
+
135
+ ### 创建(Create)
136
+
137
+ ```typescript
138
+ import type { IMongoDBService } from '@linyjs/shared-module-interface';
139
+
140
+ class ArticleService {
141
+ constructor(private mongodbService: IMongoDBService) {}
142
+
143
+ async createArticle(data: any) {
144
+ const db = this.mongodbService.getDb();
145
+ const collection = db.collection('articles');
146
+
147
+ const result = await collection.insertOne({
148
+ ...data,
149
+ createdAt: new Date(),
150
+ updatedAt: new Date()
151
+ });
152
+
153
+ return {
154
+ id: result.insertedId,
155
+ ...data
156
+ };
157
+ }
158
+ }
159
+ ```
160
+
161
+ ### 读取(Read)
162
+
163
+ #### 获取单个文档
164
+
165
+ ```typescript
166
+ import type { IMongoDBService } from '@linyjs/shared-module-interface';
167
+
168
+ class ArticleService {
169
+ constructor(private mongoDBService: IMongoDBService) {}
170
+
171
+ async getArticleById(id: string) {
172
+ const db = this.mongoDBService.getDb();
173
+ const collection = db.collection('articles');
174
+
175
+ const article = await collection.findOne({
176
+ _id: new this.mongoDBService.ObjectId(id)
177
+ });
178
+
179
+ if (!article) {
180
+ throw new Error('Article not found');
181
+ }
182
+
183
+ return article;
184
+ }
185
+ }
186
+ ```
187
+
188
+ #### 获取列表(支持分页)
189
+
190
+ ```typescript
191
+ async getArticles(page = 1, limit = 10) {
192
+ const db = this.mongodbService.getDb();
193
+ const collection = db.collection('articles');
194
+
195
+ const skip = (page - 1) * limit;
196
+
197
+ // 获取总数
198
+ const total = await collection.countDocuments();
199
+
200
+ // 获取数据
201
+ const articles = await collection.find()
202
+ .skip(skip)
203
+ .limit(limit)
204
+ .sort({ createdAt: -1 })
205
+ .toArray();
206
+
207
+ return {
208
+ data: articles,
209
+ total,
210
+ page,
211
+ limit,
212
+ totalPages: Math.ceil(total / limit)
213
+ };
214
+ }
215
+ ```
216
+
217
+ #### 条件查询
218
+
219
+ ```typescript
220
+ async getArticlesByAuthor(authorId: string) {
221
+ const db = this.mongodbService.getDb();
222
+ const collection = db.collection('articles');
223
+
224
+ const articles = await collection.find({
225
+ authorId
226
+ }).toArray();
227
+
228
+ return articles;
229
+ }
230
+ ```
231
+
232
+ ### 更新(Update)
233
+
234
+ #### 完整更新
235
+
236
+ ```typescript
237
+ async updateArticle(id: string, data: any) {
238
+ const db = this.mongodbService.getDb();
239
+ const collection = db.collection('articles');
240
+
241
+ const result = await collection.updateOne(
242
+ { _id: new this.mongoDBService.ObjectId(id) },
243
+ {
244
+ $set: {
245
+ ...data,
246
+ updatedAt: new Date()
247
+ }
248
+ }
249
+ );
250
+
251
+ if (result.matchedCount === 0) {
252
+ throw new Error('Article not found');
253
+ }
254
+
255
+ return { success: true };
256
+ }
257
+ ```
258
+
259
+ #### 部分更新
260
+
261
+ ```typescript
262
+ async updateArticleTitle(id: string, title: string) {
263
+ const db = this.mongodbService.getDb();
264
+ const collection = db.collection('articles');
265
+
266
+ await collection.updateOne(
267
+ { _id: new this.mongoDBService.ObjectId(id) },
268
+ {
269
+ $set: {
270
+ title,
271
+ updatedAt: new Date()
272
+ }
273
+ }
274
+ );
275
+ }
276
+ ```
277
+
278
+ ### 删除(Delete)
279
+
280
+ ```typescript
281
+ async deleteArticle(id: string) {
282
+ const db = this.mongodbService.getDb();
283
+ const collection = db.collection('articles');
284
+
285
+ const result = await collection.deleteOne({
286
+ _id: new this.mongoDBService.ObjectId(id)
287
+ });
288
+
289
+ if (result.deletedCount === 0) {
290
+ throw new Error('Article not found');
291
+ }
292
+
293
+ return { success: true };
294
+ }
295
+ ```
296
+
297
+ ## 高级查询
298
+
299
+ ### 复杂条件
300
+
301
+ ```typescript
302
+ async searchArticles(query: string, options: any) {
303
+ const db = this.mongodbService.getDb();
304
+ const collection = db.collection('articles');
305
+
306
+ // 构建查询条件
307
+ const conditions: any = {};
308
+
309
+ if (query) {
310
+ conditions.$or = [
311
+ { title: { $regex: query, $options: 'i' } },
312
+ { content: { $regex: query, $options: 'i' } }
313
+ ];
314
+ }
315
+
316
+ if (options.authorId) {
317
+ conditions.authorId = options.authorId;
318
+ }
319
+
320
+ if (options.status) {
321
+ conditions.status = options.status;
322
+ }
323
+
324
+ // 日期范围
325
+ if (options.startDate || options.endDate) {
326
+ conditions.createdAt = {};
327
+ if (options.startDate) {
328
+ conditions.createdAt.$gte = new Date(options.startDate);
329
+ }
330
+ if (options.endDate) {
331
+ conditions.createdAt.$lte = new Date(options.endDate);
332
+ }
333
+ }
334
+
335
+ const articles = await collection.find(conditions).toArray();
336
+
337
+ return articles;
338
+ }
339
+ ```
340
+
341
+ ### 聚合管道
342
+
343
+ ```typescript
344
+ async getArticleStats() {
345
+ const db = this.mongodbService.getDb();
346
+ const collection = db.collection('articles');
347
+
348
+ const stats = await collection.aggregate([
349
+ // 按作者分组
350
+ {
351
+ $group: {
352
+ _id: '$authorId',
353
+ articleCount: { $sum: 1 },
354
+ totalViews: { $sum: '$views' },
355
+ avgViews: { $avg: '$views' }
356
+ }
357
+ },
358
+ // 排序
359
+ {
360
+ $sort: { articleCount: -1 }
361
+ },
362
+ // 限制结果数
363
+ {
364
+ $limit: 10
365
+ }
366
+ ]).toArray();
367
+
368
+ return stats;
369
+ }
370
+ ```
371
+
372
+ ### 联表查询
373
+
374
+ ```typescript
375
+ async getArticlesWithAuthors() {
376
+ const db = this.mongodbService.getDb();
377
+ const articlesCollection = db.collection('articles');
378
+ const usersCollection = db.collection('users');
379
+
380
+ const articles = await articlesCollection.aggregate([
381
+ // 联查用户表
382
+ {
383
+ $lookup: {
384
+ from: 'users',
385
+ localField: 'authorId',
386
+ foreignField: '_id',
387
+ as: 'author'
388
+ }
389
+ },
390
+ // 展开数组
391
+ {
392
+ $unwind: '$author'
393
+ },
394
+ // 投影字段
395
+ {
396
+ $project: {
397
+ title: 1,
398
+ content: 1,
399
+ createdAt: 1,
400
+ 'author.name': 1,
401
+ 'author.email': 1
402
+ }
403
+ }
404
+ ]).toArray();
405
+
406
+ return articles;
407
+ }
408
+ ```
409
+
410
+ ## 索引优化
411
+
412
+ ### 创建索引
413
+
414
+ ```typescript
415
+ async createIndexes() {
416
+ const db = this.mongodbService.getDb();
417
+ const collection = db.collection('articles');
418
+
419
+ // 单字段索引
420
+ await collection.createIndex({ authorId: 1 });
421
+
422
+ // 复合索引
423
+ await collection.createIndex({ authorId: 1, createdAt: -1 });
424
+
425
+ // 文本索引(用于全文搜索)
426
+ await collection.createIndex({
427
+ title: 'text',
428
+ content: 'text'
429
+ });
430
+
431
+ // 唯一索引
432
+ await collection.createIndex({ slug: 1 }, { unique: true });
433
+ }
434
+ ```
435
+
436
+ ### 使用索引
437
+
438
+ ```typescript
439
+ // MongoDB 会自动使用合适的索引
440
+ async getArticlesByAuthor(authorId: string) {
441
+ const db = this.mongodbService.getDb();
442
+ const collection = db.collection('articles');
443
+
444
+ // 自动使用 authorId 索引
445
+ return await collection.find({ authorId }).toArray();
446
+ }
447
+ ```
448
+
449
+ ## 事务处理
450
+
451
+ ### 使用事务
452
+
453
+ ```typescript
454
+ async transferArticleAuthor(articleId: string, newAuthorId: string) {
455
+ const db = this.mongodbService.getDb();
456
+ const session = db.startSession();
457
+
458
+ try {
459
+ session.startTransaction();
460
+
461
+ const articlesCollection = db.collection('articles');
462
+ const usersCollection = db.collection('users');
463
+
464
+ // 检查新作者是否存在
465
+ const user = await usersCollection.findOne(
466
+ { _id: new this.mongoDBService.ObjectId(newAuthorId) },
467
+ { session }
468
+ );
469
+
470
+ if (!user) {
471
+ throw new Error('User not found');
472
+ }
473
+
474
+ // 更新文章作者
475
+ await articlesCollection.updateOne(
476
+ { _id: new this.mongoDBService.ObjectId(articleId) },
477
+ { $set: { authorId: newAuthorId } },
478
+ { session }
479
+ );
480
+
481
+ // 提交事务
482
+ await session.commitTransaction();
483
+
484
+ return { success: true };
485
+ } catch (error) {
486
+ // 回滚事务
487
+ await session.abortTransaction();
488
+ throw error;
489
+ } finally {
490
+ session.endSession();
491
+ }
492
+ }
493
+ ```
494
+
495
+ ## 数据验证
496
+
497
+ ### Schema 验证
498
+
499
+ ```typescript
500
+ async createArticle(data: any) {
501
+ // 验证必填字段
502
+ if (!data.title || !data.content) {
503
+ throw new Error('Title and content are required');
504
+ }
505
+
506
+ // 验证标题长度
507
+ if (data.title.length > 200) {
508
+ throw new Error('Title too long');
509
+ }
510
+
511
+ // 验证内容长度
512
+ if (data.content.length > 50000) {
513
+ throw new Error('Content too long');
514
+ }
515
+
516
+ const db = this.mongodbService.getDb();
517
+ const collection = db.collection('articles');
518
+
519
+ return await collection.insertOne({
520
+ title: data.title.trim(),
521
+ content: data.content.trim(),
522
+ authorId: data.authorId,
523
+ status: 'draft',
524
+ createdAt: new Date(),
525
+ updatedAt: new Date()
526
+ });
527
+ }
528
+ ```
529
+
530
+ ## 最佳实践
531
+
532
+ ### 1. 错误处理
533
+
534
+ ```typescript
535
+ async safeOperation() {
536
+ try {
537
+ const db = this.mongodbService.getDb();
538
+ const collection = db.collection('articles');
539
+
540
+ const result = await collection.insertOne({ /* ... */ });
541
+ return result;
542
+ } catch (error) {
543
+ console.error('Database operation failed:', error);
544
+ throw new Error('Failed to save article');
545
+ }
546
+ }
547
+ ```
548
+
549
+ ### 2. 连接池管理
550
+
551
+ MongoDB 驱动会自动管理连接池,无需手动处理。
552
+
553
+ ### 3. 避免 N+1 查询
554
+
555
+ ```typescript
556
+ // ❌ 糟糕的做法 - N+1 查询
557
+ async getArticlesWithAuthors() {
558
+ const articles = await collection.find().toArray();
559
+
560
+ for (const article of articles) {
561
+ article.author = await usersCollection.findOne({
562
+ _id: article.authorId
563
+ });
564
+ }
565
+
566
+ return articles;
567
+ }
568
+
569
+ // ✅ 好的做法 - 使用聚合
570
+ async getArticlesWithAuthors() {
571
+ return await collection.aggregate([
572
+ {
573
+ $lookup: {
574
+ from: 'users',
575
+ localField: 'authorId',
576
+ foreignField: '_id',
577
+ as: 'author'
578
+ }
579
+ },
580
+ { $unwind: '$author' }
581
+ ]).toArray();
582
+ }
583
+ ```
584
+
585
+ ### 4. 分页优化
586
+
587
+ ```typescript
588
+ async getArticlesPaginated(page: number, limit: number) {
589
+ const db = this.mongodbService.getDb();
590
+ const collection = db.collection('articles');
591
+
592
+ // 使用游标分页(更高效)
593
+ const skip = (page - 1) * limit;
594
+
595
+ return await collection.find()
596
+ .skip(skip)
597
+ .limit(limit)
598
+ .sort({ createdAt: -1 })
599
+ .toArray();
600
+ }
601
+ ```
602
+
603
+ ### 5. 数据缓存
604
+
605
+ ```typescript
606
+ import NodeCache from 'node-cache';
607
+
608
+ const cache = new NodeCache({ stdTTL: 300 }); // 5分钟缓存
609
+
610
+ async getCachedArticle(id: string) {
611
+ // 检查缓存
612
+ const cached = cache.get(id);
613
+ if (cached) {
614
+ return cached;
615
+ }
616
+
617
+ // 从数据库获取
618
+ const article = await this.getArticleById(id);
619
+
620
+ // 存入缓存
621
+ cache.set(id, article);
622
+
623
+ return article;
624
+ }
625
+ ```
626
+
627
+ ## 完整示例
628
+
629
+ 查看博客插件中的数据持久化实现:
630
+
631
+ - 📁 [Blog Plugin 示例](../../examples/blog-plugin/src/server/services/ArticleService.ts)
632
+
633
+ ## 相关文档
634
+
635
+ - 🔒 [权限管理](./permissions.md)
636
+ - 🎨 [UI 扩展插槽](./ui-slots.md)
637
+
638
+ ---
639
+
640
+ **上一篇**: [权限管理](./permissions.md) | **下一篇**: [最佳实践](../best-practices/naming-conventions.md)