@honua/sdk-esri-compat 0.0.6-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/README.md +5 -0
  2. package/contract/edit-session.d.ts +203 -0
  3. package/contract/edit-session.d.ts.map +1 -0
  4. package/contract/edit-session.js +717 -0
  5. package/contract/index.d.ts +20 -0
  6. package/contract/index.d.ts.map +1 -0
  7. package/contract/index.js +15 -0
  8. package/contract/jobs.d.ts +115 -0
  9. package/contract/jobs.d.ts.map +1 -0
  10. package/contract/jobs.js +22 -0
  11. package/contract/source.d.ts +138 -0
  12. package/contract/source.d.ts.map +1 -0
  13. package/contract/source.js +3364 -0
  14. package/contract/spatial-aggregation.d.ts +312 -0
  15. package/contract/spatial-aggregation.d.ts.map +1 -0
  16. package/contract/spatial-aggregation.js +196 -0
  17. package/contract/types.d.ts +542 -0
  18. package/contract/types.d.ts.map +1 -0
  19. package/contract/types.js +171 -0
  20. package/core/batch.d.ts +37 -0
  21. package/core/batch.d.ts.map +1 -0
  22. package/core/batch.js +78 -0
  23. package/core/cache-state.d.ts +76 -0
  24. package/core/cache-state.d.ts.map +1 -0
  25. package/core/cache-state.js +84 -0
  26. package/core/client.d.ts +289 -0
  27. package/core/client.d.ts.map +1 -0
  28. package/core/client.js +2625 -0
  29. package/core/errors.d.ts +68 -0
  30. package/core/errors.d.ts.map +1 -0
  31. package/core/errors.js +116 -0
  32. package/core/grpc-adapter.d.ts +23 -0
  33. package/core/grpc-adapter.d.ts.map +1 -0
  34. package/core/grpc-adapter.js +704 -0
  35. package/core/odata.d.ts +347 -0
  36. package/core/odata.d.ts.map +1 -0
  37. package/core/odata.js +837 -0
  38. package/core/ogc-conformance.d.ts +35 -0
  39. package/core/ogc-conformance.d.ts.map +1 -0
  40. package/core/ogc-conformance.js +121 -0
  41. package/core/ogc-maps.d.ts +45 -0
  42. package/core/ogc-maps.d.ts.map +1 -0
  43. package/core/ogc-maps.js +53 -0
  44. package/core/ogc-processes.d.ts +92 -0
  45. package/core/ogc-processes.d.ts.map +1 -0
  46. package/core/ogc-processes.js +325 -0
  47. package/core/ogc-tiles.d.ts +55 -0
  48. package/core/ogc-tiles.d.ts.map +1 -0
  49. package/core/ogc-tiles.js +81 -0
  50. package/core/pbf-decoder.d.ts +28 -0
  51. package/core/pbf-decoder.d.ts.map +1 -0
  52. package/core/pbf-decoder.js +627 -0
  53. package/core/query-builder.d.ts +261 -0
  54. package/core/query-builder.d.ts.map +1 -0
  55. package/core/query-builder.js +538 -0
  56. package/core/spatial-filter.d.ts +93 -0
  57. package/core/spatial-filter.d.ts.map +1 -0
  58. package/core/spatial-filter.js +153 -0
  59. package/core/stac.d.ts +43 -0
  60. package/core/stac.d.ts.map +1 -0
  61. package/core/stac.js +116 -0
  62. package/core/surfaces.d.ts +464 -0
  63. package/core/surfaces.d.ts.map +1 -0
  64. package/core/surfaces.js +1322 -0
  65. package/core/types.d.ts +1238 -0
  66. package/core/types.d.ts.map +1 -0
  67. package/core/types.js +13 -0
  68. package/core/wfs-capabilities.d.ts +143 -0
  69. package/core/wfs-capabilities.d.ts.map +1 -0
  70. package/core/wfs-capabilities.js +478 -0
  71. package/core/wfs-filter.d.ts +118 -0
  72. package/core/wfs-filter.d.ts.map +1 -0
  73. package/core/wfs-filter.js +586 -0
  74. package/core/wfs.d.ts +219 -0
  75. package/core/wfs.d.ts.map +1 -0
  76. package/core/wfs.js +406 -0
  77. package/core/wms-capabilities.d.ts +110 -0
  78. package/core/wms-capabilities.d.ts.map +1 -0
  79. package/core/wms-capabilities.js +566 -0
  80. package/core/wms-types.d.ts +128 -0
  81. package/core/wms-types.d.ts.map +1 -0
  82. package/core/wms-types.js +32 -0
  83. package/core/wms.d.ts +108 -0
  84. package/core/wms.d.ts.map +1 -0
  85. package/core/wms.js +182 -0
  86. package/core/wmts-capabilities.d.ts +82 -0
  87. package/core/wmts-capabilities.d.ts.map +1 -0
  88. package/core/wmts-capabilities.js +409 -0
  89. package/core/wmts.d.ts +80 -0
  90. package/core/wmts.d.ts.map +1 -0
  91. package/core/wmts.js +173 -0
  92. package/esri-compat/basemap-gallery.d.ts +38 -0
  93. package/esri-compat/basemap-gallery.d.ts.map +1 -0
  94. package/esri-compat/basemap-gallery.js +159 -0
  95. package/esri-compat/basemap-layer-list.d.ts +35 -0
  96. package/esri-compat/basemap-layer-list.d.ts.map +1 -0
  97. package/esri-compat/basemap-layer-list.js +139 -0
  98. package/esri-compat/basemap.d.ts +32 -0
  99. package/esri-compat/basemap.d.ts.map +1 -0
  100. package/esri-compat/basemap.js +84 -0
  101. package/esri-compat/bookmarks.d.ts +36 -0
  102. package/esri-compat/bookmarks.d.ts.map +1 -0
  103. package/esri-compat/bookmarks.js +108 -0
  104. package/esri-compat/class-breaks-renderer.d.ts +50 -0
  105. package/esri-compat/class-breaks-renderer.d.ts.map +1 -0
  106. package/esri-compat/class-breaks-renderer.js +164 -0
  107. package/esri-compat/color.d.ts +22 -0
  108. package/esri-compat/color.d.ts.map +1 -0
  109. package/esri-compat/color.js +106 -0
  110. package/esri-compat/controls.d.ts +174 -0
  111. package/esri-compat/controls.d.ts.map +1 -0
  112. package/esri-compat/controls.js +479 -0
  113. package/esri-compat/coordinate-conversion.d.ts +41 -0
  114. package/esri-compat/coordinate-conversion.d.ts.map +1 -0
  115. package/esri-compat/coordinate-conversion.js +125 -0
  116. package/esri-compat/directions.d.ts +45 -0
  117. package/esri-compat/directions.d.ts.map +1 -0
  118. package/esri-compat/directions.js +123 -0
  119. package/esri-compat/editor.d.ts +47 -0
  120. package/esri-compat/editor.d.ts.map +1 -0
  121. package/esri-compat/editor.js +170 -0
  122. package/esri-compat/esri-config.d.ts +16 -0
  123. package/esri-compat/esri-config.d.ts.map +1 -0
  124. package/esri-compat/esri-config.js +23 -0
  125. package/esri-compat/esri-request.d.ts +17 -0
  126. package/esri-compat/esri-request.d.ts.map +1 -0
  127. package/esri-compat/esri-request.js +66 -0
  128. package/esri-compat/event-bus.d.ts +106 -0
  129. package/esri-compat/event-bus.d.ts.map +1 -0
  130. package/esri-compat/event-bus.js +90 -0
  131. package/esri-compat/expand.d.ts +36 -0
  132. package/esri-compat/expand.d.ts.map +1 -0
  133. package/esri-compat/expand.js +97 -0
  134. package/esri-compat/extent.d.ts +43 -0
  135. package/esri-compat/extent.d.ts.map +1 -0
  136. package/esri-compat/extent.js +140 -0
  137. package/esri-compat/feature-form.d.ts +64 -0
  138. package/esri-compat/feature-form.d.ts.map +1 -0
  139. package/esri-compat/feature-form.js +137 -0
  140. package/esri-compat/feature-layer.d.ts +173 -0
  141. package/esri-compat/feature-layer.d.ts.map +1 -0
  142. package/esri-compat/feature-layer.js +655 -0
  143. package/esri-compat/feature-set.d.ts +32 -0
  144. package/esri-compat/feature-set.d.ts.map +1 -0
  145. package/esri-compat/feature-set.js +80 -0
  146. package/esri-compat/feature-table.d.ts +141 -0
  147. package/esri-compat/feature-table.d.ts.map +1 -0
  148. package/esri-compat/feature-table.js +500 -0
  149. package/esri-compat/feature-templates.d.ts +41 -0
  150. package/esri-compat/feature-templates.d.ts.map +1 -0
  151. package/esri-compat/feature-templates.js +97 -0
  152. package/esri-compat/feature.d.ts +33 -0
  153. package/esri-compat/feature.d.ts.map +1 -0
  154. package/esri-compat/feature.js +83 -0
  155. package/esri-compat/graphic.d.ts +46 -0
  156. package/esri-compat/graphic.d.ts.map +1 -0
  157. package/esri-compat/graphic.js +103 -0
  158. package/esri-compat/graphics-layer.d.ts +49 -0
  159. package/esri-compat/graphics-layer.d.ts.map +1 -0
  160. package/esri-compat/graphics-layer.js +185 -0
  161. package/esri-compat/group-layer.d.ts +48 -0
  162. package/esri-compat/group-layer.d.ts.map +1 -0
  163. package/esri-compat/group-layer.js +212 -0
  164. package/esri-compat/identify.d.ts +71 -0
  165. package/esri-compat/identify.d.ts.map +1 -0
  166. package/esri-compat/identify.js +299 -0
  167. package/esri-compat/identity-manager.d.ts +31 -0
  168. package/esri-compat/identity-manager.d.ts.map +1 -0
  169. package/esri-compat/identity-manager.js +115 -0
  170. package/esri-compat/label-class.d.ts +31 -0
  171. package/esri-compat/label-class.d.ts.map +1 -0
  172. package/esri-compat/label-class.js +102 -0
  173. package/esri-compat/layer-list.d.ts +77 -0
  174. package/esri-compat/layer-list.d.ts.map +1 -0
  175. package/esri-compat/layer-list.js +342 -0
  176. package/esri-compat/legend.d.ts +53 -0
  177. package/esri-compat/legend.d.ts.map +1 -0
  178. package/esri-compat/legend.js +254 -0
  179. package/esri-compat/map-image-layer.d.ts +162 -0
  180. package/esri-compat/map-image-layer.d.ts.map +1 -0
  181. package/esri-compat/map-image-layer.js +704 -0
  182. package/esri-compat/map-view.d.ts +315 -0
  183. package/esri-compat/map-view.d.ts.map +1 -0
  184. package/esri-compat/map-view.js +1110 -0
  185. package/esri-compat/map.d.ts +47 -0
  186. package/esri-compat/map.d.ts.map +1 -0
  187. package/esri-compat/map.js +209 -0
  188. package/esri-compat/measurement-2d.d.ts +61 -0
  189. package/esri-compat/measurement-2d.d.ts.map +1 -0
  190. package/esri-compat/measurement-2d.js +184 -0
  191. package/esri-compat/measurement.d.ts +45 -0
  192. package/esri-compat/measurement.d.ts.map +1 -0
  193. package/esri-compat/measurement.js +193 -0
  194. package/esri-compat/oauth-info.d.ts +35 -0
  195. package/esri-compat/oauth-info.d.ts.map +1 -0
  196. package/esri-compat/oauth-info.js +115 -0
  197. package/esri-compat/picture-marker-symbol.d.ts +35 -0
  198. package/esri-compat/picture-marker-symbol.d.ts.map +1 -0
  199. package/esri-compat/picture-marker-symbol.js +126 -0
  200. package/esri-compat/point.d.ts +31 -0
  201. package/esri-compat/point.d.ts.map +1 -0
  202. package/esri-compat/point.js +102 -0
  203. package/esri-compat/polygon.d.ts +31 -0
  204. package/esri-compat/polygon.d.ts.map +1 -0
  205. package/esri-compat/polygon.js +107 -0
  206. package/esri-compat/polyline.d.ts +31 -0
  207. package/esri-compat/polyline.d.ts.map +1 -0
  208. package/esri-compat/polyline.js +107 -0
  209. package/esri-compat/popup-template.d.ts +55 -0
  210. package/esri-compat/popup-template.d.ts.map +1 -0
  211. package/esri-compat/popup-template.js +128 -0
  212. package/esri-compat/popup.d.ts +54 -0
  213. package/esri-compat/popup.d.ts.map +1 -0
  214. package/esri-compat/popup.js +312 -0
  215. package/esri-compat/print.d.ts +47 -0
  216. package/esri-compat/print.d.ts.map +1 -0
  217. package/esri-compat/print.js +105 -0
  218. package/esri-compat/query.d.ts +46 -0
  219. package/esri-compat/query.d.ts.map +1 -0
  220. package/esri-compat/query.js +119 -0
  221. package/esri-compat/reactive-utils.d.ts +23 -0
  222. package/esri-compat/reactive-utils.d.ts.map +1 -0
  223. package/esri-compat/reactive-utils.js +178 -0
  224. package/esri-compat/request.d.ts +41 -0
  225. package/esri-compat/request.d.ts.map +1 -0
  226. package/esri-compat/request.js +253 -0
  227. package/esri-compat/route-layer.d.ts +59 -0
  228. package/esri-compat/route-layer.d.ts.map +1 -0
  229. package/esri-compat/route-layer.js +223 -0
  230. package/esri-compat/route-task.d.ts +88 -0
  231. package/esri-compat/route-task.d.ts.map +1 -0
  232. package/esri-compat/route-task.js +225 -0
  233. package/esri-compat/scene-view.d.ts +41 -0
  234. package/esri-compat/scene-view.d.ts.map +1 -0
  235. package/esri-compat/scene-view.js +68 -0
  236. package/esri-compat/search.d.ts +112 -0
  237. package/esri-compat/search.d.ts.map +1 -0
  238. package/esri-compat/search.js +820 -0
  239. package/esri-compat/simple-fill-symbol.d.ts +27 -0
  240. package/esri-compat/simple-fill-symbol.d.ts.map +1 -0
  241. package/esri-compat/simple-fill-symbol.js +85 -0
  242. package/esri-compat/simple-line-symbol.d.ts +27 -0
  243. package/esri-compat/simple-line-symbol.d.ts.map +1 -0
  244. package/esri-compat/simple-line-symbol.js +85 -0
  245. package/esri-compat/simple-marker-symbol.d.ts +29 -0
  246. package/esri-compat/simple-marker-symbol.d.ts.map +1 -0
  247. package/esri-compat/simple-marker-symbol.js +92 -0
  248. package/esri-compat/simple-renderer.d.ts +29 -0
  249. package/esri-compat/simple-renderer.d.ts.map +1 -0
  250. package/esri-compat/simple-renderer.js +92 -0
  251. package/esri-compat/sketch.d.ts +64 -0
  252. package/esri-compat/sketch.d.ts.map +1 -0
  253. package/esri-compat/sketch.js +227 -0
  254. package/esri-compat/spatial-reference.d.ts +31 -0
  255. package/esri-compat/spatial-reference.d.ts.map +1 -0
  256. package/esri-compat/spatial-reference.js +102 -0
  257. package/esri-compat/swipe.d.ts +34 -0
  258. package/esri-compat/swipe.d.ts.map +1 -0
  259. package/esri-compat/swipe.js +93 -0
  260. package/esri-compat/table-list.d.ts +36 -0
  261. package/esri-compat/table-list.d.ts.map +1 -0
  262. package/esri-compat/table-list.js +126 -0
  263. package/esri-compat/text-symbol.d.ts +37 -0
  264. package/esri-compat/text-symbol.d.ts.map +1 -0
  265. package/esri-compat/text-symbol.js +123 -0
  266. package/esri-compat/tile-layer.d.ts +52 -0
  267. package/esri-compat/tile-layer.d.ts.map +1 -0
  268. package/esri-compat/tile-layer.js +167 -0
  269. package/esri-compat/time-slider.d.ts +70 -0
  270. package/esri-compat/time-slider.d.ts.map +1 -0
  271. package/esri-compat/time-slider.js +208 -0
  272. package/esri-compat/track.d.ts +51 -0
  273. package/esri-compat/track.d.ts.map +1 -0
  274. package/esri-compat/track.js +174 -0
  275. package/esri-compat/unique-value-renderer.d.ts +41 -0
  276. package/esri-compat/unique-value-renderer.d.ts.map +1 -0
  277. package/esri-compat/unique-value-renderer.js +127 -0
  278. package/esri-compat/url.d.ts +12 -0
  279. package/esri-compat/url.d.ts.map +1 -0
  280. package/esri-compat/url.js +54 -0
  281. package/esri-compat/web-map.d.ts +14 -0
  282. package/esri-compat/web-map.d.ts.map +1 -0
  283. package/esri-compat/web-map.js +24 -0
  284. package/gen/honua/v1/feature_service_pb.d.ts +918 -0
  285. package/gen/honua/v1/feature_service_pb.d.ts.map +1 -0
  286. package/gen/honua/v1/feature_service_pb.js +375 -0
  287. package/index.d.ts +130 -0
  288. package/index.js +65 -0
  289. package/package.json +22 -0
@@ -0,0 +1,627 @@
1
+ /**
2
+ * Minimal protobuf wire-format reader and Esri PBF query response decoder.
3
+ *
4
+ * Decodes `FeatureCollectionPBuffer` responses (from `f=pbf`) into the same
5
+ * JSON-compatible shape as `f=json`, making the binary format transparent
6
+ * to callers.
7
+ *
8
+ * No external protobuf library dependency. Implements only the subset of
9
+ * the wire format needed for the Esri PBF query schema.
10
+ *
11
+ * @module
12
+ */
13
+ // ── Wire format constants ────────────────────────────────────
14
+ const WIRE_VARINT = 0;
15
+ const WIRE_64BIT = 1;
16
+ const WIRE_LENGTH_DELIMITED = 2;
17
+ const WIRE_32BIT = 5;
18
+ // ── Low-level protobuf reader ────────────────────────────────
19
+ /** Reads protobuf wire-format primitives from a byte buffer. */
20
+ class PbfReader {
21
+ view;
22
+ bytes;
23
+ pos;
24
+ end;
25
+ constructor(buffer, offset = 0, length) {
26
+ this.bytes = buffer;
27
+ this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
28
+ this.pos = offset;
29
+ this.end = length !== undefined ? offset + length : buffer.length;
30
+ }
31
+ /** Read an unsigned 32-bit varint. */
32
+ readVarint() {
33
+ let result = 0;
34
+ let shift = 0;
35
+ while (this.pos < this.end) {
36
+ const byte = this.bytes[this.pos++];
37
+ result |= (byte & 0x7f) << shift;
38
+ if ((byte & 0x80) === 0)
39
+ return result >>> 0;
40
+ shift += 7;
41
+ if (shift > 35)
42
+ throw new Error("Varint too long");
43
+ }
44
+ throw new Error("Unexpected end of buffer reading varint");
45
+ }
46
+ /** Read a 64-bit varint as a JavaScript number (safe for values < 2^53). */
47
+ readVarint64() {
48
+ let lo = 0;
49
+ let hi = 0;
50
+ let shift = 0;
51
+ while (shift < 28 && this.pos < this.end) {
52
+ const byte = this.bytes[this.pos++];
53
+ lo |= (byte & 0x7f) << shift;
54
+ shift += 7;
55
+ if ((byte & 0x80) === 0)
56
+ return lo >>> 0;
57
+ }
58
+ // Remaining bits go into hi
59
+ while (this.pos < this.end) {
60
+ const byte = this.bytes[this.pos++];
61
+ hi |= (byte & 0x7f) << (shift - 28);
62
+ shift += 7;
63
+ if ((byte & 0x80) === 0)
64
+ break;
65
+ if (shift > 63)
66
+ throw new Error("Varint too long");
67
+ }
68
+ return (hi >>> 0) * 0x10000000 + (lo >>> 0);
69
+ }
70
+ /** Read a signed 64-bit varint (zigzag-decoded) as a JavaScript number. */
71
+ readSVarint64() {
72
+ const n = this.readVarint64();
73
+ // Zigzag decode: (n >>> 1) ^ -(n & 1)
74
+ // For numbers that fit in 32 bits this is straightforward.
75
+ // For larger numbers, we do the math in floating point (safe for ints < 2^53).
76
+ const half = Math.floor(n / 2);
77
+ return n % 2 === 0 ? half : -(half + 1);
78
+ }
79
+ /** Read a signed 32-bit varint (zigzag-decoded). */
80
+ readSVarint32() {
81
+ const n = this.readVarint();
82
+ return (n >>> 1) ^ -(n & 1);
83
+ }
84
+ /** Read a little-endian 64-bit float. */
85
+ readDouble() {
86
+ const val = this.view.getFloat64(this.pos, true);
87
+ this.pos += 8;
88
+ return val;
89
+ }
90
+ /** Read a little-endian 32-bit float. */
91
+ readFloat() {
92
+ const val = this.view.getFloat32(this.pos, true);
93
+ this.pos += 4;
94
+ return val;
95
+ }
96
+ /** Read a UTF-8 string of the given byte length. */
97
+ readString(byteLength) {
98
+ const slice = this.bytes.subarray(this.pos, this.pos + byteLength);
99
+ this.pos += byteLength;
100
+ return textDecoder.decode(slice);
101
+ }
102
+ /** Read a boolean from a varint. */
103
+ readBool() {
104
+ return this.readVarint() !== 0;
105
+ }
106
+ /** Read a field tag, returning [fieldNumber, wireType]. */
107
+ readTag() {
108
+ const tag = this.readVarint();
109
+ return [tag >>> 3, tag & 0x07];
110
+ }
111
+ /** Skip a field value based on wire type. */
112
+ skip(wireType) {
113
+ switch (wireType) {
114
+ case WIRE_VARINT:
115
+ this.readVarint64();
116
+ break;
117
+ case WIRE_64BIT:
118
+ this.pos += 8;
119
+ break;
120
+ case WIRE_LENGTH_DELIMITED: {
121
+ const len = this.readVarint();
122
+ this.pos += len;
123
+ break;
124
+ }
125
+ case WIRE_32BIT:
126
+ this.pos += 4;
127
+ break;
128
+ default:
129
+ throw new Error(`Unknown wire type: ${wireType}`);
130
+ }
131
+ }
132
+ /** Create a sub-reader for a length-delimited field. */
133
+ subReader(byteLength) {
134
+ const sub = new PbfReader(this.bytes, this.pos, byteLength);
135
+ this.pos += byteLength;
136
+ return sub;
137
+ }
138
+ /** Read packed repeated sint64 values. */
139
+ readPackedSInt64(byteLength) {
140
+ const result = [];
141
+ const end = this.pos + byteLength;
142
+ while (this.pos < end) {
143
+ result.push(this.readSVarint64());
144
+ }
145
+ return result;
146
+ }
147
+ /** Read packed repeated uint32 values. */
148
+ readPackedUInt32(byteLength) {
149
+ const result = [];
150
+ const end = this.pos + byteLength;
151
+ while (this.pos < end) {
152
+ result.push(this.readVarint());
153
+ }
154
+ return result;
155
+ }
156
+ }
157
+ const textDecoder = new TextDecoder();
158
+ // ── Esri PBF geometry type enum ──────────────────────────────
159
+ const PBF_GEOMETRY_TYPE_NAMES = {
160
+ 0: "esriGeometryPoint",
161
+ 1: "esriGeometryMultipoint",
162
+ 2: "esriGeometryPolyline",
163
+ 3: "esriGeometryPolygon",
164
+ 4: "esriGeometryEnvelope",
165
+ 127: "esriGeometryNull",
166
+ };
167
+ function decodeScale(reader) {
168
+ let xScale = 0;
169
+ let yScale = 0;
170
+ while (reader.pos < reader.end) {
171
+ const [field, wire] = reader.readTag();
172
+ if (field === 1 && wire === WIRE_64BIT)
173
+ xScale = reader.readDouble();
174
+ else if (field === 2 && wire === WIRE_64BIT)
175
+ yScale = reader.readDouble();
176
+ else
177
+ reader.skip(wire);
178
+ }
179
+ return { xScale, yScale };
180
+ }
181
+ function decodeTranslate(reader) {
182
+ let xTranslate = 0;
183
+ let yTranslate = 0;
184
+ while (reader.pos < reader.end) {
185
+ const [field, wire] = reader.readTag();
186
+ if (field === 1 && wire === WIRE_64BIT)
187
+ xTranslate = reader.readDouble();
188
+ else if (field === 2 && wire === WIRE_64BIT)
189
+ yTranslate = reader.readDouble();
190
+ else
191
+ reader.skip(wire);
192
+ }
193
+ return { xTranslate, yTranslate };
194
+ }
195
+ function decodeTransform(reader) {
196
+ let xScale = 1;
197
+ let yScale = 1;
198
+ let xTranslate = 0;
199
+ let yTranslate = 0;
200
+ while (reader.pos < reader.end) {
201
+ const [field, wire] = reader.readTag();
202
+ if (field === 2 && wire === WIRE_LENGTH_DELIMITED) {
203
+ const len = reader.readVarint();
204
+ const sub = reader.subReader(len);
205
+ const s = decodeScale(sub);
206
+ xScale = s.xScale;
207
+ yScale = s.yScale;
208
+ }
209
+ else if (field === 3 && wire === WIRE_LENGTH_DELIMITED) {
210
+ const len = reader.readVarint();
211
+ const sub = reader.subReader(len);
212
+ const t = decodeTranslate(sub);
213
+ xTranslate = t.xTranslate;
214
+ yTranslate = t.yTranslate;
215
+ }
216
+ else {
217
+ reader.skip(wire);
218
+ }
219
+ }
220
+ return { xScale, yScale, xTranslate, yTranslate };
221
+ }
222
+ function decodeField(reader) {
223
+ let name = "";
224
+ let fieldType = 0;
225
+ let alias = "";
226
+ while (reader.pos < reader.end) {
227
+ const [field, wire] = reader.readTag();
228
+ if (field === 1 && wire === WIRE_LENGTH_DELIMITED) {
229
+ const len = reader.readVarint();
230
+ name = reader.readString(len);
231
+ }
232
+ else if (field === 2 && wire === WIRE_VARINT) {
233
+ fieldType = reader.readVarint();
234
+ }
235
+ else if (field === 3 && wire === WIRE_LENGTH_DELIMITED) {
236
+ const len = reader.readVarint();
237
+ alias = reader.readString(len);
238
+ }
239
+ else {
240
+ reader.skip(wire);
241
+ }
242
+ }
243
+ return { name, fieldType, alias: alias || name };
244
+ }
245
+ function decodeSpatialReference(reader) {
246
+ let wkid = 0;
247
+ let latestWkid = 0;
248
+ while (reader.pos < reader.end) {
249
+ const [field, wire] = reader.readTag();
250
+ if (field === 1 && wire === WIRE_VARINT)
251
+ wkid = reader.readVarint();
252
+ else if (field === 2 && wire === WIRE_VARINT)
253
+ latestWkid = reader.readVarint();
254
+ else
255
+ reader.skip(wire);
256
+ }
257
+ return { wkid, latestWkid: latestWkid || wkid };
258
+ }
259
+ function decodeValue(reader) {
260
+ let value = null;
261
+ let fieldIndex = -1;
262
+ while (reader.pos < reader.end) {
263
+ const [field, wire] = reader.readTag();
264
+ switch (field) {
265
+ case 1: // string_value
266
+ if (wire === WIRE_LENGTH_DELIMITED) {
267
+ const len = reader.readVarint();
268
+ value = reader.readString(len);
269
+ }
270
+ else
271
+ reader.skip(wire);
272
+ break;
273
+ case 2: // float_value
274
+ if (wire === WIRE_32BIT)
275
+ value = reader.readFloat();
276
+ else
277
+ reader.skip(wire);
278
+ break;
279
+ case 3: // double_value
280
+ if (wire === WIRE_64BIT)
281
+ value = reader.readDouble();
282
+ else
283
+ reader.skip(wire);
284
+ break;
285
+ case 4: // sint_value (sint32)
286
+ if (wire === WIRE_VARINT)
287
+ value = reader.readSVarint32();
288
+ else
289
+ reader.skip(wire);
290
+ break;
291
+ case 5: // uint_value
292
+ if (wire === WIRE_VARINT)
293
+ value = reader.readVarint();
294
+ else
295
+ reader.skip(wire);
296
+ break;
297
+ case 6: // int64_value
298
+ if (wire === WIRE_VARINT)
299
+ value = reader.readVarint64();
300
+ else
301
+ reader.skip(wire);
302
+ break;
303
+ case 7: // uint64_value
304
+ if (wire === WIRE_VARINT)
305
+ value = reader.readVarint64();
306
+ else
307
+ reader.skip(wire);
308
+ break;
309
+ case 9: // bool_value
310
+ if (wire === WIRE_VARINT)
311
+ value = reader.readBool();
312
+ else
313
+ reader.skip(wire);
314
+ break;
315
+ case 10: // null_value
316
+ if (wire === WIRE_VARINT) {
317
+ reader.readVarint(); // consume the bool
318
+ value = null;
319
+ }
320
+ else
321
+ reader.skip(wire);
322
+ break;
323
+ case 11: // field_index
324
+ if (wire === WIRE_VARINT)
325
+ fieldIndex = reader.readVarint();
326
+ else
327
+ reader.skip(wire);
328
+ break;
329
+ default:
330
+ reader.skip(wire);
331
+ }
332
+ }
333
+ return { value, fieldIndex };
334
+ }
335
+ function decodeGeometry(reader, transform, layerGeometryType) {
336
+ let lengths = [];
337
+ let coords = [];
338
+ while (reader.pos < reader.end) {
339
+ const [field, wire] = reader.readTag();
340
+ if (field === 1 && wire === WIRE_VARINT) {
341
+ reader.readVarint(); // geometryType — we use layerGeometryType instead
342
+ }
343
+ else if (field === 2 && wire === WIRE_LENGTH_DELIMITED) {
344
+ const len = reader.readVarint();
345
+ lengths = reader.readPackedUInt32(len);
346
+ }
347
+ else if (field === 3 && wire === WIRE_LENGTH_DELIMITED) {
348
+ const len = reader.readVarint();
349
+ coords = reader.readPackedSInt64(len);
350
+ }
351
+ else {
352
+ reader.skip(wire);
353
+ }
354
+ }
355
+ if (coords.length === 0)
356
+ return null;
357
+ // Delta-decode and transform coordinates
358
+ const xScale = transform?.xScale ?? 1;
359
+ const yScale = transform?.yScale ?? 1;
360
+ const xTranslate = transform?.xTranslate ?? 0;
361
+ const yTranslate = transform?.yTranslate ?? 0;
362
+ // Undo delta encoding: each coordinate pair is (deltaX, deltaY)
363
+ let prevX = 0;
364
+ let prevY = 0;
365
+ const worldCoords = [];
366
+ for (let i = 0; i < coords.length; i += 2) {
367
+ prevX += coords[i];
368
+ prevY += coords[i + 1];
369
+ worldCoords.push([prevX * xScale + xTranslate, prevY * yScale + yTranslate]);
370
+ }
371
+ return buildGeoServicesGeometry(layerGeometryType, worldCoords, lengths);
372
+ }
373
+ function buildGeoServicesGeometry(geometryType, worldCoords, lengths) {
374
+ switch (geometryType) {
375
+ case "esriGeometryPoint":
376
+ return worldCoords.length > 0 ? { x: worldCoords[0][0], y: worldCoords[0][1] } : { x: null, y: null };
377
+ case "esriGeometryMultipoint":
378
+ return { points: worldCoords };
379
+ case "esriGeometryPolyline": {
380
+ const paths = [];
381
+ let offset = 0;
382
+ for (const len of lengths) {
383
+ paths.push(worldCoords.slice(offset, offset + len));
384
+ offset += len;
385
+ }
386
+ return { paths: paths.length > 0 ? paths : [worldCoords] };
387
+ }
388
+ case "esriGeometryPolygon": {
389
+ const rings = [];
390
+ let offset = 0;
391
+ for (const len of lengths) {
392
+ rings.push(worldCoords.slice(offset, offset + len));
393
+ offset += len;
394
+ }
395
+ return { rings: rings.length > 0 ? rings : [worldCoords] };
396
+ }
397
+ default:
398
+ return { x: worldCoords[0]?.[0] ?? null, y: worldCoords[0]?.[1] ?? null };
399
+ }
400
+ }
401
+ function decodeFeature(reader, fields, transform, geometryType) {
402
+ const attributes = {};
403
+ let geometry = null;
404
+ const valueEntries = [];
405
+ while (reader.pos < reader.end) {
406
+ const [field, wire] = reader.readTag();
407
+ if (field === 1 && wire === WIRE_LENGTH_DELIMITED) {
408
+ const len = reader.readVarint();
409
+ const sub = reader.subReader(len);
410
+ valueEntries.push(decodeValue(sub));
411
+ }
412
+ else if (field === 2 && wire === WIRE_LENGTH_DELIMITED) {
413
+ const len = reader.readVarint();
414
+ const sub = reader.subReader(len);
415
+ geometry = decodeGeometry(sub, transform, geometryType);
416
+ }
417
+ else {
418
+ reader.skip(wire);
419
+ }
420
+ }
421
+ // Map value entries to field names using field indices
422
+ for (const entry of valueEntries) {
423
+ if (entry.fieldIndex >= 0 && entry.fieldIndex < fields.length) {
424
+ attributes[fields[entry.fieldIndex].name] = entry.value;
425
+ }
426
+ }
427
+ const result = { attributes };
428
+ if (geometry !== null) {
429
+ result.geometry = geometry;
430
+ }
431
+ return result;
432
+ }
433
+ function decodeFeatureResult(reader) {
434
+ let objectIdFieldName = "";
435
+ let geometryType = "";
436
+ let spatialReference = null;
437
+ let exceededTransferLimit = false;
438
+ let hasZ = false;
439
+ let hasM = false;
440
+ let transform = null;
441
+ const fields = [];
442
+ const featureReaders = [];
443
+ while (reader.pos < reader.end) {
444
+ const [field, wire] = reader.readTag();
445
+ switch (field) {
446
+ case 1: // objectIdFieldName
447
+ if (wire === WIRE_LENGTH_DELIMITED) {
448
+ const len = reader.readVarint();
449
+ objectIdFieldName = reader.readString(len);
450
+ }
451
+ else
452
+ reader.skip(wire);
453
+ break;
454
+ case 7: // geometryType
455
+ if (wire === WIRE_VARINT) {
456
+ const gt = reader.readVarint();
457
+ geometryType = PBF_GEOMETRY_TYPE_NAMES[gt] ?? "esriGeometryNull";
458
+ }
459
+ else
460
+ reader.skip(wire);
461
+ break;
462
+ case 8: // spatialReference
463
+ if (wire === WIRE_LENGTH_DELIMITED) {
464
+ const len = reader.readVarint();
465
+ spatialReference = decodeSpatialReference(reader.subReader(len));
466
+ }
467
+ else
468
+ reader.skip(wire);
469
+ break;
470
+ case 9: // exceededTransferLimit
471
+ if (wire === WIRE_VARINT)
472
+ exceededTransferLimit = reader.readBool();
473
+ else
474
+ reader.skip(wire);
475
+ break;
476
+ case 10: // hasZ
477
+ if (wire === WIRE_VARINT)
478
+ hasZ = reader.readBool();
479
+ else
480
+ reader.skip(wire);
481
+ break;
482
+ case 11: // hasM
483
+ if (wire === WIRE_VARINT)
484
+ hasM = reader.readBool();
485
+ else
486
+ reader.skip(wire);
487
+ break;
488
+ case 12: // transform
489
+ if (wire === WIRE_LENGTH_DELIMITED) {
490
+ const len = reader.readVarint();
491
+ transform = decodeTransform(reader.subReader(len));
492
+ }
493
+ else
494
+ reader.skip(wire);
495
+ break;
496
+ case 13: // fields (repeated)
497
+ if (wire === WIRE_LENGTH_DELIMITED) {
498
+ const len = reader.readVarint();
499
+ fields.push(decodeField(reader.subReader(len)));
500
+ }
501
+ else
502
+ reader.skip(wire);
503
+ break;
504
+ case 15: // features (repeated)
505
+ if (wire === WIRE_LENGTH_DELIMITED) {
506
+ const len = reader.readVarint();
507
+ // Defer feature decoding until we have all fields and transform
508
+ featureReaders.push(reader.subReader(len));
509
+ }
510
+ else
511
+ reader.skip(wire);
512
+ break;
513
+ default:
514
+ reader.skip(wire);
515
+ }
516
+ }
517
+ // Now decode features with full field/transform context
518
+ const features = featureReaders.map((fr) => decodeFeature(fr, fields, transform, geometryType));
519
+ // Build JSON-compatible response matching f=json shape
520
+ const result = {
521
+ objectIdFieldName,
522
+ fields: fields.map((f) => ({
523
+ name: f.name,
524
+ type: mapPbfFieldTypeToGeoServices(f.fieldType),
525
+ alias: f.alias,
526
+ })),
527
+ features,
528
+ };
529
+ if (geometryType && geometryType !== "esriGeometryNull") {
530
+ result.geometryType = geometryType;
531
+ }
532
+ if (spatialReference) {
533
+ result.spatialReference = spatialReference;
534
+ }
535
+ if (hasZ)
536
+ result.hasZ = true;
537
+ if (hasM)
538
+ result.hasM = true;
539
+ if (exceededTransferLimit) {
540
+ result.exceededTransferLimit = true;
541
+ }
542
+ return result;
543
+ }
544
+ function mapPbfFieldTypeToGeoServices(fieldType) {
545
+ switch (fieldType) {
546
+ case 0:
547
+ return "esriFieldTypeSmallInteger";
548
+ case 1:
549
+ return "esriFieldTypeInteger";
550
+ case 2:
551
+ return "esriFieldTypeSingle";
552
+ case 3:
553
+ return "esriFieldTypeDouble";
554
+ case 4:
555
+ return "esriFieldTypeString";
556
+ case 5:
557
+ return "esriFieldTypeDate";
558
+ case 6:
559
+ return "esriFieldTypeOID";
560
+ case 7:
561
+ return "esriFieldTypeGeometry";
562
+ case 8:
563
+ return "esriFieldTypeBlob";
564
+ case 10:
565
+ return "esriFieldTypeGUID";
566
+ case 11:
567
+ return "esriFieldTypeGlobalID";
568
+ case 12:
569
+ return "esriFieldTypeXML";
570
+ case 13:
571
+ return "esriFieldTypeBigInteger";
572
+ default:
573
+ return "esriFieldTypeString";
574
+ }
575
+ }
576
+ // ── Public API ───────────────────────────────────────────────
577
+ /**
578
+ * Decode an Esri FeatureCollectionPBuffer response into a JSON-compatible
579
+ * query response object.
580
+ *
581
+ * The returned object has the same shape as an `f=json` response:
582
+ * `{ objectIdFieldName, geometryType, spatialReference, fields, features, ... }`
583
+ *
584
+ * @param buffer - The raw PBF bytes from a `f=pbf` response.
585
+ * @returns A JSON-compatible query response object.
586
+ */
587
+ export function decodePbfQueryResponse(buffer) {
588
+ const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
589
+ const reader = new PbfReader(bytes);
590
+ let queryResult = {};
591
+ // FeatureCollectionPBuffer
592
+ while (reader.pos < reader.end) {
593
+ const [field, wire] = reader.readTag();
594
+ if (field === 1 && wire === WIRE_LENGTH_DELIMITED) {
595
+ // version string — skip
596
+ const len = reader.readVarint();
597
+ reader.pos += len;
598
+ }
599
+ else if (field === 2 && wire === WIRE_LENGTH_DELIMITED) {
600
+ // queryResult
601
+ const len = reader.readVarint();
602
+ const qrReader = reader.subReader(len);
603
+ // QueryResult → featureResult (field 1)
604
+ while (qrReader.pos < qrReader.end) {
605
+ const [qrField, qrWire] = qrReader.readTag();
606
+ if (qrField === 1 && qrWire === WIRE_LENGTH_DELIMITED) {
607
+ const frLen = qrReader.readVarint();
608
+ queryResult = decodeFeatureResult(qrReader.subReader(frLen));
609
+ }
610
+ else {
611
+ qrReader.skip(qrWire);
612
+ }
613
+ }
614
+ }
615
+ else {
616
+ reader.skip(wire);
617
+ }
618
+ }
619
+ return queryResult;
620
+ }
621
+ /**
622
+ * Check whether a Response has a protobuf content type.
623
+ */
624
+ export function isPbfResponse(response) {
625
+ const ct = response.headers.get("content-type") ?? "";
626
+ return ct.includes("application/x-protobuf") || ct.includes("application/protobuf");
627
+ }