uomtiles 0.1.2 → 0.1.3

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 (303) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/7KYNy7kZ.js +1 -0
  3. package/.output/public/_nuxt/7Rgc2iDI2.js +1 -0
  4. package/.output/public/_nuxt/BA52uD81.js +1 -0
  5. package/.output/public/_nuxt/{CU486JdV2.js → BHSn2vP72.js} +2 -2
  6. package/.output/public/_nuxt/BRsHq3Fz2.js +1 -0
  7. package/.output/public/_nuxt/Bh2Uv1S7.js +1 -0
  8. package/.output/public/_nuxt/BiRI-vq-.js +1 -0
  9. package/.output/public/_nuxt/Bpc1HTfh.js +1 -0
  10. package/.output/public/_nuxt/C-b4mqsD.js +1 -0
  11. package/.output/public/_nuxt/C5Y76DD6.js +1 -0
  12. package/.output/public/_nuxt/CD84FXNW.js +1 -0
  13. package/.output/public/_nuxt/CGkIG2vL2.js +1 -0
  14. package/.output/public/_nuxt/CM9IbYJz.js +1 -0
  15. package/.output/public/_nuxt/CUJ4QmLF.js +1 -0
  16. package/.output/public/_nuxt/CUQ3MZqI.js +1 -0
  17. package/.output/public/_nuxt/CVwoxklV.js +1 -0
  18. package/.output/public/_nuxt/CeHZqNQ0.js +1 -0
  19. package/.output/public/_nuxt/CkfS_Wbu.js +3 -0
  20. package/.output/public/_nuxt/CoPjdBwX.js +1 -0
  21. package/.output/public/_nuxt/CxkDmpVY.js +1 -0
  22. package/.output/public/_nuxt/CzRdWh7s2.js +1 -0
  23. package/.output/public/_nuxt/D-IOtyQX.js +1 -0
  24. package/.output/public/_nuxt/D3Us7gX72.js +1 -0
  25. package/.output/public/_nuxt/{DaQqwE3R.js → D8GHPYwQ.js} +44 -44
  26. package/.output/public/_nuxt/DLIy3f3M.js +1 -0
  27. package/.output/public/_nuxt/{CovBj6WN.js → DQ8r1OSk.js} +1 -1
  28. package/.output/public/_nuxt/D_9SjQFe.js +1 -0
  29. package/.output/public/_nuxt/D_Ggu6R_2.js +1 -0
  30. package/.output/public/_nuxt/{Q79ec-Ro.js → DnVJUY7B.js} +1 -1
  31. package/.output/public/_nuxt/{Bd1EvHmY.js → DuGgjt-h2.js} +1 -1
  32. package/.output/public/_nuxt/GEOST6As.js +1 -0
  33. package/.output/public/_nuxt/{DpIPeY5m.js → GqgcWtrL.js} +1 -1
  34. package/.output/public/_nuxt/{0hm88Oke.js → Hbp_Okvs.js} +1 -1
  35. package/.output/public/_nuxt/JdUwgqKv.js +1 -0
  36. package/.output/public/_nuxt/KttxEAyP2.js +1 -0
  37. package/.output/public/_nuxt/L0GXeO1Y2.js +1 -0
  38. package/.output/public/_nuxt/builds/latest.json +1 -1
  39. package/.output/public/_nuxt/builds/meta/ad8f3148-5aa4-4a0f-8e7a-e55147c5de1a.json +1 -0
  40. package/.output/public/_nuxt/entry.U-KS0GEu.css +1 -0
  41. package/.output/public/_nuxt/sMWyPZfC2.js +1 -0
  42. package/.output/public/_nuxt/zUWhKXtw2.js +1 -0
  43. package/.output/server/chunks/_/antigravity-nfz.mjs +629 -0
  44. package/.output/server/chunks/_/antigravity-nfz.mjs.map +1 -0
  45. package/.output/server/chunks/_/config.mjs +1 -1
  46. package/.output/server/chunks/_/file-workspace.mjs +1 -1
  47. package/.output/server/chunks/_/map-layer-update-manager.mjs +770 -0
  48. package/.output/server/chunks/_/map-layer-update-manager.mjs.map +1 -0
  49. package/.output/server/chunks/_/map-service.mjs +1 -1
  50. package/.output/server/chunks/_/uom-auth.mjs +1 -1
  51. package/.output/server/chunks/build/{CompletedTaskSelect-CKTpyHS3.mjs → CompletedTaskSelect-Ba03kTs9.mjs} +6 -7
  52. package/.output/server/chunks/build/{CompletedTaskSelect-CKTpyHS3.mjs.map → CompletedTaskSelect-Ba03kTs9.mjs.map} +1 -1
  53. package/.output/server/chunks/build/{Empty-BGIn09cL.mjs → Empty-CKvANuoV.mjs} +4 -103
  54. package/.output/server/chunks/build/Empty-CKvANuoV.mjs.map +1 -0
  55. package/.output/server/chunks/build/{FormField-DnJWfrKE.mjs → FormField-BJHVyy1m.mjs} +4 -35
  56. package/.output/server/chunks/build/FormField-BJHVyy1m.mjs.map +1 -0
  57. package/.output/server/chunks/build/{Input-AdlINKtJ.mjs → Input-DnAric-z.mjs} +1 -1
  58. package/.output/server/chunks/build/{Input-AdlINKtJ.mjs.map → Input-DnAric-z.mjs.map} +1 -1
  59. package/.output/server/chunks/build/MapLayerControl-DpNmYvcU.mjs +5720 -0
  60. package/.output/server/chunks/build/MapLayerControl-DpNmYvcU.mjs.map +1 -0
  61. package/.output/server/chunks/build/{Modal-CozaqIp1.mjs → Modal-BLhN9Eg2.mjs} +4 -18
  62. package/.output/server/chunks/build/{Modal-CozaqIp1.mjs.map → Modal-BLhN9Eg2.mjs.map} +1 -1
  63. package/.output/server/chunks/build/{OnlineMap-cFSicmkV.mjs → OnlineMap-B-sCfHkC.mjs} +6 -3
  64. package/.output/server/chunks/build/OnlineMap-B-sCfHkC.mjs.map +1 -0
  65. package/.output/server/chunks/build/{Pagination-GvNCxmOW.mjs → Pagination-CUzoLc_-.mjs} +1 -1
  66. package/.output/server/chunks/build/{Pagination-GvNCxmOW.mjs.map → Pagination-CUzoLc_-.mjs.map} +1 -1
  67. package/.output/server/chunks/build/Skeleton-CHp-GjOx.mjs +59 -0
  68. package/.output/server/chunks/build/Skeleton-CHp-GjOx.mjs.map +1 -0
  69. package/.output/server/chunks/build/{Slider-zQx1c7hB.mjs → Slider-CrIUK3pl.mjs} +5 -5
  70. package/.output/server/chunks/build/{Slider-zQx1c7hB.mjs.map → Slider-CrIUK3pl.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{MapBaseLayerTabs-CRl5Zwlr.mjs → Tabs-cdLsZZoL.mjs} +429 -931
  72. package/.output/server/chunks/build/Tabs-cdLsZZoL.mjs.map +1 -0
  73. package/.output/server/chunks/build/{Tooltip-DNUdH4oF.mjs → Tooltip-DExIlyhu.mjs} +4 -195
  74. package/.output/server/chunks/build/Tooltip-DExIlyhu.mjs.map +1 -0
  75. package/.output/server/chunks/build/{advanced-5ZGMUBqC.mjs → advanced-DaSpS8Px.mjs} +31 -34
  76. package/.output/server/chunks/build/advanced-DaSpS8Px.mjs.map +1 -0
  77. package/.output/server/chunks/build/{compare-CtgF4Anj.mjs → compare-DaE10Dhp.mjs} +56 -37
  78. package/.output/server/chunks/build/compare-DaE10Dhp.mjs.map +1 -0
  79. package/.output/server/chunks/build/cookie-CziAmOf1.mjs +175 -0
  80. package/.output/server/chunks/build/cookie-CziAmOf1.mjs.map +1 -0
  81. package/.output/server/chunks/build/{dashboard-GneN-WPG.mjs → dashboard-Dq8mphss.mjs} +12 -6
  82. package/.output/server/chunks/build/{dashboard-GneN-WPG.mjs.map → dashboard-Dq8mphss.mjs.map} +1 -1
  83. package/.output/server/chunks/build/{details-CgufnL1d.mjs → details-DCNvSBgn.mjs} +5 -4
  84. package/.output/server/chunks/build/{details-CgufnL1d.mjs.map → details-DCNvSBgn.mjs.map} +1 -1
  85. package/.output/server/chunks/build/error-404-D9aQjJRn.mjs +1 -1
  86. package/.output/server/chunks/build/error-500-BNyA3wrb.mjs +1 -1
  87. package/.output/server/chunks/build/file-workspace-DMzPuPyG.mjs +104 -0
  88. package/.output/server/chunks/build/file-workspace-DMzPuPyG.mjs.map +1 -0
  89. package/.output/server/chunks/build/{interval-9B2MrM2e.mjs → interval-i5OZnTaK.mjs} +2 -2
  90. package/.output/server/chunks/build/{interval-9B2MrM2e.mjs.map → interval-i5OZnTaK.mjs.map} +1 -1
  91. package/.output/server/chunks/build/layers-50nqoWES.mjs +553 -0
  92. package/.output/server/chunks/build/layers-50nqoWES.mjs.map +1 -0
  93. package/.output/server/chunks/build/{login-Cf5EiCE4.mjs → login-BHSHtO-R.mjs} +6 -5
  94. package/.output/server/chunks/build/{login-Cf5EiCE4.mjs.map → login-BHSHtO-R.mjs.map} +1 -1
  95. package/.output/server/chunks/build/map-layers-C3HJoCLw.mjs +86 -0
  96. package/.output/server/chunks/build/map-layers-C3HJoCLw.mjs.map +1 -0
  97. package/.output/server/chunks/build/{DashboardSidebarToggle-CUI9NSow.mjs → overlay-BS4_B29H.mjs} +411 -4
  98. package/.output/server/chunks/build/overlay-BS4_B29H.mjs.map +1 -0
  99. package/.output/server/chunks/build/pages-5yYRS5nX.mjs +37 -0
  100. package/.output/server/chunks/build/pages-5yYRS5nX.mjs.map +1 -0
  101. package/.output/server/chunks/build/{pages-0c5sp_lv.mjs → pages-DfOPr0fC.mjs} +21 -21
  102. package/.output/server/chunks/build/pages-DfOPr0fC.mjs.map +1 -0
  103. package/.output/server/chunks/build/{services-BB49kSpd.mjs → services-DWlDpsbi.mjs} +45 -41
  104. package/.output/server/chunks/build/{services-BB49kSpd.mjs.map → services-DWlDpsbi.mjs.map} +1 -1
  105. package/.output/server/chunks/build/{tasks-BRcMLuRW.mjs → tasks-4b6D39Uy.mjs} +44 -100
  106. package/.output/server/chunks/build/{tasks-BRcMLuRW.mjs.map → tasks-4b6D39Uy.mjs.map} +1 -1
  107. package/.output/server/chunks/build/{tasks-Aa8PwjVL.mjs → tasks-BPPx2UMG.mjs} +10 -6
  108. package/.output/server/chunks/build/tasks-BPPx2UMG.mjs.map +1 -0
  109. package/.output/server/chunks/nitro/nitro.mjs +303 -244
  110. package/.output/server/chunks/routes/api/map/layers/_overlayLayer/update.get.mjs +29 -0
  111. package/.output/server/chunks/routes/api/map/layers/_overlayLayer/update.get.mjs.map +1 -0
  112. package/.output/server/chunks/routes/api/map/layers/_overlayLayer/update.post.mjs +31 -0
  113. package/.output/server/chunks/routes/api/map/layers/_overlayLayer/update.post.mjs.map +1 -0
  114. package/.output/server/chunks/routes/api/map/layers/_overlayLayer_.get.mjs +39 -0
  115. package/.output/server/chunks/routes/api/map/layers/_overlayLayer_.get.mjs.map +1 -0
  116. package/.output/server/chunks/routes/api/map/layers/status.get.mjs +60 -0
  117. package/.output/server/chunks/routes/api/map/layers/status.get.mjs.map +1 -0
  118. package/.output/server/chunks/routes/api/map/live/status.get.mjs +1 -1
  119. package/.output/server/chunks/routes/api/map/online/_layerGroup/_zoom/_tileX/_tileY_.get.mjs +1 -1
  120. package/.output/server/chunks/routes/api/map/online-root/_layerGroup/_rootX/_rootY_.get.mjs +1 -1
  121. package/.output/server/chunks/routes/api/workspace/_filename/analysis.get.mjs +1 -1
  122. package/.output/server/chunks/routes/api/workspace/_filename/download.get.mjs +1 -1
  123. package/.output/server/chunks/routes/api/workspace/_filename/export/_format_.get.mjs +1 -1
  124. package/.output/server/chunks/routes/api/workspace/_filename/export-estimate.get.mjs +1 -1
  125. package/.output/server/chunks/routes/api/workspace/_filename/tile.get.mjs +1 -1
  126. package/.output/server/chunks/routes/api/workspace/_filename/tiles.get.mjs +1 -1
  127. package/.output/server/chunks/routes/api/workspace/_filename_.delete.mjs +1 -1
  128. package/.output/server/chunks/routes/api/workspace/compare/batch.get.mjs +1 -1
  129. package/.output/server/chunks/routes/api/workspace/files.post.mjs +1 -1
  130. package/.output/server/chunks/routes/api/workspace/stop.post.mjs +1 -1
  131. package/.output/server/chunks/routes/api/workspace/tasks.post.mjs +2 -2
  132. package/.output/server/chunks/routes/renderer.mjs +3 -3
  133. package/.output/server/chunks/routes/services/wms.get.mjs +1 -1
  134. package/.output/server/chunks/routes/services/wmts.get.mjs +1 -1
  135. package/.output/server/chunks/virtual/entry.mjs +320 -443
  136. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  137. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  138. package/.output/server/chunks/virtual/styles.mjs +1 -1
  139. package/.output/server/node_modules/undici/index.js +234 -0
  140. package/.output/server/node_modules/undici/lib/api/abort-signal.js +59 -0
  141. package/.output/server/node_modules/undici/lib/api/api-connect.js +110 -0
  142. package/.output/server/node_modules/undici/lib/api/api-pipeline.js +252 -0
  143. package/.output/server/node_modules/undici/lib/api/api-request.js +214 -0
  144. package/.output/server/node_modules/undici/lib/api/api-stream.js +209 -0
  145. package/.output/server/node_modules/undici/lib/api/api-upgrade.js +111 -0
  146. package/.output/server/node_modules/undici/lib/api/index.js +7 -0
  147. package/.output/server/node_modules/undici/lib/api/readable.js +580 -0
  148. package/.output/server/node_modules/undici/lib/cache/memory-cache-store.js +279 -0
  149. package/.output/server/node_modules/undici/lib/cache/sqlite-cache-store.js +467 -0
  150. package/.output/server/node_modules/undici/lib/core/connect.js +153 -0
  151. package/.output/server/node_modules/undici/lib/core/constants.js +143 -0
  152. package/.output/server/node_modules/undici/lib/core/diagnostics.js +227 -0
  153. package/.output/server/node_modules/undici/lib/core/errors.js +477 -0
  154. package/.output/server/node_modules/undici/lib/core/request.js +464 -0
  155. package/.output/server/node_modules/undici/lib/core/socks5-client.js +422 -0
  156. package/.output/server/node_modules/undici/lib/core/socks5-utils.js +212 -0
  157. package/.output/server/node_modules/undici/lib/core/symbols.js +75 -0
  158. package/.output/server/node_modules/undici/lib/core/tree.js +160 -0
  159. package/.output/server/node_modules/undici/lib/core/util.js +992 -0
  160. package/.output/server/node_modules/undici/lib/dispatcher/agent.js +158 -0
  161. package/.output/server/node_modules/undici/lib/dispatcher/balanced-pool.js +219 -0
  162. package/.output/server/node_modules/undici/lib/dispatcher/client-h1.js +1731 -0
  163. package/.output/server/node_modules/undici/lib/dispatcher/client-h2.js +995 -0
  164. package/.output/server/node_modules/undici/lib/dispatcher/client.js +664 -0
  165. package/.output/server/node_modules/undici/lib/dispatcher/dispatcher-base.js +184 -0
  166. package/.output/server/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
  167. package/.output/server/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
  168. package/.output/server/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
  169. package/.output/server/node_modules/undici/lib/dispatcher/h2c-client.js +51 -0
  170. package/.output/server/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
  171. package/.output/server/node_modules/undici/lib/dispatcher/pool.js +118 -0
  172. package/.output/server/node_modules/undici/lib/dispatcher/proxy-agent.js +319 -0
  173. package/.output/server/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
  174. package/.output/server/node_modules/undici/lib/dispatcher/round-robin-pool.js +137 -0
  175. package/.output/server/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +260 -0
  176. package/.output/server/node_modules/undici/lib/encoding/index.js +33 -0
  177. package/.output/server/node_modules/undici/lib/global.js +59 -0
  178. package/.output/server/node_modules/undici/lib/handler/cache-handler.js +760 -0
  179. package/.output/server/node_modules/undici/lib/handler/cache-revalidation-handler.js +124 -0
  180. package/.output/server/node_modules/undici/lib/handler/decorator-handler.js +67 -0
  181. package/.output/server/node_modules/undici/lib/handler/deduplication-handler.js +460 -0
  182. package/.output/server/node_modules/undici/lib/handler/redirect-handler.js +238 -0
  183. package/.output/server/node_modules/undici/lib/handler/retry-handler.js +418 -0
  184. package/.output/server/node_modules/undici/lib/handler/unwrap-handler.js +106 -0
  185. package/.output/server/node_modules/undici/lib/handler/wrap-handler.js +105 -0
  186. package/.output/server/node_modules/undici/lib/interceptor/cache.js +602 -0
  187. package/.output/server/node_modules/undici/lib/interceptor/decompress.js +259 -0
  188. package/.output/server/node_modules/undici/lib/interceptor/deduplicate.js +117 -0
  189. package/.output/server/node_modules/undici/lib/interceptor/dns.js +571 -0
  190. package/.output/server/node_modules/undici/lib/interceptor/dump.js +112 -0
  191. package/.output/server/node_modules/undici/lib/interceptor/redirect.js +21 -0
  192. package/.output/server/node_modules/undici/lib/interceptor/response-error.js +95 -0
  193. package/.output/server/node_modules/undici/lib/interceptor/retry.js +19 -0
  194. package/.output/server/node_modules/undici/lib/llhttp/constants.js +531 -0
  195. package/.output/server/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
  196. package/.output/server/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
  197. package/.output/server/node_modules/undici/lib/llhttp/utils.js +12 -0
  198. package/.output/server/node_modules/undici/lib/mock/mock-agent.js +232 -0
  199. package/.output/server/node_modules/undici/lib/mock/mock-call-history.js +248 -0
  200. package/.output/server/node_modules/undici/lib/mock/mock-client.js +68 -0
  201. package/.output/server/node_modules/undici/lib/mock/mock-errors.js +29 -0
  202. package/.output/server/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
  203. package/.output/server/node_modules/undici/lib/mock/mock-pool.js +68 -0
  204. package/.output/server/node_modules/undici/lib/mock/mock-symbols.js +32 -0
  205. package/.output/server/node_modules/undici/lib/mock/mock-utils.js +486 -0
  206. package/.output/server/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
  207. package/.output/server/node_modules/undici/lib/mock/snapshot-agent.js +353 -0
  208. package/.output/server/node_modules/undici/lib/mock/snapshot-recorder.js +588 -0
  209. package/.output/server/node_modules/undici/lib/mock/snapshot-utils.js +158 -0
  210. package/.output/server/node_modules/undici/lib/util/cache.js +676 -0
  211. package/.output/server/node_modules/undici/lib/util/date.js +670 -0
  212. package/.output/server/node_modules/undici/lib/util/promise.js +28 -0
  213. package/.output/server/node_modules/undici/lib/util/runtime-features.js +124 -0
  214. package/.output/server/node_modules/undici/lib/util/stats.js +32 -0
  215. package/.output/server/node_modules/undici/lib/util/timers.js +425 -0
  216. package/.output/server/node_modules/undici/lib/web/cache/cache.js +864 -0
  217. package/.output/server/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
  218. package/.output/server/node_modules/undici/lib/web/cache/util.js +45 -0
  219. package/.output/server/node_modules/undici/lib/web/cookies/constants.js +12 -0
  220. package/.output/server/node_modules/undici/lib/web/cookies/index.js +199 -0
  221. package/.output/server/node_modules/undici/lib/web/cookies/parse.js +314 -0
  222. package/.output/server/node_modules/undici/lib/web/cookies/util.js +352 -0
  223. package/.output/server/node_modules/undici/lib/web/eventsource/eventsource-stream.js +399 -0
  224. package/.output/server/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
  225. package/.output/server/node_modules/undici/lib/web/eventsource/util.js +29 -0
  226. package/.output/server/node_modules/undici/lib/web/fetch/body.js +509 -0
  227. package/.output/server/node_modules/undici/lib/web/fetch/constants.js +131 -0
  228. package/.output/server/node_modules/undici/lib/web/fetch/data-url.js +596 -0
  229. package/.output/server/node_modules/undici/lib/web/fetch/formdata-parser.js +586 -0
  230. package/.output/server/node_modules/undici/lib/web/fetch/formdata.js +259 -0
  231. package/.output/server/node_modules/undici/lib/web/fetch/global.js +40 -0
  232. package/.output/server/node_modules/undici/lib/web/fetch/headers.js +719 -0
  233. package/.output/server/node_modules/undici/lib/web/fetch/index.js +2413 -0
  234. package/.output/server/node_modules/undici/lib/web/fetch/request.js +1115 -0
  235. package/.output/server/node_modules/undici/lib/web/fetch/response.js +641 -0
  236. package/.output/server/node_modules/undici/lib/web/fetch/util.js +1522 -0
  237. package/.output/server/node_modules/undici/lib/web/infra/index.js +229 -0
  238. package/.output/server/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +307 -0
  239. package/.output/server/node_modules/undici/lib/web/webidl/index.js +1006 -0
  240. package/.output/server/node_modules/undici/lib/web/websocket/connection.js +329 -0
  241. package/.output/server/node_modules/undici/lib/web/websocket/constants.js +126 -0
  242. package/.output/server/node_modules/undici/lib/web/websocket/events.js +331 -0
  243. package/.output/server/node_modules/undici/lib/web/websocket/frame.js +133 -0
  244. package/.output/server/node_modules/undici/lib/web/websocket/permessage-deflate.js +100 -0
  245. package/.output/server/node_modules/undici/lib/web/websocket/receiver.js +507 -0
  246. package/.output/server/node_modules/undici/lib/web/websocket/sender.js +109 -0
  247. package/.output/server/node_modules/undici/lib/web/websocket/stream/websocketerror.js +104 -0
  248. package/.output/server/node_modules/undici/lib/web/websocket/stream/websocketstream.js +498 -0
  249. package/.output/server/node_modules/undici/lib/web/websocket/util.js +347 -0
  250. package/.output/server/node_modules/undici/lib/web/websocket/websocket.js +758 -0
  251. package/.output/server/node_modules/undici/package.json +152 -0
  252. package/.output/server/package.json +2 -1
  253. package/LICENSE +201 -2
  254. package/README.md +17 -4
  255. package/dist/package.json +3 -2
  256. package/dist/shared/antigravity-schema.js +45 -0
  257. package/dist/shared/dji-grid.js +62 -0
  258. package/dist/shared/types/map-layers.js +2 -0
  259. package/dist/src/cli.js +63 -5
  260. package/dist/src/core/dji-snapshot.js +135 -0
  261. package/dist/src/core/map-layer-paths.js +11 -0
  262. package/dist/src/map-layer-update.js +646 -0
  263. package/package.json +3 -2
  264. package/.output/public/_nuxt/BNfSclJ4.js +0 -1
  265. package/.output/public/_nuxt/BYzlinOr2.js +0 -1
  266. package/.output/public/_nuxt/Be4dNlar.js +0 -1
  267. package/.output/public/_nuxt/C7fHMLd7.js +0 -1
  268. package/.output/public/_nuxt/CNs_Ozdc.js +0 -1
  269. package/.output/public/_nuxt/CQ8inUdm.js +0 -1
  270. package/.output/public/_nuxt/Cc_JfSB1.js +0 -1
  271. package/.output/public/_nuxt/CyZDc0eO2.js +0 -1
  272. package/.output/public/_nuxt/CzFefJH0.js +0 -1
  273. package/.output/public/_nuxt/D-t0hXHB.js +0 -1
  274. package/.output/public/_nuxt/D3Pl7yw22.js +0 -1
  275. package/.output/public/_nuxt/D4gbGuiW.js +0 -1
  276. package/.output/public/_nuxt/DDp9lK3g.js +0 -1
  277. package/.output/public/_nuxt/DIIXHC50.js +0 -1
  278. package/.output/public/_nuxt/DWFUvzz0.js +0 -1
  279. package/.output/public/_nuxt/D_VoD6-f.js +0 -1
  280. package/.output/public/_nuxt/DfXX-x_z.js +0 -1
  281. package/.output/public/_nuxt/Dgyf2aNY.js +0 -1
  282. package/.output/public/_nuxt/GM5myUL22.js +0 -1
  283. package/.output/public/_nuxt/IC4wc76W.js +0 -1
  284. package/.output/public/_nuxt/IfL46N3Z.js +0 -1
  285. package/.output/public/_nuxt/KEU2l6zJ.js +0 -3
  286. package/.output/public/_nuxt/SEETjfdJ.js +0 -1
  287. package/.output/public/_nuxt/builds/meta/2c4adba2-91b5-44e4-91d3-50a61695207b.json +0 -1
  288. package/.output/public/_nuxt/entry.CZ_dkjcs.css +0 -1
  289. package/.output/public/_nuxt/nGp0t_eD.js +0 -1
  290. package/.output/server/chunks/build/Alert-DHVVSgdD.mjs +0 -1074
  291. package/.output/server/chunks/build/Alert-DHVVSgdD.mjs.map +0 -1
  292. package/.output/server/chunks/build/DashboardSidebarToggle-CUI9NSow.mjs.map +0 -1
  293. package/.output/server/chunks/build/Empty-BGIn09cL.mjs.map +0 -1
  294. package/.output/server/chunks/build/FocusScope-DNZVMnza.mjs +0 -207
  295. package/.output/server/chunks/build/FocusScope-DNZVMnza.mjs.map +0 -1
  296. package/.output/server/chunks/build/FormField-DnJWfrKE.mjs.map +0 -1
  297. package/.output/server/chunks/build/MapBaseLayerTabs-CRl5Zwlr.mjs.map +0 -1
  298. package/.output/server/chunks/build/OnlineMap-cFSicmkV.mjs.map +0 -1
  299. package/.output/server/chunks/build/Tooltip-DNUdH4oF.mjs.map +0 -1
  300. package/.output/server/chunks/build/advanced-5ZGMUBqC.mjs.map +0 -1
  301. package/.output/server/chunks/build/compare-CtgF4Anj.mjs.map +0 -1
  302. package/.output/server/chunks/build/pages-0c5sp_lv.mjs.map +0 -1
  303. package/.output/server/chunks/build/tasks-Aa8PwjVL.mjs.map +0 -1
@@ -0,0 +1,646 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { mkdir, readFile, readdir, rename, rm, stat, unlink, writeFile } from 'node:fs/promises';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { DatabaseSync } from 'node:sqlite';
5
+ import { fetch as undiciFetch, ProxyAgent } from 'undici';
6
+ import { assertAntigravityDatabaseSchema } from "../shared/antigravity-schema.js";
7
+ import { DJI_COVERAGE, DJI_ENDPOINT, DJI_LEVELS, DJI_MAX_SPLIT_DEPTH, DJI_OVERLAP_DEGREES, DJI_ROW_DEGREES, DJI_SATURATION_LIMIT, DJI_TARGET_DIAGONAL_KM, makeDjiBaseGrid, splitDjiCell, } from "../shared/dji-grid.js";
8
+ import { parseDjiSnapshot } from "./core/dji-snapshot.js";
9
+ export const DEFAULT_DJI_CONCURRENCY = 12;
10
+ export const DJI_RESUME_MAX_AGE_MS = 6 * 60 * 60 * 1000;
11
+ export const ANTIGRAVITY_VERSION_ENDPOINT = 'https://service.aerovista360.com/geo/open/getGeoDBInfo';
12
+ const ANTIGRAVITY_DOWNLOAD_HOST = 'static.aerovista360.com';
13
+ const ANTIGRAVITY_SNAPSHOT_TYPE = 0;
14
+ const MAX_ANTIGRAVITY_MANIFEST_BYTES = 1024 * 1024;
15
+ const MAX_ANTIGRAVITY_SNAPSHOT_BYTES = 64 * 1024 * 1024;
16
+ export async function updateMapLayers(options) {
17
+ const context = createUpdateContext(options);
18
+ try {
19
+ await mkdir(context.outputDirectory, { recursive: true });
20
+ const dji = await downloadDjiSnapshot(context);
21
+ const antigravity = await downloadAntigravitySnapshot(context);
22
+ return { dji, antigravity };
23
+ }
24
+ finally {
25
+ await closeUpdateContext(context);
26
+ }
27
+ }
28
+ export async function updateDjiSnapshot(options) {
29
+ const context = createUpdateContext(options);
30
+ try {
31
+ await mkdir(context.outputDirectory, { recursive: true });
32
+ return await downloadDjiSnapshot(context, snapshotDestination(context.outputDirectory, options.destinationPath, 'dji-nfz.json'));
33
+ }
34
+ finally {
35
+ await closeUpdateContext(context);
36
+ }
37
+ }
38
+ export async function updateAntigravitySnapshot(options) {
39
+ const context = createUpdateContext(options);
40
+ try {
41
+ await mkdir(context.outputDirectory, { recursive: true });
42
+ return await downloadAntigravitySnapshot(context, snapshotDestination(context.outputDirectory, options.destinationPath, 'antigravity-nfz.sqlite'));
43
+ }
44
+ finally {
45
+ await closeUpdateContext(context);
46
+ }
47
+ }
48
+ function createUpdateContext(options) {
49
+ if (!options || typeof options.outputDirectory !== 'string' || !options.outputDirectory.trim()) {
50
+ throw new RangeError('Map layer output directory cannot be empty');
51
+ }
52
+ const outputDirectory = resolve(options.outputDirectory);
53
+ const djiConcurrency = options.djiConcurrency ?? DEFAULT_DJI_CONCURRENCY;
54
+ const djiResume = options.djiResume ?? true;
55
+ if (!Number.isInteger(djiConcurrency) || djiConcurrency <= 0)
56
+ throw new RangeError('DJI concurrency must be a positive integer');
57
+ const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.https_proxy || process.env.http_proxy;
58
+ return {
59
+ outputDirectory,
60
+ djiRawDirectory: resolve(options.djiRawDirectory || resolve(outputDirectory, 'dji-raw')),
61
+ djiConcurrency,
62
+ djiResume,
63
+ onProgress: options.onProgress,
64
+ ...(proxy ? { dispatcher: new ProxyAgent(proxy) } : {}),
65
+ };
66
+ }
67
+ async function closeUpdateContext(context) {
68
+ await context.dispatcher?.close();
69
+ }
70
+ async function downloadDjiSnapshot(context, destination = resolve(context.outputDirectory, 'dji-nfz.json')) {
71
+ await mkdir(dirname(destination), { recursive: true });
72
+ const cells = makeDjiBaseGrid().map(queryCell);
73
+ reportProgress(context, 'dji-nfz', 'checking', 0, 1, '正在连接 DJI Flysafe');
74
+ const rawRootDirectory = context.djiRawDirectory;
75
+ await mkdir(rawRootDirectory, { recursive: true });
76
+ const session = await openDjiUpdateSession(rawRootDirectory, context.djiResume);
77
+ const rawDirectory = session.directory;
78
+ await mkdir(rawDirectory, { recursive: true });
79
+ reportProgress(context, 'dji-nfz', 'downloading', 0, cells.length, '正在检查 DJI Flysafe 区域分片');
80
+ const areas = new Map();
81
+ const serializedAreas = new Map();
82
+ let completed = 0;
83
+ let queryCount = 0;
84
+ let occurrenceCount = 0;
85
+ let conflictingDuplicateCount = 0;
86
+ let resumedQueryCount = 0;
87
+ let saturatedQueryCount = 0;
88
+ let maximumLeafResultCount = 0;
89
+ const querySummaries = [];
90
+ const startedAtMilliseconds = Date.now();
91
+ const startedAt = session.startedAt;
92
+ async function processBatch(batch) {
93
+ const saturated = new Array(batch.length);
94
+ const workerCount = Math.min(context.djiConcurrency, batch.length);
95
+ const workers = Array.from({ length: workerCount }, async (_, worker) => {
96
+ for (let index = worker; index < batch.length; index += workerCount) {
97
+ const cell = batch[index];
98
+ const result = await readOrFetchDjiCell(cell, rawDirectory, context.djiResume, context.dispatcher);
99
+ if (result.resumed)
100
+ resumedQueryCount++;
101
+ occurrenceCount += result.areas.length;
102
+ for (const area of result.areas) {
103
+ const key = djiAreaKey(area);
104
+ const serialized = JSON.stringify(area);
105
+ if (!areas.has(key)) {
106
+ areas.set(key, area);
107
+ serializedAreas.set(key, serialized);
108
+ }
109
+ else if (serializedAreas.get(key) !== serialized) {
110
+ conflictingDuplicateCount++;
111
+ }
112
+ }
113
+ const isSaturated = result.areas.length >= DJI_SATURATION_LIMIT;
114
+ querySummaries.push({
115
+ id: djiCellName(cell),
116
+ ...(cell.parentId ? { parentId: cell.parentId } : {}),
117
+ depth: cell.depth,
118
+ bounds: [cell.west, cell.south, cell.east, cell.north],
119
+ resultCount: result.areas.length,
120
+ saturated: isSaturated,
121
+ });
122
+ if (isSaturated) {
123
+ if (cell.depth >= DJI_MAX_SPLIT_DEPTH)
124
+ throw new Error(`DJI saturated cell reached maximum split depth: ${djiCellName(cell)}`);
125
+ saturated[index] = cell;
126
+ saturatedQueryCount++;
127
+ }
128
+ else {
129
+ maximumLeafResultCount = Math.max(maximumLeafResultCount, result.areas.length);
130
+ }
131
+ completed++;
132
+ queryCount++;
133
+ reportProgress(context, 'dji-nfz', 'downloading', completed, cells.length + saturatedQueryCount * 4, `已检查 ${completed} 个 DJI Flysafe 区域分片`);
134
+ if (completed % 20 === 0) {
135
+ const seconds = ((Date.now() - startedAtMilliseconds) / 1000).toFixed(1);
136
+ process.stderr.write(`DJI FlySafe: ${completed} queries, ${areas.size} unique areas, ${seconds}s\n`);
137
+ }
138
+ }
139
+ });
140
+ await Promise.all(workers);
141
+ return saturated.filter((cell) => Boolean(cell));
142
+ }
143
+ let frontier = cells;
144
+ while (frontier.length) {
145
+ const saturated = await processBatch(frontier);
146
+ frontier = saturated.flatMap(cell => splitDjiCell(queryCell(cell)).map(queryCell));
147
+ if (frontier.length)
148
+ process.stderr.write(`DJI FlySafe: splitting ${saturated.length} saturated queries into ${frontier.length} children\n`);
149
+ }
150
+ if (conflictingDuplicateCount)
151
+ throw new Error(`DJI returned ${conflictingDuplicateCount} conflicting duplicate areas`);
152
+ reportProgress(context, 'dji-nfz', 'validating', 0, 1, '正在校验 DJI Flysafe 数据');
153
+ const sortedAreas = [...areas.values()].sort((left, right) => String(left?.area_id ?? '').localeCompare(String(right?.area_id ?? ''), 'en', { numeric: true }));
154
+ const areasJson = JSON.stringify(sortedAreas);
155
+ const areasSha256 = createHash('sha256').update(areasJson).digest('hex');
156
+ const completedAt = new Date().toISOString();
157
+ const snapshot = {
158
+ formatVersion: 2,
159
+ source: 'DJI FlySafe',
160
+ scope: 'global',
161
+ startedAt,
162
+ completedAt,
163
+ fetchedAt: completedAt,
164
+ coverage: DJI_COVERAGE,
165
+ query: {
166
+ algorithmVersion: 'global-adaptive-grid-v1',
167
+ endpoint: DJI_ENDPOINT,
168
+ zonesMode: 'flysafe_website',
169
+ drone: 'dji-mavic-3',
170
+ levels: DJI_LEVELS,
171
+ rowDegrees: DJI_ROW_DEGREES,
172
+ targetDiagonalKm: DJI_TARGET_DIAGONAL_KM,
173
+ overlapDegrees: DJI_OVERLAP_DEGREES,
174
+ saturationLimit: DJI_SATURATION_LIMIT,
175
+ maxSplitDepth: DJI_MAX_SPLIT_DEPTH,
176
+ queryCount,
177
+ baseQueryCount: cells.length,
178
+ recursiveQueryCount: queryCount - cells.length,
179
+ saturatedQueryCount,
180
+ maximumLeafResultCount,
181
+ allLeafQueriesBelowSaturationLimit: true,
182
+ occurrenceCount,
183
+ uniqueAreaCount: sortedAreas.length,
184
+ duplicateOccurrences: occurrenceCount - sortedAreas.length,
185
+ conflictingDuplicateCount,
186
+ resumedQueryCount,
187
+ queries: querySummaries.sort((left, right) => left.id.localeCompare(right.id, 'en', { numeric: true })),
188
+ },
189
+ areasSha256,
190
+ areas: sortedAreas,
191
+ };
192
+ const contents = `${JSON.stringify(snapshot)}\n`;
193
+ const existing = await readDjiSnapshotIdentity(destination);
194
+ if (existing?.areasSha256 === areasSha256) {
195
+ // DJI exposes no release manifest. Keep the content hash stable, but
196
+ // refresh the snapshot timestamp so the catalog records this successful
197
+ // full check instead of making the data appear stale indefinitely.
198
+ reportProgress(context, 'dji-nfz', 'writing', 0, 1, '正在记录 DJI Flysafe 检查时间');
199
+ await atomicWrite(destination, contents);
200
+ await completeDjiUpdateSession(session);
201
+ reportProgress(context, 'dji-nfz', 'writing', 1, 1, '已检查,区域数据未变化');
202
+ return {
203
+ path: destination,
204
+ rawDirectory: rawRootDirectory,
205
+ queries: queryCount,
206
+ areas: sortedAreas.length,
207
+ bytes: Buffer.byteLength(contents),
208
+ sha256: createHash('sha256').update(contents).digest('hex'),
209
+ areasSha256,
210
+ fetchedAt: completedAt,
211
+ updated: false,
212
+ noUpdate: true,
213
+ };
214
+ }
215
+ reportProgress(context, 'dji-nfz', 'writing', 0, 1, '正在写入 DJI Flysafe 快照');
216
+ await atomicWrite(destination, contents);
217
+ await completeDjiUpdateSession(session);
218
+ reportProgress(context, 'dji-nfz', 'writing', 1, 1, 'DJI Flysafe 更新完成');
219
+ return {
220
+ path: destination,
221
+ rawDirectory: rawRootDirectory,
222
+ queries: queryCount,
223
+ areas: snapshot.areas.length,
224
+ bytes: (await stat(destination)).size,
225
+ sha256: createHash('sha256').update(contents).digest('hex'),
226
+ areasSha256,
227
+ fetchedAt: completedAt,
228
+ updated: true,
229
+ noUpdate: false,
230
+ };
231
+ }
232
+ async function readOrFetchDjiCell(cell, rawDirectory, resume, dispatcher) {
233
+ const url = djiRequestUrl(cell);
234
+ const requestHash = createHash('sha256').update(url.href).digest('hex').slice(0, 16);
235
+ const rawPath = resolve(rawDirectory, `${djiCellName(cell)}_${requestHash}.json`);
236
+ if (resume) {
237
+ try {
238
+ const payload = JSON.parse(await readFile(rawPath, 'utf8'));
239
+ return { areas: djiResponseAreas(payload), resumed: true };
240
+ }
241
+ catch { }
242
+ }
243
+ let lastError;
244
+ for (let attempt = 1; attempt <= 7; attempt++) {
245
+ try {
246
+ const response = await undiciFetch(url, {
247
+ signal: AbortSignal.timeout(60_000),
248
+ headers: { accept: 'application/json', 'user-agent': 'Mozilla/5.0 uomtiles-map-layer-updater/1.0' },
249
+ ...(dispatcher ? { dispatcher } : {}),
250
+ });
251
+ if (!response.ok) {
252
+ const error = new Error(`HTTP ${response.status}`);
253
+ error.retryAfterMilliseconds = retryAfterMilliseconds(response.headers.get('retry-after'));
254
+ throw error;
255
+ }
256
+ const declaredLength = Number(response.headers.get('content-length') || 0);
257
+ if (declaredLength > 16 * 1024 * 1024)
258
+ throw new Error('DJI response is unexpectedly large');
259
+ const body = await response.text();
260
+ if (Buffer.byteLength(body) > 16 * 1024 * 1024)
261
+ throw new Error('DJI response is unexpectedly large');
262
+ const payload = JSON.parse(body);
263
+ const responseAreas = djiResponseAreas(payload);
264
+ await atomicWrite(rawPath, body);
265
+ return { areas: responseAreas, resumed: false };
266
+ }
267
+ catch (error) {
268
+ lastError = error;
269
+ if (attempt < 7) {
270
+ const backoff = Math.min(20_000, 600 * 2 ** (attempt - 1)) + Math.floor(Math.random() * 500);
271
+ const retryAfter = error instanceof Error && 'retryAfterMilliseconds' in error
272
+ ? Number(error.retryAfterMilliseconds || 0)
273
+ : 0;
274
+ const delay = Math.max(backoff, retryAfter);
275
+ await new Promise(resolvePromise => setTimeout(resolvePromise, delay));
276
+ }
277
+ }
278
+ }
279
+ throw new Error(`DJI cell ${djiCellName(cell)} failed: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
280
+ }
281
+ function djiRequestUrl(cell) {
282
+ const url = new URL(DJI_ENDPOINT);
283
+ url.searchParams.set('ltlat', String(cell.north));
284
+ url.searchParams.set('ltlng', String(cell.west));
285
+ url.searchParams.set('rblat', String(cell.south));
286
+ url.searchParams.set('rblng', String(cell.east));
287
+ url.searchParams.set('zones_mode', 'flysafe_website');
288
+ url.searchParams.set('drone', 'dji-mavic-3');
289
+ url.searchParams.set('level', DJI_LEVELS);
290
+ return url;
291
+ }
292
+ function retryAfterMilliseconds(value) {
293
+ if (!value)
294
+ return 0;
295
+ const seconds = Number(value);
296
+ if (Number.isFinite(seconds))
297
+ return Math.max(0, seconds * 1000);
298
+ const date = Date.parse(value);
299
+ return Number.isFinite(date) ? Math.max(0, date - Date.now()) : 0;
300
+ }
301
+ function djiResponseAreas(payload) {
302
+ if (!isRecord(payload) || payload.code !== 0 || !isRecord(payload.data) || !Array.isArray(payload.data.areas)) {
303
+ throw new Error(djiResponseError(payload));
304
+ }
305
+ if (!payload.data.areas.every(isRecord))
306
+ throw new Error('invalid DJI response areas');
307
+ return payload.data.areas;
308
+ }
309
+ function djiResponseError(payload) {
310
+ if (!isRecord(payload))
311
+ return 'invalid DJI response';
312
+ if (payload.data !== undefined && payload.data !== null)
313
+ return String(payload.data);
314
+ if (isRecord(payload.message) && typeof payload.message.english === 'string')
315
+ return payload.message.english;
316
+ return 'invalid DJI response';
317
+ }
318
+ function djiCellName(cell) {
319
+ return cell.id;
320
+ }
321
+ function djiAreaKey(area) {
322
+ if (area?.area_id === undefined || area?.area_id === null || String(area.area_id).trim() === '') {
323
+ throw new Error('DJI response area is missing area_id');
324
+ }
325
+ return `id:${area.area_id}`;
326
+ }
327
+ async function downloadAntigravitySnapshot(context, destination = resolve(context.outputDirectory, 'antigravity-nfz.sqlite')) {
328
+ await mkdir(dirname(destination), { recursive: true });
329
+ const fetchedAt = new Date().toISOString();
330
+ reportProgress(context, 'antigravity-nfz', 'checking', 0, 1, '正在检查 Antigravity 在线版本');
331
+ const manifest = await fetchAntigravityManifest(context);
332
+ const current = await inspectAntigravitySnapshot(destination).catch(() => null);
333
+ if (current?.version === manifest.versionCode) {
334
+ reportProgress(context, 'antigravity-nfz', 'checking', 1, 1, '无新版本');
335
+ return {
336
+ path: destination,
337
+ bytes: current.bytes,
338
+ sha256: current.sha256,
339
+ sqliteSha256: current.sha256,
340
+ fences: current.fences,
341
+ version: current.version,
342
+ releasedAt: current.releasedAt,
343
+ expiresAt: current.expiresAt,
344
+ fetchedAt,
345
+ updated: false,
346
+ noUpdate: true,
347
+ };
348
+ }
349
+ const wrapped = await downloadAntigravityFile(context, manifest);
350
+ reportProgress(context, 'antigravity-nfz', 'validating', 0, 1, '正在校验 Antigravity 数据');
351
+ const databaseBytes = extractAntigravitySqlite(wrapped, manifest);
352
+ const temporary = `${destination}.${process.pid}.${Date.now()}.tmp`;
353
+ try {
354
+ await writeFile(temporary, databaseBytes, { mode: 0o644 });
355
+ const candidate = await inspectAntigravitySnapshot(temporary);
356
+ if (candidate.version !== manifest.versionCode) {
357
+ throw new Error(`Antigravity 版本校验失败:预期 ${manifest.versionCode},实际 ${candidate.version || '未知'}`);
358
+ }
359
+ reportProgress(context, 'antigravity-nfz', 'writing', 0, 1, '正在写入 Antigravity 快照');
360
+ await rename(temporary, destination);
361
+ reportProgress(context, 'antigravity-nfz', 'writing', 1, 1, 'Antigravity 更新完成');
362
+ return {
363
+ path: destination,
364
+ bytes: candidate.bytes,
365
+ sha256: candidate.sha256,
366
+ sqliteSha256: candidate.sha256,
367
+ fences: candidate.fences,
368
+ version: candidate.version,
369
+ releasedAt: candidate.releasedAt || manifest.releasedAt,
370
+ expiresAt: candidate.expiresAt || manifest.expiresAt,
371
+ fetchedAt,
372
+ updated: current?.sha256 !== candidate.sha256,
373
+ noUpdate: current?.sha256 === candidate.sha256,
374
+ };
375
+ }
376
+ finally {
377
+ await unlink(temporary).catch(() => { });
378
+ }
379
+ }
380
+ async function fetchAntigravityManifest(context) {
381
+ const response = await undiciFetch(ANTIGRAVITY_VERSION_ENDPOINT, {
382
+ method: 'POST',
383
+ redirect: 'error',
384
+ signal: AbortSignal.timeout(30_000),
385
+ headers: {
386
+ accept: 'application/json',
387
+ 'content-type': 'application/json',
388
+ 'user-agent': 'uomtiles-map-layer-updater/1.0',
389
+ },
390
+ body: JSON.stringify({ snapshotType: ANTIGRAVITY_SNAPSHOT_TYPE }),
391
+ ...(context.dispatcher ? { dispatcher: context.dispatcher } : {}),
392
+ });
393
+ if (!response.ok)
394
+ throw new Error(`Antigravity 版本检查失败:HTTP ${response.status}`);
395
+ const declaredLength = Number(response.headers.get('content-length') || 0);
396
+ if (declaredLength > MAX_ANTIGRAVITY_MANIFEST_BYTES)
397
+ throw new Error('Antigravity 版本响应过大');
398
+ const body = await response.text();
399
+ if (Buffer.byteLength(body) > MAX_ANTIGRAVITY_MANIFEST_BYTES)
400
+ throw new Error('Antigravity 版本响应过大');
401
+ let payload;
402
+ try {
403
+ payload = JSON.parse(body);
404
+ }
405
+ catch {
406
+ throw new Error('Antigravity 版本响应格式无效');
407
+ }
408
+ return parseAntigravityVersionManifest(payload);
409
+ }
410
+ export function parseAntigravityVersionManifest(payload) {
411
+ if (!isRecord(payload) || payload.code !== 0 || !isRecord(payload.data)) {
412
+ const message = isRecord(payload) && typeof payload.msg === 'string' ? payload.msg : '响应格式无效';
413
+ throw new Error(`Antigravity 版本检查失败:${message}`);
414
+ }
415
+ const versionCode = optionalString(payload.data.versionCode)?.trim();
416
+ const fileUrl = optionalString(payload.data.fileUrl)?.trim();
417
+ const fileSize = Number(payload.data.fileSize);
418
+ const verifyToken = optionalString(payload.data.verifyToken)?.trim().toLowerCase();
419
+ if (!versionCode || !/^[0-9][0-9A-Za-z._-]{1,63}$/.test(versionCode))
420
+ throw new Error('Antigravity 版本号无效');
421
+ if (!fileUrl)
422
+ throw new Error('Antigravity 下载地址缺失');
423
+ validateAntigravityDownloadUrl(fileUrl);
424
+ if (!Number.isSafeInteger(fileSize) || fileSize < 4096 || fileSize > MAX_ANTIGRAVITY_SNAPSHOT_BYTES) {
425
+ throw new Error('Antigravity 文件大小无效');
426
+ }
427
+ if (!verifyToken || !/^[0-9a-f]{32}$/.test(verifyToken))
428
+ throw new Error('Antigravity 校验令牌无效');
429
+ return {
430
+ versionCode,
431
+ fileUrl,
432
+ fileSize,
433
+ verifyToken,
434
+ releasedAt: optionalString(payload.data.releasedTime),
435
+ expiresAt: optionalString(payload.data.expiredTime),
436
+ };
437
+ }
438
+ export function extractAntigravitySqlite(contents, manifest) {
439
+ const wrapped = Buffer.from(contents);
440
+ if (wrapped.length !== manifest.fileSize)
441
+ throw new Error('Antigravity 下载文件大小与版本信息不符');
442
+ const wrappedMd5 = createHash('md5').update(wrapped).digest('hex');
443
+ if (wrappedMd5 !== manifest.verifyToken.toLowerCase())
444
+ throw new Error('Antigravity 下载文件校验失败');
445
+ const marker = wrapped.indexOf(Buffer.from('SQLite format 3\0', 'ascii'));
446
+ if (marker < 0)
447
+ throw new Error('Antigravity 数据中未找到 SQLite 快照');
448
+ const databaseBytes = wrapped.subarray(marker);
449
+ if (databaseBytes.length < 4096 || databaseBytes.length % 4096 !== 0) {
450
+ throw new Error('Antigravity SQLite 快照长度异常');
451
+ }
452
+ return Buffer.from(databaseBytes);
453
+ }
454
+ async function downloadAntigravityFile(context, manifest) {
455
+ let url = new URL(manifest.fileUrl);
456
+ let response;
457
+ for (let redirects = 0;; redirects++) {
458
+ validateAntigravityDownloadUrl(url.href);
459
+ response = await undiciFetch(url, {
460
+ redirect: 'manual',
461
+ signal: AbortSignal.timeout(60_000),
462
+ headers: { accept: 'application/octet-stream', 'user-agent': 'uomtiles-map-layer-updater/1.0' },
463
+ ...(context.dispatcher ? { dispatcher: context.dispatcher } : {}),
464
+ });
465
+ if (response.status < 300 || response.status >= 400)
466
+ break;
467
+ if (redirects >= 3)
468
+ throw new Error('Antigravity 下载重定向过多');
469
+ const location = response.headers.get('location');
470
+ if (!location)
471
+ throw new Error('Antigravity 下载重定向无效');
472
+ url = new URL(location, url);
473
+ }
474
+ if (!response.ok)
475
+ throw new Error(`Antigravity 下载失败:HTTP ${response.status}`);
476
+ const declaredLength = Number(response.headers.get('content-length') || 0);
477
+ if (declaredLength && declaredLength !== manifest.fileSize)
478
+ throw new Error('Antigravity 下载文件大小与版本信息不符');
479
+ if (!response.body)
480
+ throw new Error('Antigravity 下载响应为空');
481
+ const chunks = [];
482
+ let completed = 0;
483
+ reportProgress(context, 'antigravity-nfz', 'downloading', 0, manifest.fileSize, '正在下载 Antigravity 数据');
484
+ for await (const chunk of response.body) {
485
+ const bytes = Buffer.from(chunk);
486
+ completed += bytes.length;
487
+ if (completed > manifest.fileSize || completed > MAX_ANTIGRAVITY_SNAPSHOT_BYTES) {
488
+ throw new Error('Antigravity 下载文件过大');
489
+ }
490
+ chunks.push(bytes);
491
+ reportProgress(context, 'antigravity-nfz', 'downloading', completed, manifest.fileSize, '正在下载 Antigravity 数据');
492
+ }
493
+ if (completed !== manifest.fileSize)
494
+ throw new Error('Antigravity 下载文件不完整');
495
+ return Buffer.concat(chunks, completed);
496
+ }
497
+ function validateAntigravityDownloadUrl(value) {
498
+ let url;
499
+ try {
500
+ url = new URL(value);
501
+ }
502
+ catch {
503
+ throw new Error('Antigravity 下载地址不受信任');
504
+ }
505
+ if (url.protocol !== 'https:' || url.hostname !== ANTIGRAVITY_DOWNLOAD_HOST || url.port || url.username || url.password || !url.pathname.endsWith('.InstaCry')) {
506
+ throw new Error('Antigravity 下载地址不受信任');
507
+ }
508
+ }
509
+ async function inspectAntigravitySnapshot(path) {
510
+ const contents = await readFile(path);
511
+ const database = new DatabaseSync(path, { readOnly: true });
512
+ try {
513
+ const integrity = database.prepare('PRAGMA integrity_check').get()?.integrity_check;
514
+ if (integrity !== 'ok')
515
+ throw new Error(`Antigravity SQLite 完整性校验失败:${integrity}`);
516
+ assertAntigravityDatabaseSchema(database);
517
+ const version = database.prepare(`
518
+ SELECT version_code, released_time, expired_time
519
+ FROM version
520
+ WHERE COALESCE(is_deleted, 0) = 0
521
+ ORDER BY id DESC LIMIT 1
522
+ `).get();
523
+ const countRow = database.prepare('SELECT COUNT(*) AS count FROM fences WHERE is_valid = 1 AND is_deleted = 0').get();
524
+ const fences = Number(countRow?.count || 0);
525
+ if (!Number.isSafeInteger(fences) || fences <= 0)
526
+ throw new Error('Antigravity 有效区域数量无效');
527
+ return {
528
+ bytes: contents.length,
529
+ sha256: createHash('sha256').update(contents).digest('hex'),
530
+ fences,
531
+ version: optionalString(version?.version_code),
532
+ releasedAt: optionalString(version?.released_time),
533
+ expiresAt: optionalString(version?.expired_time),
534
+ };
535
+ }
536
+ finally {
537
+ database.close();
538
+ }
539
+ }
540
+ function queryCell(cell) {
541
+ const [west, south, east, north] = cell.bounds;
542
+ return { ...cell, west, south, east, north };
543
+ }
544
+ const DJI_UPDATE_FINGERPRINT = createHash('sha256').update(JSON.stringify({
545
+ algorithmVersion: 'global-adaptive-grid-v1',
546
+ endpoint: DJI_ENDPOINT,
547
+ coverage: DJI_COVERAGE,
548
+ levels: DJI_LEVELS,
549
+ rowDegrees: DJI_ROW_DEGREES,
550
+ targetDiagonalKm: DJI_TARGET_DIAGONAL_KM,
551
+ overlapDegrees: DJI_OVERLAP_DEGREES,
552
+ saturationLimit: DJI_SATURATION_LIMIT,
553
+ maxSplitDepth: DJI_MAX_SPLIT_DEPTH,
554
+ })).digest('hex');
555
+ export async function openDjiUpdateSession(rawRootDirectory, resume = true) {
556
+ await mkdir(rawRootDirectory, { recursive: true });
557
+ const manifestPath = resolve(rawRootDirectory, 'active-session.json');
558
+ if (resume) {
559
+ try {
560
+ const manifest = JSON.parse(await readFile(manifestPath, 'utf8'));
561
+ if (isDjiSessionManifest(manifest) && manifest.fingerprint === DJI_UPDATE_FINGERPRINT && isRecentDjiSession(manifest.startedAt)) {
562
+ const session = {
563
+ manifestPath,
564
+ sessionId: manifest.sessionId,
565
+ startedAt: manifest.startedAt,
566
+ directory: resolve(rawRootDirectory, manifest.sessionId),
567
+ };
568
+ await pruneDjiUpdateSessions(rawRootDirectory, session.sessionId);
569
+ return session;
570
+ }
571
+ }
572
+ catch { }
573
+ }
574
+ const startedAt = new Date().toISOString();
575
+ const sessionId = `${startedAt.replace(/[:.]/g, '-')}-${randomUUID()}`;
576
+ await atomicWrite(manifestPath, `${JSON.stringify({ fingerprint: DJI_UPDATE_FINGERPRINT, sessionId, startedAt })}\n`);
577
+ await pruneDjiUpdateSessions(rawRootDirectory, sessionId);
578
+ return { manifestPath, sessionId, startedAt, directory: resolve(rawRootDirectory, sessionId) };
579
+ }
580
+ export async function completeDjiUpdateSession(session) {
581
+ await rm(session.directory, { recursive: true, force: true }).catch(() => { });
582
+ try {
583
+ const manifest = JSON.parse(await readFile(session.manifestPath, 'utf8'));
584
+ if (isDjiSessionManifest(manifest) && manifest.sessionId === session.sessionId)
585
+ await unlink(session.manifestPath);
586
+ }
587
+ catch (error) {
588
+ if (error?.code !== 'ENOENT')
589
+ throw error;
590
+ }
591
+ }
592
+ async function pruneDjiUpdateSessions(rawRootDirectory, keepSessionId) {
593
+ const entries = await readdir(rawRootDirectory, { withFileTypes: true }).catch(() => []);
594
+ await Promise.all(entries
595
+ .filter(entry => entry.isDirectory() && entry.name !== keepSessionId && isDjiSessionId(entry.name))
596
+ .map(entry => rm(resolve(rawRootDirectory, entry.name), { recursive: true, force: true }).catch(() => { })));
597
+ }
598
+ function isRecentDjiSession(startedAt) {
599
+ const age = Date.now() - Date.parse(startedAt);
600
+ return Number.isFinite(age) && age >= 0 && age <= DJI_RESUME_MAX_AGE_MS;
601
+ }
602
+ function isDjiSessionId(value) {
603
+ return /^[0-9TZa-f-]+$/.test(value);
604
+ }
605
+ function isDjiSessionManifest(value) {
606
+ return isRecord(value)
607
+ && typeof value.fingerprint === 'string'
608
+ && typeof value.sessionId === 'string'
609
+ && isDjiSessionId(value.sessionId)
610
+ && typeof value.startedAt === 'string'
611
+ && Number.isFinite(Date.parse(value.startedAt));
612
+ }
613
+ async function atomicWrite(destination, data) {
614
+ const temporary = `${destination}.${process.pid}.${Date.now()}.tmp`;
615
+ await writeFile(temporary, data, { mode: 0o644 });
616
+ await rename(temporary, destination);
617
+ }
618
+ function snapshotDestination(outputDirectory, configuredPath, filename) {
619
+ const configured = configuredPath?.trim();
620
+ return configured ? resolve(configured) : resolve(outputDirectory, filename);
621
+ }
622
+ async function readDjiSnapshotIdentity(path) {
623
+ try {
624
+ const contents = await readFile(path, 'utf8');
625
+ const snapshot = parseDjiSnapshot(contents);
626
+ const areasSha256 = snapshot.areasSha256;
627
+ return {
628
+ areasSha256,
629
+ sha256: createHash('sha256').update(contents).digest('hex'),
630
+ bytes: Buffer.byteLength(contents),
631
+ fetchedAt: snapshot.fetchedAt,
632
+ };
633
+ }
634
+ catch {
635
+ return null;
636
+ }
637
+ }
638
+ function reportProgress(context, source, phase, completed, total, message) {
639
+ context.onProgress?.({ source, phase, completed, total, message });
640
+ }
641
+ function optionalString(value) {
642
+ return value === undefined || value === null ? undefined : String(value);
643
+ }
644
+ function isRecord(value) {
645
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
646
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uomtiles",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "UOM 适飞地图预览、下载、对比与 MBTiles/PMTiles 发布工具",
5
5
  "keywords": [
6
6
  "uom",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "type": "module",
18
18
  "private": false,
19
- "license": "SEE LICENSE IN LICENSE",
19
+ "license": "Apache-2.0",
20
20
  "bin": {
21
21
  "uomtiles": "dist/src/cli.js"
22
22
  },
@@ -37,6 +37,7 @@
37
37
  "dev": "pnpm build:cli && nuxt dev",
38
38
  "build:cli": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.cli.json",
39
39
  "build": "pnpm build:cli && nuxt build",
40
+ "map-layers:update": "node --experimental-strip-types --no-warnings src/cli.ts map-layers-update",
40
41
  "test": "vitest run",
41
42
  "prepack": "pnpm build",
42
43
  "preview": "nuxt preview",