@xyo-network/quadkey 7.0.11 → 7.0.13

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 CHANGED
@@ -1,3 +1,49 @@
1
+ [![logo][]](https://xyo.network)
2
+
1
3
  # @xyo-network/quadkey
2
4
 
3
- Deprecated compatibility stub. Use `@xyo-network/sdk-protocol/quadkey` instead.
5
+ [![npm][npm-badge]][npm-link]
6
+ [![license][license-badge]][license-link]
7
+
8
+ > Primary SDK for using XYO Protocol 2.0
9
+
10
+ ## Install
11
+
12
+ Using npm:
13
+
14
+ ```sh
15
+ npm install {{name}}
16
+ ```
17
+
18
+ Using yarn:
19
+
20
+ ```sh
21
+ yarn add {{name}}
22
+ ```
23
+
24
+ Using pnpm:
25
+
26
+ ```sh
27
+ pnpm add {{name}}
28
+ ```
29
+
30
+ Using bun:
31
+
32
+ ```sh
33
+ bun add {{name}}
34
+ ```
35
+
36
+
37
+ ## License
38
+
39
+ See the [LICENSE](LICENSE) file for license rights and limitations (LGPL-3.0-only).
40
+
41
+ ## Credits
42
+
43
+ [Made with 🔥 and ❄️ by XYO Foundation](https://xyo.network)
44
+
45
+ [npm-badge]: https://img.shields.io/npm/v/@xyo-network/quadkey.svg
46
+ [npm-link]: https://www.npmjs.com/package/@xyo-network/quadkey
47
+ [license-badge]: https://img.shields.io/npm/l/@xyo-network/quadkey.svg
48
+ [license-link]: https://github.com/xylabs/sdk-js/blob/main/LICENSE
49
+ [logo]: https://cdn.xy.company/img/brand/XYO_full_colored.png
@@ -0,0 +1,65 @@
1
+ import type { MercatorBoundingBox, MercatorLngLatLike, MercatorTile } from '@xylabs/geo';
2
+ import { GeoJson, MercatorLngLat } from '@xylabs/geo';
3
+ export declare const isQuadkey: (obj: {
4
+ type: string;
5
+ }) => boolean;
6
+ export declare class Quadkey {
7
+ static readonly Zero: Quadkey;
8
+ static readonly root: Quadkey;
9
+ static readonly type = "Quadkey";
10
+ private _geoJson?;
11
+ key: bigint;
12
+ type: string;
13
+ constructor(key?: bigint);
14
+ static from(zoom: number, id: bigint): Quadkey;
15
+ static fromArrayBuffer(zoom: number, id: ArrayBuffer): Quadkey;
16
+ static fromBase16String(value: string): Quadkey;
17
+ static fromBase4String(value?: string): Quadkey;
18
+ static fromBoundingBox(boundingBox: MercatorBoundingBox, zoom: number): Quadkey[];
19
+ static fromLngLat(point: MercatorLngLatLike, zoom: number): Quadkey;
20
+ static fromString(zoom: number, id: string, base?: number): Quadkey;
21
+ static fromTile(tile: MercatorTile): Quadkey;
22
+ get base10String(): string;
23
+ get base16String(): string;
24
+ get base4Hash(): string;
25
+ get base4HashLabel(): string;
26
+ get boundingBox(): MercatorBoundingBox;
27
+ get center(): MercatorLngLat;
28
+ get children(): Quadkey[];
29
+ get gridLocation(): {
30
+ col: number;
31
+ row: number;
32
+ zoom: number;
33
+ };
34
+ get id(): bigint;
35
+ get parent(): Quadkey | undefined;
36
+ get siblings(): Quadkey[];
37
+ get tile(): MercatorTile;
38
+ get valid(): boolean;
39
+ get zoom(): number;
40
+ childrenByZoom(zoom: number): Quadkey[];
41
+ clone(): Quadkey;
42
+ equals(obj: Quadkey): boolean;
43
+ geoJson(): GeoJson;
44
+ getGridBoundingBox(size: number): {
45
+ height: number;
46
+ left: number;
47
+ top: number;
48
+ width: number;
49
+ };
50
+ /** @deprecated use .gridLocation instead */
51
+ getGridLocation(): {
52
+ col: number;
53
+ row: number;
54
+ zoom: number;
55
+ };
56
+ isInBoundingBox(boundingBox: MercatorBoundingBox): boolean;
57
+ relative(direction: string): Quadkey;
58
+ setId(id: bigint): this;
59
+ setKey(zoom: number, key: bigint): this;
60
+ setZoom(zoom: number): this;
61
+ toJSON(): string;
62
+ toString(): string;
63
+ protected guessZoom(): void;
64
+ }
65
+ //# sourceMappingURL=Quadkey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Quadkey.d.ts","sourceRoot":"","sources":["../../src/Quadkey.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAEL,OAAO,EACP,cAAc,EAMf,MAAM,aAAa,CAAA;AAMpB,eAAO,MAAM,SAAS,GAAI,KAAK;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,YAA+B,CAAA;AA2B9E,qBAAa,OAAO;IAClB,MAAM,CAAC,QAAQ,CAAC,IAAI,UAAsB;IAC1C,MAAM,CAAC,QAAQ,CAAC,IAAI,UAAgB;IACpC,MAAM,CAAC,QAAQ,CAAC,IAAI,aAAY;IAEhC,OAAO,CAAC,QAAQ,CAAC,CAAS;IAE1B,GAAG,EAAE,MAAM,CAAA;IAEX,IAAI,SAAe;gBAEP,GAAG,SAAK;IAMpB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAKpC,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW;IAKpD,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM;IAIrC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM;IAcrC,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM;IAKrE,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM;IAMzD,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,SAAK;IAWrD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY;IAIlC,IAAI,YAAY,WAEf;IAED,IAAI,YAAY,WAEf;IAED,IAAI,SAAS,WAKZ;IAED,IAAI,cAAc,WAGjB;IAED,IAAI,WAAW,IAAI,mBAAmB,CAErC;IAED,IAAI,MAAM,mBAGT;IAED,IAAI,QAAQ,cASX;IAED,IAAI,YAAY,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAQ7D;IAED,IAAI,EAAE,WAEL;IAED,IAAI,MAAM,IAAI,OAAO,GAAG,SAAS,CAMhC;IAED,IAAI,QAAQ,cAKX;IAED,IAAI,IAAI,IAAI,YAAY,CAEvB;IAED,IAAI,KAAK,YAGR;IAED,IAAI,IAAI,WAGP;IAED,cAAc,CAAC,IAAI,EAAE,MAAM;IAc3B,KAAK;IAIL,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAI7B,OAAO;IAKP,kBAAkB,CAAC,IAAI,EAAE,MAAM;;;;;;IAwB/B,4CAA4C;IAC5C,eAAe;aA/FY,MAAM;aAAO,MAAM;cAAQ,MAAM;;IAmG5D,eAAe,CAAC,WAAW,EAAE,mBAAmB;IAUhD,QAAQ,CAAC,SAAS,EAAE,MAAM;IAyB1B,KAAK,CAAC,EAAE,EAAE,MAAM;IAMhB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAOhC,OAAO,CAAC,IAAI,EAAE,MAAM;IAMpB,MAAM,IAAI,MAAM;IAIhB,QAAQ;IAIR,SAAS,CAAC,SAAS;CAIpB"}
@@ -0,0 +1,2 @@
1
+ export declare const RelativeDirectionConstantLookup: Record<string, number>;
2
+ //# sourceMappingURL=RelativeDirectionConstantLookup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelativeDirectionConstantLookup.d.ts","sourceRoot":"","sources":["../../src/RelativeDirectionConstantLookup.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKlE,CAAA"}
@@ -1,6 +1,2 @@
1
- /**
2
- * @deprecated Use `@xyo-network/sdk-protocol/quadkey` instead.
3
- * `@xyo-network/quadkey` is a backward-compatibility re-export stub.
4
- */
5
- export * from '@xyo-network/sdk-protocol/quadkey';
1
+ export * from './Quadkey.ts';
6
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,mCAAmC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA"}
@@ -1,3 +1,281 @@
1
- // src/index.ts
2
- export * from "@xyo-network/sdk-protocol/quadkey";
1
+ // src/Quadkey.ts
2
+ import {
3
+ assertEx,
4
+ hexFromArrayBuffer,
5
+ hexFromHexString
6
+ } from "@ariestools/sdk";
7
+ import {
8
+ boundingBoxToCenter,
9
+ GeoJson,
10
+ MercatorLngLat,
11
+ tileFromPoint,
12
+ tileFromQuadkey,
13
+ tilesFromBoundingBox,
14
+ tileToBoundingBox,
15
+ tileToQuadkey
16
+ } from "@xylabs/geo";
17
+
18
+ // src/RelativeDirectionConstantLookup.ts
19
+ var RelativeDirectionConstantLookup = {
20
+ e: 1,
21
+ n: -2,
22
+ s: 2,
23
+ w: -1
24
+ };
25
+
26
+ // src/Quadkey.ts
27
+ var MAX_ZOOM = 124;
28
+ var isQuadkey = (obj) => obj?.type === Quadkey.type;
29
+ var FULL_MASK = 2n ** 256n - 1n;
30
+ var ZOOM_MASK = 0xFFn << 248n;
31
+ var ID_MASK = ZOOM_MASK ^ FULL_MASK;
32
+ var assertMaxBitUint = (value, bits = 256n) => {
33
+ assertEx(value < 2n ** bits && value >= 0, () => "Not a 256 Bit Uint!");
34
+ };
35
+ function gridOffsetForDigit(digit, blockSize) {
36
+ switch (digit) {
37
+ case "1": {
38
+ return { left: blockSize, top: 0 };
39
+ }
40
+ case "2": {
41
+ return { left: 0, top: blockSize };
42
+ }
43
+ case "3": {
44
+ return { left: blockSize, top: blockSize };
45
+ }
46
+ default: {
47
+ return { left: 0, top: 0 };
48
+ }
49
+ }
50
+ }
51
+ var Quadkey = class _Quadkey {
52
+ static Zero = _Quadkey.from(0, 0n);
53
+ static root = new _Quadkey();
54
+ static type = "Quadkey";
55
+ _geoJson;
56
+ key;
57
+ type = _Quadkey.type;
58
+ constructor(key = 0n) {
59
+ assertMaxBitUint(key);
60
+ this.key = key;
61
+ this.guessZoom();
62
+ }
63
+ static from(zoom, id) {
64
+ const quadkey = new _Quadkey();
65
+ return quadkey.setId(id).setZoom(zoom);
66
+ }
67
+ static fromArrayBuffer(zoom, id) {
68
+ const quadkey = new _Quadkey();
69
+ return quadkey.setId(BigInt(hexFromArrayBuffer(id, { prefix: true }))).setZoom(zoom);
70
+ }
71
+ static fromBase16String(value) {
72
+ return new _Quadkey(BigInt(hexFromHexString(value, { prefix: true })));
73
+ }
74
+ static fromBase4String(value) {
75
+ if (value === void 0 || ["fhr", ""].includes(value)) {
76
+ return this.root;
77
+ }
78
+ let id = 0n;
79
+ for (const digit of value) {
80
+ const nibble = Number.parseInt(digit);
81
+ assertEx(nibble < 4 && nibble >= 0, () => `Invalid Base4 String: ${value}`);
82
+ id = id << 2n | BigInt(nibble);
83
+ }
84
+ const quadkey = new _Quadkey();
85
+ return quadkey.setId(id).setZoom(value.length);
86
+ }
87
+ static fromBoundingBox(boundingBox, zoom) {
88
+ const tiles = tilesFromBoundingBox(boundingBox, Math.floor(zoom));
89
+ return Array.from(tiles, (tile) => assertEx(this.fromTile(tile), () => "Bad Quadkey"));
90
+ }
91
+ static fromLngLat(point, zoom) {
92
+ const tile = tileFromPoint(point, zoom);
93
+ const quadkeyString = tileToQuadkey(tile);
94
+ return this.fromBase4String(quadkeyString);
95
+ }
96
+ static fromString(zoom, id, base = 16) {
97
+ switch (base) {
98
+ case 16: {
99
+ return this.fromBase16String(id).setZoom(zoom);
100
+ }
101
+ default: {
102
+ throw new Error(`Invalid base [${base}]`);
103
+ }
104
+ }
105
+ }
106
+ static fromTile(tile) {
107
+ return this.fromBase4String(tileToQuadkey(tile));
108
+ }
109
+ get base10String() {
110
+ return this.id.toString(10);
111
+ }
112
+ get base16String() {
113
+ return this.id.toString(16).padStart(62, "0");
114
+ }
115
+ get base4Hash() {
116
+ if (this.id === 0n && this.zoom === 0) {
117
+ return "";
118
+ }
119
+ return this.id.toString(4).padStart(this.zoom, "0");
120
+ }
121
+ get base4HashLabel() {
122
+ const hash = this.base4Hash;
123
+ return hash.length === 0 ? "fhr" : hash;
124
+ }
125
+ get boundingBox() {
126
+ return tileToBoundingBox(this.tile);
127
+ }
128
+ get center() {
129
+ const result = boundingBoxToCenter(this.boundingBox);
130
+ return new MercatorLngLat(result[0], result[1]);
131
+ }
132
+ get children() {
133
+ assertEx(this.zoom < MAX_ZOOM - 1, () => "Can not get children of bottom tiles");
134
+ const result = [];
135
+ const shiftedId = this.id << 2n;
136
+ for (let i = 0n; i < 4n; i++) {
137
+ const quadkey = new _Quadkey();
138
+ result.push(quadkey.setId(shiftedId | i).setZoom(this.zoom + 1));
139
+ }
140
+ return result;
141
+ }
142
+ get gridLocation() {
143
+ const tileData = tileFromQuadkey(this.base4Hash);
144
+ return {
145
+ col: 2 ** tileData[2] - tileData[1] - 1,
146
+ row: tileData[0],
147
+ zoom: tileData[2]
148
+ };
149
+ }
150
+ get id() {
151
+ return this.key & ID_MASK;
152
+ }
153
+ get parent() {
154
+ if (this.zoom <= 0) {
155
+ return;
156
+ }
157
+ const quadkey = new _Quadkey();
158
+ return quadkey.setId(this.id >> 2n).setZoom(this.zoom - 1);
159
+ }
160
+ get siblings() {
161
+ const siblings = assertEx(this.parent?.children, () => `siblings: parentChildren ${this.base4Hash}`);
162
+ const filteredSiblings = siblings.filter((quadkey) => quadkey.key !== this.key);
163
+ assertEx(filteredSiblings.length === 3, () => `siblings: expected 3 [${filteredSiblings.length}]`);
164
+ return filteredSiblings;
165
+ }
166
+ get tile() {
167
+ return tileFromQuadkey(this.base4Hash);
168
+ }
169
+ get valid() {
170
+ return this.id.toString(4) === this.base4Hash.padStart(64, "0");
171
+ }
172
+ get zoom() {
173
+ return Number((this.key & ZOOM_MASK) >> 248n);
174
+ }
175
+ childrenByZoom(zoom) {
176
+ if (zoom > 0 && zoom === this.zoom) {
177
+ return [this];
178
+ }
179
+ let deepResult = [];
180
+ for (const quadkey of this.children) {
181
+ deepResult = [...deepResult, ...quadkey.childrenByZoom(zoom)];
182
+ }
183
+ return deepResult;
184
+ }
185
+ clone() {
186
+ return new _Quadkey(this.key);
187
+ }
188
+ equals(obj) {
189
+ return obj.key == this.key;
190
+ }
191
+ geoJson() {
192
+ this._geoJson = this._geoJson ?? new GeoJson(this.base4Hash);
193
+ return this._geoJson;
194
+ }
195
+ getGridBoundingBox(size) {
196
+ const hash = this.base4Hash;
197
+ let index = 0;
198
+ let left = 0;
199
+ let top = 0;
200
+ let blockSize = size;
201
+ while (index < hash.length) {
202
+ blockSize >>= 1;
203
+ const offset = gridOffsetForDigit(hash[index], blockSize);
204
+ left += offset.left;
205
+ top += offset.top;
206
+ index++;
207
+ }
208
+ if (blockSize < 2) {
209
+ blockSize = 2;
210
+ }
211
+ return {
212
+ height: blockSize,
213
+ left,
214
+ top,
215
+ width: blockSize
216
+ };
217
+ }
218
+ /** @deprecated use .gridLocation instead */
219
+ getGridLocation() {
220
+ return this.gridLocation;
221
+ }
222
+ isInBoundingBox(boundingBox) {
223
+ const tileBoundingBox = tileToBoundingBox(this.tile);
224
+ return boundingBox.contains(tileBoundingBox.getNorthEast()) || boundingBox.contains(tileBoundingBox.getNorthWest()) || boundingBox.contains(tileBoundingBox.getSouthEast()) || boundingBox.contains(tileBoundingBox.getSouthWest());
225
+ }
226
+ relative(direction) {
227
+ const directionConstant = assertEx(RelativeDirectionConstantLookup[direction], () => "Invalid direction");
228
+ let quadkey = this.base4Hash;
229
+ if (quadkey.length === 0) {
230
+ return this;
231
+ }
232
+ let index = quadkey.length - 1;
233
+ while (index >= 0) {
234
+ let number = Number.parseInt(quadkey.charAt(index));
235
+ number += directionConstant;
236
+ if (number > 3) {
237
+ number -= 4;
238
+ quadkey = quadkey.slice(0, Math.max(0, index)) + number.toString() + quadkey.slice(Math.max(0, index + 1));
239
+ index--;
240
+ } else if (number < 0) {
241
+ number += 4;
242
+ quadkey = quadkey.slice(0, Math.max(0, index)) + number.toString() + quadkey.slice(Math.max(0, index + 1));
243
+ index--;
244
+ } else {
245
+ index = -1;
246
+ }
247
+ }
248
+ return _Quadkey.fromBase4String(quadkey);
249
+ }
250
+ setId(id) {
251
+ assertMaxBitUint(id, 248n);
252
+ this.setKey(this.zoom, id);
253
+ return this;
254
+ }
255
+ setKey(zoom, key) {
256
+ assertMaxBitUint(key);
257
+ this.key = key;
258
+ this.setZoom(zoom);
259
+ return this;
260
+ }
261
+ setZoom(zoom) {
262
+ assertEx(zoom < MAX_ZOOM, () => `Invalid zoom [${zoom}] max=${MAX_ZOOM}`);
263
+ this.key = this.key & ID_MASK | BigInt(zoom) << 248n;
264
+ return this;
265
+ }
266
+ toJSON() {
267
+ return this.base4HashLabel;
268
+ }
269
+ toString() {
270
+ return this.base4Hash;
271
+ }
272
+ guessZoom() {
273
+ const quadkeySimple = this.id.toString(4);
274
+ this.setZoom(quadkeySimple.length);
275
+ }
276
+ };
277
+ export {
278
+ Quadkey,
279
+ isQuadkey
280
+ };
3
281
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["/**\n * @deprecated Use `@xyo-network/sdk-protocol/quadkey` instead.\n * `@xyo-network/quadkey` is a backward-compatibility re-export stub.\n */\nexport * from '@xyo-network/sdk-protocol/quadkey'\n"],
5
- "mappings": ";AAIA,cAAc;",
3
+ "sources": ["../../src/Quadkey.ts", "../../src/RelativeDirectionConstantLookup.ts"],
4
+ "sourcesContent": ["import {\n assertEx, hexFromArrayBuffer, hexFromHexString,\n} from '@ariestools/sdk'\nimport type {\n MercatorBoundingBox,\n MercatorLngLatLike,\n MercatorTile,\n} from '@xylabs/geo'\nimport {\n boundingBoxToCenter,\n GeoJson,\n MercatorLngLat,\n tileFromPoint,\n tileFromQuadkey,\n tilesFromBoundingBox,\n tileToBoundingBox,\n tileToQuadkey,\n} from '@xylabs/geo'\n\nimport { RelativeDirectionConstantLookup } from './RelativeDirectionConstantLookup.ts'\n\nconst MAX_ZOOM = 124\n\nexport const isQuadkey = (obj: { type: string }) => obj?.type === Quadkey.type\n\nconst FULL_MASK = 2n ** 256n - 1n\nconst ZOOM_MASK = 0xFFn << 248n\nconst ID_MASK = ZOOM_MASK ^ FULL_MASK\n\nconst assertMaxBitUint = (value: bigint, bits = 256n) => {\n assertEx(value < 2n ** bits && value >= 0, () => 'Not a 256 Bit Uint!')\n}\n\nfunction gridOffsetForDigit(digit: string, blockSize: number): { left: number; top: number } {\n switch (digit) {\n case '1': {\n return { left: blockSize, top: 0 }\n }\n case '2': {\n return { left: 0, top: blockSize }\n }\n case '3': {\n return { left: blockSize, top: blockSize }\n }\n default: {\n return { left: 0, top: 0 }\n }\n }\n}\n\nexport class Quadkey {\n static readonly Zero = Quadkey.from(0, 0n)\n static readonly root = new Quadkey()\n static readonly type = 'Quadkey'\n\n private _geoJson?: GeoJson\n\n key: bigint\n\n type = Quadkey.type\n\n constructor(key = 0n) {\n assertMaxBitUint(key)\n this.key = key\n this.guessZoom()\n }\n\n static from(zoom: number, id: bigint) {\n const quadkey = new Quadkey()\n return quadkey.setId(id).setZoom(zoom)\n }\n\n static fromArrayBuffer(zoom: number, id: ArrayBuffer) {\n const quadkey = new Quadkey()\n return quadkey.setId(BigInt(hexFromArrayBuffer(id, { prefix: true }))).setZoom(zoom)\n }\n\n static fromBase16String(value: string) {\n return new Quadkey(BigInt(hexFromHexString(value, { prefix: true })))\n }\n\n static fromBase4String(value?: string) {\n if (value === undefined || ['fhr', ''].includes(value)) {\n return this.root\n }\n let id = 0n\n for (const digit of value) {\n const nibble = Number.parseInt(digit)\n assertEx(nibble < 4 && nibble >= 0, () => `Invalid Base4 String: ${value}`)\n id = (id << 2n) | BigInt(nibble)\n }\n const quadkey = new Quadkey()\n return quadkey.setId(id).setZoom(value.length)\n }\n\n static fromBoundingBox(boundingBox: MercatorBoundingBox, zoom: number) {\n const tiles = tilesFromBoundingBox(boundingBox, Math.floor(zoom))\n return Array.from(tiles, tile => assertEx(this.fromTile(tile), () => 'Bad Quadkey'))\n }\n\n static fromLngLat(point: MercatorLngLatLike, zoom: number) {\n const tile = tileFromPoint(point as MercatorLngLat, zoom)\n const quadkeyString = tileToQuadkey(tile)\n return this.fromBase4String(quadkeyString)\n }\n\n static fromString(zoom: number, id: string, base = 16) {\n switch (base) {\n case 16: {\n return this.fromBase16String(id).setZoom(zoom)\n }\n default: {\n throw new Error(`Invalid base [${base}]`)\n }\n }\n }\n\n static fromTile(tile: MercatorTile) {\n return this.fromBase4String(tileToQuadkey(tile))\n }\n\n get base10String() {\n return this.id.toString(10)\n }\n\n get base16String() {\n return this.id.toString(16).padStart(62, '0')\n }\n\n get base4Hash() {\n if (this.id === 0n && this.zoom === 0) {\n return ''\n }\n return this.id.toString(4).padStart(this.zoom, '0')\n }\n\n get base4HashLabel() {\n const hash = this.base4Hash\n return hash.length === 0 ? 'fhr' : hash\n }\n\n get boundingBox(): MercatorBoundingBox {\n return tileToBoundingBox(this.tile)\n }\n\n get center() {\n const result = boundingBoxToCenter(this.boundingBox)\n return new MercatorLngLat(result[0], result[1])\n }\n\n get children() {\n assertEx(this.zoom < MAX_ZOOM - 1, () => 'Can not get children of bottom tiles')\n const result: Quadkey[] = []\n const shiftedId = this.id << 2n\n for (let i = 0n; i < 4n; i++) {\n const quadkey = new Quadkey()\n result.push(quadkey.setId(shiftedId | i).setZoom(this.zoom + 1))\n }\n return result\n }\n\n get gridLocation(): { col: number; row: number; zoom: number } {\n const tileData = tileFromQuadkey(this.base4Hash)\n\n return {\n col: 2 ** tileData[2] - tileData[1] - 1,\n row: tileData[0],\n zoom: tileData[2],\n }\n }\n\n get id() {\n return this.key & ID_MASK\n }\n\n get parent(): Quadkey | undefined {\n if (this.zoom <= 0) {\n return\n }\n const quadkey = new Quadkey()\n return quadkey.setId(this.id >> 2n).setZoom(this.zoom - 1)\n }\n\n get siblings() {\n const siblings = assertEx(this.parent?.children, () => `siblings: parentChildren ${this.base4Hash}`)\n const filteredSiblings = siblings.filter(quadkey => quadkey.key !== this.key)\n assertEx(filteredSiblings.length === 3, () => `siblings: expected 3 [${filteredSiblings.length}]`)\n return filteredSiblings\n }\n\n get tile(): MercatorTile {\n return tileFromQuadkey(this.base4Hash)\n }\n\n get valid() {\n // check for additional data outside zoom scope\n return this.id.toString(4) === this.base4Hash.padStart(64, '0')\n }\n\n get zoom() {\n // zoom is stored in top byte\n return Number((this.key & ZOOM_MASK) >> 248n)\n }\n\n childrenByZoom(zoom: number) {\n // if we are limiting by zoom, and we are already at that limit, just return this quadkey\n if (zoom > 0 && zoom === this.zoom) {\n return [this]\n }\n\n // recursively get children\n let deepResult: Quadkey[] = []\n for (const quadkey of this.children) {\n deepResult = [...deepResult, ...quadkey.childrenByZoom(zoom)]\n }\n return deepResult\n }\n\n clone() {\n return new Quadkey(this.key)\n }\n\n equals(obj: Quadkey): boolean {\n return obj.key == this.key\n }\n\n geoJson() {\n this._geoJson = this._geoJson ?? new GeoJson(this.base4Hash)\n return this._geoJson\n }\n\n getGridBoundingBox(size: number) {\n const hash = this.base4Hash\n let index = 0\n let left = 0\n let top = 0\n let blockSize = size\n while (index < hash.length) {\n blockSize >>= 1\n const offset = gridOffsetForDigit(hash[index], blockSize)\n left += offset.left\n top += offset.top\n index++\n }\n if (blockSize < 2) {\n blockSize = 2\n }\n return {\n height: blockSize,\n left,\n top,\n width: blockSize,\n }\n }\n\n /** @deprecated use .gridLocation instead */\n getGridLocation() {\n return this.gridLocation\n }\n\n isInBoundingBox(boundingBox: MercatorBoundingBox) {\n const tileBoundingBox = tileToBoundingBox(this.tile)\n return (\n boundingBox.contains(tileBoundingBox.getNorthEast())\n || boundingBox.contains(tileBoundingBox.getNorthWest())\n || boundingBox.contains(tileBoundingBox.getSouthEast())\n || boundingBox.contains(tileBoundingBox.getSouthWest())\n )\n }\n\n relative(direction: string) {\n const directionConstant = assertEx(RelativeDirectionConstantLookup[direction], () => 'Invalid direction')\n let quadkey = this.base4Hash\n if (quadkey.length === 0) {\n return this\n }\n let index = quadkey.length - 1\n while (index >= 0) {\n let number = Number.parseInt(quadkey.charAt(index))\n number += directionConstant\n if (number > 3) {\n number -= 4\n quadkey = quadkey.slice(0, Math.max(0, index)) + number.toString() + quadkey.slice(Math.max(0, index + 1))\n index--\n } else if (number < 0) {\n number += 4\n quadkey = quadkey.slice(0, Math.max(0, index)) + number.toString() + quadkey.slice(Math.max(0, index + 1))\n index--\n } else {\n index = -1\n }\n }\n return Quadkey.fromBase4String(quadkey)\n }\n\n setId(id: bigint) {\n assertMaxBitUint(id, 248n)\n this.setKey(this.zoom, id)\n return this\n }\n\n setKey(zoom: number, key: bigint) {\n assertMaxBitUint(key)\n this.key = key\n this.setZoom(zoom)\n return this\n }\n\n setZoom(zoom: number) {\n assertEx(zoom < MAX_ZOOM, () => `Invalid zoom [${zoom}] max=${MAX_ZOOM}`)\n this.key = (this.key & ID_MASK) | (BigInt(zoom) << 248n)\n return this\n }\n\n toJSON(): string {\n return this.base4HashLabel\n }\n\n toString() {\n return this.base4Hash\n }\n\n protected guessZoom() {\n const quadkeySimple = this.id.toString(4)\n this.setZoom(quadkeySimple.length)\n }\n}\n", "export const RelativeDirectionConstantLookup: Record<string, number> = {\n e: 1,\n n: -2,\n s: 2,\n w: -1,\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@xyo-network/quadkey",
3
- "version": "7.0.11",
4
- "description": "DEPRECATED - use @xyo-network/sdk-protocol/quadkey. Backward-compatibility re-export stub for @xyo-network/quadkey.",
5
- "deprecated": "Use @xyo-network/sdk-protocol/quadkey instead. @xyo-network/quadkey is a backward-compatibility re-export stub and will not receive further updates.",
3
+ "version": "7.0.13",
4
+ "description": "Primary SDK for using XYO Protocol 2.0",
6
5
  "homepage": "https://xyo.network",
7
6
  "bugs": {
8
7
  "url": "git+https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues",
@@ -34,35 +33,30 @@
34
33
  "!**/*.test.*",
35
34
  "README.md"
36
35
  ],
37
- "dependencies": {
38
- "@xyo-network/sdk-protocol": "~7.0.11"
39
- },
40
36
  "devDependencies": {
41
- "@xylabs/toolchain": "~8.5.15",
42
- "@xylabs/tsconfig": "~8.5.15",
43
- "browserslist": "4.28.4",
44
- "eslint": "^10.6.0",
45
- "eslint-import-resolver-typescript": "^4.4.5",
46
- "typescript": "~6.0.3"
37
+ "@ariestools/sdk": "~7.0.8",
38
+ "@opentelemetry/api": "~1.9.1",
39
+ "@opentelemetry/sdk-trace-base": "~2.9.0",
40
+ "@xylabs/geo": "~7.0.8",
41
+ "@xylabs/toolchain": "~8.6.2",
42
+ "@xylabs/tsconfig": "~8.6.2",
43
+ "@xylabs/vitest-extended": "~7.0.8",
44
+ "async-mutex": "~0.5.0",
45
+ "browserslist": "~4.28.4",
46
+ "eslint": "~10.6.0",
47
+ "eslint-import-resolver-typescript": "~4.4.5",
48
+ "typescript": "~6.0.3",
49
+ "vite": "~8.1.3",
50
+ "vitest": "~4.1.9",
51
+ "zod": "~4.4.3"
47
52
  },
48
53
  "peerDependencies": {
49
- "@ariestools/sdk": "^7.0.4",
50
- "@bitauth/libauth": "~3.0",
51
- "@noble/post-quantum": "~0.6.1",
52
- "@opentelemetry/api": "^1.9",
53
- "@opentelemetry/sdk-trace-base": "^2.7",
54
- "@scure/base": "~2.2",
55
- "@scure/bip39": "~2.2",
56
- "@xylabs/geo": "^7.0",
57
- "@xylabs/threads": "^7.0",
58
- "ajv": "^8.20",
59
- "async-mutex": "^0.5",
60
- "debug": "^4.4",
61
- "ethers": "^6.16",
62
- "hash-wasm": "~4.12",
63
- "idb": "^8.0",
64
- "observable-fns": "^0.6",
65
- "zod": "^4.4"
54
+ "@ariestools/sdk": "^7.0.8",
55
+ "@opentelemetry/api": "^1.9.1",
56
+ "@opentelemetry/sdk-trace-base": "^2.9.0",
57
+ "@xylabs/geo": "^7.0.8",
58
+ "async-mutex": "^0.5.0",
59
+ "zod": "^4.4.3"
66
60
  },
67
61
  "engines": {
68
62
  "node": "^24"