@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,620 @@
1
+ # 安全性
2
+
3
+ 本指南提供 linyjs 插件开发中的安全最佳实践。
4
+
5
+ ## 为什么需要关注安全?
6
+
7
+ - 🔒 **保护用户数据** - 防止敏感信息泄露
8
+ - 🛡️ **防止恶意攻击** - 抵御常见网络安全威胁
9
+ - ⚖️ **保持合规性** - 满足隐私保护和数据安全法规
10
+ - 🤝 **建立用户信任** - 安全可靠的应用获得用户信赖
11
+
12
+ ## 输入验证和清理
13
+
14
+ ### 服务端输入验证
15
+
16
+ ```typescript
17
+ // 严格的输入验证
18
+ handler: async (params, ctx) => {
19
+ const { email, password, age } = params.body;
20
+
21
+ // 邮箱格式验证
22
+ if (!isValidEmail(email)) {
23
+ return {
24
+ status: 400,
25
+ data: { error: 'Invalid email format', field: 'email' }
26
+ };
27
+ }
28
+
29
+ // 密码强度验证
30
+ if (!isStrongPassword(password)) {
31
+ return {
32
+ status: 400,
33
+ data: { error: 'Password too weak', field: 'password' }
34
+ };
35
+ }
36
+
37
+ // 数值范围验证
38
+ if (!Number.isInteger(age) || age < 0 || age > 150) {
39
+ return {
40
+ status: 400,
41
+ data: { error: 'Invalid age', field: 'age' }
42
+ };
43
+ }
44
+
45
+ return { success: true };
46
+ };
47
+
48
+ // 验证函数
49
+ function isValidEmail(email: string): boolean {
50
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
51
+ return emailRegex.test(email);
52
+ }
53
+
54
+ function isStrongPassword(password: string): boolean {
55
+ // 至少8个字符,包含大写、小写、数字和特殊字符
56
+ const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
57
+ return strongPasswordRegex.test(password);
58
+ }
59
+ ```
60
+
61
+ ### 使用验证库
62
+
63
+ ```typescript
64
+ import * as Joi from 'joi';
65
+
66
+ // 定义验证模式
67
+ const userSchema = Joi.object({
68
+ email: Joi.string().email().required(),
69
+ password: Joi.string().min(8).pattern(new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)')).required(),
70
+ age: Joi.number().integer().min(0).max(150).required(),
71
+ role: Joi.string().valid('user', 'admin', 'moderator').optional()
72
+ });
73
+
74
+ // 在处理器中使用验证
75
+ handler: async (params, ctx) => {
76
+ const { error, value } = userSchema.validate(params.body);
77
+
78
+ if (error) {
79
+ return {
80
+ status: 400,
81
+ data: {
82
+ error: 'Validation failed',
83
+ details: error.details.map(detail => ({
84
+ field: detail.path.join('.'),
85
+ message: detail.message
86
+ }))
87
+ }
88
+ };
89
+ }
90
+
91
+ // 验证通过,处理业务逻辑
92
+ return await createUser(value);
93
+ };
94
+ ```
95
+
96
+ ## SQL注入和NoSQL注入防护
97
+
98
+ ### MongoDB注入防护
99
+
100
+ ```typescript
101
+ // ✅ 推荐:使用 MongoDB 驱动程序的内置防护
102
+ class SafeUserService {
103
+ constructor(private mongodb: IMongoDBService) {}
104
+
105
+ async findUserByEmail(email: string) {
106
+ const db = this.mongodb.getDb();
107
+ const collection = db.collection('users');
108
+
109
+ // MongoDB 驱动程序会自动转义参数
110
+ return collection.findOne({ email: email });
111
+ }
112
+
113
+ async searchUsers(query: string) {
114
+ const db = this.mongodb.getDb();
115
+ const collection = db.collection('users');
116
+
117
+ // 使用安全的正则表达式查询
118
+ return collection.find({
119
+ $or: [
120
+ { name: { $regex: escapeRegex(query), $options: 'i' } },
121
+ { email: { $regex: escapeRegex(query), $options: 'i' } }
122
+ ]
123
+ }).toArray();
124
+ }
125
+ }
126
+
127
+ // 转义正则表达式特殊字符
128
+ function escapeRegex(str: string): string {
129
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
130
+ }
131
+
132
+ // ❌ 避免:字符串拼接查询
133
+ const unsafeQuery = `db.users.find({name: "${userInput}"})`; // 危险!
134
+ ```
135
+
136
+ ### 参数化查询
137
+
138
+ ```typescript
139
+ // 如果使用原生 SQL,始终使用参数化查询
140
+ async function safeDatabaseQuery(userId: string) {
141
+ // ✅ 推荐:参数化查询
142
+ const result = await db.query(
143
+ 'SELECT * FROM users WHERE id = $1',
144
+ [userId]
145
+ );
146
+
147
+ return result.rows;
148
+ }
149
+
150
+ // ❌ 避免:字符串拼接
151
+ const unsafeQuery = `SELECT * FROM users WHERE id = ${userId}`; // 危险!
152
+ ```
153
+
154
+ ## XSS防护
155
+
156
+ ### 服务端输出编码
157
+
158
+ ```typescript
159
+ // HTML编码函数
160
+ function escapeHtml(text: string): string {
161
+ const div = document.createElement('div');
162
+ div.textContent = text;
163
+ return div.innerHTML;
164
+ }
165
+
166
+ // 或者使用专业的编码库
167
+ import { encode } from 'html-entities';
168
+
169
+ function safeOutput(data: any): string {
170
+ return encode(JSON.stringify(data));
171
+ }
172
+
173
+ // 在响应中设置安全头
174
+ handler: async (params, ctx) => {
175
+ ctx.response.setHeader('X-XSS-Protection', '1; mode=block');
176
+ ctx.response.setHeader('X-Content-Type-Options', 'nosniff');
177
+ ctx.response.setHeader('X-Frame-Options', 'DENY');
178
+
179
+ return { data: safeOutput(data) };
180
+ };
181
+ ```
182
+
183
+ ### 客户端XSS防护
184
+
185
+ ```typescript
186
+ // 安全的HTML输出
187
+ function SafeDisplay({ content }: { content: string }) {
188
+ // ✅ 推荐:转义HTML
189
+ const escaped = escapeHtml(content);
190
+ return <div dangerouslySetInnerHTML={{ __html: escaped }} />;
191
+ }
192
+
193
+ // 或者更安全的文本节点
194
+ function SaferDisplay({ content }: { content: string }) {
195
+ return <div>{content}</div>; // React会自动转义
196
+ }
197
+
198
+ // 安全的链接处理
199
+ function SafeLink({ url, text }: { url: string; text: string }) {
200
+ // 验证URL协议
201
+ if (!url.startsWith('https://') && !url.startsWith('http://')) {
202
+ return <span>{text}</span>; // 无效协议显示为文本
203
+ }
204
+
205
+ return (
206
+ <a
207
+ href={url}
208
+ rel="noopener noreferrer"
209
+ target="_blank"
210
+ >
211
+ {text}
212
+ </a>
213
+ );
214
+ }
215
+ ```
216
+
217
+ ## CSRF防护
218
+
219
+ ### 生成和验证CSRF令牌
220
+
221
+ ```typescript
222
+ // CSRF令牌生成服务
223
+ class CsrfService {
224
+ private tokens = new Map<string, { token: string; expires: number }>();
225
+
226
+ generateToken(sessionId: string): string {
227
+ const token = crypto.randomBytes(32).toString('hex');
228
+ const expires = Date.now() + 30 * 60 * 1000; // 30分钟有效期
229
+
230
+ this.tokens.set(sessionId, { token, expires });
231
+ return token;
232
+ }
233
+
234
+ validateToken(sessionId: string, token: string): boolean {
235
+ const stored = this.tokens.get(sessionId);
236
+
237
+ if (!stored || Date.now() > stored.expires) {
238
+ this.tokens.delete(sessionId);
239
+ return false;
240
+ }
241
+
242
+ const isValid = stored.token === token;
243
+ if (isValid) {
244
+ // 使用后删除令牌(一次性)
245
+ this.tokens.delete(sessionId);
246
+ }
247
+
248
+ return isValid;
249
+ }
250
+ }
251
+
252
+ // CSRF防护中间件
253
+ class CsrfMiddleware implements IMiddlewareService {
254
+ constructor(private csrfService: CsrfService) {}
255
+
256
+ async process(payload: any, ctx: any, next: () => Promise<any>) {
257
+ const sessionId = ctx.session?.id;
258
+ const method = ctx.request?.method;
259
+
260
+ // 只对修改请求进行CSRF检查
261
+ if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(method)) {
262
+ const csrfToken = ctx.request?.headers['x-csrf-token'] ||
263
+ ctx.request?.body?._csrf;
264
+
265
+ if (!csrfToken || !this.csrfService.validateToken(sessionId, csrfToken)) {
266
+ return {
267
+ status: 403,
268
+ data: { error: 'Invalid CSRF token' }
269
+ };
270
+ }
271
+ }
272
+
273
+ return await next();
274
+ }
275
+ }
276
+ ```
277
+
278
+ ## 身份验证和授权
279
+
280
+ ### JWT安全处理
281
+
282
+ ```typescript
283
+ // 安全的JWT操作
284
+ class AuthService {
285
+ private readonly JWT_SECRET = process.env.JWT_SECRET!;
286
+ private readonly JWT_EXPIRES_IN = '24h';
287
+
288
+ generateToken(user: any): string {
289
+ return jwt.sign(
290
+ {
291
+ userId: user.id,
292
+ email: user.email,
293
+ role: user.role
294
+ },
295
+ this.JWT_SECRET,
296
+ {
297
+ expiresIn: this.JWT_EXPIRES_IN,
298
+ issuer: 'linyjs-plugin'
299
+ }
300
+ );
301
+ }
302
+
303
+ verifyToken(token: string): any {
304
+ try {
305
+ return jwt.verify(token, this.JWT_SECRET);
306
+ } catch (error) {
307
+ throw new Error('Invalid token');
308
+ }
309
+ }
310
+
311
+ // 刷新令牌
312
+ generateRefreshToken(userId: string): string {
313
+ return jwt.sign(
314
+ { userId },
315
+ this.JWT_SECRET + '_refresh',
316
+ { expiresIn: '7d' }
317
+ );
318
+ }
319
+ }
320
+
321
+ // 认证中间件
322
+ class AuthMiddleware implements IMiddlewareService {
323
+ async process(payload: any, ctx: any, next: () => Promise<any>) {
324
+ const authHeader = ctx.request?.headers.authorization;
325
+
326
+ if (!authHeader?.startsWith('Bearer ')) {
327
+ return {
328
+ status: 401,
329
+ data: { error: 'Missing authorization header' }
330
+ };
331
+ }
332
+
333
+ const token = authHeader.substring(7);
334
+ const authService = new AuthService();
335
+
336
+ try {
337
+ const decoded = authService.verifyToken(token);
338
+ ctx.user = decoded; // 将用户信息附加到上下文
339
+ return await next();
340
+ } catch (error) {
341
+ return {
342
+ status: 401,
343
+ data: { error: 'Invalid token' }
344
+ };
345
+ }
346
+ }
347
+ }
348
+ ```
349
+
350
+ ### 权限检查
351
+
352
+ ```typescript
353
+ // 权限中间件
354
+ class PermissionMiddleware implements IMiddlewareService {
355
+ constructor(private requiredRole?: string) {}
356
+
357
+ async process(payload: any, ctx: any, next: () => Promise<any>) {
358
+ const user = ctx.user;
359
+
360
+ if (!user) {
361
+ return {
362
+ status: 401,
363
+ data: { error: 'Authentication required' }
364
+ };
365
+ }
366
+
367
+ // 角色检查
368
+ if (this.requiredRole && user.role !== this.requiredRole) {
369
+ return {
370
+ status: 403,
371
+ data: { error: 'Insufficient permissions' }
372
+ };
373
+ }
374
+
375
+ // 所有权检查
376
+ if (payload.userId && user.userId !== payload.userId && user.role !== 'admin') {
377
+ return {
378
+ status: 403,
379
+ data: { error: 'Cannot access other user\'s data' }
380
+ };
381
+ }
382
+
383
+ return await next();
384
+ }
385
+ }
386
+
387
+ // 使用权限中间件
388
+ {
389
+ middlewares: [
390
+ 'auth',
391
+ { serviceTag: 'permission', requiredRole: 'admin' }
392
+ ],
393
+ handler: async () => {
394
+ // 只有管理员可以访问
395
+ }
396
+ }
397
+ ```
398
+
399
+ ## 数据安全
400
+
401
+ ### 敏感数据加密
402
+
403
+ ```typescript
404
+ // 数据加密服务
405
+ class EncryptionService {
406
+ private readonly ENCRYPTION_KEY = process.env.ENCRYPTION_KEY!;
407
+
408
+ encrypt(text: string): string {
409
+ const cipher = crypto.createCipher('aes-256-cbc', this.ENCRYPTION_KEY);
410
+ let encrypted = cipher.update(text, 'utf8', 'hex');
411
+ encrypted += cipher.final('hex');
412
+ return encrypted;
413
+ }
414
+
415
+ decrypt(encryptedText: string): string {
416
+ const decipher = crypto.createDecipher('aes-256-cbc', this.ENCRYPTION_KEY);
417
+ let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
418
+ decrypted += decipher.final('utf8');
419
+ return decrypted;
420
+ }
421
+ }
422
+
423
+ // 安全的密码哈希
424
+ import * as bcrypt from 'bcrypt';
425
+
426
+ class PasswordService {
427
+ private readonly SALT_ROUNDS = 12;
428
+
429
+ async hashPassword(password: string): Promise<string> {
430
+ return await bcrypt.hash(password, this.SALT_ROUNDS);
431
+ }
432
+
433
+ async verifyPassword(password: string, hash: string): Promise<boolean> {
434
+ return await bcrypt.compare(password, hash);
435
+ }
436
+ }
437
+ ```
438
+
439
+ ### 安全的数据传输
440
+
441
+ ```typescript
442
+ // 强制HTTPS
443
+ handler: async (params, ctx) => {
444
+ if (ctx.request?.protocol !== 'https') {
445
+ return {
446
+ status: 403,
447
+ data: { error: 'HTTPS required' }
448
+ };
449
+ }
450
+
451
+ // 设置安全头
452
+ ctx.response.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
453
+ ctx.response.setHeader('Content-Security-Policy', "default-src 'self'");
454
+
455
+ return { data: 'secure response' };
456
+ };
457
+ ```
458
+
459
+ ## 日志记录和监控
460
+
461
+ ### 安全日志记录
462
+
463
+ ```typescript
464
+ // 安全日志服务
465
+ class SecurityLogger {
466
+ constructor(private logger: ILogger) {}
467
+
468
+ logSecurityEvent(event: string, details: any) {
469
+ // 脱敏处理敏感信息
470
+ const sanitizedDetails = this.sanitizeData(details);
471
+
472
+ this.logger.warn('Security Event', {
473
+ event,
474
+ ...sanitizedDetails,
475
+ timestamp: new Date().toISOString(),
476
+ ip: this.getClientIp(),
477
+ userAgent: this.getUserAgent()
478
+ });
479
+ }
480
+
481
+ private sanitizeData(data: any): any {
482
+ const sanitized = { ...data };
483
+
484
+ // 移除或遮盖敏感字段
485
+ const sensitiveFields = ['password', 'token', 'creditCard', 'ssn'];
486
+ for (const field of sensitiveFields) {
487
+ if (sanitized[field]) {
488
+ sanitized[field] = '[REDACTED]';
489
+ }
490
+ }
491
+
492
+ return sanitized;
493
+ }
494
+
495
+ private getClientIp(): string {
496
+ // 获取客户端IP,考虑代理
497
+ return 'client-ip';
498
+ }
499
+
500
+ private getUserAgent(): string {
501
+ // 获取用户代理
502
+ return 'user-agent';
503
+ }
504
+ }
505
+
506
+ // 记录安全事件
507
+ class LoginAttemptsService {
508
+ private attempts = new Map<string, number>();
509
+ private readonly MAX_ATTEMPTS = 5;
510
+ private readonly LOCKOUT_DURATION = 15 * 60 * 1000; // 15分钟
511
+
512
+ async checkLoginAttempts(ip: string): Promise<boolean> {
513
+ const attempts = this.attempts.get(ip) || 0;
514
+ return attempts < this.MAX_ATTEMPTS;
515
+ }
516
+
517
+ recordFailedAttempt(ip: string) {
518
+ const attempts = (this.attempts.get(ip) || 0) + 1;
519
+ this.attempts.set(ip, attempts);
520
+
521
+ // 锁定IP
522
+ if (attempts >= this.MAX_ATTEMPTS) {
523
+ setTimeout(() => {
524
+ this.attempts.delete(ip);
525
+ }, this.LOCKOUT_DURATION);
526
+
527
+ // 记录安全事件
528
+ const securityLogger = new SecurityLogger(logger);
529
+ securityLogger.logSecurityEvent('ACCOUNT_LOCKOUT', { ip, attempts });
530
+ }
531
+ }
532
+ }
533
+ ```
534
+
535
+ ## 安全配置
536
+
537
+ ### 安全HTTP头
538
+
539
+ ```typescript
540
+ // 安全头中间件
541
+ class SecurityHeadersMiddleware implements IMiddlewareService {
542
+ async process(payload: any, ctx: any, next: () => Promise<any>) {
543
+ // 设置安全HTTP头
544
+ ctx.response.setHeader('X-Content-Type-Options', 'nosniff');
545
+ ctx.response.setHeader('X-Frame-Options', 'DENY');
546
+ ctx.response.setHeader('X-XSS-Protection', '1; mode=block');
547
+ ctx.response.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
548
+ ctx.response.setHeader('Permissions-Policy', 'geolocation=(), microphone=()');
549
+
550
+ // Content Security Policy
551
+ ctx.response.setHeader(
552
+ 'Content-Security-Policy',
553
+ [
554
+ "default-src 'self'",
555
+ "script-src 'self' 'unsafe-inline'",
556
+ "style-src 'self' 'unsafe-inline'",
557
+ "img-src 'self' data: https:",
558
+ "connect-src 'self'",
559
+ "font-src 'self'"
560
+ ].join('; ')
561
+ );
562
+
563
+ return await next();
564
+ }
565
+ }
566
+ ```
567
+
568
+ ### 依赖安全
569
+
570
+ ```json
571
+ {
572
+ "scripts": {
573
+ "audit": "npm audit",
574
+ "audit:fix": "npm audit fix",
575
+ "audit:ci": "npm audit --audit-level=high"
576
+ }
577
+ }
578
+ ```
579
+
580
+ ## 安全清单
581
+
582
+ ### 开发和测试
583
+
584
+ - ✅ 启用依赖审计`npm audit`
585
+ - ✅ 使用安全linting规则
586
+ - ✅ 实施代码审查流程
587
+ - ✅ 定期安全扫描
588
+
589
+ ### 构建和部署
590
+
591
+ - ✅ 最小化生产依赖
592
+ - ✅ 移除调试代码
593
+ - ✅ 环境变量管理密钥
594
+ - ✅ 启用安全传输
595
+
596
+ ### 运行时
597
+
598
+ - ✅ 输入验证和清理
599
+ - ✅ 安全的错误处理
600
+ - ✅ 适当的身份验证和授权
601
+ - ✅ 安全的会话管理
602
+ - ✅ 日志脱敏
603
+ - ✅ 监控和警报
604
+
605
+ ## 完整示例
606
+
607
+ 查看安全实践:
608
+
609
+ - 📁 [Blog Plugin 示例](../../examples/blog-plugin/) - 完整的用户认证实现
610
+ - 📁 [Analytics Plugin 示例](../../examples/analytics-plugin/) - 数据安全处理
611
+
612
+ ## 相关文档
613
+
614
+ - 📝 [命名规范](./naming-conventions.md)
615
+ - ⚠️ [错误处理](./error-handling.md)
616
+ - ⚡ [性能优化](./performance.md)
617
+
618
+ ---
619
+
620
+ **上一篇**: [性能优化](./performance.md) | **下一篇**: [FAQ](../faq.md)