mm_os 3.3.0 → 4.0.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 (380) hide show
  1. package/LICENSE +21 -201
  2. package/README.md +491 -99
  3. package/README_EN.md +498 -0
  4. package/adapter/adapter.js +431 -0
  5. package/adapter/custom_persistence.js +660 -0
  6. package/adapter/mqtt.js +273 -0
  7. package/adapter/socket.js +113 -0
  8. package/adapter/web.js +67 -0
  9. package/adapter/websocket.js +146 -0
  10. package/com/api/com.json +5 -0
  11. package/{core/com → com}/api/config.tpl.json +8 -8
  12. package/com/api/drive.js +708 -0
  13. package/com/api/index.js +198 -0
  14. package/com/api/oauth.js +200 -0
  15. package/com/api/script.tpl.js +32 -0
  16. package/com/cmd/README.md +11 -0
  17. package/com/cmd/com.json +5 -0
  18. package/com/cmd/config.tpl.json +122 -0
  19. package/com/cmd/drive.js +1548 -0
  20. package/com/cmd/index.js +1066 -0
  21. package/com/cmd/msg.json +48 -0
  22. package/com/cmd/nlp.js +525 -0
  23. package/com/cmd/script.tpl.js +32 -0
  24. package/com/db/com.json +5 -0
  25. package/com/db/drive.js +1999 -0
  26. package/com/db/index.js +242 -0
  27. package/com/event/com.json +5 -0
  28. package/{core/com → com}/event/config.tpl.json +8 -8
  29. package/com/event/drive.js +59 -0
  30. package/com/event/index.js +409 -0
  31. package/com/event/script.tpl.js +23 -0
  32. package/com/mqtt/com.json +5 -0
  33. package/{core/com → com}/mqtt/config.tpl.json +3 -5
  34. package/com/mqtt/drive.js +676 -0
  35. package/com/mqtt/index.js +822 -0
  36. package/com/mqtt/mm_mqtt.js +425 -0
  37. package/com/mqtt/script.tpl.js +723 -0
  38. package/com/nav/com.json +5 -0
  39. package/com/nav/config.tpl.json +84 -0
  40. package/com/nav/drive.js +702 -0
  41. package/com/nav/index.js +231 -0
  42. package/{core/com → com}/nav/tpl/admin_pc/page_config.vue +280 -280
  43. package/{core/com → com}/nav/tpl/admin_pc/page_config_form.vue +194 -194
  44. package/com/nav/tpl/admin_pc/page_form.vue +180 -0
  45. package/com/nav/tpl/admin_pc/page_view.vue +124 -0
  46. package/com/nav/tpl/dev_pc/page_default.vue +247 -0
  47. package/com/nav/tpl/dev_pc/page_type.vue +313 -0
  48. package/com/nav/tpl/home_pc/page_default.vue +234 -0
  49. package/com/nav/tpl/home_pc/page_form.vue +137 -0
  50. package/com/nav/tpl/home_pc/page_list.vue +234 -0
  51. package/com/nav/tpl/home_pc/page_nav.vue +221 -0
  52. package/com/nav/tpl/home_pc/page_type.vue +234 -0
  53. package/com/nav/tpl/home_pc/page_view.vue +125 -0
  54. package/com/nav/tpl/home_phone/page_channel.vue +234 -0
  55. package/com/nav/tpl/home_phone/page_default.vue +234 -0
  56. package/com/nav/tpl/home_phone/page_form.vue +137 -0
  57. package/com/nav/tpl/home_phone/page_nav.vue +237 -0
  58. package/com/nav/tpl/home_phone/page_type.vue +234 -0
  59. package/com/nav/tpl/home_phone/page_view.vue +125 -0
  60. package/com/nav/viewmodel.js +446 -0
  61. package/com/param/com.json +5 -0
  62. package/{core/com → com}/param/config.tpl.json +7 -1
  63. package/com/param/drive.js +502 -0
  64. package/com/param/index.js +155 -0
  65. package/com/param/script.tpl.js +12 -0
  66. package/com/pendant/com.json +5 -0
  67. package/{core/com/component → com/pendant}/config.tpl.json +15 -13
  68. package/com/pendant/drive.js +204 -0
  69. package/com/pendant/index.js +441 -0
  70. package/com/pendant/pendant.html +16 -0
  71. package/com/pendant/script.tpl.js +18 -0
  72. package/com/socket/com.json +5 -0
  73. package/com/socket/config.tpl.json +12 -0
  74. package/com/socket/drive.js +651 -0
  75. package/com/socket/index.js +351 -0
  76. package/com/socket/script.tpl.js +41 -0
  77. package/com/sql/com.json +5 -0
  78. package/{core/com → com}/sql/config.tpl.json +13 -9
  79. package/com/sql/drive.js +1259 -0
  80. package/com/sql/index.js +150 -0
  81. package/com/sql/script.tpl.js +47 -0
  82. package/com/static/com.json +5 -0
  83. package/{core/com → com}/static/config.tpl.json +10 -6
  84. package/com/static/drive.js +194 -0
  85. package/com/static/index.js +226 -0
  86. package/com/static/script.tpl.js +28 -0
  87. package/com/task/com.json +5 -0
  88. package/{core/com → com}/task/config.tpl.json +4 -6
  89. package/com/task/drive.js +405 -0
  90. package/com/task/index.js +148 -0
  91. package/com/task/script.tpl.js +37 -0
  92. package/com/template/com.json +5 -0
  93. package/com/template/config.tpl.json +16 -0
  94. package/com/template/drive.js +80 -0
  95. package/com/template/index.js +141 -0
  96. package/com.js +156 -0
  97. package/common/README.md +2 -0
  98. package/common/handler/msg/handler.json +22 -0
  99. package/common/handler/msg/index.js +23 -0
  100. package/common/handler/player/handler.json +22 -0
  101. package/common/handler/player/index.js +287 -0
  102. package/common/handler/user/handler.json +22 -0
  103. package/common/handler/user/index.js +23 -0
  104. package/common/middleware/web_after/index.js +29 -0
  105. package/common/middleware/web_after/middleware.json +9 -0
  106. package/common/middleware/web_base/index.js +113 -0
  107. package/common/middleware/web_base/middleware.json +19 -0
  108. package/common/middleware/web_before/index.js +33 -0
  109. package/common/middleware/web_before/middleware.json +9 -0
  110. package/common/middleware/web_cors/index.js +87 -0
  111. package/common/middleware/web_cors/middleware.json +24 -0
  112. package/common/middleware/web_error/index.js +119 -0
  113. package/common/middleware/web_error/middleware.json +18 -0
  114. package/common/middleware/web_ip/index.js +15 -0
  115. package/common/middleware/web_ip/middleware.json +14 -0
  116. package/common/middleware/web_logger/index.js +156 -0
  117. package/common/middleware/web_logger/middleware.json +14 -0
  118. package/common/middleware/web_main/index.js +24 -0
  119. package/common/middleware/web_main/middleware.json +9 -0
  120. package/common/middleware/web_static/index.js +73 -0
  121. package/common/middleware/web_static/middleware.json +54 -0
  122. package/common/middleware/web_waf/index.js +385 -0
  123. package/common/middleware/web_waf/middleware.json +13 -0
  124. package/common/model/msg/index.js +88 -0
  125. package/common/model/msg/model.json +401 -0
  126. package/common/model/player/index.js +63 -0
  127. package/common/model/player/model.json +185 -0
  128. package/common/model/user/index.js +11 -0
  129. package/common/model/user/model.json +219 -0
  130. package/core/app/config.tpl.json +67 -0
  131. package/core/app/index.js +632 -0
  132. package/core/app/script.tpl.js +52 -0
  133. package/core/channel/index.js +899 -0
  134. package/core/channel/matcher.js +585 -0
  135. package/core/com/config.tpl.json +16 -0
  136. package/core/com/index.js +74 -0
  137. package/core/com/script.tpl.js +5 -0
  138. package/core/component/component.js +42 -0
  139. package/core/component/config.tpl.json +63 -0
  140. package/core/component/index.js +273 -0
  141. package/core/component/script.tpl.js +19 -0
  142. package/core/controller/config.tpl.json +14 -0
  143. package/core/controller/index.js +373 -0
  144. package/core/controller/script.tpl.js +27 -0
  145. package/core/factory/config.tpl.json +14 -0
  146. package/core/factory/entity.js +275 -0
  147. package/core/factory/index.js +241 -0
  148. package/core/factory/script.tpl.js +16 -0
  149. package/core/game/bat/index.js +137 -0
  150. package/core/game/bat/world.js +622 -0
  151. package/core/game/config.tpl.json +16 -0
  152. package/core/game/entity_admin.js +230 -0
  153. package/core/game/index.js +186 -0
  154. package/core/handler/config.tpl.json +22 -0
  155. package/core/handler/index.js +181 -0
  156. package/core/handler/script.tpl.js +23 -0
  157. package/core/logic/config.tpl.json +14 -0
  158. package/core/logic/index.js +59 -0
  159. package/core/logic/script.tpl.js +19 -0
  160. package/core/middleware/config.tpl.json +16 -0
  161. package/core/middleware/index.js +125 -0
  162. package/core/middleware/script.tpl.js +37 -0
  163. package/core/mod/config.tpl.json +22 -0
  164. package/core/mod/index.js +130 -0
  165. package/core/mod/script.tpl.js +34 -0
  166. package/core/model/config.tpl.json +219 -0
  167. package/core/model/index.js +272 -0
  168. package/core/model/model.js +27 -0
  169. package/core/model/script.tpl.js +20 -0
  170. package/core/notifier/config.tpl.json +14 -0
  171. package/core/notifier/index.js +77 -0
  172. package/core/notifier/script.tpl.js +20 -0
  173. package/core/plugin/config.tpl.json +24 -0
  174. package/core/plugin/index.js +232 -0
  175. package/core/plugin/script.tpl.js +51 -0
  176. package/core/pusher/config.tpl.json +14 -0
  177. package/core/pusher/index.js +161 -0
  178. package/core/pusher/script.tpl.js +20 -0
  179. package/core/room/bat/index.js +170 -0
  180. package/core/room/bat/room.js +524 -0
  181. package/core/room/config.tpl.json +20 -0
  182. package/core/room/index.js +249 -0
  183. package/core/room/room.js +61 -0
  184. package/core/scene/config.tpl.json +14 -0
  185. package/core/scene/index.js +466 -0
  186. package/core/scene/loop.js +1255 -0
  187. package/core/scene/map.js +28 -0
  188. package/core/scene/script.tpl.js +22 -0
  189. package/core/sender/config.tpl.json +14 -0
  190. package/core/sender/index.js +79 -0
  191. package/core/sender/script.tpl.js +20 -0
  192. package/core/service/config.tpl.json +14 -0
  193. package/core/service/index.js +100 -0
  194. package/core/service/script.tpl.js +25 -0
  195. package/core/store/config.tpl.json +26 -0
  196. package/core/store/index.js +1755 -0
  197. package/core/store/script.tpl.js +22 -0
  198. package/core/store/sql.js +1464 -0
  199. package/core/system/config.tpl.json +18 -0
  200. package/core/system/index.js +312 -0
  201. package/core/system/script.tpl.js +77 -0
  202. package/core/view/config.tpl.json +14 -0
  203. package/core/view/index.js +91 -0
  204. package/core/view/script.tpl.js +20 -0
  205. package/core/zone/bat/index.js +725 -0
  206. package/core/zone/config.tpl.json +54 -0
  207. package/core/zone/index.js +614 -0
  208. package/core/zone/script.tpl.js +10 -0
  209. package/core/zone/zone_bat.js +136 -0
  210. package/core//345/237/272/347/261/273/346/250/241/345/235/227/346/270/205/345/215/225.md +24 -0
  211. package/index.js +17 -314
  212. package/os.js +57 -0
  213. package/package.json +60 -58
  214. package/server.js +598 -0
  215. package/README.en.md +0 -36
  216. package/conf.json +0 -3
  217. package/core/base/mqtt/index.js +0 -1107
  218. package/core/base/mqtt/lib.js +0 -40
  219. package/core/base/web/index.js +0 -243
  220. package/core/com/api/com.json +0 -4
  221. package/core/com/api/drive.js +0 -668
  222. package/core/com/api/index.js +0 -108
  223. package/core/com/api/oauth.js +0 -158
  224. package/core/com/api/script.js +0 -32
  225. package/core/com/app/README.md +0 -3
  226. package/core/com/app/com.json +0 -4
  227. package/core/com/app/config.tpl.json +0 -16
  228. package/core/com/app/drive.js +0 -309
  229. package/core/com/app/index.js +0 -211
  230. package/core/com/app/script.js +0 -155
  231. package/core/com/cmd/com.json +0 -4
  232. package/core/com/cmd/config.tpl.json +0 -66
  233. package/core/com/cmd/drive.js +0 -513
  234. package/core/com/cmd/index.js +0 -354
  235. package/core/com/cmd/old/5w2h.js +0 -54
  236. package/core/com/cmd/old/drive.js +0 -423
  237. package/core/com/cmd/script.js +0 -11
  238. package/core/com/component/README.md +0 -3
  239. package/core/com/component/com.json +0 -4
  240. package/core/com/component/component.html +0 -16
  241. package/core/com/component/drive.js +0 -197
  242. package/core/com/component/index.js +0 -312
  243. package/core/com/component/script.js +0 -18
  244. package/core/com/db/com.json +0 -4
  245. package/core/com/db/drive.js +0 -1160
  246. package/core/com/db/index.js +0 -176
  247. package/core/com/event/com.json +0 -4
  248. package/core/com/event/drive.js +0 -133
  249. package/core/com/event/index.js +0 -345
  250. package/core/com/event/script.js +0 -26
  251. package/core/com/eventer/com.js +0 -477
  252. package/core/com/eventer/com.json +0 -4
  253. package/core/com/middleware/com.js +0 -153
  254. package/core/com/middleware/com.json +0 -4
  255. package/core/com/middleware/config.tpl.json +0 -8
  256. package/core/com/middleware/script.js +0 -9
  257. package/core/com/mqtt/com.json +0 -4
  258. package/core/com/mqtt/drive.js +0 -600
  259. package/core/com/mqtt/index.js +0 -572
  260. package/core/com/mqtt/mm_mqtt.js +0 -330
  261. package/core/com/mqtt/script.js +0 -604
  262. package/core/com/msg/com.js +0 -296
  263. package/core/com/msg/com.json +0 -4
  264. package/core/com/nav/com.json +0 -4
  265. package/core/com/nav/config.tpl.json +0 -75
  266. package/core/com/nav/drive.js +0 -549
  267. package/core/com/nav/index.js +0 -182
  268. package/core/com/nav/tpl/admin_pc/page_form.vue +0 -180
  269. package/core/com/nav/tpl/admin_pc/page_view.vue +0 -124
  270. package/core/com/nav/tpl/dev_pc/page_default.vue +0 -247
  271. package/core/com/nav/tpl/dev_pc/page_type.vue +0 -313
  272. package/core/com/nav/tpl/home_pc/page_default.vue +0 -234
  273. package/core/com/nav/tpl/home_pc/page_form.vue +0 -137
  274. package/core/com/nav/tpl/home_pc/page_list.vue +0 -234
  275. package/core/com/nav/tpl/home_pc/page_nav.vue +0 -221
  276. package/core/com/nav/tpl/home_pc/page_type.vue +0 -234
  277. package/core/com/nav/tpl/home_pc/page_view.vue +0 -125
  278. package/core/com/nav/tpl/home_phone/page_channel.vue +0 -234
  279. package/core/com/nav/tpl/home_phone/page_default.vue +0 -234
  280. package/core/com/nav/tpl/home_phone/page_form.vue +0 -137
  281. package/core/com/nav/tpl/home_phone/page_nav.vue +0 -237
  282. package/core/com/nav/tpl/home_phone/page_type.vue +0 -234
  283. package/core/com/nav/tpl/home_phone/page_view.vue +0 -125
  284. package/core/com/nav/viewmodel.js +0 -296
  285. package/core/com/param/drive.js +0 -366
  286. package/core/com/param/index.js +0 -80
  287. package/core/com/param/script.js +0 -12
  288. package/core/com/param/test.js +0 -98
  289. package/core/com/plugin/README.md +0 -3
  290. package/core/com/plugin/com.json +0 -4
  291. package/core/com/plugin/config.tpl.json +0 -26
  292. package/core/com/plugin/drive.js +0 -536
  293. package/core/com/plugin/index.js +0 -259
  294. package/core/com/plugin/script.js +0 -213
  295. package/core/com/rpc/com.json +0 -4
  296. package/core/com/rpc/drive.js +0 -160
  297. package/core/com/rpc/index.js +0 -87
  298. package/core/com/rpc/rpc.js +0 -118
  299. package/core/com/socket/com.json +0 -4
  300. package/core/com/socket/config.tpl.json +0 -14
  301. package/core/com/socket/drive.js +0 -403
  302. package/core/com/socket/index.js +0 -62
  303. package/core/com/socket/script.js +0 -42
  304. package/core/com/sql/drive.js +0 -1087
  305. package/core/com/sql/index.js +0 -83
  306. package/core/com/sql/script.js +0 -48
  307. package/core/com/static/com.json +0 -4
  308. package/core/com/static/drive.js +0 -220
  309. package/core/com/static/index.js +0 -149
  310. package/core/com/static/script.js +0 -28
  311. package/core/com/task/com.json +0 -4
  312. package/core/com/task/drive.js +0 -403
  313. package/core/com/task/index.js +0 -110
  314. package/core/com/task/script.js +0 -37
  315. package/core/com/timer/com.js +0 -217
  316. package/core/com/timer/com.json +0 -4
  317. package/core/com/tpl/com.js +0 -19
  318. package/core/com/tpl/com.json +0 -4
  319. package/lib/actions.js +0 -50
  320. package/lib/base.js +0 -361
  321. package/lib/com.js +0 -29
  322. package/lib/ref.js +0 -121
  323. package/middleware/mqtt_base/index.js +0 -10
  324. package/middleware/mqtt_base/middleware.json +0 -10
  325. package/middleware/performance/index.js +0 -151
  326. package/middleware/performance/middleware.json +0 -16
  327. package/middleware/security_audit/index.js +0 -549
  328. package/middleware/security_audit/middleware.json +0 -48
  329. package/middleware/security_headers/index.js +0 -487
  330. package/middleware/security_headers/middleware.json +0 -45
  331. package/middleware/waf/index.js +0 -348
  332. package/middleware/waf/middleware.json +0 -10
  333. package/middleware/waf_ddos/index.js +0 -520
  334. package/middleware/waf_ddos/middleware.json +0 -38
  335. package/middleware/waf_ip/index.js +0 -379
  336. package/middleware/waf_ip/middleware.json +0 -49
  337. package/middleware/waf_xss/index.js +0 -269
  338. package/middleware/waf_xss/middleware.json +0 -18
  339. package/middleware/web_after/index.js +0 -33
  340. package/middleware/web_after/middleware.json +0 -9
  341. package/middleware/web_base/index.js +0 -90
  342. package/middleware/web_base/middleware.json +0 -9
  343. package/middleware/web_before/index.js +0 -27
  344. package/middleware/web_before/middleware.json +0 -9
  345. package/middleware/web_check/index.js +0 -28
  346. package/middleware/web_check/middleware.json +0 -9
  347. package/middleware/web_main/index.js +0 -28
  348. package/middleware/web_main/middleware.json +0 -9
  349. package/middleware/web_proxy/index.js +0 -37
  350. package/middleware/web_proxy/middleware.json +0 -9
  351. package/middleware/web_render/index.js +0 -87
  352. package/middleware/web_render/middleware.json +0 -9
  353. package/middleware/web_socket/index.js +0 -34
  354. package/middleware/web_socket/middleware.json +0 -9
  355. package/middleware/web_static/index.js +0 -115
  356. package/middleware/web_static/middleware.json +0 -9
  357. /package/{core/com → com}/api/README.md +0 -0
  358. /package/{core/com → com}/db/README.md +0 -0
  359. /package/{core/com → com}/event/README.md +0 -0
  360. /package/{core/com → com}/mqtt/README.md +0 -0
  361. /package/{core/com → com}/nav/README.md +0 -0
  362. /package/{core/com → com}/nav/tpl/admin_pc/page_channel.vue +0 -0
  363. /package/{core/com → com}/nav/tpl/admin_pc/page_default.vue +0 -0
  364. /package/{core/com → com}/nav/tpl/admin_pc/page_lang.vue +0 -0
  365. /package/{core/com → com}/nav/tpl/admin_pc/page_nav.vue +0 -0
  366. /package/{core/com → com}/nav/tpl/admin_pc/page_table.vue +0 -0
  367. /package/{core/com → com}/nav/tpl/admin_pc/page_type.vue +0 -0
  368. /package/{core/com → com}/nav/tpl/dev_pc/page_channel.vue +0 -0
  369. /package/{core/com → com}/nav/tpl/dev_pc/page_config.vue +0 -0
  370. /package/{core/com → com}/nav/tpl/dev_pc/page_form.vue +0 -0
  371. /package/{core/com → com}/nav/tpl/dev_pc/page_nav.vue +0 -0
  372. /package/{core/com → com}/nav/tpl/dev_pc/page_table.vue +0 -0
  373. /package/{core/com → com}/nav/tpl/home_pc/page_channel.vue +0 -0
  374. /package/{core/com → com}/nav/tpl/home_phone/page_list.vue +0 -0
  375. /package/{core/com → com}/param/README.md +0 -0
  376. /package/{core/com/cmd → com/pendant}/README.md +0 -0
  377. /package/{core/com → com}/socket/README.md +0 -0
  378. /package/{core/com → com}/sql/README.md +0 -0
  379. /package/{core/com → com}/static/README.md +0 -0
  380. /package/{core/com → com}/task/README.md +0 -0
@@ -0,0 +1,660 @@
1
+ const { Readable } = require('stream');
2
+
3
+ /**
4
+ * 自定义持久化类 - 为Aedes MQTT broker提供持久化存储支持
5
+ */
6
+ class Persist {
7
+ /**
8
+ * 构造函数
9
+ * @param {object} config 配置参数
10
+ * @param {object} cache 缓存管理器
11
+ */
12
+ constructor(config, cache) {
13
+ // 配置参数
14
+ this.config = {
15
+ // 缓存配置
16
+ cache: true,
17
+ // 缓存前缀
18
+ prefix: 'mqtt:',
19
+ // 缓存过期时间(毫秒)
20
+ ttl: 3600000,
21
+ ...config
22
+ };
23
+
24
+ // 缓存管理器,提供set、get、del、keys功能
25
+ this._cache = cache;
26
+
27
+ if (!this._cache) {
28
+ throw new Error('缓存管理器不能为空');
29
+ }
30
+
31
+ // 验证缓存管理器是否实现了必要的方法
32
+ let req_methods = ['set', 'get', 'delete', 'keys'];
33
+ for (let method of req_methods) {
34
+ if (typeof this._cache[method] !== 'function') {
35
+ throw new Error(`缓存管理器必须实现${method}方法`);
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ /**
42
+ * 生成带前缀的缓存键
43
+ * @private
44
+ * @param {string} key - 原始键
45
+ * @returns {string} 带前缀的缓存键
46
+ */
47
+ Persist.prototype._getCacheKey = function(key) {
48
+ return this.config.prefix + key;
49
+ };
50
+
51
+ /**
52
+ * 获取所有匹配模式的键
53
+ * @private
54
+ * @param {string} pattern - 键模式
55
+ * @returns {Array} 匹配的键数组
56
+ */
57
+ Persist.prototype._getKeysByPattern = function(pattern) {
58
+ let prefix = this.config.prefix;
59
+ let regex = new RegExp('^' + prefix + pattern.replace(/\*/g, '.*') + '$');
60
+ return this._cache.keys().filter(key => regex.test(key)).map(key => key.slice(prefix.length));
61
+ };
62
+
63
+ // ------------------- 订阅管理 -------------------
64
+
65
+ /**
66
+ * 添加订阅
67
+ * @param {object} client - 客户端对象
68
+ * @param {object} sub - 订阅对象
69
+ * @param {Function} cb - 回调函数
70
+ */
71
+ Persist.prototype.addSub = function(client, sub, cb) {
72
+ try {
73
+ if (!client || !client.clientId) {
74
+ throw new Error('无效的客户端对象');
75
+ }
76
+
77
+ if (!sub || !sub.topic) {
78
+ throw new Error('无效的订阅对象');
79
+ }
80
+
81
+ let key = this._getCacheKey(`subscription:${client.clientId}:${sub.topic}`);
82
+ this._cache.set(key, sub, this.config.ttl);
83
+
84
+ if (cb) cb(null);
85
+ } catch (error) {
86
+ if (cb) cb(error);
87
+ }
88
+ };
89
+
90
+ /**
91
+ * 删除订阅
92
+ * @param {object} client - 客户端对象
93
+ * @param {object} sub - 订阅对象
94
+ * @param {Function} cb - 回调函数
95
+ */
96
+ Persist.prototype.removeSub = function(client, sub, cb) {
97
+ try {
98
+ if (!client || !client.clientId) {
99
+ throw new Error('无效的客户端对象');
100
+ }
101
+
102
+ if (!sub || !sub.topic) {
103
+ throw new Error('无效的订阅对象');
104
+ }
105
+
106
+ let key = this._getCacheKey(`subscription:${client.clientId}:${sub.topic}`);
107
+ this._cache.delete(key);
108
+
109
+ if (cb) cb(null);
110
+ } catch (error) {
111
+ if (cb) cb(error);
112
+ }
113
+ };
114
+
115
+ /**
116
+ * 删除客户端的所有订阅
117
+ * @param {object} client - 客户端对象
118
+ * @param {Function} cb - 回调函数
119
+ */
120
+ Persist.prototype.removeSubs = function(client, cb) {
121
+ try {
122
+ if (!client || !client.clientId) {
123
+ throw new Error('无效的客户端对象');
124
+ }
125
+
126
+ let pat = `subscription:${client.clientId}:*`;
127
+ let keys = this._getKeysByPattern(pat);
128
+
129
+ // 同步执行所有删除操作
130
+ keys.forEach(key => {
131
+ this._cache.delete(this._getCacheKey(key));
132
+ });
133
+
134
+ if (cb) cb(null);
135
+ } catch (error) {
136
+ if (cb) cb(error);
137
+ }
138
+ };
139
+
140
+ /**
141
+ * 获取客户端的所有订阅
142
+ * @param {object} client - 客户端对象
143
+ * @param {Function} cb - 回调函数
144
+ */
145
+ Persist.prototype.getSubs = function(client, cb) {
146
+ try {
147
+ if (!client || !client.clientId) {
148
+ throw new Error('无效的客户端对象');
149
+ }
150
+
151
+ let pattern = `subscription:${client.clientId}:*`;
152
+ let keys = this._getKeysByPattern(pattern);
153
+
154
+ // 同步执行所有获取操作
155
+ let subs = keys.map(key => {
156
+ return this._cache.get(this._getCacheKey(key));
157
+ }).filter(Boolean);
158
+
159
+ if (cb) cb(null, subs);
160
+ } catch (error) {
161
+ if (cb) cb(error);
162
+ }
163
+ };
164
+
165
+ /**
166
+ * 获取订阅了指定主题的所有客户端
167
+ * @param {string} topic - 主题
168
+ * @param {Function} cb - 回调函数
169
+ */
170
+ Persist.prototype.subsByTopic = function(topic, cb) {
171
+ try {
172
+ if (!topic) {
173
+ throw new Error('主题不能为空');
174
+ }
175
+
176
+ // 简单实现,实际可能需要支持通配符匹配
177
+ let pat = `subscription:*:${topic}`;
178
+ let keys = this._getKeysByPattern(pat);
179
+
180
+ // 同步执行所有获取操作
181
+ let subs = keys.map(key => {
182
+ let parts = key.split(':');
183
+ if (parts.length >= 3) {
184
+ let cid = parts[1];
185
+ let sub = this._cache.get(this._getCacheKey(key));
186
+ if (sub) {
187
+ return {
188
+ client_id: cid,
189
+ sub: sub
190
+ };
191
+ }
192
+ }
193
+ return null;
194
+ }).filter(Boolean);
195
+
196
+ if (cb) cb(null, subs);
197
+ } catch (error) {
198
+ if (cb) cb(error);
199
+ }
200
+ };
201
+
202
+ // ------------------- 保留消息 -------------------
203
+
204
+ /**
205
+ * 存储保留消息
206
+ * @param {object} packet - MQTT消息包
207
+ * @param {Function} callback - 回调函数
208
+ */
209
+ Persist.prototype.storeRetained = function(packet, callback) {
210
+ try {
211
+ if (!packet || !packet.topic) {
212
+ throw new Error('无效的消息包');
213
+ }
214
+
215
+ let key = this._getCacheKey(`retained:${packet.topic}`);
216
+ this._cache.set(key, packet, this.config.ttl);
217
+
218
+ if (callback) callback(null);
219
+ } catch (error) {
220
+ if (callback) callback(error);
221
+ }
222
+ };
223
+
224
+ /**
225
+ * 删除保留消息
226
+ * @param {string} topic - 主题
227
+ * @param {Function} callback - 回调函数
228
+ */
229
+ Persist.prototype.cleanRetained = function(topic, callback) {
230
+ try {
231
+ if (!topic) {
232
+ throw new Error('主题不能为空');
233
+ }
234
+
235
+ let key = this._getCacheKey(`retained:${topic}`);
236
+ this._cache.delete(key);
237
+
238
+ if (callback) callback(null);
239
+ } catch (error) {
240
+ if (callback) callback(error);
241
+ }
242
+ };
243
+
244
+ /**
245
+ * 获取保留消息
246
+ * @param {string} topic - 主题
247
+ * @param {Function} cb - 回调函数
248
+ */
249
+ Persist.prototype.getRetained = function(topic, cb) {
250
+ try {
251
+ if (!topic) {
252
+ throw new Error('主题不能为空');
253
+ }
254
+
255
+ let key = this._getCacheKey(`retained:${topic}`);
256
+ let retained = this._cache.get(key);
257
+
258
+ if (cb) cb(null, retained ? [retained] : []);
259
+ } catch (error) {
260
+ if (cb) cb(error);
261
+ }
262
+ };
263
+
264
+ // ------------------- 传输中消息 (QoS) -------------------
265
+
266
+ /**
267
+ * 存储传输中消息
268
+ * @param {object} client - 客户端对象
269
+ * @param {object} packet - MQTT消息包
270
+ * @param {Function} callback - 回调函数
271
+ */
272
+ Persist.prototype.storePacket = function(client, packet, callback) {
273
+ try {
274
+ if (!client || !client.clientId) {
275
+ throw new Error('无效的客户端对象');
276
+ }
277
+
278
+ if (!packet || !packet.msgId) {
279
+ throw new Error('无效的消息包');
280
+ }
281
+
282
+ let key = this._getCacheKey(`packet:${client.clientId}:${packet.msgId}`);
283
+ this._cache.set(key, packet, this.config.ttl);
284
+
285
+ if (callback) callback(null);
286
+ } catch (error) {
287
+ if (callback) callback(error);
288
+ }
289
+ };
290
+
291
+ /**
292
+ * 删除传输中消息
293
+ * @param {object} client - 客户端对象
294
+ * @param {object} packet - MQTT消息包
295
+ * @param {Function} callback - 回调函数
296
+ */
297
+ Persist.prototype.removePacket = function(client, packet, callback) {
298
+ try {
299
+ if (!client || !client.clientId) {
300
+ throw new Error('无效的客户端对象');
301
+ }
302
+
303
+ if (!packet || !packet.msgId) {
304
+ throw new Error('无效的消息包');
305
+ }
306
+
307
+ let key = this._getCacheKey(`packet:${client.clientId}:${packet.msgId}`);
308
+ this._cache.delete(key);
309
+
310
+ if (callback) callback(null);
311
+ } catch (error) {
312
+ if (callback) callback(error);
313
+ }
314
+ };
315
+
316
+ /**
317
+ * 获取传输中消息
318
+ * @param {object} client - 客户端对象
319
+ * @param {object} packet - MQTT消息包
320
+ * @param {Function} callback - 回调函数
321
+ */
322
+ Persist.prototype.getPacket = function(client, packet, callback) {
323
+ try {
324
+ if (!client || !client.clientId) {
325
+ throw new Error('无效的客户端对象');
326
+ }
327
+
328
+ if (!packet || !packet.msgId) {
329
+ throw new Error('无效的消息包');
330
+ }
331
+
332
+ let key = this._getCacheKey(`packet:${client.clientId}:${packet.msgId}`);
333
+
334
+ if (callback) callback(null, this._cache.get(key));
335
+ } catch (error) {
336
+ if (callback) callback(error);
337
+ }
338
+ };
339
+
340
+ /**
341
+ * 获取客户端的所有传输中消息
342
+ * @param {object} client - 客户端对象
343
+ * @param {Function} callback - 回调函数
344
+ */
345
+ Persist.prototype.getPackets = function(client, callback) {
346
+ try {
347
+ if (!client || !client.clientId) {
348
+ throw new Error('无效的客户端对象');
349
+ }
350
+
351
+ let pattern = `packet:${client.clientId}:*`;
352
+ let keys = this._getKeysByPattern(pattern);
353
+
354
+ // 同步执行所有获取操作
355
+ let packets = keys.map(key => {
356
+ let packet = this._cache.get(this._getCacheKey(key));
357
+ return packet;
358
+ }).filter(Boolean);
359
+
360
+ if (callback) callback(null, packets);
361
+ } catch (error) {
362
+ if (callback) callback(error);
363
+ }
364
+ };
365
+
366
+ /**
367
+ * 删除过期的传输中消息
368
+ * @param {object} packet - MQTT消息包
369
+ * @param {Function} callback - 回调函数
370
+ */
371
+ Persist.prototype.delOutdatedPacket = function(packet, callback) {
372
+ try {
373
+ if (!packet || !packet.msgId) {
374
+ throw new Error('无效的消息包');
375
+ }
376
+
377
+ // 注意:这个方法可能需要客户端信息,这里简单处理
378
+ let pattern = `packet:*:${packet.msgId}`;
379
+ let keys = this._getKeysByPattern(pattern);
380
+
381
+ // 同步执行所有删除操作
382
+ keys.forEach(key => {
383
+ this._cache.delete(this._getCacheKey(key));
384
+ });
385
+
386
+ if (callback) callback(null);
387
+ } catch (error) {
388
+ if (callback) callback(error);
389
+ }
390
+ };
391
+
392
+ // ------------------- 遗嘱消息 -------------------
393
+
394
+ /**
395
+ * 存储遗嘱消息
396
+ * @param {object} client - 客户端对象
397
+ * @param {object} packet - MQTT消息包
398
+ * @param {Function} callback - 回调函数
399
+ */
400
+ Persist.prototype.storeWill = function(client, packet, callback) {
401
+ try {
402
+ if (!client || !client.clientId) {
403
+ throw new Error('无效的客户端对象');
404
+ }
405
+
406
+ if (!packet) {
407
+ throw new Error('无效的消息包');
408
+ }
409
+
410
+ let key = this._getCacheKey(`will:${client.clientId}`);
411
+ this._cache.set(key, packet, this.config.ttl);
412
+
413
+ if (callback) callback(null);
414
+ } catch (error) {
415
+ if (callback) callback(error);
416
+ }
417
+ };
418
+
419
+ /**
420
+ * 删除遗嘱消息
421
+ * @param {object} client - 客户端对象
422
+ * @param {Function} callback - 回调函数
423
+ */
424
+ Persist.prototype.removeWill = function(client, callback) {
425
+ try {
426
+ if (!client || !client.clientId) {
427
+ throw new Error('无效的客户端对象');
428
+ }
429
+
430
+ let key = this._getCacheKey(`will:${client.clientId}`);
431
+ this._cache.delete(key);
432
+
433
+ if (callback) callback(null);
434
+ } catch (error) {
435
+ if (callback) callback(error);
436
+ }
437
+ };
438
+
439
+ /**
440
+ * 获取遗嘱消息
441
+ * @param {object} client - 客户端对象
442
+ * @param {Function} callback - 回调函数
443
+ */
444
+ Persist.prototype.getWill = function(client, callback) {
445
+ try {
446
+ if (!client || !client.clientId) {
447
+ throw new Error('无效的客户端对象');
448
+ }
449
+
450
+ let key = this._getCacheKey(`will:${client.clientId}`);
451
+ let will = this._cache.get(key);
452
+
453
+ if (callback) callback(null, will);
454
+ } catch (error) {
455
+ if (callback) callback(error);
456
+ }
457
+ };
458
+
459
+ // ------------------- 离线消息 -------------------
460
+
461
+ /**
462
+ * 存储离线消息
463
+ * @param {object} client - 客户端对象
464
+ * @param {object} packet - MQTT消息包
465
+ * @param {Function} callback - 回调函数
466
+ */
467
+ Persist.prototype.storeOfflinePacket = function(client, packet, callback) {
468
+ try {
469
+ if (!client || !client.clientId) {
470
+ throw new Error('无效的客户端对象');
471
+ }
472
+
473
+ if (!packet || !packet.msgId) {
474
+ throw new Error('无效的消息包');
475
+ }
476
+
477
+ let key = this._getCacheKey(`offline:${client.clientId}:${packet.msgId}`);
478
+ this._cache.set(key, packet, this.config.ttl);
479
+
480
+ if (callback) callback(null);
481
+ } catch (error) {
482
+ if (callback) callback(error);
483
+ }
484
+ };
485
+
486
+ /**
487
+ * 获取客户端的所有离线消息
488
+ * @param {object} client - 客户端对象
489
+ * @param {Function} callback - 回调函数
490
+ */
491
+ Persist.prototype.getOfflinePackets = function(client, callback) {
492
+ try {
493
+ if (!client || !client.clientId) {
494
+ throw new Error('无效的客户端对象');
495
+ }
496
+
497
+ let pattern = `offline:${client.clientId}:*`;
498
+ let keys = this._getKeysByPattern(pattern);
499
+
500
+ // 同步执行所有获取操作
501
+ let packets = keys.map(key => {
502
+ let packet = this._cache.get(this._getCacheKey(key));
503
+ return packet;
504
+ }).filter(Boolean);
505
+
506
+ if (callback) callback(null, packets);
507
+ } catch (error) {
508
+ if (callback) callback(error);
509
+ }
510
+ };
511
+
512
+ // ------------------- 流式恢复(重要!) -------------------
513
+
514
+ /**
515
+ * 处理保留消息
516
+ * @private
517
+ * @param {object} self 当前实例
518
+ * @param {object} stream 可读流
519
+ */
520
+ Persist.prototype._procRetainMsgs = function(self, stream) {
521
+ let keys = self._getKeysByPattern('retained:*');
522
+ let msgs = keys.map(key => {
523
+ let packet = self._cache.get(self._getCacheKey(key));
524
+ if (packet) {
525
+ return {
526
+ type: 'retained',
527
+ topic: packet.topic,
528
+ payload: packet.payload,
529
+ qos: packet.qos,
530
+ retain: packet.retain
531
+ };
532
+ }
533
+ return null;
534
+ }).filter(Boolean);
535
+ msgs.forEach(msg => {
536
+ stream.push(msg);
537
+ });
538
+ };
539
+
540
+ /**
541
+ * 处理订阅信息
542
+ * @private
543
+ * @param {object} self 当前实例
544
+ * @param {object} stream 可读流
545
+ */
546
+ Persist.prototype._procSubs = function(self, stream) {
547
+ let keys = self._getKeysByPattern('subscription:*:*');
548
+ let subs = keys.map(key => {
549
+ let parts = key.split(':');
550
+ if (parts.length >= 3) {
551
+ let cid = parts[1];
552
+ let sub = self._cache.get(self._getCacheKey(key));
553
+ if (sub) {
554
+ return {
555
+ type: 'subscription',
556
+ client_id: cid,
557
+ sub: sub
558
+ };
559
+ }
560
+ }
561
+ return null;
562
+ }).filter(Boolean);
563
+ subs.forEach(sub => {
564
+ stream.push(sub);
565
+ });
566
+ };
567
+
568
+ /**
569
+ * 处理遗嘱消息
570
+ * @private
571
+ * @param {object} self 当前实例
572
+ * @param {object} stream 可读流
573
+ */
574
+ Persist.prototype._procWills = function(self, stream) {
575
+ let keys = self._getKeysByPattern('will:*');
576
+ let wills = keys.map(key => {
577
+ let parts = key.split(':');
578
+ if (parts.length >= 2) {
579
+ let cid = parts[1];
580
+ let will = self._cache.get(self._getCacheKey(key));
581
+ if (will) {
582
+ return {
583
+ type: 'will',
584
+ client_id: cid,
585
+ will: will
586
+ };
587
+ }
588
+ }
589
+ return null;
590
+ }).filter(Boolean);
591
+ wills.forEach(will => {
592
+ stream.push(will);
593
+ });
594
+ };
595
+
596
+ /**
597
+ * 处理传输中消息
598
+ * @private
599
+ * @param {object} self 当前实例
600
+ * @param {object} stream 可读流
601
+ */
602
+ Persist.prototype._procInflightMsgs = function(self, stream) {
603
+ let keys = self._getKeysByPattern('packet:*:*');
604
+ let packets = keys.map(key => {
605
+ let parts = key.split(':');
606
+ if (parts.length >= 3) {
607
+ let cid = parts[1];
608
+ let packet = self._cache.get(self._getCacheKey(key));
609
+ if (packet) {
610
+ return {
611
+ type: 'inflight',
612
+ client_id: cid,
613
+ packet: packet
614
+ };
615
+ }
616
+ }
617
+ return null;
618
+ }).filter(Boolean);
619
+ packets.forEach(packet => {
620
+ stream.push(packet);
621
+ });
622
+ };
623
+
624
+ /**
625
+ * 创建可读流,用于恢复Aedes状态
626
+ * @returns {Readable} 可读流
627
+ */
628
+ Persist.prototype.createStream = function() {
629
+ let self = this;
630
+
631
+ return new Readable({
632
+ obj_mode: true,
633
+
634
+ read() {
635
+ try {
636
+ // 处理保留消息
637
+ self._procRetainMsgs(self, this);
638
+
639
+ // 处理订阅信息
640
+ self._procSubs(self, this);
641
+
642
+ // 处理遗嘱消息
643
+ self._procWills(self, this);
644
+
645
+ // 处理传输中消息
646
+ self._procInflightMsgs(self, this);
647
+
648
+ // 结束流
649
+ this.push(null);
650
+ } catch (error) {
651
+ self._cache.log && self._cache.log('error', '创建恢复流时出错:', error);
652
+ this.push(null);
653
+ }
654
+ }
655
+ });
656
+ };
657
+
658
+ module.exports = {
659
+ Persist
660
+ };