@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.
- package/README.md +5 -0
- package/contract/edit-session.d.ts +203 -0
- package/contract/edit-session.d.ts.map +1 -0
- package/contract/edit-session.js +717 -0
- package/contract/index.d.ts +20 -0
- package/contract/index.d.ts.map +1 -0
- package/contract/index.js +15 -0
- package/contract/jobs.d.ts +115 -0
- package/contract/jobs.d.ts.map +1 -0
- package/contract/jobs.js +22 -0
- package/contract/source.d.ts +138 -0
- package/contract/source.d.ts.map +1 -0
- package/contract/source.js +3364 -0
- package/contract/spatial-aggregation.d.ts +312 -0
- package/contract/spatial-aggregation.d.ts.map +1 -0
- package/contract/spatial-aggregation.js +196 -0
- package/contract/types.d.ts +542 -0
- package/contract/types.d.ts.map +1 -0
- package/contract/types.js +171 -0
- package/core/batch.d.ts +37 -0
- package/core/batch.d.ts.map +1 -0
- package/core/batch.js +78 -0
- package/core/cache-state.d.ts +76 -0
- package/core/cache-state.d.ts.map +1 -0
- package/core/cache-state.js +84 -0
- package/core/client.d.ts +289 -0
- package/core/client.d.ts.map +1 -0
- package/core/client.js +2625 -0
- package/core/errors.d.ts +68 -0
- package/core/errors.d.ts.map +1 -0
- package/core/errors.js +116 -0
- package/core/grpc-adapter.d.ts +23 -0
- package/core/grpc-adapter.d.ts.map +1 -0
- package/core/grpc-adapter.js +704 -0
- package/core/odata.d.ts +347 -0
- package/core/odata.d.ts.map +1 -0
- package/core/odata.js +837 -0
- package/core/ogc-conformance.d.ts +35 -0
- package/core/ogc-conformance.d.ts.map +1 -0
- package/core/ogc-conformance.js +121 -0
- package/core/ogc-maps.d.ts +45 -0
- package/core/ogc-maps.d.ts.map +1 -0
- package/core/ogc-maps.js +53 -0
- package/core/ogc-processes.d.ts +92 -0
- package/core/ogc-processes.d.ts.map +1 -0
- package/core/ogc-processes.js +325 -0
- package/core/ogc-tiles.d.ts +55 -0
- package/core/ogc-tiles.d.ts.map +1 -0
- package/core/ogc-tiles.js +81 -0
- package/core/pbf-decoder.d.ts +28 -0
- package/core/pbf-decoder.d.ts.map +1 -0
- package/core/pbf-decoder.js +627 -0
- package/core/query-builder.d.ts +261 -0
- package/core/query-builder.d.ts.map +1 -0
- package/core/query-builder.js +538 -0
- package/core/spatial-filter.d.ts +93 -0
- package/core/spatial-filter.d.ts.map +1 -0
- package/core/spatial-filter.js +153 -0
- package/core/stac.d.ts +43 -0
- package/core/stac.d.ts.map +1 -0
- package/core/stac.js +116 -0
- package/core/surfaces.d.ts +464 -0
- package/core/surfaces.d.ts.map +1 -0
- package/core/surfaces.js +1322 -0
- package/core/types.d.ts +1238 -0
- package/core/types.d.ts.map +1 -0
- package/core/types.js +13 -0
- package/core/wfs-capabilities.d.ts +143 -0
- package/core/wfs-capabilities.d.ts.map +1 -0
- package/core/wfs-capabilities.js +478 -0
- package/core/wfs-filter.d.ts +118 -0
- package/core/wfs-filter.d.ts.map +1 -0
- package/core/wfs-filter.js +586 -0
- package/core/wfs.d.ts +219 -0
- package/core/wfs.d.ts.map +1 -0
- package/core/wfs.js +406 -0
- package/core/wms-capabilities.d.ts +110 -0
- package/core/wms-capabilities.d.ts.map +1 -0
- package/core/wms-capabilities.js +566 -0
- package/core/wms-types.d.ts +128 -0
- package/core/wms-types.d.ts.map +1 -0
- package/core/wms-types.js +32 -0
- package/core/wms.d.ts +108 -0
- package/core/wms.d.ts.map +1 -0
- package/core/wms.js +182 -0
- package/core/wmts-capabilities.d.ts +82 -0
- package/core/wmts-capabilities.d.ts.map +1 -0
- package/core/wmts-capabilities.js +409 -0
- package/core/wmts.d.ts +80 -0
- package/core/wmts.d.ts.map +1 -0
- package/core/wmts.js +173 -0
- package/esri-compat/basemap-gallery.d.ts +38 -0
- package/esri-compat/basemap-gallery.d.ts.map +1 -0
- package/esri-compat/basemap-gallery.js +159 -0
- package/esri-compat/basemap-layer-list.d.ts +35 -0
- package/esri-compat/basemap-layer-list.d.ts.map +1 -0
- package/esri-compat/basemap-layer-list.js +139 -0
- package/esri-compat/basemap.d.ts +32 -0
- package/esri-compat/basemap.d.ts.map +1 -0
- package/esri-compat/basemap.js +84 -0
- package/esri-compat/bookmarks.d.ts +36 -0
- package/esri-compat/bookmarks.d.ts.map +1 -0
- package/esri-compat/bookmarks.js +108 -0
- package/esri-compat/class-breaks-renderer.d.ts +50 -0
- package/esri-compat/class-breaks-renderer.d.ts.map +1 -0
- package/esri-compat/class-breaks-renderer.js +164 -0
- package/esri-compat/color.d.ts +22 -0
- package/esri-compat/color.d.ts.map +1 -0
- package/esri-compat/color.js +106 -0
- package/esri-compat/controls.d.ts +174 -0
- package/esri-compat/controls.d.ts.map +1 -0
- package/esri-compat/controls.js +479 -0
- package/esri-compat/coordinate-conversion.d.ts +41 -0
- package/esri-compat/coordinate-conversion.d.ts.map +1 -0
- package/esri-compat/coordinate-conversion.js +125 -0
- package/esri-compat/directions.d.ts +45 -0
- package/esri-compat/directions.d.ts.map +1 -0
- package/esri-compat/directions.js +123 -0
- package/esri-compat/editor.d.ts +47 -0
- package/esri-compat/editor.d.ts.map +1 -0
- package/esri-compat/editor.js +170 -0
- package/esri-compat/esri-config.d.ts +16 -0
- package/esri-compat/esri-config.d.ts.map +1 -0
- package/esri-compat/esri-config.js +23 -0
- package/esri-compat/esri-request.d.ts +17 -0
- package/esri-compat/esri-request.d.ts.map +1 -0
- package/esri-compat/esri-request.js +66 -0
- package/esri-compat/event-bus.d.ts +106 -0
- package/esri-compat/event-bus.d.ts.map +1 -0
- package/esri-compat/event-bus.js +90 -0
- package/esri-compat/expand.d.ts +36 -0
- package/esri-compat/expand.d.ts.map +1 -0
- package/esri-compat/expand.js +97 -0
- package/esri-compat/extent.d.ts +43 -0
- package/esri-compat/extent.d.ts.map +1 -0
- package/esri-compat/extent.js +140 -0
- package/esri-compat/feature-form.d.ts +64 -0
- package/esri-compat/feature-form.d.ts.map +1 -0
- package/esri-compat/feature-form.js +137 -0
- package/esri-compat/feature-layer.d.ts +173 -0
- package/esri-compat/feature-layer.d.ts.map +1 -0
- package/esri-compat/feature-layer.js +655 -0
- package/esri-compat/feature-set.d.ts +32 -0
- package/esri-compat/feature-set.d.ts.map +1 -0
- package/esri-compat/feature-set.js +80 -0
- package/esri-compat/feature-table.d.ts +141 -0
- package/esri-compat/feature-table.d.ts.map +1 -0
- package/esri-compat/feature-table.js +500 -0
- package/esri-compat/feature-templates.d.ts +41 -0
- package/esri-compat/feature-templates.d.ts.map +1 -0
- package/esri-compat/feature-templates.js +97 -0
- package/esri-compat/feature.d.ts +33 -0
- package/esri-compat/feature.d.ts.map +1 -0
- package/esri-compat/feature.js +83 -0
- package/esri-compat/graphic.d.ts +46 -0
- package/esri-compat/graphic.d.ts.map +1 -0
- package/esri-compat/graphic.js +103 -0
- package/esri-compat/graphics-layer.d.ts +49 -0
- package/esri-compat/graphics-layer.d.ts.map +1 -0
- package/esri-compat/graphics-layer.js +185 -0
- package/esri-compat/group-layer.d.ts +48 -0
- package/esri-compat/group-layer.d.ts.map +1 -0
- package/esri-compat/group-layer.js +212 -0
- package/esri-compat/identify.d.ts +71 -0
- package/esri-compat/identify.d.ts.map +1 -0
- package/esri-compat/identify.js +299 -0
- package/esri-compat/identity-manager.d.ts +31 -0
- package/esri-compat/identity-manager.d.ts.map +1 -0
- package/esri-compat/identity-manager.js +115 -0
- package/esri-compat/label-class.d.ts +31 -0
- package/esri-compat/label-class.d.ts.map +1 -0
- package/esri-compat/label-class.js +102 -0
- package/esri-compat/layer-list.d.ts +77 -0
- package/esri-compat/layer-list.d.ts.map +1 -0
- package/esri-compat/layer-list.js +342 -0
- package/esri-compat/legend.d.ts +53 -0
- package/esri-compat/legend.d.ts.map +1 -0
- package/esri-compat/legend.js +254 -0
- package/esri-compat/map-image-layer.d.ts +162 -0
- package/esri-compat/map-image-layer.d.ts.map +1 -0
- package/esri-compat/map-image-layer.js +704 -0
- package/esri-compat/map-view.d.ts +315 -0
- package/esri-compat/map-view.d.ts.map +1 -0
- package/esri-compat/map-view.js +1110 -0
- package/esri-compat/map.d.ts +47 -0
- package/esri-compat/map.d.ts.map +1 -0
- package/esri-compat/map.js +209 -0
- package/esri-compat/measurement-2d.d.ts +61 -0
- package/esri-compat/measurement-2d.d.ts.map +1 -0
- package/esri-compat/measurement-2d.js +184 -0
- package/esri-compat/measurement.d.ts +45 -0
- package/esri-compat/measurement.d.ts.map +1 -0
- package/esri-compat/measurement.js +193 -0
- package/esri-compat/oauth-info.d.ts +35 -0
- package/esri-compat/oauth-info.d.ts.map +1 -0
- package/esri-compat/oauth-info.js +115 -0
- package/esri-compat/picture-marker-symbol.d.ts +35 -0
- package/esri-compat/picture-marker-symbol.d.ts.map +1 -0
- package/esri-compat/picture-marker-symbol.js +126 -0
- package/esri-compat/point.d.ts +31 -0
- package/esri-compat/point.d.ts.map +1 -0
- package/esri-compat/point.js +102 -0
- package/esri-compat/polygon.d.ts +31 -0
- package/esri-compat/polygon.d.ts.map +1 -0
- package/esri-compat/polygon.js +107 -0
- package/esri-compat/polyline.d.ts +31 -0
- package/esri-compat/polyline.d.ts.map +1 -0
- package/esri-compat/polyline.js +107 -0
- package/esri-compat/popup-template.d.ts +55 -0
- package/esri-compat/popup-template.d.ts.map +1 -0
- package/esri-compat/popup-template.js +128 -0
- package/esri-compat/popup.d.ts +54 -0
- package/esri-compat/popup.d.ts.map +1 -0
- package/esri-compat/popup.js +312 -0
- package/esri-compat/print.d.ts +47 -0
- package/esri-compat/print.d.ts.map +1 -0
- package/esri-compat/print.js +105 -0
- package/esri-compat/query.d.ts +46 -0
- package/esri-compat/query.d.ts.map +1 -0
- package/esri-compat/query.js +119 -0
- package/esri-compat/reactive-utils.d.ts +23 -0
- package/esri-compat/reactive-utils.d.ts.map +1 -0
- package/esri-compat/reactive-utils.js +178 -0
- package/esri-compat/request.d.ts +41 -0
- package/esri-compat/request.d.ts.map +1 -0
- package/esri-compat/request.js +253 -0
- package/esri-compat/route-layer.d.ts +59 -0
- package/esri-compat/route-layer.d.ts.map +1 -0
- package/esri-compat/route-layer.js +223 -0
- package/esri-compat/route-task.d.ts +88 -0
- package/esri-compat/route-task.d.ts.map +1 -0
- package/esri-compat/route-task.js +225 -0
- package/esri-compat/scene-view.d.ts +41 -0
- package/esri-compat/scene-view.d.ts.map +1 -0
- package/esri-compat/scene-view.js +68 -0
- package/esri-compat/search.d.ts +112 -0
- package/esri-compat/search.d.ts.map +1 -0
- package/esri-compat/search.js +820 -0
- package/esri-compat/simple-fill-symbol.d.ts +27 -0
- package/esri-compat/simple-fill-symbol.d.ts.map +1 -0
- package/esri-compat/simple-fill-symbol.js +85 -0
- package/esri-compat/simple-line-symbol.d.ts +27 -0
- package/esri-compat/simple-line-symbol.d.ts.map +1 -0
- package/esri-compat/simple-line-symbol.js +85 -0
- package/esri-compat/simple-marker-symbol.d.ts +29 -0
- package/esri-compat/simple-marker-symbol.d.ts.map +1 -0
- package/esri-compat/simple-marker-symbol.js +92 -0
- package/esri-compat/simple-renderer.d.ts +29 -0
- package/esri-compat/simple-renderer.d.ts.map +1 -0
- package/esri-compat/simple-renderer.js +92 -0
- package/esri-compat/sketch.d.ts +64 -0
- package/esri-compat/sketch.d.ts.map +1 -0
- package/esri-compat/sketch.js +227 -0
- package/esri-compat/spatial-reference.d.ts +31 -0
- package/esri-compat/spatial-reference.d.ts.map +1 -0
- package/esri-compat/spatial-reference.js +102 -0
- package/esri-compat/swipe.d.ts +34 -0
- package/esri-compat/swipe.d.ts.map +1 -0
- package/esri-compat/swipe.js +93 -0
- package/esri-compat/table-list.d.ts +36 -0
- package/esri-compat/table-list.d.ts.map +1 -0
- package/esri-compat/table-list.js +126 -0
- package/esri-compat/text-symbol.d.ts +37 -0
- package/esri-compat/text-symbol.d.ts.map +1 -0
- package/esri-compat/text-symbol.js +123 -0
- package/esri-compat/tile-layer.d.ts +52 -0
- package/esri-compat/tile-layer.d.ts.map +1 -0
- package/esri-compat/tile-layer.js +167 -0
- package/esri-compat/time-slider.d.ts +70 -0
- package/esri-compat/time-slider.d.ts.map +1 -0
- package/esri-compat/time-slider.js +208 -0
- package/esri-compat/track.d.ts +51 -0
- package/esri-compat/track.d.ts.map +1 -0
- package/esri-compat/track.js +174 -0
- package/esri-compat/unique-value-renderer.d.ts +41 -0
- package/esri-compat/unique-value-renderer.d.ts.map +1 -0
- package/esri-compat/unique-value-renderer.js +127 -0
- package/esri-compat/url.d.ts +12 -0
- package/esri-compat/url.d.ts.map +1 -0
- package/esri-compat/url.js +54 -0
- package/esri-compat/web-map.d.ts +14 -0
- package/esri-compat/web-map.d.ts.map +1 -0
- package/esri-compat/web-map.js +24 -0
- package/gen/honua/v1/feature_service_pb.d.ts +918 -0
- package/gen/honua/v1/feature_service_pb.d.ts.map +1 -0
- package/gen/honua/v1/feature_service_pb.js +375 -0
- package/index.d.ts +130 -0
- package/index.js +65 -0
- 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
|
+
}
|