sa2kit 1.6.30 → 1.6.31

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 (237) hide show
  1. package/dist/AliyunOSSProvider-P6TOVKMM.mjs +6 -0
  2. package/dist/{AliyunOSSProvider-KJYRIZES.mjs.map → AliyunOSSProvider-P6TOVKMM.mjs.map} +1 -1
  3. package/dist/AliyunOSSProvider-Z5BRBCG6.js +15 -0
  4. package/dist/{AliyunOSSProvider-FWAKUB2T.js.map → AliyunOSSProvider-Z5BRBCG6.js.map} +1 -1
  5. package/dist/ConfigService-3DIC6C3Q.js +21 -0
  6. package/dist/{ConfigService-7MEZXKJ5.js.map → ConfigService-3DIC6C3Q.js.map} +1 -1
  7. package/dist/ConfigService-V6ZK273Z.mjs +4 -0
  8. package/dist/{ConfigService-BV57YYFW.mjs.map → ConfigService-V6ZK273Z.mjs.map} +1 -1
  9. package/dist/LocalStorageProvider-3RVPCQB3.mjs +6 -0
  10. package/dist/{LocalStorageProvider-RTPMUOZ2.mjs.map → LocalStorageProvider-3RVPCQB3.mjs.map} +1 -1
  11. package/dist/LocalStorageProvider-PP7MA5OT.js +15 -0
  12. package/dist/{LocalStorageProvider-XSRCUXOU.js.map → LocalStorageProvider-PP7MA5OT.js.map} +1 -1
  13. package/dist/PMXParser-2VTA737I.js +13 -0
  14. package/dist/{PMXParser-YBS3B6HM.js.map → PMXParser-2VTA737I.js.map} +1 -1
  15. package/dist/PMXParser-RNVQL76A.mjs +4 -0
  16. package/dist/{PMXParser-L6IWHL4I.mjs.map → PMXParser-RNVQL76A.mjs.map} +1 -1
  17. package/dist/analytics/index.js +46 -45
  18. package/dist/analytics/index.js.map +1 -1
  19. package/dist/analytics/index.mjs +45 -44
  20. package/dist/analytics/index.mjs.map +1 -1
  21. package/dist/analytics/server/index.js +4 -4
  22. package/dist/analytics/server/index.js.map +1 -1
  23. package/dist/analytics/server/index.mjs +4 -4
  24. package/dist/analytics/server/index.mjs.map +1 -1
  25. package/dist/api/index.js +5 -5
  26. package/dist/api/index.js.map +1 -1
  27. package/dist/api/index.mjs +5 -5
  28. package/dist/api/index.mjs.map +1 -1
  29. package/dist/audioDetection/index.js +17 -16
  30. package/dist/audioDetection/index.js.map +1 -1
  31. package/dist/audioDetection/index.mjs +17 -16
  32. package/dist/audioDetection/index.mjs.map +1 -1
  33. package/dist/auth/client/index.js +4 -4
  34. package/dist/auth/client/index.mjs +1 -1
  35. package/dist/auth/components/index.js +3 -3
  36. package/dist/auth/components/index.js.map +1 -1
  37. package/dist/auth/components/index.mjs +3 -3
  38. package/dist/auth/components/index.mjs.map +1 -1
  39. package/dist/auth/index.js +29 -29
  40. package/dist/auth/index.mjs +5 -5
  41. package/dist/auth/middleware/index.js +3 -3
  42. package/dist/auth/middleware/index.mjs +2 -2
  43. package/dist/auth/routes/index.js +14 -14
  44. package/dist/auth/routes/index.mjs +2 -2
  45. package/dist/auth/services/index.js +7 -7
  46. package/dist/auth/services/index.mjs +1 -1
  47. package/dist/calendar/index.js +146 -182
  48. package/dist/calendar/index.js.map +1 -1
  49. package/dist/calendar/index.mjs +139 -175
  50. package/dist/calendar/index.mjs.map +1 -1
  51. package/dist/calendar/routes/index.js +1 -1
  52. package/dist/calendar/routes/index.js.map +1 -1
  53. package/dist/calendar/routes/index.mjs +1 -1
  54. package/dist/calendar/routes/index.mjs.map +1 -1
  55. package/dist/{chunk-5YQ5B7IZ.js → chunk-24HGREE6.js} +5 -5
  56. package/dist/{chunk-5YQ5B7IZ.js.map → chunk-24HGREE6.js.map} +1 -1
  57. package/dist/{chunk-6PRFP5EG.js → chunk-25OFOKNF.js} +6 -6
  58. package/dist/chunk-25OFOKNF.js.map +1 -0
  59. package/dist/{chunk-KQGP6BTS.mjs → chunk-3DXPQ4YV.mjs} +6 -6
  60. package/dist/chunk-3DXPQ4YV.mjs.map +1 -0
  61. package/dist/{chunk-3BGPZN4X.mjs → chunk-3NHAT7D4.mjs} +12 -12
  62. package/dist/chunk-3NHAT7D4.mjs.map +1 -0
  63. package/dist/{chunk-MW4BCIZC.mjs → chunk-4HC6M7FK.mjs} +3 -3
  64. package/dist/chunk-4HC6M7FK.mjs.map +1 -0
  65. package/dist/{chunk-ESRCX5TQ.mjs → chunk-52TN2QSS.mjs} +3 -3
  66. package/dist/{chunk-ESRCX5TQ.mjs.map → chunk-52TN2QSS.mjs.map} +1 -1
  67. package/dist/{chunk-DW2ZTOCV.js → chunk-5A7ERLKK.js} +105 -106
  68. package/dist/chunk-5A7ERLKK.js.map +1 -0
  69. package/dist/{chunk-CNTILN5J.mjs → chunk-5YQ62BKX.mjs} +20 -19
  70. package/dist/chunk-5YQ62BKX.mjs.map +1 -0
  71. package/dist/{chunk-6W5BMXJG.js → chunk-6OWNMJKG.js} +4 -4
  72. package/dist/{chunk-6W5BMXJG.js.map → chunk-6OWNMJKG.js.map} +1 -1
  73. package/dist/{chunk-TV3VKRJK.mjs → chunk-77M5AQG3.mjs} +37 -37
  74. package/dist/chunk-77M5AQG3.mjs.map +1 -0
  75. package/dist/{chunk-DUHZ7VZP.js → chunk-7VRT55ZD.js} +3 -3
  76. package/dist/chunk-7VRT55ZD.js.map +1 -0
  77. package/dist/{chunk-LX4XX6W7.js → chunk-C54W2CMK.js} +16 -16
  78. package/dist/chunk-C54W2CMK.js.map +1 -0
  79. package/dist/{chunk-3WOAPLEG.mjs → chunk-EB4NR623.mjs} +27 -26
  80. package/dist/chunk-EB4NR623.mjs.map +1 -0
  81. package/dist/{chunk-CD77U7LZ.js → chunk-GBPLX42J.js} +9 -9
  82. package/dist/chunk-GBPLX42J.js.map +1 -0
  83. package/dist/{chunk-TFQF2HDO.mjs → chunk-HDEOCX2L.mjs} +12 -12
  84. package/dist/chunk-HDEOCX2L.mjs.map +1 -0
  85. package/dist/{chunk-LFG6FPM5.mjs → chunk-KIP2CERU.mjs} +37 -38
  86. package/dist/chunk-KIP2CERU.mjs.map +1 -0
  87. package/dist/{chunk-6YKMCPQI.mjs → chunk-KZKIH4AS.mjs} +4 -4
  88. package/dist/chunk-KZKIH4AS.mjs.map +1 -0
  89. package/dist/{chunk-6MQUBPKB.mjs → chunk-LJ4CCSSY.mjs} +3 -3
  90. package/dist/{chunk-6MQUBPKB.mjs.map → chunk-LJ4CCSSY.mjs.map} +1 -1
  91. package/dist/{chunk-TOC5FSHP.js → chunk-NJ2SNXBJ.js} +12 -12
  92. package/dist/chunk-NJ2SNXBJ.js.map +1 -0
  93. package/dist/{chunk-OCR5DS4C.mjs → chunk-PE5EAHZK.mjs} +3 -3
  94. package/dist/chunk-PE5EAHZK.mjs.map +1 -0
  95. package/dist/{chunk-LZHMNOED.js → chunk-Q5EDCKQA.js} +26 -26
  96. package/dist/chunk-Q5EDCKQA.js.map +1 -0
  97. package/dist/{chunk-CLKKZSPZ.js → chunk-RBKGYWME.js} +20 -19
  98. package/dist/chunk-RBKGYWME.js.map +1 -0
  99. package/dist/{chunk-VRTRSEEH.mjs → chunk-RSJSZ7QH.mjs} +11 -11
  100. package/dist/chunk-RSJSZ7QH.mjs.map +1 -0
  101. package/dist/{chunk-E7RGBAYJ.js → chunk-TDCDEBGP.js} +30 -29
  102. package/dist/chunk-TDCDEBGP.js.map +1 -0
  103. package/dist/{chunk-T5OZHYVM.mjs → chunk-TVROG2Q4.mjs} +15 -15
  104. package/dist/chunk-TVROG2Q4.mjs.map +1 -0
  105. package/dist/{chunk-JZXJQMVE.js → chunk-UIFFDRTE.js} +11 -11
  106. package/dist/chunk-UIFFDRTE.js.map +1 -0
  107. package/dist/{chunk-UOFTHYIH.js → chunk-UL6XJGUZ.js} +4 -4
  108. package/dist/chunk-UL6XJGUZ.js.map +1 -0
  109. package/dist/{chunk-A3UP56MS.js → chunk-WA67GZSZ.js} +3 -3
  110. package/dist/chunk-WA67GZSZ.js.map +1 -0
  111. package/dist/{chunk-OLHGZXN3.mjs → chunk-WEEXCPSE.mjs} +5 -5
  112. package/dist/chunk-WEEXCPSE.mjs.map +1 -0
  113. package/dist/{chunk-OPPF3326.js → chunk-X3UU7JHT.js} +38 -38
  114. package/dist/chunk-X3UU7JHT.js.map +1 -0
  115. package/dist/{chunk-QU5OT4DF.js → chunk-XJ7ZAGC5.js} +5 -5
  116. package/dist/chunk-XJ7ZAGC5.js.map +1 -0
  117. package/dist/{chunk-ZI25QCHD.mjs → chunk-YOTQG4NP.mjs} +25 -25
  118. package/dist/chunk-YOTQG4NP.mjs.map +1 -0
  119. package/dist/{chunk-QAT2RWAO.mjs → chunk-Z36R3P62.mjs} +7 -7
  120. package/dist/chunk-Z36R3P62.mjs.map +1 -0
  121. package/dist/{chunk-7Z5LLJ3A.js → chunk-ZWQJSZEY.js} +13 -13
  122. package/dist/chunk-ZWQJSZEY.js.map +1 -0
  123. package/dist/config/index.js +6 -6
  124. package/dist/config/index.js.map +1 -1
  125. package/dist/config/index.mjs +6 -6
  126. package/dist/config/index.mjs.map +1 -1
  127. package/dist/config/server/index.js +37 -37
  128. package/dist/config/server/index.js.map +1 -1
  129. package/dist/config/server/index.mjs +37 -37
  130. package/dist/config/server/index.mjs.map +1 -1
  131. package/dist/i18n/index.d.mts +2 -2
  132. package/dist/i18n/index.d.ts +2 -2
  133. package/dist/i18n/index.js +16 -17
  134. package/dist/i18n/index.js.map +1 -1
  135. package/dist/i18n/index.mjs +16 -17
  136. package/dist/i18n/index.mjs.map +1 -1
  137. package/dist/imageCrop/index.js +11 -10
  138. package/dist/imageCrop/index.js.map +1 -1
  139. package/dist/imageCrop/index.mjs +11 -10
  140. package/dist/imageCrop/index.mjs.map +1 -1
  141. package/dist/index.js +221 -246
  142. package/dist/index.js.map +1 -1
  143. package/dist/index.mjs +79 -104
  144. package/dist/index.mjs.map +1 -1
  145. package/dist/logger/index.js +6 -6
  146. package/dist/logger/index.mjs +1 -1
  147. package/dist/mmd/admin/index.js +11 -10
  148. package/dist/mmd/admin/index.js.map +1 -1
  149. package/dist/mmd/admin/index.mjs +11 -10
  150. package/dist/mmd/admin/index.mjs.map +1 -1
  151. package/dist/mmd/index.js +223 -241
  152. package/dist/mmd/index.js.map +1 -1
  153. package/dist/mmd/index.mjs +220 -238
  154. package/dist/mmd/index.mjs.map +1 -1
  155. package/dist/mmd/server/index.js +6 -6
  156. package/dist/mmd/server/index.js.map +1 -1
  157. package/dist/mmd/server/index.mjs +6 -6
  158. package/dist/mmd/server/index.mjs.map +1 -1
  159. package/dist/music/index.js +16 -16
  160. package/dist/music/index.mjs +2 -2
  161. package/dist/music/server/index.js +8 -8
  162. package/dist/music/server/index.mjs +1 -1
  163. package/dist/request/index.js +2 -2
  164. package/dist/request/index.js.map +1 -1
  165. package/dist/request/index.mjs +2 -2
  166. package/dist/request/index.mjs.map +1 -1
  167. package/dist/storage/index.js +11 -11
  168. package/dist/storage/index.mjs +2 -2
  169. package/dist/testYourself/admin/index.js +3 -3
  170. package/dist/testYourself/admin/index.mjs +1 -1
  171. package/dist/testYourself/index.js +22 -22
  172. package/dist/testYourself/index.js.map +1 -1
  173. package/dist/testYourself/index.mjs +14 -14
  174. package/dist/testYourself/index.mjs.map +1 -1
  175. package/dist/testYourself/server/index.js +4 -4
  176. package/dist/testYourself/server/index.mjs +1 -1
  177. package/dist/universalExport/index.d.mts +3 -3
  178. package/dist/universalExport/index.d.ts +3 -3
  179. package/dist/universalExport/index.js +48 -47
  180. package/dist/universalExport/index.js.map +1 -1
  181. package/dist/universalExport/index.mjs +48 -47
  182. package/dist/universalExport/index.mjs.map +1 -1
  183. package/dist/universalExport/server/index.js +29 -29
  184. package/dist/universalExport/server/index.js.map +1 -1
  185. package/dist/universalExport/server/index.mjs +28 -28
  186. package/dist/universalExport/server/index.mjs.map +1 -1
  187. package/dist/universalFile/index.d.mts +3 -3
  188. package/dist/universalFile/index.d.ts +3 -3
  189. package/dist/universalFile/index.js +73 -72
  190. package/dist/universalFile/index.js.map +1 -1
  191. package/dist/universalFile/index.mjs +73 -72
  192. package/dist/universalFile/index.mjs.map +1 -1
  193. package/dist/universalFile/server/index.js +258 -260
  194. package/dist/universalFile/server/index.js.map +1 -1
  195. package/dist/universalFile/server/index.mjs +244 -246
  196. package/dist/universalFile/server/index.mjs.map +1 -1
  197. package/dist/utils/index.js +11 -11
  198. package/dist/utils/index.mjs +2 -2
  199. package/package.json +1 -1
  200. package/dist/AliyunOSSProvider-FWAKUB2T.js +0 -15
  201. package/dist/AliyunOSSProvider-KJYRIZES.mjs +0 -6
  202. package/dist/ConfigService-7MEZXKJ5.js +0 -21
  203. package/dist/ConfigService-BV57YYFW.mjs +0 -4
  204. package/dist/LocalStorageProvider-RTPMUOZ2.mjs +0 -6
  205. package/dist/LocalStorageProvider-XSRCUXOU.js +0 -15
  206. package/dist/PMXParser-L6IWHL4I.mjs +0 -4
  207. package/dist/PMXParser-YBS3B6HM.js +0 -13
  208. package/dist/chunk-3BGPZN4X.mjs.map +0 -1
  209. package/dist/chunk-3WOAPLEG.mjs.map +0 -1
  210. package/dist/chunk-6PRFP5EG.js.map +0 -1
  211. package/dist/chunk-6YKMCPQI.mjs.map +0 -1
  212. package/dist/chunk-7Z5LLJ3A.js.map +0 -1
  213. package/dist/chunk-A3UP56MS.js.map +0 -1
  214. package/dist/chunk-CD77U7LZ.js.map +0 -1
  215. package/dist/chunk-CLKKZSPZ.js.map +0 -1
  216. package/dist/chunk-CNTILN5J.mjs.map +0 -1
  217. package/dist/chunk-DUHZ7VZP.js.map +0 -1
  218. package/dist/chunk-DW2ZTOCV.js.map +0 -1
  219. package/dist/chunk-E7RGBAYJ.js.map +0 -1
  220. package/dist/chunk-JZXJQMVE.js.map +0 -1
  221. package/dist/chunk-KQGP6BTS.mjs.map +0 -1
  222. package/dist/chunk-LFG6FPM5.mjs.map +0 -1
  223. package/dist/chunk-LX4XX6W7.js.map +0 -1
  224. package/dist/chunk-LZHMNOED.js.map +0 -1
  225. package/dist/chunk-MW4BCIZC.mjs.map +0 -1
  226. package/dist/chunk-OCR5DS4C.mjs.map +0 -1
  227. package/dist/chunk-OLHGZXN3.mjs.map +0 -1
  228. package/dist/chunk-OPPF3326.js.map +0 -1
  229. package/dist/chunk-QAT2RWAO.mjs.map +0 -1
  230. package/dist/chunk-QU5OT4DF.js.map +0 -1
  231. package/dist/chunk-T5OZHYVM.mjs.map +0 -1
  232. package/dist/chunk-TFQF2HDO.mjs.map +0 -1
  233. package/dist/chunk-TOC5FSHP.js.map +0 -1
  234. package/dist/chunk-TV3VKRJK.mjs.map +0 -1
  235. package/dist/chunk-UOFTHYIH.js.map +0 -1
  236. package/dist/chunk-VRTRSEEH.mjs.map +0 -1
  237. package/dist/chunk-ZI25QCHD.mjs.map +0 -1
@@ -83,7 +83,7 @@ var defaultNormalizer = (value) => {
83
83
  if (value.startsWith("http://") || value.startsWith("https://")) {
84
84
  return value;
85
85
  }
86
- return value.startsWith("/") ? value : `/${value}`;
86
+ return value.startsWith("/") ? value : "/" + value;
87
87
  };
88
88
  function buildMmdPlaylistFromSources(options) {
89
89
  if (!options.models.length) {
@@ -114,7 +114,7 @@ function buildMmdPlaylistFromSources(options) {
114
114
  });
115
115
  return {
116
116
  id: options.playlistId,
117
- name: options.playlistName ?? `MMD \u64AD\u653E\u5217\u8868 - ${options.playlistId}`,
117
+ name: options.playlistName ?? "MMD \u64AD\u653E\u5217\u8868 - " + options.playlistId,
118
118
  nodes,
119
119
  loop: options.loop ?? true,
120
120
  preload: options.preload ?? "next",
@@ -135,14 +135,14 @@ var MMD_FILE_EXTENSIONS = {
135
135
  };
136
136
  async function uploadMmdResource(fileService, options) {
137
137
  const { file, resourceType, name, description, userId } = options;
138
- const ext = `.${file.name.split(".").pop()?.toLowerCase()}`;
138
+ const ext = "." + file.name.split(".").pop()?.toLowerCase();
139
139
  const allowedExtensions = MMD_FILE_EXTENSIONS[resourceType];
140
140
  if (!allowedExtensions.includes(ext)) {
141
141
  throw new Error(
142
- `\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u6269\u5C55\u540D: ${ext}\u3002\u652F\u6301\u7684\u683C\u5F0F: ${allowedExtensions.join(", ")}`
142
+ "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u6269\u5C55\u540D: " + ext + "\u3002\u652F\u6301\u7684\u683C\u5F0F: " + allowedExtensions.join(", ")
143
143
  );
144
144
  }
145
- const moduleId = `mmd-${resourceType}s`;
145
+ const moduleId = "mmd-" + resourceType + "s";
146
146
  const metadata = await fileService.uploadFile({
147
147
  file,
148
148
  moduleId,
@@ -203,7 +203,7 @@ async function batchUploadMmdResources(fileService, uploads) {
203
203
  const result = await uploadMmdResource(fileService, uploadOptions);
204
204
  results.push(result);
205
205
  } catch (error) {
206
- console.error(`\u4E0A\u4F20\u5931\u8D25: ${uploadOptions.file.name}`, error);
206
+ console.error("\u4E0A\u4F20\u5931\u8D25: " + uploadOptions.file.name, error);
207
207
  }
208
208
  }
209
209
  return results;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/mmd/server/modelArchive.ts","../../../src/mmd/server/playlistBuilder.ts","../../../src/mmd/server/mmdUpload.ts"],"names":["randomUUID","path","mkdir","AdmZip","rm","writeFile"],"mappings":"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","file":"index.js","sourcesContent":["import AdmZip from 'adm-zip';\nimport { randomUUID } from 'crypto';\nimport { mkdir, rm, writeFile } from 'fs/promises';\nimport path from 'path';\n\nexport type SupportedModelFormat = 'pmx' | 'pmd';\n\nexport interface ProcessMmdModelArchiveOptions {\n /**\n * 绝对路径,指向模型解压根目录,例如 /app/uploads/mmd/models\n */\n storageRoot: string;\n /**\n * 对外暴露的公共路径前缀,例如 /uploads/mmd/models\n * 默认与 storageRoot 中的叶子目录一致\n */\n publicRoot?: string;\n /**\n * 自定义文件夹名称,默认使用随机 UUID\n */\n folderName?: string;\n}\n\nexport interface ProcessMmdModelArchiveResult {\n /** 解压出来的目录(绝对路径) */\n directory: string;\n /** 与 storageRoot 相对的目录名 */\n relativeDirectory: string;\n /** 模型文件相对目录(包含子目录) */\n modelRelativePath: string;\n /** 可供前端使用的模型 URL */\n modelUrl: string;\n /** 模型格式 */\n format: SupportedModelFormat;\n /** 解压得到的文件数量 */\n filesExtracted: number;\n}\n\nexport const MMD_MODEL_ARCHIVE_MIME_TYPES = [\n 'application/zip',\n 'application/x-zip-compressed',\n 'multipart/x-zip',\n] as const;\n\n/**\n * 解析上传的 MMD 模型压缩包,保留目录结构并返回模型路径\n */\nexport async function processMmdModelArchive(\n buffer: Buffer,\n options: ProcessMmdModelArchiveOptions,\n): Promise<ProcessMmdModelArchiveResult> {\n const folderName = options.folderName ?? randomUUID();\n const targetDir = path.join(options.storageRoot, folderName);\n await mkdir(targetDir, { recursive: true });\n\n const zip = new AdmZip(buffer);\n const entries = zip.getEntries();\n if (!entries.length) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包为空,请检查上传文件内容');\n }\n\n let modelRelativePath: string | null = null;\n let filesExtracted = 0;\n\n for (const entry of entries) {\n if (!entry.entryName || entry.entryName.startsWith('__MACOSX') || entry.entryName.endsWith('.DS_Store')) {\n continue;\n }\n\n const safeRelativePath = sanitizeEntryPath(entry.entryName);\n if (!safeRelativePath) {\n continue;\n }\n\n const destinationPath = path.join(targetDir, safeRelativePath);\n\n if (entry.isDirectory) {\n await mkdir(destinationPath, { recursive: true });\n continue;\n }\n\n await mkdir(path.dirname(destinationPath), { recursive: true });\n await writeFile(destinationPath, entry.getData());\n filesExtracted += 1;\n\n const entryExt = path.extname(safeRelativePath).toLowerCase();\n if (!modelRelativePath && (entryExt === '.pmx' || entryExt === '.pmd')) {\n modelRelativePath = safeRelativePath.split(path.sep).join('/');\n }\n }\n\n if (!modelRelativePath) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包中未找到 PMX/PMD 模型文件,请确认目录结构是否正确');\n }\n\n const format = path.extname(modelRelativePath).slice(1).toLowerCase() as SupportedModelFormat;\n const publicRoot = options.publicRoot ?? `/uploads/mmd/models`;\n const modelUrl = joinPublicPath(publicRoot, folderName, modelRelativePath);\n\n return {\n directory: targetDir,\n relativeDirectory: folderName,\n modelRelativePath,\n modelUrl,\n format,\n filesExtracted,\n };\n}\n\nfunction sanitizeEntryPath(entryName: string): string | null {\n const normalized = path.normalize(entryName).replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\n if (!normalized || normalized === '.' || normalized.startsWith('..') || path.isAbsolute(normalized)) {\n return null;\n }\n return normalized;\n}\n\nfunction joinPublicPath(...segments: string[]) {\n return segments\n .map((segment) => segment.replace(/\\/+/g, '/').replace(/^\\//, '').replace(/\\/$/, ''))\n .filter(Boolean)\n .join('/')\n .replace(/\\/{2,}/g, '/')\n .replace(/^/, '/');\n}\n\n","import type { MMDPlaylistConfig, MMDPlaylistNode } from '../types';\n\nexport interface PlaylistModelSource {\n id: string | number;\n name: string;\n filePath: string;\n thumbnailPath?: string | null;\n}\n\nexport interface PlaylistMotionSource {\n id: string | number;\n name?: string;\n filePath: string;\n}\n\nexport interface BuildMmdPlaylistOptions {\n playlistId: string;\n playlistName?: string;\n models: PlaylistModelSource[];\n motions?: PlaylistMotionSource[];\n limit?: number;\n loop?: boolean;\n preload?: 'none' | 'next' | 'all';\n autoPlay?: boolean;\n nodeDuration?: number;\n normalizeUrl?: (pathOrUrl: string) => string;\n}\n\nconst defaultNormalizer = (value: string) => {\n if (!value) return '';\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return value;\n }\n return value.startsWith('/') ? value : `/${value}`;\n};\n\n/**\n * 根据数据库中的模型/动作记录快速构建 MMDPlaylistConfig\n */\nexport function buildMmdPlaylistFromSources(options: BuildMmdPlaylistOptions): MMDPlaylistConfig {\n if (!options.models.length) {\n throw new Error('构建 MMD 播放列表失败:models 为空');\n }\n\n const limit = Math.max(1, Math.min(options.limit ?? options.models.length, options.models.length));\n const normalizeUrl = options.normalizeUrl ?? defaultNormalizer;\n const motions = options.motions ?? [];\n const hasMotions = motions.length > 0;\n const duration = options.nodeDuration ?? 30;\n\n const nodes: MMDPlaylistNode[] = options.models.slice(0, limit).map((model, index) => {\n const motion = hasMotions ? motions[index % motions.length] : undefined;\n return {\n id: String(model.id ?? index),\n name: model.name,\n loop: options.loop ?? true,\n duration,\n thumbnail: model.thumbnailPath ? normalizeUrl(model.thumbnailPath) : undefined,\n resources: {\n modelPath: normalizeUrl(model.filePath),\n motionPath: motion ? normalizeUrl(motion.filePath) : undefined,\n cameraPath: undefined,\n audioPath: undefined,\n stageModelPath: undefined,\n additionalMotions: undefined,\n },\n };\n });\n\n return {\n id: options.playlistId,\n name: options.playlistName ?? `MMD 播放列表 - ${options.playlistId}`,\n nodes,\n loop: options.loop ?? true,\n preload: options.preload ?? 'next',\n autoPlay: options.autoPlay ?? true,\n };\n}\n\n","/**\n * MMD 资源上传辅助函数\n * \n * 整合 UniversalFileService 用于 MMD 资源上传\n */\n\nimport type { UniversalFileService } from '../../universalFile/server/UniversalFileService';\nimport type { FileMetadata } from '../../universalFile/types';\nimport { processMmdModelArchive, MMD_MODEL_ARCHIVE_MIME_TYPES } from './modelArchive';\n\nexport const MMD_SUPPORTED_TYPES = {\n model: [...MMD_MODEL_ARCHIVE_MIME_TYPES],\n animation: ['application/octet-stream', 'animation/vmd'],\n audio: ['audio/wav', 'audio/mp3', 'audio/mpeg', 'audio/ogg'],\n};\n\nexport const MMD_FILE_EXTENSIONS = {\n model: ['.zip'],\n animation: ['.vmd'],\n audio: ['.wav', '.mp3', '.ogg'],\n};\n\nexport interface MmdUploadOptions {\n file: File;\n resourceType: 'model' | 'animation' | 'audio';\n name: string;\n description?: string;\n userId: string;\n}\n\nexport interface MmdUploadResult {\n id: string;\n name: string;\n url: string;\n filePath: string;\n fileSize: number;\n type: string;\n format: string;\n uploadTime: Date;\n metadata?: FileMetadata;\n}\n\n/**\n * 使用 UniversalFileService 上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果\n */\nexport async function uploadMmdResource(\n fileService: UniversalFileService,\n options: MmdUploadOptions\n): Promise<MmdUploadResult> {\n const { file, resourceType, name, description, userId } = options;\n\n // 验证文件扩展名\n const ext = `.${file.name.split('.').pop()?.toLowerCase()}`;\n const allowedExtensions = MMD_FILE_EXTENSIONS[resourceType];\n\n if (!allowedExtensions.includes(ext)) {\n throw new Error(\n `不支持的文件扩展名: ${ext}。支持的格式: ${allowedExtensions.join(', ')}`\n );\n }\n\n // 确定模块ID\n const moduleId = `mmd-${resourceType}s`;\n\n // 上传文件\n const metadata = await fileService.uploadFile({\n file,\n moduleId,\n businessId: 'default',\n permission: 'public',\n metadata: {\n uploadedBy: userId,\n uploadedAt: new Date().toISOString(),\n originalFileName: file.name,\n resourceType,\n name,\n description: description || '',\n },\n needsProcessing: false,\n });\n\n // 构建返回结果\n const format = ext.slice(1).toUpperCase();\n const fileUrl = metadata.cdnUrl || metadata.storagePath;\n\n return {\n id: metadata.id,\n name,\n url: fileUrl,\n filePath: metadata.storagePath,\n fileSize: metadata.size,\n type: resourceType,\n format,\n uploadTime: metadata.uploadTime,\n metadata,\n };\n}\n\n/**\n * 上传 MMD 模型 (ZIP 压缩包)\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果,包含解压后的模型路径\n */\nexport async function uploadMmdModel(\n fileService: UniversalFileService,\n options: MmdUploadOptions & { storageRoot: string; publicRoot: string }\n): Promise<MmdUploadResult & { extractedPath?: string }> {\n const { file, storageRoot, publicRoot } = options;\n\n // 首先上传 ZIP 文件\n const baseResult = await uploadMmdResource(fileService, options);\n\n // 处理 ZIP 压缩包\n try {\n const fileBuffer = Buffer.from(await file.arrayBuffer());\n const archiveResult = await processMmdModelArchive(fileBuffer, {\n storageRoot,\n publicRoot,\n folderName: baseResult.id,\n });\n\n return {\n ...baseResult,\n url: archiveResult.modelUrl,\n filePath: archiveResult.modelUrl,\n format: archiveResult.format.toUpperCase(),\n extractedPath: archiveResult.modelUrl,\n };\n } catch (extractError) {\n console.error('模型压缩包处理失败:', extractError);\n throw new Error(\n extractError instanceof Error ? extractError.message : '模型压缩包处理失败'\n );\n }\n}\n\n/**\n * 批量上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param uploads - 上传选项数组\n * @returns 上传结果数组\n */\nexport async function batchUploadMmdResources(\n fileService: UniversalFileService,\n uploads: MmdUploadOptions[]\n): Promise<MmdUploadResult[]> {\n const results: MmdUploadResult[] = [];\n\n for (const uploadOptions of uploads) {\n try {\n const result = await uploadMmdResource(fileService, uploadOptions);\n results.push(result);\n } catch (error) {\n console.error(`上传失败: ${uploadOptions.file.name}`, error);\n // 继续处理其他文件\n }\n }\n\n return results;\n}\n\n"]}
1
+ {"version":3,"sources":["../../../src/mmd/server/modelArchive.ts","../../../src/mmd/server/playlistBuilder.ts","../../../src/mmd/server/mmdUpload.ts"],"names":["randomUUID","path","mkdir","AdmZip","rm","writeFile"],"mappings":"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","file":"index.js","sourcesContent":["import AdmZip from 'adm-zip';\nimport { randomUUID } from 'crypto';\nimport { mkdir, rm, writeFile } from 'fs/promises';\nimport path from 'path';\n\nexport type SupportedModelFormat = 'pmx' | 'pmd';\n\nexport interface ProcessMmdModelArchiveOptions {\n /**\n * 绝对路径,指向模型解压根目录,例如 /app/uploads/mmd/models\n */\n storageRoot: string;\n /**\n * 对外暴露的公共路径前缀,例如 /uploads/mmd/models\n * 默认与 storageRoot 中的叶子目录一致\n */\n publicRoot?: string;\n /**\n * 自定义文件夹名称,默认使用随机 UUID\n */\n folderName?: string;\n}\n\nexport interface ProcessMmdModelArchiveResult {\n /** 解压出来的目录(绝对路径) */\n directory: string;\n /** 与 storageRoot 相对的目录名 */\n relativeDirectory: string;\n /** 模型文件相对目录(包含子目录) */\n modelRelativePath: string;\n /** 可供前端使用的模型 URL */\n modelUrl: string;\n /** 模型格式 */\n format: SupportedModelFormat;\n /** 解压得到的文件数量 */\n filesExtracted: number;\n}\n\nexport const MMD_MODEL_ARCHIVE_MIME_TYPES = [\n 'application/zip',\n 'application/x-zip-compressed',\n 'multipart/x-zip',\n] as const;\n\n/**\n * 解析上传的 MMD 模型压缩包,保留目录结构并返回模型路径\n */\nexport async function processMmdModelArchive(\n buffer: Buffer,\n options: ProcessMmdModelArchiveOptions,\n): Promise<ProcessMmdModelArchiveResult> {\n const folderName = options.folderName ?? randomUUID();\n const targetDir = path.join(options.storageRoot, folderName);\n await mkdir(targetDir, { recursive: true });\n\n const zip = new AdmZip(buffer);\n const entries = zip.getEntries();\n if (!entries.length) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包为空,请检查上传文件内容');\n }\n\n let modelRelativePath: string | null = null;\n let filesExtracted = 0;\n\n for (const entry of entries) {\n if (!entry.entryName || entry.entryName.startsWith('__MACOSX') || entry.entryName.endsWith('.DS_Store')) {\n continue;\n }\n\n const safeRelativePath = sanitizeEntryPath(entry.entryName);\n if (!safeRelativePath) {\n continue;\n }\n\n const destinationPath = path.join(targetDir, safeRelativePath);\n\n if (entry.isDirectory) {\n await mkdir(destinationPath, { recursive: true });\n continue;\n }\n\n await mkdir(path.dirname(destinationPath), { recursive: true });\n await writeFile(destinationPath, entry.getData());\n filesExtracted += 1;\n\n const entryExt = path.extname(safeRelativePath).toLowerCase();\n if (!modelRelativePath && (entryExt === '.pmx' || entryExt === '.pmd')) {\n modelRelativePath = safeRelativePath.split(path.sep).join('/');\n }\n }\n\n if (!modelRelativePath) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包中未找到 PMX/PMD 模型文件,请确认目录结构是否正确');\n }\n\n const format = path.extname(modelRelativePath).slice(1).toLowerCase() as SupportedModelFormat;\n const publicRoot = options.publicRoot ?? `/uploads/mmd/models`;\n const modelUrl = joinPublicPath(publicRoot, folderName, modelRelativePath);\n\n return {\n directory: targetDir,\n relativeDirectory: folderName,\n modelRelativePath,\n modelUrl,\n format,\n filesExtracted,\n };\n}\n\nfunction sanitizeEntryPath(entryName: string): string | null {\n const normalized = path.normalize(entryName).replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\n if (!normalized || normalized === '.' || normalized.startsWith('..') || path.isAbsolute(normalized)) {\n return null;\n }\n return normalized;\n}\n\nfunction joinPublicPath(...segments: string[]) {\n return segments\n .map((segment) => segment.replace(/\\/+/g, '/').replace(/^\\//, '').replace(/\\/$/, ''))\n .filter(Boolean)\n .join('/')\n .replace(/\\/{2,}/g, '/')\n .replace(/^/, '/');\n}\n\n","import type { MMDPlaylistConfig, MMDPlaylistNode } from '../types';\n\nexport interface PlaylistModelSource {\n id: string | number;\n name: string;\n filePath: string;\n thumbnailPath?: string | null;\n}\n\nexport interface PlaylistMotionSource {\n id: string | number;\n name?: string;\n filePath: string;\n}\n\nexport interface BuildMmdPlaylistOptions {\n playlistId: string;\n playlistName?: string;\n models: PlaylistModelSource[];\n motions?: PlaylistMotionSource[];\n limit?: number;\n loop?: boolean;\n preload?: 'none' | 'next' | 'all';\n autoPlay?: boolean;\n nodeDuration?: number;\n normalizeUrl?: (pathOrUrl: string) => string;\n}\n\nconst defaultNormalizer = (value: string) => {\n if (!value) return '';\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return value;\n }\n return value.startsWith('/') ? value : '/' + (value);\n};\n\n/**\n * 根据数据库中的模型/动作记录快速构建 MMDPlaylistConfig\n */\nexport function buildMmdPlaylistFromSources(options: BuildMmdPlaylistOptions): MMDPlaylistConfig {\n if (!options.models.length) {\n throw new Error('构建 MMD 播放列表失败:models 为空');\n }\n\n const limit = Math.max(1, Math.min(options.limit ?? options.models.length, options.models.length));\n const normalizeUrl = options.normalizeUrl ?? defaultNormalizer;\n const motions = options.motions ?? [];\n const hasMotions = motions.length > 0;\n const duration = options.nodeDuration ?? 30;\n\n const nodes: MMDPlaylistNode[] = options.models.slice(0, limit).map((model, index) => {\n const motion = hasMotions ? motions[index % motions.length] : undefined;\n return {\n id: String(model.id ?? index),\n name: model.name,\n loop: options.loop ?? true,\n duration,\n thumbnail: model.thumbnailPath ? normalizeUrl(model.thumbnailPath) : undefined,\n resources: {\n modelPath: normalizeUrl(model.filePath),\n motionPath: motion ? normalizeUrl(motion.filePath) : undefined,\n cameraPath: undefined,\n audioPath: undefined,\n stageModelPath: undefined,\n additionalMotions: undefined,\n },\n };\n });\n\n return {\n id: options.playlistId,\n name: options.playlistName ?? 'MMD 播放列表 - ' + (options.playlistId),\n nodes,\n loop: options.loop ?? true,\n preload: options.preload ?? 'next',\n autoPlay: options.autoPlay ?? true,\n };\n}\n\n","/**\n * MMD 资源上传辅助函数\n * \n * 整合 UniversalFileService 用于 MMD 资源上传\n */\n\nimport type { UniversalFileService } from '../../universalFile/server/UniversalFileService';\nimport type { FileMetadata } from '../../universalFile/types';\nimport { processMmdModelArchive, MMD_MODEL_ARCHIVE_MIME_TYPES } from './modelArchive';\n\nexport const MMD_SUPPORTED_TYPES = {\n model: [...MMD_MODEL_ARCHIVE_MIME_TYPES],\n animation: ['application/octet-stream', 'animation/vmd'],\n audio: ['audio/wav', 'audio/mp3', 'audio/mpeg', 'audio/ogg'],\n};\n\nexport const MMD_FILE_EXTENSIONS = {\n model: ['.zip'],\n animation: ['.vmd'],\n audio: ['.wav', '.mp3', '.ogg'],\n};\n\nexport interface MmdUploadOptions {\n file: File;\n resourceType: 'model' | 'animation' | 'audio';\n name: string;\n description?: string;\n userId: string;\n}\n\nexport interface MmdUploadResult {\n id: string;\n name: string;\n url: string;\n filePath: string;\n fileSize: number;\n type: string;\n format: string;\n uploadTime: Date;\n metadata?: FileMetadata;\n}\n\n/**\n * 使用 UniversalFileService 上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果\n */\nexport async function uploadMmdResource(\n fileService: UniversalFileService,\n options: MmdUploadOptions\n): Promise<MmdUploadResult> {\n const { file, resourceType, name, description, userId } = options;\n\n // 验证文件扩展名\n const ext = '.' + (file.name.split('.').pop()?.toLowerCase());\n const allowedExtensions = MMD_FILE_EXTENSIONS[resourceType];\n\n if (!allowedExtensions.includes(ext)) {\n throw new Error(\n '不支持的文件扩展名: ' + (ext) + '。支持的格式: ' + (allowedExtensions.join(', '))\n );\n }\n\n // 确定模块ID\n const moduleId = 'mmd-' + (resourceType) + 's';\n\n // 上传文件\n const metadata = await fileService.uploadFile({\n file,\n moduleId,\n businessId: 'default',\n permission: 'public',\n metadata: {\n uploadedBy: userId,\n uploadedAt: new Date().toISOString(),\n originalFileName: file.name,\n resourceType,\n name,\n description: description || '',\n },\n needsProcessing: false,\n });\n\n // 构建返回结果\n const format = ext.slice(1).toUpperCase();\n const fileUrl = metadata.cdnUrl || metadata.storagePath;\n\n return {\n id: metadata.id,\n name,\n url: fileUrl,\n filePath: metadata.storagePath,\n fileSize: metadata.size,\n type: resourceType,\n format,\n uploadTime: metadata.uploadTime,\n metadata,\n };\n}\n\n/**\n * 上传 MMD 模型 (ZIP 压缩包)\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果,包含解压后的模型路径\n */\nexport async function uploadMmdModel(\n fileService: UniversalFileService,\n options: MmdUploadOptions & { storageRoot: string; publicRoot: string }\n): Promise<MmdUploadResult & { extractedPath?: string }> {\n const { file, storageRoot, publicRoot } = options;\n\n // 首先上传 ZIP 文件\n const baseResult = await uploadMmdResource(fileService, options);\n\n // 处理 ZIP 压缩包\n try {\n const fileBuffer = Buffer.from(await file.arrayBuffer());\n const archiveResult = await processMmdModelArchive(fileBuffer, {\n storageRoot,\n publicRoot,\n folderName: baseResult.id,\n });\n\n return {\n ...baseResult,\n url: archiveResult.modelUrl,\n filePath: archiveResult.modelUrl,\n format: archiveResult.format.toUpperCase(),\n extractedPath: archiveResult.modelUrl,\n };\n } catch (extractError) {\n console.error('模型压缩包处理失败:', extractError);\n throw new Error(\n extractError instanceof Error ? extractError.message : '模型压缩包处理失败'\n );\n }\n}\n\n/**\n * 批量上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param uploads - 上传选项数组\n * @returns 上传结果数组\n */\nexport async function batchUploadMmdResources(\n fileService: UniversalFileService,\n uploads: MmdUploadOptions[]\n): Promise<MmdUploadResult[]> {\n const results: MmdUploadResult[] = [];\n\n for (const uploadOptions of uploads) {\n try {\n const result = await uploadMmdResource(fileService, uploadOptions);\n results.push(result);\n } catch (error) {\n console.error('上传失败: ' + (uploadOptions.file.name), error);\n // 继续处理其他文件\n }\n }\n\n return results;\n}\n\n"]}
@@ -76,7 +76,7 @@ var defaultNormalizer = (value) => {
76
76
  if (value.startsWith("http://") || value.startsWith("https://")) {
77
77
  return value;
78
78
  }
79
- return value.startsWith("/") ? value : `/${value}`;
79
+ return value.startsWith("/") ? value : "/" + value;
80
80
  };
81
81
  function buildMmdPlaylistFromSources(options) {
82
82
  if (!options.models.length) {
@@ -107,7 +107,7 @@ function buildMmdPlaylistFromSources(options) {
107
107
  });
108
108
  return {
109
109
  id: options.playlistId,
110
- name: options.playlistName ?? `MMD \u64AD\u653E\u5217\u8868 - ${options.playlistId}`,
110
+ name: options.playlistName ?? "MMD \u64AD\u653E\u5217\u8868 - " + options.playlistId,
111
111
  nodes,
112
112
  loop: options.loop ?? true,
113
113
  preload: options.preload ?? "next",
@@ -128,14 +128,14 @@ var MMD_FILE_EXTENSIONS = {
128
128
  };
129
129
  async function uploadMmdResource(fileService, options) {
130
130
  const { file, resourceType, name, description, userId } = options;
131
- const ext = `.${file.name.split(".").pop()?.toLowerCase()}`;
131
+ const ext = "." + file.name.split(".").pop()?.toLowerCase();
132
132
  const allowedExtensions = MMD_FILE_EXTENSIONS[resourceType];
133
133
  if (!allowedExtensions.includes(ext)) {
134
134
  throw new Error(
135
- `\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u6269\u5C55\u540D: ${ext}\u3002\u652F\u6301\u7684\u683C\u5F0F: ${allowedExtensions.join(", ")}`
135
+ "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u6269\u5C55\u540D: " + ext + "\u3002\u652F\u6301\u7684\u683C\u5F0F: " + allowedExtensions.join(", ")
136
136
  );
137
137
  }
138
- const moduleId = `mmd-${resourceType}s`;
138
+ const moduleId = "mmd-" + resourceType + "s";
139
139
  const metadata = await fileService.uploadFile({
140
140
  file,
141
141
  moduleId,
@@ -196,7 +196,7 @@ async function batchUploadMmdResources(fileService, uploads) {
196
196
  const result = await uploadMmdResource(fileService, uploadOptions);
197
197
  results.push(result);
198
198
  } catch (error) {
199
- console.error(`\u4E0A\u4F20\u5931\u8D25: ${uploadOptions.file.name}`, error);
199
+ console.error("\u4E0A\u4F20\u5931\u8D25: " + uploadOptions.file.name, error);
200
200
  }
201
201
  }
202
202
  return results;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/mmd/server/modelArchive.ts","../../../src/mmd/server/playlistBuilder.ts","../../../src/mmd/server/mmdUpload.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import AdmZip from 'adm-zip';\nimport { randomUUID } from 'crypto';\nimport { mkdir, rm, writeFile } from 'fs/promises';\nimport path from 'path';\n\nexport type SupportedModelFormat = 'pmx' | 'pmd';\n\nexport interface ProcessMmdModelArchiveOptions {\n /**\n * 绝对路径,指向模型解压根目录,例如 /app/uploads/mmd/models\n */\n storageRoot: string;\n /**\n * 对外暴露的公共路径前缀,例如 /uploads/mmd/models\n * 默认与 storageRoot 中的叶子目录一致\n */\n publicRoot?: string;\n /**\n * 自定义文件夹名称,默认使用随机 UUID\n */\n folderName?: string;\n}\n\nexport interface ProcessMmdModelArchiveResult {\n /** 解压出来的目录(绝对路径) */\n directory: string;\n /** 与 storageRoot 相对的目录名 */\n relativeDirectory: string;\n /** 模型文件相对目录(包含子目录) */\n modelRelativePath: string;\n /** 可供前端使用的模型 URL */\n modelUrl: string;\n /** 模型格式 */\n format: SupportedModelFormat;\n /** 解压得到的文件数量 */\n filesExtracted: number;\n}\n\nexport const MMD_MODEL_ARCHIVE_MIME_TYPES = [\n 'application/zip',\n 'application/x-zip-compressed',\n 'multipart/x-zip',\n] as const;\n\n/**\n * 解析上传的 MMD 模型压缩包,保留目录结构并返回模型路径\n */\nexport async function processMmdModelArchive(\n buffer: Buffer,\n options: ProcessMmdModelArchiveOptions,\n): Promise<ProcessMmdModelArchiveResult> {\n const folderName = options.folderName ?? randomUUID();\n const targetDir = path.join(options.storageRoot, folderName);\n await mkdir(targetDir, { recursive: true });\n\n const zip = new AdmZip(buffer);\n const entries = zip.getEntries();\n if (!entries.length) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包为空,请检查上传文件内容');\n }\n\n let modelRelativePath: string | null = null;\n let filesExtracted = 0;\n\n for (const entry of entries) {\n if (!entry.entryName || entry.entryName.startsWith('__MACOSX') || entry.entryName.endsWith('.DS_Store')) {\n continue;\n }\n\n const safeRelativePath = sanitizeEntryPath(entry.entryName);\n if (!safeRelativePath) {\n continue;\n }\n\n const destinationPath = path.join(targetDir, safeRelativePath);\n\n if (entry.isDirectory) {\n await mkdir(destinationPath, { recursive: true });\n continue;\n }\n\n await mkdir(path.dirname(destinationPath), { recursive: true });\n await writeFile(destinationPath, entry.getData());\n filesExtracted += 1;\n\n const entryExt = path.extname(safeRelativePath).toLowerCase();\n if (!modelRelativePath && (entryExt === '.pmx' || entryExt === '.pmd')) {\n modelRelativePath = safeRelativePath.split(path.sep).join('/');\n }\n }\n\n if (!modelRelativePath) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包中未找到 PMX/PMD 模型文件,请确认目录结构是否正确');\n }\n\n const format = path.extname(modelRelativePath).slice(1).toLowerCase() as SupportedModelFormat;\n const publicRoot = options.publicRoot ?? `/uploads/mmd/models`;\n const modelUrl = joinPublicPath(publicRoot, folderName, modelRelativePath);\n\n return {\n directory: targetDir,\n relativeDirectory: folderName,\n modelRelativePath,\n modelUrl,\n format,\n filesExtracted,\n };\n}\n\nfunction sanitizeEntryPath(entryName: string): string | null {\n const normalized = path.normalize(entryName).replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\n if (!normalized || normalized === '.' || normalized.startsWith('..') || path.isAbsolute(normalized)) {\n return null;\n }\n return normalized;\n}\n\nfunction joinPublicPath(...segments: string[]) {\n return segments\n .map((segment) => segment.replace(/\\/+/g, '/').replace(/^\\//, '').replace(/\\/$/, ''))\n .filter(Boolean)\n .join('/')\n .replace(/\\/{2,}/g, '/')\n .replace(/^/, '/');\n}\n\n","import type { MMDPlaylistConfig, MMDPlaylistNode } from '../types';\n\nexport interface PlaylistModelSource {\n id: string | number;\n name: string;\n filePath: string;\n thumbnailPath?: string | null;\n}\n\nexport interface PlaylistMotionSource {\n id: string | number;\n name?: string;\n filePath: string;\n}\n\nexport interface BuildMmdPlaylistOptions {\n playlistId: string;\n playlistName?: string;\n models: PlaylistModelSource[];\n motions?: PlaylistMotionSource[];\n limit?: number;\n loop?: boolean;\n preload?: 'none' | 'next' | 'all';\n autoPlay?: boolean;\n nodeDuration?: number;\n normalizeUrl?: (pathOrUrl: string) => string;\n}\n\nconst defaultNormalizer = (value: string) => {\n if (!value) return '';\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return value;\n }\n return value.startsWith('/') ? value : `/${value}`;\n};\n\n/**\n * 根据数据库中的模型/动作记录快速构建 MMDPlaylistConfig\n */\nexport function buildMmdPlaylistFromSources(options: BuildMmdPlaylistOptions): MMDPlaylistConfig {\n if (!options.models.length) {\n throw new Error('构建 MMD 播放列表失败:models 为空');\n }\n\n const limit = Math.max(1, Math.min(options.limit ?? options.models.length, options.models.length));\n const normalizeUrl = options.normalizeUrl ?? defaultNormalizer;\n const motions = options.motions ?? [];\n const hasMotions = motions.length > 0;\n const duration = options.nodeDuration ?? 30;\n\n const nodes: MMDPlaylistNode[] = options.models.slice(0, limit).map((model, index) => {\n const motion = hasMotions ? motions[index % motions.length] : undefined;\n return {\n id: String(model.id ?? index),\n name: model.name,\n loop: options.loop ?? true,\n duration,\n thumbnail: model.thumbnailPath ? normalizeUrl(model.thumbnailPath) : undefined,\n resources: {\n modelPath: normalizeUrl(model.filePath),\n motionPath: motion ? normalizeUrl(motion.filePath) : undefined,\n cameraPath: undefined,\n audioPath: undefined,\n stageModelPath: undefined,\n additionalMotions: undefined,\n },\n };\n });\n\n return {\n id: options.playlistId,\n name: options.playlistName ?? `MMD 播放列表 - ${options.playlistId}`,\n nodes,\n loop: options.loop ?? true,\n preload: options.preload ?? 'next',\n autoPlay: options.autoPlay ?? true,\n };\n}\n\n","/**\n * MMD 资源上传辅助函数\n * \n * 整合 UniversalFileService 用于 MMD 资源上传\n */\n\nimport type { UniversalFileService } from '../../universalFile/server/UniversalFileService';\nimport type { FileMetadata } from '../../universalFile/types';\nimport { processMmdModelArchive, MMD_MODEL_ARCHIVE_MIME_TYPES } from './modelArchive';\n\nexport const MMD_SUPPORTED_TYPES = {\n model: [...MMD_MODEL_ARCHIVE_MIME_TYPES],\n animation: ['application/octet-stream', 'animation/vmd'],\n audio: ['audio/wav', 'audio/mp3', 'audio/mpeg', 'audio/ogg'],\n};\n\nexport const MMD_FILE_EXTENSIONS = {\n model: ['.zip'],\n animation: ['.vmd'],\n audio: ['.wav', '.mp3', '.ogg'],\n};\n\nexport interface MmdUploadOptions {\n file: File;\n resourceType: 'model' | 'animation' | 'audio';\n name: string;\n description?: string;\n userId: string;\n}\n\nexport interface MmdUploadResult {\n id: string;\n name: string;\n url: string;\n filePath: string;\n fileSize: number;\n type: string;\n format: string;\n uploadTime: Date;\n metadata?: FileMetadata;\n}\n\n/**\n * 使用 UniversalFileService 上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果\n */\nexport async function uploadMmdResource(\n fileService: UniversalFileService,\n options: MmdUploadOptions\n): Promise<MmdUploadResult> {\n const { file, resourceType, name, description, userId } = options;\n\n // 验证文件扩展名\n const ext = `.${file.name.split('.').pop()?.toLowerCase()}`;\n const allowedExtensions = MMD_FILE_EXTENSIONS[resourceType];\n\n if (!allowedExtensions.includes(ext)) {\n throw new Error(\n `不支持的文件扩展名: ${ext}。支持的格式: ${allowedExtensions.join(', ')}`\n );\n }\n\n // 确定模块ID\n const moduleId = `mmd-${resourceType}s`;\n\n // 上传文件\n const metadata = await fileService.uploadFile({\n file,\n moduleId,\n businessId: 'default',\n permission: 'public',\n metadata: {\n uploadedBy: userId,\n uploadedAt: new Date().toISOString(),\n originalFileName: file.name,\n resourceType,\n name,\n description: description || '',\n },\n needsProcessing: false,\n });\n\n // 构建返回结果\n const format = ext.slice(1).toUpperCase();\n const fileUrl = metadata.cdnUrl || metadata.storagePath;\n\n return {\n id: metadata.id,\n name,\n url: fileUrl,\n filePath: metadata.storagePath,\n fileSize: metadata.size,\n type: resourceType,\n format,\n uploadTime: metadata.uploadTime,\n metadata,\n };\n}\n\n/**\n * 上传 MMD 模型 (ZIP 压缩包)\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果,包含解压后的模型路径\n */\nexport async function uploadMmdModel(\n fileService: UniversalFileService,\n options: MmdUploadOptions & { storageRoot: string; publicRoot: string }\n): Promise<MmdUploadResult & { extractedPath?: string }> {\n const { file, storageRoot, publicRoot } = options;\n\n // 首先上传 ZIP 文件\n const baseResult = await uploadMmdResource(fileService, options);\n\n // 处理 ZIP 压缩包\n try {\n const fileBuffer = Buffer.from(await file.arrayBuffer());\n const archiveResult = await processMmdModelArchive(fileBuffer, {\n storageRoot,\n publicRoot,\n folderName: baseResult.id,\n });\n\n return {\n ...baseResult,\n url: archiveResult.modelUrl,\n filePath: archiveResult.modelUrl,\n format: archiveResult.format.toUpperCase(),\n extractedPath: archiveResult.modelUrl,\n };\n } catch (extractError) {\n console.error('模型压缩包处理失败:', extractError);\n throw new Error(\n extractError instanceof Error ? extractError.message : '模型压缩包处理失败'\n );\n }\n}\n\n/**\n * 批量上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param uploads - 上传选项数组\n * @returns 上传结果数组\n */\nexport async function batchUploadMmdResources(\n fileService: UniversalFileService,\n uploads: MmdUploadOptions[]\n): Promise<MmdUploadResult[]> {\n const results: MmdUploadResult[] = [];\n\n for (const uploadOptions of uploads) {\n try {\n const result = await uploadMmdResource(fileService, uploadOptions);\n results.push(result);\n } catch (error) {\n console.error(`上传失败: ${uploadOptions.file.name}`, error);\n // 继续处理其他文件\n }\n }\n\n return results;\n}\n\n"]}
1
+ {"version":3,"sources":["../../../src/mmd/server/modelArchive.ts","../../../src/mmd/server/playlistBuilder.ts","../../../src/mmd/server/mmdUpload.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import AdmZip from 'adm-zip';\nimport { randomUUID } from 'crypto';\nimport { mkdir, rm, writeFile } from 'fs/promises';\nimport path from 'path';\n\nexport type SupportedModelFormat = 'pmx' | 'pmd';\n\nexport interface ProcessMmdModelArchiveOptions {\n /**\n * 绝对路径,指向模型解压根目录,例如 /app/uploads/mmd/models\n */\n storageRoot: string;\n /**\n * 对外暴露的公共路径前缀,例如 /uploads/mmd/models\n * 默认与 storageRoot 中的叶子目录一致\n */\n publicRoot?: string;\n /**\n * 自定义文件夹名称,默认使用随机 UUID\n */\n folderName?: string;\n}\n\nexport interface ProcessMmdModelArchiveResult {\n /** 解压出来的目录(绝对路径) */\n directory: string;\n /** 与 storageRoot 相对的目录名 */\n relativeDirectory: string;\n /** 模型文件相对目录(包含子目录) */\n modelRelativePath: string;\n /** 可供前端使用的模型 URL */\n modelUrl: string;\n /** 模型格式 */\n format: SupportedModelFormat;\n /** 解压得到的文件数量 */\n filesExtracted: number;\n}\n\nexport const MMD_MODEL_ARCHIVE_MIME_TYPES = [\n 'application/zip',\n 'application/x-zip-compressed',\n 'multipart/x-zip',\n] as const;\n\n/**\n * 解析上传的 MMD 模型压缩包,保留目录结构并返回模型路径\n */\nexport async function processMmdModelArchive(\n buffer: Buffer,\n options: ProcessMmdModelArchiveOptions,\n): Promise<ProcessMmdModelArchiveResult> {\n const folderName = options.folderName ?? randomUUID();\n const targetDir = path.join(options.storageRoot, folderName);\n await mkdir(targetDir, { recursive: true });\n\n const zip = new AdmZip(buffer);\n const entries = zip.getEntries();\n if (!entries.length) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包为空,请检查上传文件内容');\n }\n\n let modelRelativePath: string | null = null;\n let filesExtracted = 0;\n\n for (const entry of entries) {\n if (!entry.entryName || entry.entryName.startsWith('__MACOSX') || entry.entryName.endsWith('.DS_Store')) {\n continue;\n }\n\n const safeRelativePath = sanitizeEntryPath(entry.entryName);\n if (!safeRelativePath) {\n continue;\n }\n\n const destinationPath = path.join(targetDir, safeRelativePath);\n\n if (entry.isDirectory) {\n await mkdir(destinationPath, { recursive: true });\n continue;\n }\n\n await mkdir(path.dirname(destinationPath), { recursive: true });\n await writeFile(destinationPath, entry.getData());\n filesExtracted += 1;\n\n const entryExt = path.extname(safeRelativePath).toLowerCase();\n if (!modelRelativePath && (entryExt === '.pmx' || entryExt === '.pmd')) {\n modelRelativePath = safeRelativePath.split(path.sep).join('/');\n }\n }\n\n if (!modelRelativePath) {\n await rm(targetDir, { recursive: true, force: true });\n throw new Error('压缩包中未找到 PMX/PMD 模型文件,请确认目录结构是否正确');\n }\n\n const format = path.extname(modelRelativePath).slice(1).toLowerCase() as SupportedModelFormat;\n const publicRoot = options.publicRoot ?? `/uploads/mmd/models`;\n const modelUrl = joinPublicPath(publicRoot, folderName, modelRelativePath);\n\n return {\n directory: targetDir,\n relativeDirectory: folderName,\n modelRelativePath,\n modelUrl,\n format,\n filesExtracted,\n };\n}\n\nfunction sanitizeEntryPath(entryName: string): string | null {\n const normalized = path.normalize(entryName).replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\n if (!normalized || normalized === '.' || normalized.startsWith('..') || path.isAbsolute(normalized)) {\n return null;\n }\n return normalized;\n}\n\nfunction joinPublicPath(...segments: string[]) {\n return segments\n .map((segment) => segment.replace(/\\/+/g, '/').replace(/^\\//, '').replace(/\\/$/, ''))\n .filter(Boolean)\n .join('/')\n .replace(/\\/{2,}/g, '/')\n .replace(/^/, '/');\n}\n\n","import type { MMDPlaylistConfig, MMDPlaylistNode } from '../types';\n\nexport interface PlaylistModelSource {\n id: string | number;\n name: string;\n filePath: string;\n thumbnailPath?: string | null;\n}\n\nexport interface PlaylistMotionSource {\n id: string | number;\n name?: string;\n filePath: string;\n}\n\nexport interface BuildMmdPlaylistOptions {\n playlistId: string;\n playlistName?: string;\n models: PlaylistModelSource[];\n motions?: PlaylistMotionSource[];\n limit?: number;\n loop?: boolean;\n preload?: 'none' | 'next' | 'all';\n autoPlay?: boolean;\n nodeDuration?: number;\n normalizeUrl?: (pathOrUrl: string) => string;\n}\n\nconst defaultNormalizer = (value: string) => {\n if (!value) return '';\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return value;\n }\n return value.startsWith('/') ? value : '/' + (value);\n};\n\n/**\n * 根据数据库中的模型/动作记录快速构建 MMDPlaylistConfig\n */\nexport function buildMmdPlaylistFromSources(options: BuildMmdPlaylistOptions): MMDPlaylistConfig {\n if (!options.models.length) {\n throw new Error('构建 MMD 播放列表失败:models 为空');\n }\n\n const limit = Math.max(1, Math.min(options.limit ?? options.models.length, options.models.length));\n const normalizeUrl = options.normalizeUrl ?? defaultNormalizer;\n const motions = options.motions ?? [];\n const hasMotions = motions.length > 0;\n const duration = options.nodeDuration ?? 30;\n\n const nodes: MMDPlaylistNode[] = options.models.slice(0, limit).map((model, index) => {\n const motion = hasMotions ? motions[index % motions.length] : undefined;\n return {\n id: String(model.id ?? index),\n name: model.name,\n loop: options.loop ?? true,\n duration,\n thumbnail: model.thumbnailPath ? normalizeUrl(model.thumbnailPath) : undefined,\n resources: {\n modelPath: normalizeUrl(model.filePath),\n motionPath: motion ? normalizeUrl(motion.filePath) : undefined,\n cameraPath: undefined,\n audioPath: undefined,\n stageModelPath: undefined,\n additionalMotions: undefined,\n },\n };\n });\n\n return {\n id: options.playlistId,\n name: options.playlistName ?? 'MMD 播放列表 - ' + (options.playlistId),\n nodes,\n loop: options.loop ?? true,\n preload: options.preload ?? 'next',\n autoPlay: options.autoPlay ?? true,\n };\n}\n\n","/**\n * MMD 资源上传辅助函数\n * \n * 整合 UniversalFileService 用于 MMD 资源上传\n */\n\nimport type { UniversalFileService } from '../../universalFile/server/UniversalFileService';\nimport type { FileMetadata } from '../../universalFile/types';\nimport { processMmdModelArchive, MMD_MODEL_ARCHIVE_MIME_TYPES } from './modelArchive';\n\nexport const MMD_SUPPORTED_TYPES = {\n model: [...MMD_MODEL_ARCHIVE_MIME_TYPES],\n animation: ['application/octet-stream', 'animation/vmd'],\n audio: ['audio/wav', 'audio/mp3', 'audio/mpeg', 'audio/ogg'],\n};\n\nexport const MMD_FILE_EXTENSIONS = {\n model: ['.zip'],\n animation: ['.vmd'],\n audio: ['.wav', '.mp3', '.ogg'],\n};\n\nexport interface MmdUploadOptions {\n file: File;\n resourceType: 'model' | 'animation' | 'audio';\n name: string;\n description?: string;\n userId: string;\n}\n\nexport interface MmdUploadResult {\n id: string;\n name: string;\n url: string;\n filePath: string;\n fileSize: number;\n type: string;\n format: string;\n uploadTime: Date;\n metadata?: FileMetadata;\n}\n\n/**\n * 使用 UniversalFileService 上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果\n */\nexport async function uploadMmdResource(\n fileService: UniversalFileService,\n options: MmdUploadOptions\n): Promise<MmdUploadResult> {\n const { file, resourceType, name, description, userId } = options;\n\n // 验证文件扩展名\n const ext = '.' + (file.name.split('.').pop()?.toLowerCase());\n const allowedExtensions = MMD_FILE_EXTENSIONS[resourceType];\n\n if (!allowedExtensions.includes(ext)) {\n throw new Error(\n '不支持的文件扩展名: ' + (ext) + '。支持的格式: ' + (allowedExtensions.join(', '))\n );\n }\n\n // 确定模块ID\n const moduleId = 'mmd-' + (resourceType) + 's';\n\n // 上传文件\n const metadata = await fileService.uploadFile({\n file,\n moduleId,\n businessId: 'default',\n permission: 'public',\n metadata: {\n uploadedBy: userId,\n uploadedAt: new Date().toISOString(),\n originalFileName: file.name,\n resourceType,\n name,\n description: description || '',\n },\n needsProcessing: false,\n });\n\n // 构建返回结果\n const format = ext.slice(1).toUpperCase();\n const fileUrl = metadata.cdnUrl || metadata.storagePath;\n\n return {\n id: metadata.id,\n name,\n url: fileUrl,\n filePath: metadata.storagePath,\n fileSize: metadata.size,\n type: resourceType,\n format,\n uploadTime: metadata.uploadTime,\n metadata,\n };\n}\n\n/**\n * 上传 MMD 模型 (ZIP 压缩包)\n * \n * @param fileService - UniversalFileService 实例\n * @param options - 上传选项\n * @returns 上传结果,包含解压后的模型路径\n */\nexport async function uploadMmdModel(\n fileService: UniversalFileService,\n options: MmdUploadOptions & { storageRoot: string; publicRoot: string }\n): Promise<MmdUploadResult & { extractedPath?: string }> {\n const { file, storageRoot, publicRoot } = options;\n\n // 首先上传 ZIP 文件\n const baseResult = await uploadMmdResource(fileService, options);\n\n // 处理 ZIP 压缩包\n try {\n const fileBuffer = Buffer.from(await file.arrayBuffer());\n const archiveResult = await processMmdModelArchive(fileBuffer, {\n storageRoot,\n publicRoot,\n folderName: baseResult.id,\n });\n\n return {\n ...baseResult,\n url: archiveResult.modelUrl,\n filePath: archiveResult.modelUrl,\n format: archiveResult.format.toUpperCase(),\n extractedPath: archiveResult.modelUrl,\n };\n } catch (extractError) {\n console.error('模型压缩包处理失败:', extractError);\n throw new Error(\n extractError instanceof Error ? extractError.message : '模型压缩包处理失败'\n );\n }\n}\n\n/**\n * 批量上传 MMD 资源\n * \n * @param fileService - UniversalFileService 实例\n * @param uploads - 上传选项数组\n * @returns 上传结果数组\n */\nexport async function batchUploadMmdResources(\n fileService: UniversalFileService,\n uploads: MmdUploadOptions[]\n): Promise<MmdUploadResult[]> {\n const results: MmdUploadResult[] = [];\n\n for (const uploadOptions of uploads) {\n try {\n const result = await uploadMmdResource(fileService, uploadOptions);\n results.push(result);\n } catch (error) {\n console.error('上传失败: ' + (uploadOptions.file.name), error);\n // 继续处理其他文件\n }\n }\n\n return results;\n}\n\n"]}
@@ -1,66 +1,66 @@
1
1
  'use strict';
2
2
 
3
- var chunkE7RGBAYJ_js = require('../chunk-E7RGBAYJ.js');
4
- var chunkA3UP56MS_js = require('../chunk-A3UP56MS.js');
3
+ var chunkTDCDEBGP_js = require('../chunk-TDCDEBGP.js');
4
+ var chunkWA67GZSZ_js = require('../chunk-WA67GZSZ.js');
5
5
  require('../chunk-DGUM43GV.js');
6
6
 
7
7
 
8
8
 
9
9
  Object.defineProperty(exports, "MikutapMusicPlayer", {
10
10
  enumerable: true,
11
- get: function () { return chunkE7RGBAYJ_js.MikutapMusicPlayer; }
11
+ get: function () { return chunkTDCDEBGP_js.MikutapMusicPlayer; }
12
12
  });
13
13
  Object.defineProperty(exports, "MusicPlayer", {
14
14
  enumerable: true,
15
- get: function () { return chunkE7RGBAYJ_js.MusicPlayer; }
15
+ get: function () { return chunkTDCDEBGP_js.MusicPlayer; }
16
16
  });
17
17
  Object.defineProperty(exports, "kugouAdapter", {
18
18
  enumerable: true,
19
- get: function () { return chunkE7RGBAYJ_js.kugouAdapter; }
19
+ get: function () { return chunkTDCDEBGP_js.kugouAdapter; }
20
20
  });
21
21
  Object.defineProperty(exports, "neteaseAdapter", {
22
22
  enumerable: true,
23
- get: function () { return chunkE7RGBAYJ_js.neteaseAdapter; }
23
+ get: function () { return chunkTDCDEBGP_js.neteaseAdapter; }
24
24
  });
25
25
  Object.defineProperty(exports, "tencentAdapter", {
26
26
  enumerable: true,
27
- get: function () { return chunkE7RGBAYJ_js.tencentAdapter; }
27
+ get: function () { return chunkTDCDEBGP_js.tencentAdapter; }
28
28
  });
29
29
  Object.defineProperty(exports, "useMusic", {
30
30
  enumerable: true,
31
- get: function () { return chunkE7RGBAYJ_js.useMusic; }
31
+ get: function () { return chunkTDCDEBGP_js.useMusic; }
32
32
  });
33
33
  Object.defineProperty(exports, "xiamiAdapter", {
34
34
  enumerable: true,
35
- get: function () { return chunkE7RGBAYJ_js.xiamiAdapter; }
35
+ get: function () { return chunkTDCDEBGP_js.xiamiAdapter; }
36
36
  });
37
37
  Object.defineProperty(exports, "MetingService", {
38
38
  enumerable: true,
39
- get: function () { return chunkA3UP56MS_js.MetingService; }
39
+ get: function () { return chunkWA67GZSZ_js.MetingService; }
40
40
  });
41
41
  Object.defineProperty(exports, "MikuMusicService", {
42
42
  enumerable: true,
43
- get: function () { return chunkA3UP56MS_js.MikuMusicService; }
43
+ get: function () { return chunkWA67GZSZ_js.MikuMusicService; }
44
44
  });
45
45
  Object.defineProperty(exports, "createLyricHandler", {
46
46
  enumerable: true,
47
- get: function () { return chunkA3UP56MS_js.createLyricHandler; }
47
+ get: function () { return chunkWA67GZSZ_js.createLyricHandler; }
48
48
  });
49
49
  Object.defineProperty(exports, "createSearchHandler", {
50
50
  enumerable: true,
51
- get: function () { return chunkA3UP56MS_js.createSearchHandler; }
51
+ get: function () { return chunkWA67GZSZ_js.createSearchHandler; }
52
52
  });
53
53
  Object.defineProperty(exports, "createSongUrlHandler", {
54
54
  enumerable: true,
55
- get: function () { return chunkA3UP56MS_js.createSongUrlHandler; }
55
+ get: function () { return chunkWA67GZSZ_js.createSongUrlHandler; }
56
56
  });
57
57
  Object.defineProperty(exports, "mikuMusicService", {
58
58
  enumerable: true,
59
- get: function () { return chunkA3UP56MS_js.mikuMusicService; }
59
+ get: function () { return chunkWA67GZSZ_js.mikuMusicService; }
60
60
  });
61
61
  Object.defineProperty(exports, "musicService", {
62
62
  enumerable: true,
63
- get: function () { return chunkA3UP56MS_js.musicService; }
63
+ get: function () { return chunkWA67GZSZ_js.musicService; }
64
64
  });
65
65
  //# sourceMappingURL=index.js.map
66
66
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- export { MikutapMusicPlayer, MusicPlayer, kugouAdapter, neteaseAdapter, tencentAdapter, useMusic, xiamiAdapter } from '../chunk-3WOAPLEG.mjs';
2
- export { MetingService, MikuMusicService, createLyricHandler, createSearchHandler, createSongUrlHandler, mikuMusicService, musicService } from '../chunk-MW4BCIZC.mjs';
1
+ export { MikutapMusicPlayer, MusicPlayer, kugouAdapter, neteaseAdapter, tencentAdapter, useMusic, xiamiAdapter } from '../chunk-EB4NR623.mjs';
2
+ export { MetingService, MikuMusicService, createLyricHandler, createSearchHandler, createSongUrlHandler, mikuMusicService, musicService } from '../chunk-4HC6M7FK.mjs';
3
3
  import '../chunk-BJTO5JO5.mjs';
4
4
  //# sourceMappingURL=index.mjs.map
5
5
  //# sourceMappingURL=index.mjs.map
@@ -1,37 +1,37 @@
1
1
  'use strict';
2
2
 
3
- var chunkA3UP56MS_js = require('../../chunk-A3UP56MS.js');
3
+ var chunkWA67GZSZ_js = require('../../chunk-WA67GZSZ.js');
4
4
  require('../../chunk-DGUM43GV.js');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "MetingService", {
9
9
  enumerable: true,
10
- get: function () { return chunkA3UP56MS_js.MetingService; }
10
+ get: function () { return chunkWA67GZSZ_js.MetingService; }
11
11
  });
12
12
  Object.defineProperty(exports, "MikuMusicService", {
13
13
  enumerable: true,
14
- get: function () { return chunkA3UP56MS_js.MikuMusicService; }
14
+ get: function () { return chunkWA67GZSZ_js.MikuMusicService; }
15
15
  });
16
16
  Object.defineProperty(exports, "createLyricHandler", {
17
17
  enumerable: true,
18
- get: function () { return chunkA3UP56MS_js.createLyricHandler; }
18
+ get: function () { return chunkWA67GZSZ_js.createLyricHandler; }
19
19
  });
20
20
  Object.defineProperty(exports, "createSearchHandler", {
21
21
  enumerable: true,
22
- get: function () { return chunkA3UP56MS_js.createSearchHandler; }
22
+ get: function () { return chunkWA67GZSZ_js.createSearchHandler; }
23
23
  });
24
24
  Object.defineProperty(exports, "createSongUrlHandler", {
25
25
  enumerable: true,
26
- get: function () { return chunkA3UP56MS_js.createSongUrlHandler; }
26
+ get: function () { return chunkWA67GZSZ_js.createSongUrlHandler; }
27
27
  });
28
28
  Object.defineProperty(exports, "mikuMusicService", {
29
29
  enumerable: true,
30
- get: function () { return chunkA3UP56MS_js.mikuMusicService; }
30
+ get: function () { return chunkWA67GZSZ_js.mikuMusicService; }
31
31
  });
32
32
  Object.defineProperty(exports, "musicService", {
33
33
  enumerable: true,
34
- get: function () { return chunkA3UP56MS_js.musicService; }
34
+ get: function () { return chunkWA67GZSZ_js.musicService; }
35
35
  });
36
36
  //# sourceMappingURL=index.js.map
37
37
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- export { MetingService, MikuMusicService, createLyricHandler, createSearchHandler, createSongUrlHandler, mikuMusicService, musicService } from '../../chunk-MW4BCIZC.mjs';
1
+ export { MetingService, MikuMusicService, createLyricHandler, createSearchHandler, createSongUrlHandler, mikuMusicService, musicService } from '../../chunk-4HC6M7FK.mjs';
2
2
  import '../../chunk-BJTO5JO5.mjs';
3
3
  //# sourceMappingURL=index.mjs.map
4
4
  //# sourceMappingURL=index.mjs.map
@@ -33,7 +33,7 @@ var WebRequestAdapter = class {
33
33
  if (!response.ok) {
34
34
  return {
35
35
  success: false,
36
- error: data.error || `\u8BF7\u6C42\u5931\u8D25: ${response.status}`
36
+ error: data.error || "\u8BF7\u6C42\u5931\u8D25: " + response.status
37
37
  };
38
38
  }
39
39
  return data;
@@ -66,7 +66,7 @@ var MiniappRequestAdapter = class {
66
66
  } else {
67
67
  return {
68
68
  success: false,
69
- error: data.error || `\u8BF7\u6C42\u5931\u8D25: ${response.statusCode}`
69
+ error: data.error || "\u8BF7\u6C42\u5931\u8D25: " + response.statusCode
70
70
  };
71
71
  }
72
72
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/request/adapters/web-adapter.ts","../../src/request/adapters/miniapp-adapter.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Web 平台请求适配器\n * 基于标准 fetch API\n *\n * 适用平台:\n * - Web (Next.js)\n * - Desktop (Electron)\n * - Mobile (React Native)\n */\nexport class WebRequestAdapter implements RequestAdapter {\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n // 构建 URL(如果有查询参数)\n let fullUrl = url;\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n const queryString = searchParams.toString();\n if (queryString) {\n fullUrl += (url.includes('?') ? '&' : '?') + queryString;\n }\n }\n\n // 发送请求\n const response = await fetch(fullUrl, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n credentials: 'include', // 🔐 自动发送和接收 Cookie(支持 httpOnly Cookie 认证)\n });\n\n // 解析响应\n const data = await response.json();\n\n // 如果响应不成功,返回错误格式\n if (!response.ok) {\n return {\n success: false,\n error: data.error || `请求失败: ${response.status}`,\n } as T;\n }\n\n return data;\n }\n}\n\n","import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Taro Request 接口定义\n * 兼容 @tarojs/taro request API\n */\ninterface TaroRequestStatic {\n request<T = any>(options: {\n url: string;\n method?: string;\n header?: Record<string, string>;\n data?: any;\n }): Promise<{\n statusCode: number;\n data: T;\n }>;\n}\n\n/**\n * Miniapp 平台请求适配器\n * 基于 Taro.request API\n *\n * 使用方式:\n * ```typescript\n * import Taro from '@tarojs/taro'\n * const adapter = new MiniappRequestAdapter(Taro)\n * ```\n *\n * 适用平台:\n * - WeChat Miniapp\n * - Other Taro-based miniapps\n */\nexport class MiniappRequestAdapter implements RequestAdapter {\n private taro: TaroRequestStatic;\n\n constructor(taro: TaroRequestStatic) {\n if (!taro) {\n throw new Error('MiniappRequestAdapter requires Taro instance');\n }\n this.taro = taro;\n }\n\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n try {\n const response = await this.taro.request({\n url,\n method: method as any,\n header: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n data: method === 'GET' ? params : body,\n });\n\n const data = response.data as any;\n\n // 统一返回格式\n if (response.statusCode >= 200 && response.statusCode < 300) {\n return data;\n } else {\n return {\n success: false,\n error: data.error || `请求失败: ${response.statusCode}`,\n } as T;\n }\n } catch (error) {\n console.error('[MiniappRequestAdapter] request error:', error);\n return {\n success: false,\n error: error instanceof Error ? error.message : '网络请求失败',\n } as T;\n }\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../../src/request/adapters/web-adapter.ts","../../src/request/adapters/miniapp-adapter.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Web 平台请求适配器\n * 基于标准 fetch API\n *\n * 适用平台:\n * - Web (Next.js)\n * - Desktop (Electron)\n * - Mobile (React Native)\n */\nexport class WebRequestAdapter implements RequestAdapter {\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n // 构建 URL(如果有查询参数)\n let fullUrl = url;\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n const queryString = searchParams.toString();\n if (queryString) {\n fullUrl += (url.includes('?') ? '&' : '?') + queryString;\n }\n }\n\n // 发送请求\n const response = await fetch(fullUrl, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n credentials: 'include', // 🔐 自动发送和接收 Cookie(支持 httpOnly Cookie 认证)\n });\n\n // 解析响应\n const data = await response.json();\n\n // 如果响应不成功,返回错误格式\n if (!response.ok) {\n return {\n success: false,\n error: data.error || '请求失败: ' + (response.status),\n } as T;\n }\n\n return data;\n }\n}\n\n","import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Taro Request 接口定义\n * 兼容 @tarojs/taro request API\n */\ninterface TaroRequestStatic {\n request<T = any>(options: {\n url: string;\n method?: string;\n header?: Record<string, string>;\n data?: any;\n }): Promise<{\n statusCode: number;\n data: T;\n }>;\n}\n\n/**\n * Miniapp 平台请求适配器\n * 基于 Taro.request API\n *\n * 使用方式:\n * ```typescript\n * import Taro from '@tarojs/taro'\n * const adapter = new MiniappRequestAdapter(Taro)\n * ```\n *\n * 适用平台:\n * - WeChat Miniapp\n * - Other Taro-based miniapps\n */\nexport class MiniappRequestAdapter implements RequestAdapter {\n private taro: TaroRequestStatic;\n\n constructor(taro: TaroRequestStatic) {\n if (!taro) {\n throw new Error('MiniappRequestAdapter requires Taro instance');\n }\n this.taro = taro;\n }\n\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n try {\n const response = await this.taro.request({\n url,\n method: method as any,\n header: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n data: method === 'GET' ? params : body,\n });\n\n const data = response.data as any;\n\n // 统一返回格式\n if (response.statusCode >= 200 && response.statusCode < 300) {\n return data;\n } else {\n return {\n success: false,\n error: data.error || '请求失败: ' + (response.statusCode),\n } as T;\n }\n } catch (error) {\n console.error('[MiniappRequestAdapter] request error:', error);\n return {\n success: false,\n error: error instanceof Error ? error.message : '网络请求失败',\n } as T;\n }\n }\n}\n\n"]}
@@ -31,7 +31,7 @@ var WebRequestAdapter = class {
31
31
  if (!response.ok) {
32
32
  return {
33
33
  success: false,
34
- error: data.error || `\u8BF7\u6C42\u5931\u8D25: ${response.status}`
34
+ error: data.error || "\u8BF7\u6C42\u5931\u8D25: " + response.status
35
35
  };
36
36
  }
37
37
  return data;
@@ -64,7 +64,7 @@ var MiniappRequestAdapter = class {
64
64
  } else {
65
65
  return {
66
66
  success: false,
67
- error: data.error || `\u8BF7\u6C42\u5931\u8D25: ${response.statusCode}`
67
+ error: data.error || "\u8BF7\u6C42\u5931\u8D25: " + response.statusCode
68
68
  };
69
69
  }
70
70
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/request/adapters/web-adapter.ts","../../src/request/adapters/miniapp-adapter.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Web 平台请求适配器\n * 基于标准 fetch API\n *\n * 适用平台:\n * - Web (Next.js)\n * - Desktop (Electron)\n * - Mobile (React Native)\n */\nexport class WebRequestAdapter implements RequestAdapter {\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n // 构建 URL(如果有查询参数)\n let fullUrl = url;\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n const queryString = searchParams.toString();\n if (queryString) {\n fullUrl += (url.includes('?') ? '&' : '?') + queryString;\n }\n }\n\n // 发送请求\n const response = await fetch(fullUrl, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n credentials: 'include', // 🔐 自动发送和接收 Cookie(支持 httpOnly Cookie 认证)\n });\n\n // 解析响应\n const data = await response.json();\n\n // 如果响应不成功,返回错误格式\n if (!response.ok) {\n return {\n success: false,\n error: data.error || `请求失败: ${response.status}`,\n } as T;\n }\n\n return data;\n }\n}\n\n","import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Taro Request 接口定义\n * 兼容 @tarojs/taro request API\n */\ninterface TaroRequestStatic {\n request<T = any>(options: {\n url: string;\n method?: string;\n header?: Record<string, string>;\n data?: any;\n }): Promise<{\n statusCode: number;\n data: T;\n }>;\n}\n\n/**\n * Miniapp 平台请求适配器\n * 基于 Taro.request API\n *\n * 使用方式:\n * ```typescript\n * import Taro from '@tarojs/taro'\n * const adapter = new MiniappRequestAdapter(Taro)\n * ```\n *\n * 适用平台:\n * - WeChat Miniapp\n * - Other Taro-based miniapps\n */\nexport class MiniappRequestAdapter implements RequestAdapter {\n private taro: TaroRequestStatic;\n\n constructor(taro: TaroRequestStatic) {\n if (!taro) {\n throw new Error('MiniappRequestAdapter requires Taro instance');\n }\n this.taro = taro;\n }\n\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n try {\n const response = await this.taro.request({\n url,\n method: method as any,\n header: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n data: method === 'GET' ? params : body,\n });\n\n const data = response.data as any;\n\n // 统一返回格式\n if (response.statusCode >= 200 && response.statusCode < 300) {\n return data;\n } else {\n return {\n success: false,\n error: data.error || `请求失败: ${response.statusCode}`,\n } as T;\n }\n } catch (error) {\n console.error('[MiniappRequestAdapter] request error:', error);\n return {\n success: false,\n error: error instanceof Error ? error.message : '网络请求失败',\n } as T;\n }\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../../src/request/adapters/web-adapter.ts","../../src/request/adapters/miniapp-adapter.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Web 平台请求适配器\n * 基于标准 fetch API\n *\n * 适用平台:\n * - Web (Next.js)\n * - Desktop (Electron)\n * - Mobile (React Native)\n */\nexport class WebRequestAdapter implements RequestAdapter {\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n // 构建 URL(如果有查询参数)\n let fullUrl = url;\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n const queryString = searchParams.toString();\n if (queryString) {\n fullUrl += (url.includes('?') ? '&' : '?') + queryString;\n }\n }\n\n // 发送请求\n const response = await fetch(fullUrl, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n credentials: 'include', // 🔐 自动发送和接收 Cookie(支持 httpOnly Cookie 认证)\n });\n\n // 解析响应\n const data = await response.json();\n\n // 如果响应不成功,返回错误格式\n if (!response.ok) {\n return {\n success: false,\n error: data.error || '请求失败: ' + (response.status),\n } as T;\n }\n\n return data;\n }\n}\n\n","import type { RequestAdapter, RequestConfig } from '../types/types';\n\n/**\n * Taro Request 接口定义\n * 兼容 @tarojs/taro request API\n */\ninterface TaroRequestStatic {\n request<T = any>(options: {\n url: string;\n method?: string;\n header?: Record<string, string>;\n data?: any;\n }): Promise<{\n statusCode: number;\n data: T;\n }>;\n}\n\n/**\n * Miniapp 平台请求适配器\n * 基于 Taro.request API\n *\n * 使用方式:\n * ```typescript\n * import Taro from '@tarojs/taro'\n * const adapter = new MiniappRequestAdapter(Taro)\n * ```\n *\n * 适用平台:\n * - WeChat Miniapp\n * - Other Taro-based miniapps\n */\nexport class MiniappRequestAdapter implements RequestAdapter {\n private taro: TaroRequestStatic;\n\n constructor(taro: TaroRequestStatic) {\n if (!taro) {\n throw new Error('MiniappRequestAdapter requires Taro instance');\n }\n this.taro = taro;\n }\n\n async request<T = any>(config: RequestConfig): Promise<T> {\n const { url, method = 'GET', headers = {}, body, params } = config;\n\n try {\n const response = await this.taro.request({\n url,\n method: method as any,\n header: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n data: method === 'GET' ? params : body,\n });\n\n const data = response.data as any;\n\n // 统一返回格式\n if (response.statusCode >= 200 && response.statusCode < 300) {\n return data;\n } else {\n return {\n success: false,\n error: data.error || '请求失败: ' + (response.statusCode),\n } as T;\n }\n } catch (error) {\n console.error('[MiniappRequestAdapter] request error:', error);\n return {\n success: false,\n error: error instanceof Error ? error.message : '网络请求失败',\n } as T;\n }\n }\n}\n\n"]}
@@ -1,46 +1,46 @@
1
1
  'use strict';
2
2
 
3
- var chunkLX4XX6W7_js = require('../chunk-LX4XX6W7.js');
4
- var chunkQU5OT4DF_js = require('../chunk-QU5OT4DF.js');
3
+ var chunkC54W2CMK_js = require('../chunk-C54W2CMK.js');
4
+ var chunkXJ7ZAGC5_js = require('../chunk-XJ7ZAGC5.js');
5
5
  require('../chunk-DGUM43GV.js');
6
6
 
7
7
 
8
8
 
9
9
  Object.defineProperty(exports, "ElectronStorageAdapter", {
10
10
  enumerable: true,
11
- get: function () { return chunkLX4XX6W7_js.ElectronStorageAdapter; }
11
+ get: function () { return chunkC54W2CMK_js.ElectronStorageAdapter; }
12
12
  });
13
13
  Object.defineProperty(exports, "MiniAppStorageAdapter", {
14
14
  enumerable: true,
15
- get: function () { return chunkLX4XX6W7_js.MiniAppStorageAdapter; }
15
+ get: function () { return chunkC54W2CMK_js.MiniAppStorageAdapter; }
16
16
  });
17
17
  Object.defineProperty(exports, "ReactNativeStorageAdapter", {
18
18
  enumerable: true,
19
- get: function () { return chunkLX4XX6W7_js.ReactNativeStorageAdapter; }
19
+ get: function () { return chunkC54W2CMK_js.ReactNativeStorageAdapter; }
20
20
  });
21
21
  Object.defineProperty(exports, "useAsyncStorage", {
22
22
  enumerable: true,
23
- get: function () { return chunkLX4XX6W7_js.useAsyncStorage; }
23
+ get: function () { return chunkC54W2CMK_js.useAsyncStorage; }
24
24
  });
25
25
  Object.defineProperty(exports, "useElectronStorage", {
26
26
  enumerable: true,
27
- get: function () { return chunkLX4XX6W7_js.useElectronStorage; }
27
+ get: function () { return chunkC54W2CMK_js.useElectronStorage; }
28
28
  });
29
29
  Object.defineProperty(exports, "useLocalStorage", {
30
30
  enumerable: true,
31
- get: function () { return chunkLX4XX6W7_js.useLocalStorage; }
31
+ get: function () { return chunkC54W2CMK_js.useLocalStorage; }
32
32
  });
33
33
  Object.defineProperty(exports, "useStorage", {
34
34
  enumerable: true,
35
- get: function () { return chunkLX4XX6W7_js.useStorage; }
35
+ get: function () { return chunkC54W2CMK_js.useStorage; }
36
36
  });
37
37
  Object.defineProperty(exports, "useTaroStorage", {
38
38
  enumerable: true,
39
- get: function () { return chunkLX4XX6W7_js.useTaroStorage; }
39
+ get: function () { return chunkC54W2CMK_js.useTaroStorage; }
40
40
  });
41
41
  Object.defineProperty(exports, "WebStorageAdapter", {
42
42
  enumerable: true,
43
- get: function () { return chunkQU5OT4DF_js.WebStorageAdapter; }
43
+ get: function () { return chunkXJ7ZAGC5_js.WebStorageAdapter; }
44
44
  });
45
45
  //# sourceMappingURL=index.js.map
46
46
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- export { ElectronStorageAdapter, MiniAppStorageAdapter, ReactNativeStorageAdapter, useAsyncStorage, useElectronStorage, useLocalStorage, useStorage, useTaroStorage } from '../chunk-T5OZHYVM.mjs';
2
- export { WebStorageAdapter } from '../chunk-OLHGZXN3.mjs';
1
+ export { ElectronStorageAdapter, MiniAppStorageAdapter, ReactNativeStorageAdapter, useAsyncStorage, useElectronStorage, useLocalStorage, useStorage, useTaroStorage } from '../chunk-TVROG2Q4.mjs';
2
+ export { WebStorageAdapter } from '../chunk-WEEXCPSE.mjs';
3
3
  import '../chunk-BJTO5JO5.mjs';
4
4
  //# sourceMappingURL=index.mjs.map
5
5
  //# sourceMappingURL=index.mjs.map
@@ -1,17 +1,17 @@
1
1
  'use strict';
2
2
 
3
- var chunkCLKKZSPZ_js = require('../../chunk-CLKKZSPZ.js');
3
+ var chunkRBKGYWME_js = require('../../chunk-RBKGYWME.js');
4
4
  require('../../chunk-DGUM43GV.js');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "ConfigList", {
9
9
  enumerable: true,
10
- get: function () { return chunkCLKKZSPZ_js.ConfigList; }
10
+ get: function () { return chunkRBKGYWME_js.ConfigList; }
11
11
  });
12
12
  Object.defineProperty(exports, "ConfigManager", {
13
13
  enumerable: true,
14
- get: function () { return chunkCLKKZSPZ_js.ConfigManager; }
14
+ get: function () { return chunkRBKGYWME_js.ConfigManager; }
15
15
  });
16
16
  //# sourceMappingURL=index.js.map
17
17
  //# sourceMappingURL=index.js.map