mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 02:41:09 +00:00
apply automated linting fixes (#331)
This commit is contained in:
@@ -2,13 +2,13 @@ declare const L: any;
|
|||||||
declare const window: any;
|
declare const window: any;
|
||||||
declare const document: any;
|
declare const document: any;
|
||||||
|
|
||||||
import { PMTiles, Source, TileType } from "./index";
|
import { PMTiles, TileType } from "./index";
|
||||||
|
|
||||||
export const leafletRasterLayer = (source: PMTiles, options: any) => {
|
export const leafletRasterLayer = (source: PMTiles, options: any) => {
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
let mimeType: string = "";
|
let mimeType = "";
|
||||||
const cls = L.GridLayer.extend({
|
const cls = L.GridLayer.extend({
|
||||||
createTile: function (coord: any, done: any) {
|
createTile: (coord: any, done: any) => {
|
||||||
const el: any = document.createElement("img");
|
const el: any = document.createElement("img");
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const signal = controller.signal;
|
const signal = controller.signal;
|
||||||
@@ -116,11 +116,11 @@ export class Protocol {
|
|||||||
callback: ResponseCallback
|
callback: ResponseCallback
|
||||||
): Cancelable => {
|
): Cancelable => {
|
||||||
if (params.type == "json") {
|
if (params.type == "json") {
|
||||||
const pmtiles_url = params.url.substr(10);
|
const pmtilesUrl = params.url.substr(10);
|
||||||
let instance = this.tiles.get(pmtiles_url);
|
let instance = this.tiles.get(pmtilesUrl);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = new PMTiles(pmtiles_url);
|
instance = new PMTiles(pmtilesUrl);
|
||||||
this.tiles.set(pmtiles_url, instance);
|
this.tiles.set(pmtilesUrl, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance
|
instance
|
||||||
@@ -150,12 +150,12 @@ export class Protocol {
|
|||||||
cancel: () => {},
|
cancel: () => {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const pmtiles_url = result[1];
|
const pmtilesUrl = result[1];
|
||||||
|
|
||||||
let instance = this.tiles.get(pmtiles_url);
|
let instance = this.tiles.get(pmtilesUrl);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = new PMTiles(pmtiles_url);
|
instance = new PMTiles(pmtilesUrl);
|
||||||
this.tiles.set(pmtiles_url, instance);
|
this.tiles.set(pmtilesUrl, instance);
|
||||||
}
|
}
|
||||||
const z = result[2];
|
const z = result[2];
|
||||||
const x = result[3];
|
const x = result[3];
|
||||||
@@ -163,7 +163,7 @@ export class Protocol {
|
|||||||
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const signal = controller.signal;
|
const signal = controller.signal;
|
||||||
let cancel = () => {
|
const cancel = () => {
|
||||||
controller.abort();
|
controller.abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
20
js/biome.json
Normal file
20
js/biome.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"javascript": {
|
||||||
|
"formatter": {
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"indentStyle": "space"
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"rules": {
|
||||||
|
"style": {
|
||||||
|
"useNamingConvention": {}
|
||||||
|
},
|
||||||
|
"nursery": {
|
||||||
|
"noUnusedImports": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
js/index.ts
94
js/index.ts
@@ -122,14 +122,14 @@ export function zxyToTileId(z: number, x: number, y: number): number {
|
|||||||
|
|
||||||
export function tileIdToZxy(i: number): [number, number, number] {
|
export function tileIdToZxy(i: number): [number, number, number] {
|
||||||
let acc = 0;
|
let acc = 0;
|
||||||
let z = 0;
|
const z = 0;
|
||||||
|
|
||||||
for (let z = 0; z < 27; z++) {
|
for (let z = 0; z < 27; z++) {
|
||||||
const num_tiles = (0x1 << z) * (0x1 << z);
|
const numTiles = (0x1 << z) * (0x1 << z);
|
||||||
if (acc + num_tiles > i) {
|
if (acc + numTiles > i) {
|
||||||
return idOnLevel(z, i - acc);
|
return idOnLevel(z, i - acc);
|
||||||
}
|
}
|
||||||
acc += num_tiles;
|
acc += numTiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Error("Tile zoom level exceeds max safe number limit (26)");
|
throw Error("Tile zoom level exceeds max safe number limit (26)");
|
||||||
@@ -165,8 +165,8 @@ async function defaultDecompress(
|
|||||||
if (typeof (globalThis as any).DecompressionStream == "undefined") {
|
if (typeof (globalThis as any).DecompressionStream == "undefined") {
|
||||||
return decompressSync(new Uint8Array(buf));
|
return decompressSync(new Uint8Array(buf));
|
||||||
} else {
|
} else {
|
||||||
let stream = new Response(buf).body!;
|
const stream = new Response(buf).body!;
|
||||||
let result: ReadableStream<Uint8Array> = stream.pipeThrough(
|
const result: ReadableStream<Uint8Array> = stream.pipeThrough(
|
||||||
new (globalThis as any).DecompressionStream("gzip")
|
new (globalThis as any).DecompressionStream("gzip")
|
||||||
);
|
);
|
||||||
return new Response(result).arrayBuffer();
|
return new Response(result).arrayBuffer();
|
||||||
@@ -326,14 +326,14 @@ export class FetchSource implements Source {
|
|||||||
if (resp.status === 416 && offset === 0) {
|
if (resp.status === 416 && offset === 0) {
|
||||||
// some HTTP servers don't accept ranges beyond the end of the resource.
|
// some HTTP servers don't accept ranges beyond the end of the resource.
|
||||||
// Retry with the exact length
|
// Retry with the exact length
|
||||||
const content_range = resp.headers.get("Content-Range");
|
const contentRange = resp.headers.get("Content-Range");
|
||||||
if (!content_range || !content_range.startsWith("bytes */")) {
|
if (!contentRange || !contentRange.startsWith("bytes */")) {
|
||||||
throw Error("Missing content-length on 416 response");
|
throw Error("Missing content-length on 416 response");
|
||||||
}
|
}
|
||||||
const actual_length = +content_range.substr(8);
|
const actualLength = +contentRange.substr(8);
|
||||||
resp = await fetch(this.url, {
|
resp = await fetch(this.url, {
|
||||||
signal: signal,
|
signal: signal,
|
||||||
headers: { Range: "bytes=0-" + (actual_length - 1) },
|
headers: { Range: "bytes=0-" + (actualLength - 1) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,11 +341,11 @@ export class FetchSource implements Source {
|
|||||||
throw Error("Bad response code: " + resp.status);
|
throw Error("Bad response code: " + resp.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content_length = resp.headers.get("Content-Length");
|
const contentLength = resp.headers.get("Content-Length");
|
||||||
|
|
||||||
// some well-behaved backends, e.g. DigitalOcean CDN, respond with 200 instead of 206
|
// some well-behaved backends, e.g. DigitalOcean CDN, respond with 200 instead of 206
|
||||||
// but we also need to detect no support for Byte Serving which is returning the whole file
|
// but we also need to detect no support for Byte Serving which is returning the whole file
|
||||||
if (resp.status === 200 && (!content_length || +content_length > length)) {
|
if (resp.status === 200 && (!contentLength || +contentLength > length)) {
|
||||||
if (controller) controller.abort();
|
if (controller) controller.abort();
|
||||||
throw Error(
|
throw Error(
|
||||||
"Server returned no content-length header or content-length exceeding request. Check that your storage backend supports HTTP Byte Serving."
|
"Server returned no content-length header or content-length exceeding request. Check that your storage backend supports HTTP Byte Serving."
|
||||||
@@ -370,15 +370,15 @@ export function getUint64(v: DataView, offset: number): number {
|
|||||||
|
|
||||||
export function bytesToHeader(bytes: ArrayBuffer, etag?: string): Header {
|
export function bytesToHeader(bytes: ArrayBuffer, etag?: string): Header {
|
||||||
const v = new DataView(bytes);
|
const v = new DataView(bytes);
|
||||||
const spec_version = v.getUint8(7);
|
const specVersion = v.getUint8(7);
|
||||||
if (spec_version > 3) {
|
if (specVersion > 3) {
|
||||||
throw Error(
|
throw Error(
|
||||||
`Archive is spec version ${spec_version} but this library supports up to spec version 3`
|
`Archive is spec version ${specVersion} but this library supports up to spec version 3`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
specVersion: spec_version,
|
specVersion: specVersion,
|
||||||
rootDirectoryOffset: getUint64(v, 8),
|
rootDirectoryOffset: getUint64(v, 8),
|
||||||
rootDirectoryLength: getUint64(v, 16),
|
rootDirectoryLength: getUint64(v, 16),
|
||||||
jsonMetadataOffset: getUint64(v, 24),
|
jsonMetadataOffset: getUint64(v, 24),
|
||||||
@@ -459,7 +459,7 @@ function detectVersion(a: ArrayBuffer): number {
|
|||||||
export class EtagMismatch extends Error {}
|
export class EtagMismatch extends Error {}
|
||||||
|
|
||||||
export interface Cache {
|
export interface Cache {
|
||||||
getHeader: (source: Source, current_etag?: string) => Promise<Header>;
|
getHeader: (source: Source, currentEtag?: string) => Promise<Header>;
|
||||||
getDirectory: (
|
getDirectory: (
|
||||||
source: Source,
|
source: Source,
|
||||||
offset: number,
|
offset: number,
|
||||||
@@ -472,14 +472,14 @@ export interface Cache {
|
|||||||
length: number,
|
length: number,
|
||||||
header: Header
|
header: Header
|
||||||
) => Promise<ArrayBuffer>;
|
) => Promise<ArrayBuffer>;
|
||||||
invalidate: (source: Source, current_etag: string) => Promise<void>;
|
invalidate: (source: Source, currentEtag: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getHeaderAndRoot(
|
async function getHeaderAndRoot(
|
||||||
source: Source,
|
source: Source,
|
||||||
decompress: DecompressFunc,
|
decompress: DecompressFunc,
|
||||||
prefetch: boolean,
|
prefetch: boolean,
|
||||||
current_etag?: string
|
currentEtag?: string
|
||||||
): Promise<[Header, [string, number, Entry[] | ArrayBuffer]?]> {
|
): Promise<[Header, [string, number, Entry[] | ArrayBuffer]?]> {
|
||||||
const resp = await source.getBytes(0, 16384);
|
const resp = await source.getBytes(0, 16384);
|
||||||
|
|
||||||
@@ -495,16 +495,16 @@ async function getHeaderAndRoot(
|
|||||||
|
|
||||||
const headerData = resp.data.slice(0, HEADER_SIZE_BYTES);
|
const headerData = resp.data.slice(0, HEADER_SIZE_BYTES);
|
||||||
|
|
||||||
let resp_etag = resp.etag;
|
let respEtag = resp.etag;
|
||||||
if (current_etag && resp.etag != current_etag) {
|
if (currentEtag && resp.etag != currentEtag) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"ETag conflict detected; your HTTP server might not support content-based ETag headers. ETags disabled for " +
|
"ETag conflict detected; your HTTP server might not support content-based ETag headers. ETags disabled for " +
|
||||||
source.getKey()
|
source.getKey()
|
||||||
);
|
);
|
||||||
resp_etag = undefined;
|
respEtag = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const header = bytesToHeader(headerData, resp_etag);
|
const header = bytesToHeader(headerData, respEtag);
|
||||||
|
|
||||||
// optimistically set the root directory
|
// optimistically set the root directory
|
||||||
// TODO check root bounds
|
// TODO check root bounds
|
||||||
@@ -577,7 +577,7 @@ export class ResolvedValueCache {
|
|||||||
this.decompress = decompress;
|
this.decompress = decompress;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getHeader(source: Source, current_etag?: string): Promise<Header> {
|
async getHeader(source: Source, currentEtag?: string): Promise<Header> {
|
||||||
const cacheKey = source.getKey();
|
const cacheKey = source.getKey();
|
||||||
if (this.cache.has(cacheKey)) {
|
if (this.cache.has(cacheKey)) {
|
||||||
this.cache.get(cacheKey)!.lastUsed = this.counter++;
|
this.cache.get(cacheKey)!.lastUsed = this.counter++;
|
||||||
@@ -589,7 +589,7 @@ export class ResolvedValueCache {
|
|||||||
source,
|
source,
|
||||||
this.decompress,
|
this.decompress,
|
||||||
this.prefetch,
|
this.prefetch,
|
||||||
current_etag
|
currentEtag
|
||||||
);
|
);
|
||||||
if (res[1]) {
|
if (res[1]) {
|
||||||
this.cache.set(res[1][0], {
|
this.cache.set(res[1][0], {
|
||||||
@@ -666,9 +666,9 @@ export class ResolvedValueCache {
|
|||||||
if (this.cache.size > this.maxCacheEntries) {
|
if (this.cache.size > this.maxCacheEntries) {
|
||||||
let minUsed = Infinity;
|
let minUsed = Infinity;
|
||||||
let minKey = undefined;
|
let minKey = undefined;
|
||||||
this.cache.forEach((cache_value: ResolvedValue, key: string) => {
|
this.cache.forEach((cacheValue: ResolvedValue, key: string) => {
|
||||||
if (cache_value.lastUsed < minUsed) {
|
if (cacheValue.lastUsed < minUsed) {
|
||||||
minUsed = cache_value.lastUsed;
|
minUsed = cacheValue.lastUsed;
|
||||||
minKey = key;
|
minKey = key;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -678,9 +678,9 @@ export class ResolvedValueCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async invalidate(source: Source, current_etag: string) {
|
async invalidate(source: Source, currentEtag: string) {
|
||||||
this.cache.delete(source.getKey());
|
this.cache.delete(source.getKey());
|
||||||
await this.getHeader(source, current_etag);
|
await this.getHeader(source, currentEtag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,7 +712,7 @@ export class SharedPromiseCache {
|
|||||||
this.decompress = decompress;
|
this.decompress = decompress;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getHeader(source: Source, current_etag?: string): Promise<Header> {
|
async getHeader(source: Source, currentEtag?: string): Promise<Header> {
|
||||||
const cacheKey = source.getKey();
|
const cacheKey = source.getKey();
|
||||||
if (this.cache.has(cacheKey)) {
|
if (this.cache.has(cacheKey)) {
|
||||||
this.cache.get(cacheKey)!.lastUsed = this.counter++;
|
this.cache.get(cacheKey)!.lastUsed = this.counter++;
|
||||||
@@ -721,7 +721,7 @@ export class SharedPromiseCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const p = new Promise<Header>((resolve, reject) => {
|
const p = new Promise<Header>((resolve, reject) => {
|
||||||
getHeaderAndRoot(source, this.decompress, this.prefetch, current_etag)
|
getHeaderAndRoot(source, this.decompress, this.prefetch, currentEtag)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res[1]) {
|
if (res[1]) {
|
||||||
this.cache.set(res[1][0], {
|
this.cache.set(res[1][0], {
|
||||||
@@ -807,23 +807,21 @@ export class SharedPromiseCache {
|
|||||||
if (this.cache.size >= this.maxCacheEntries) {
|
if (this.cache.size >= this.maxCacheEntries) {
|
||||||
let minUsed = Infinity;
|
let minUsed = Infinity;
|
||||||
let minKey = undefined;
|
let minKey = undefined;
|
||||||
this.cache.forEach(
|
this.cache.forEach((cacheValue: SharedPromiseCacheValue, key: string) => {
|
||||||
(cache_value: SharedPromiseCacheValue, key: string) => {
|
if (cacheValue.lastUsed < minUsed) {
|
||||||
if (cache_value.lastUsed < minUsed) {
|
minUsed = cacheValue.lastUsed;
|
||||||
minUsed = cache_value.lastUsed;
|
|
||||||
minKey = key;
|
minKey = key;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
if (minKey) {
|
if (minKey) {
|
||||||
this.cache.delete(minKey);
|
this.cache.delete(minKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async invalidate(source: Source, current_etag: string) {
|
async invalidate(source: Source, currentEtag: string) {
|
||||||
this.cache.delete(source.getKey());
|
this.cache.delete(source.getKey());
|
||||||
await this.getHeader(source, current_etag);
|
await this.getHeader(source, currentEtag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,7 +862,7 @@ export class PMTiles {
|
|||||||
y: number,
|
y: number,
|
||||||
signal?: AbortSignal
|
signal?: AbortSignal
|
||||||
): Promise<RangeResponse | undefined> {
|
): Promise<RangeResponse | undefined> {
|
||||||
const tile_id = zxyToTileId(z, x, y);
|
const tileId = zxyToTileId(z, x, y);
|
||||||
const header = await this.cache.getHeader(this.source);
|
const header = await this.cache.getHeader(this.source);
|
||||||
|
|
||||||
// V2 COMPATIBILITY
|
// V2 COMPATIBILITY
|
||||||
@@ -876,16 +874,16 @@ export class PMTiles {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let d_o = header.rootDirectoryOffset;
|
let dO = header.rootDirectoryOffset;
|
||||||
let d_l = header.rootDirectoryLength;
|
let dL = header.rootDirectoryLength;
|
||||||
for (let depth = 0; depth <= 3; depth++) {
|
for (let depth = 0; depth <= 3; depth++) {
|
||||||
const directory = await this.cache.getDirectory(
|
const directory = await this.cache.getDirectory(
|
||||||
this.source,
|
this.source,
|
||||||
d_o,
|
dO,
|
||||||
d_l,
|
dL,
|
||||||
header
|
header
|
||||||
);
|
);
|
||||||
const entry = findTile(directory, tile_id);
|
const entry = findTile(directory, tileId);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
if (entry.runLength > 0) {
|
if (entry.runLength > 0) {
|
||||||
const resp = await this.source.getBytes(
|
const resp = await this.source.getBytes(
|
||||||
@@ -902,8 +900,8 @@ export class PMTiles {
|
|||||||
expires: resp.expires,
|
expires: resp.expires,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
d_o = header.leafDirectoryOffset + entry.offset;
|
dO = header.leafDirectoryOffset + entry.offset;
|
||||||
d_l = entry.length;
|
dL = entry.length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: We should in fact return a valid RangeResponse
|
// TODO: We should in fact return a valid RangeResponse
|
||||||
|
|||||||
314
js/package-lock.json
generated
314
js/package-lock.json
generated
@@ -12,14 +12,169 @@
|
|||||||
"fflate": "^0.8.0"
|
"fflate": "^0.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@biomejs/biome": "^1.5.3",
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.9",
|
||||||
"esbuild": "^0.15.11",
|
"esbuild": "^0.15.11",
|
||||||
"esbuild-runner": "^2.2.1",
|
|
||||||
"prettier": "^2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"tsx": "^4.7.0",
|
"tsx": "^4.7.0",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.5.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@biomejs/biome": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-yvZCa/g3akwTaAQ7PCwPWDCkZs3Qa5ONg/fgOUT9e6wAWsPftCjLQFPXBeGxPK30yZSSpgEmRCfpGTmVbUjGgg==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"biome": "bin/biome"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/biome"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@biomejs/cli-darwin-arm64": "1.5.3",
|
||||||
|
"@biomejs/cli-darwin-x64": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-arm64": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-arm64-musl": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-x64": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-x64-musl": "1.5.3",
|
||||||
|
"@biomejs/cli-win32-arm64": "1.5.3",
|
||||||
|
"@biomejs/cli-win32-x64": "1.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-darwin-arm64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-ImU7mh1HghEDyqNmxEZBoMPr8SxekkZuYcs+gynKlNW+TALQs7swkERiBLkG9NR0K1B3/2uVzlvYowXrmlW8hw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-darwin-x64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-vCdASqYnlpq/swErH7FD6nrFz0czFtK4k/iLgj0/+VmZVjineFPgevOb+Sr9vz0tk0GfdQO60bSpI74zU8M9Dw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-linux-arm64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-cupBQv0sNF1OKqBfx7EDWMSsKwRrBUZfjXawT4s6hKV6ALq7p0QzWlxr/sDmbKMLOaLQtw2Qgu/77N9rm+f9Rg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-linux-arm64-musl": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-DYuMizUYUBYfS0IHGjDrOP1RGipqWfMGEvNEJ398zdtmCKLXaUvTimiox5dvx4X15mBK5M2m8wgWUgOP1giUpQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-linux-x64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-YQrSArQvcv4FYsk7Q91Yv4uuu5F8hJyORVcv3zsjCLGkjIjx2RhjYLpTL733SNL7v33GmOlZY0eFR1ko38tuUw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-linux-x64-musl": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-UUHiAnlDqr2Y/LpvshBFhUYMWkl2/Jn+bi3U6jKuav0qWbbBKU/ByHgR4+NBxpKBYoCtWxhnmatfH1bpPIuZMw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-win32-arm64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-HxatYH7vf/kX9nrD+pDYuV2GI9GV8EFo6cfKkahAecTuZLPxryHx1WEfJthp5eNsE0+09STGkKIKjirP0ufaZA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@biomejs/cli-win32-x64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-fMvbSouZEASU7mZH8SIJSANDm5OqsjgtVXlbUqxwed6BP7uuHRSs396Aqwh2+VoW8fwTpp6ybIUoC9FrzB0kyA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.19.12",
|
"version": "0.19.12",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
|
||||||
@@ -394,12 +549,6 @@
|
|||||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/buffer-from": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.15.15",
|
"version": "0.15.15",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.15.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.15.tgz",
|
||||||
@@ -693,22 +842,6 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/esbuild-runner": {
|
|
||||||
"version": "2.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/esbuild-runner/-/esbuild-runner-2.2.1.tgz",
|
|
||||||
"integrity": "sha512-VP0VfJJZiZ3cKzdOH59ZceDxx/GzBKra7tiGM8MfFMLv6CR1/cpsvtQ3IsJI3pz7HyeYxtbPyecj3fHwR+3XcQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"source-map-support": "0.5.19",
|
|
||||||
"tslib": "2.3.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"esr": "bin/esr.js"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"esbuild": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/esbuild-sunos-64": {
|
"node_modules/esbuild-sunos-64": {
|
||||||
"version": "0.15.15",
|
"version": "0.15.15",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.15.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.15.tgz",
|
||||||
@@ -828,31 +961,6 @@
|
|||||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/source-map": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/source-map-support": {
|
|
||||||
"version": "0.5.19",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
|
|
||||||
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"buffer-from": "^1.0.0",
|
|
||||||
"source-map": "^0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tslib": {
|
|
||||||
"version": "2.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
|
||||||
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/tsx": {
|
"node_modules/tsx": {
|
||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz",
|
||||||
@@ -957,6 +1065,78 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@biomejs/biome": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-yvZCa/g3akwTaAQ7PCwPWDCkZs3Qa5ONg/fgOUT9e6wAWsPftCjLQFPXBeGxPK30yZSSpgEmRCfpGTmVbUjGgg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@biomejs/cli-darwin-arm64": "1.5.3",
|
||||||
|
"@biomejs/cli-darwin-x64": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-arm64": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-arm64-musl": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-x64": "1.5.3",
|
||||||
|
"@biomejs/cli-linux-x64-musl": "1.5.3",
|
||||||
|
"@biomejs/cli-win32-arm64": "1.5.3",
|
||||||
|
"@biomejs/cli-win32-x64": "1.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@biomejs/cli-darwin-arm64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-ImU7mh1HghEDyqNmxEZBoMPr8SxekkZuYcs+gynKlNW+TALQs7swkERiBLkG9NR0K1B3/2uVzlvYowXrmlW8hw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@biomejs/cli-darwin-x64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-vCdASqYnlpq/swErH7FD6nrFz0czFtK4k/iLgj0/+VmZVjineFPgevOb+Sr9vz0tk0GfdQO60bSpI74zU8M9Dw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@biomejs/cli-linux-arm64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-cupBQv0sNF1OKqBfx7EDWMSsKwRrBUZfjXawT4s6hKV6ALq7p0QzWlxr/sDmbKMLOaLQtw2Qgu/77N9rm+f9Rg==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@biomejs/cli-linux-arm64-musl": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-DYuMizUYUBYfS0IHGjDrOP1RGipqWfMGEvNEJ398zdtmCKLXaUvTimiox5dvx4X15mBK5M2m8wgWUgOP1giUpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@biomejs/cli-linux-x64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-YQrSArQvcv4FYsk7Q91Yv4uuu5F8hJyORVcv3zsjCLGkjIjx2RhjYLpTL733SNL7v33GmOlZY0eFR1ko38tuUw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@biomejs/cli-linux-x64-musl": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-UUHiAnlDqr2Y/LpvshBFhUYMWkl2/Jn+bi3U6jKuav0qWbbBKU/ByHgR4+NBxpKBYoCtWxhnmatfH1bpPIuZMw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@biomejs/cli-win32-arm64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-HxatYH7vf/kX9nrD+pDYuV2GI9GV8EFo6cfKkahAecTuZLPxryHx1WEfJthp5eNsE0+09STGkKIKjirP0ufaZA==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@biomejs/cli-win32-x64": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-fMvbSouZEASU7mZH8SIJSANDm5OqsjgtVXlbUqxwed6BP7uuHRSs396Aqwh2+VoW8fwTpp6ybIUoC9FrzB0kyA==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"@esbuild/aix-ppc64": {
|
"@esbuild/aix-ppc64": {
|
||||||
"version": "0.19.12",
|
"version": "0.19.12",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
|
||||||
@@ -1124,12 +1304,6 @@
|
|||||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"buffer-from": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"esbuild": {
|
"esbuild": {
|
||||||
"version": "0.15.15",
|
"version": "0.15.15",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.15.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.15.tgz",
|
||||||
@@ -1272,16 +1446,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"esbuild-runner": {
|
|
||||||
"version": "2.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/esbuild-runner/-/esbuild-runner-2.2.1.tgz",
|
|
||||||
"integrity": "sha512-VP0VfJJZiZ3cKzdOH59ZceDxx/GzBKra7tiGM8MfFMLv6CR1/cpsvtQ3IsJI3pz7HyeYxtbPyecj3fHwR+3XcQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"source-map-support": "0.5.19",
|
|
||||||
"tslib": "2.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"esbuild-sunos-64": {
|
"esbuild-sunos-64": {
|
||||||
"version": "0.15.15",
|
"version": "0.15.15",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.15.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.15.tgz",
|
||||||
@@ -1343,28 +1507,6 @@
|
|||||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"source-map": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"source-map-support": {
|
|
||||||
"version": "0.5.19",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
|
|
||||||
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"buffer-from": "^1.0.0",
|
|
||||||
"source-map": "^0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tslib": {
|
|
||||||
"version": "2.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
|
||||||
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"tsx": {
|
"tsx": {
|
||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"author": "Brandon Liu",
|
"author": "Brandon Liu",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@biomejs/biome": "^1.5.3",
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.9",
|
||||||
"esbuild": "^0.15.11",
|
"esbuild": "^0.15.11",
|
||||||
"prettier": "^2.8.4",
|
"prettier": "^2.8.4",
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
import { test } from "node:test";
|
|
||||||
import assert from "node:assert";
|
import assert from "node:assert";
|
||||||
|
import { test } from "node:test";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
unshift,
|
createDirectory,
|
||||||
|
deriveLeaf,
|
||||||
getUint24,
|
getUint24,
|
||||||
getUint48,
|
getUint48,
|
||||||
deriveLeaf,
|
parseEntry,
|
||||||
queryLeafdir,
|
queryLeafdir,
|
||||||
queryTile,
|
queryTile,
|
||||||
parseEntry,
|
|
||||||
EntryV2,
|
|
||||||
createDirectory,
|
|
||||||
} from "../v2";
|
} from "../v2";
|
||||||
|
|
||||||
test("stub data", () => {
|
test("stub data", () => {
|
||||||
let dataview = new DataView(
|
const dataview = new DataView(
|
||||||
createDirectory([
|
createDirectory([
|
||||||
{ z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false },
|
{ z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false },
|
||||||
{
|
{
|
||||||
@@ -27,18 +25,18 @@ test("stub data", () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
var z_raw = dataview.getUint8(17 + 0);
|
var zRaw = dataview.getUint8(17 + 0);
|
||||||
var x = getUint24(dataview, 17 + 1);
|
var x = getUint24(dataview, 17 + 1);
|
||||||
var y = getUint24(dataview, 17 + 4);
|
var y = getUint24(dataview, 17 + 4);
|
||||||
var offset = getUint48(dataview, 17 + 7);
|
var offset = getUint48(dataview, 17 + 7);
|
||||||
var length = dataview.getUint32(17 + 13, true);
|
var length = dataview.getUint32(17 + 13, true);
|
||||||
assert.strictEqual(z_raw, 14);
|
assert.strictEqual(zRaw, 14);
|
||||||
assert.strictEqual(x, 16383);
|
assert.strictEqual(x, 16383);
|
||||||
assert.strictEqual(y, 16383);
|
assert.strictEqual(y, 16383);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("get entry", () => {
|
test("get entry", () => {
|
||||||
let view = new DataView(
|
const view = new DataView(
|
||||||
createDirectory([
|
createDirectory([
|
||||||
{ z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false },
|
{ z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false },
|
||||||
{
|
{
|
||||||
@@ -51,7 +49,7 @@ test("get entry", () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
let entry = queryTile(view, 14, 16383, 16383);
|
const entry = queryTile(view, 14, 16383, 16383);
|
||||||
assert.strictEqual(entry!.z, 14);
|
assert.strictEqual(entry!.z, 14);
|
||||||
assert.strictEqual(entry!.x, 16383);
|
assert.strictEqual(entry!.x, 16383);
|
||||||
assert.strictEqual(entry!.y, 16383);
|
assert.strictEqual(entry!.y, 16383);
|
||||||
@@ -62,7 +60,7 @@ test("get entry", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("get leafdir", () => {
|
test("get leafdir", () => {
|
||||||
let view = new DataView(
|
const view = new DataView(
|
||||||
createDirectory([
|
createDirectory([
|
||||||
{
|
{
|
||||||
z: 14,
|
z: 14,
|
||||||
@@ -74,7 +72,7 @@ test("get leafdir", () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
let entry = queryLeafdir(view, 14, 16383, 16383);
|
const entry = queryLeafdir(view, 14, 16383, 16383);
|
||||||
assert.strictEqual(entry!.z, 14);
|
assert.strictEqual(entry!.z, 14);
|
||||||
assert.strictEqual(entry!.x, 16383);
|
assert.strictEqual(entry!.x, 16383);
|
||||||
assert.strictEqual(entry!.y, 16383);
|
assert.strictEqual(entry!.y, 16383);
|
||||||
@@ -118,7 +116,7 @@ test("derive the leaf level", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("convert spec v1 directory to spec v2 directory", () => {
|
test("convert spec v1 directory to spec v2 directory", () => {
|
||||||
let view = new DataView(
|
const view = new DataView(
|
||||||
createDirectory([
|
createDirectory([
|
||||||
{
|
{
|
||||||
z: 7,
|
z: 7,
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
import { test } from "node:test";
|
|
||||||
import assert from "node:assert";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
import assert from "node:assert";
|
||||||
|
import { test } from "node:test";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Entry,
|
|
||||||
zxyToTileId,
|
|
||||||
tileIdToZxy,
|
|
||||||
findTile,
|
|
||||||
readVarint,
|
|
||||||
SharedPromiseCache,
|
|
||||||
BufferPosition,
|
BufferPosition,
|
||||||
Source,
|
Entry,
|
||||||
RangeResponse,
|
|
||||||
EtagMismatch,
|
|
||||||
PMTiles,
|
PMTiles,
|
||||||
|
RangeResponse,
|
||||||
|
SharedPromiseCache,
|
||||||
|
Source,
|
||||||
|
findTile,
|
||||||
getUint64,
|
getUint64,
|
||||||
|
readVarint,
|
||||||
|
tileIdToZxy,
|
||||||
|
zxyToTileId,
|
||||||
} from "../index";
|
} from "../index";
|
||||||
|
|
||||||
test("varint", () => {
|
test("varint", () => {
|
||||||
|
|||||||
166
js/v2.ts
166
js/v2.ts
@@ -1,12 +1,12 @@
|
|||||||
|
import { decompressSync } from "fflate";
|
||||||
import {
|
import {
|
||||||
Source,
|
|
||||||
Header,
|
|
||||||
Cache,
|
Cache,
|
||||||
RangeResponse,
|
|
||||||
Compression,
|
Compression,
|
||||||
|
Header,
|
||||||
|
RangeResponse,
|
||||||
|
Source,
|
||||||
TileType,
|
TileType,
|
||||||
} from "./index";
|
} from "./index";
|
||||||
import { decompressSync } from "fflate";
|
|
||||||
|
|
||||||
export const shift = (n: number, shift: number) => {
|
export const shift = (n: number, shift: number) => {
|
||||||
return n * Math.pow(2, shift);
|
return n * Math.pow(2, shift);
|
||||||
@@ -60,14 +60,14 @@ export const queryLeafdir = (
|
|||||||
x: number,
|
x: number,
|
||||||
y: number
|
y: number
|
||||||
): EntryV2 | null => {
|
): EntryV2 | null => {
|
||||||
const offset_len = queryView(view, z | 0x80, x, y);
|
const offsetLen = queryView(view, z | 0x80, x, y);
|
||||||
if (offset_len) {
|
if (offsetLen) {
|
||||||
return {
|
return {
|
||||||
z: z,
|
z: z,
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
offset: offset_len[0],
|
offset: offsetLen[0],
|
||||||
length: offset_len[1],
|
length: offsetLen[1],
|
||||||
is_dir: true,
|
is_dir: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -75,14 +75,14 @@ export const queryLeafdir = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const queryTile = (view: DataView, z: number, x: number, y: number) => {
|
export const queryTile = (view: DataView, z: number, x: number, y: number) => {
|
||||||
const offset_len = queryView(view, z, x, y);
|
const offsetLen = queryView(view, z, x, y);
|
||||||
if (offset_len) {
|
if (offsetLen) {
|
||||||
return {
|
return {
|
||||||
z: z,
|
z: z,
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
offset: offset_len[0],
|
offset: offsetLen[0],
|
||||||
length: offset_len[1],
|
length: offsetLen[1],
|
||||||
is_dir: false,
|
is_dir: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -128,15 +128,15 @@ const entrySort = (a: EntryV2, b: EntryV2): number => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const parseEntry = (dataview: DataView, i: number): EntryV2 => {
|
export const parseEntry = (dataview: DataView, i: number): EntryV2 => {
|
||||||
const z_raw = dataview.getUint8(i * 17);
|
const zRaw = dataview.getUint8(i * 17);
|
||||||
const z = z_raw & 127;
|
const z = zRaw & 127;
|
||||||
return {
|
return {
|
||||||
z: z,
|
z: z,
|
||||||
x: getUint24(dataview, i * 17 + 1),
|
x: getUint24(dataview, i * 17 + 1),
|
||||||
y: getUint24(dataview, i * 17 + 4),
|
y: getUint24(dataview, i * 17 + 4),
|
||||||
offset: getUint48(dataview, i * 17 + 7),
|
offset: getUint48(dataview, i * 17 + 7),
|
||||||
length: dataview.getUint32(i * 17 + 13, true),
|
length: dataview.getUint32(i * 17 + 13, true),
|
||||||
is_dir: z_raw >> 7 === 1,
|
is_dir: zRaw >> 7 === 1,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -188,11 +188,11 @@ export const deriveLeaf = (view: DataView, tile: Zxy): Zxy | null => {
|
|||||||
const numEntries = view.byteLength / 17;
|
const numEntries = view.byteLength / 17;
|
||||||
const entry = parseEntry(view, numEntries - 1);
|
const entry = parseEntry(view, numEntries - 1);
|
||||||
if (entry.is_dir) {
|
if (entry.is_dir) {
|
||||||
const leaf_level = entry.z;
|
const leafLevel = entry.z;
|
||||||
const level_diff = tile.z - leaf_level;
|
const levelDiff = tile.z - leafLevel;
|
||||||
const leaf_x = Math.trunc(tile.x / (1 << level_diff));
|
const leafX = Math.trunc(tile.x / (1 << levelDiff));
|
||||||
const leaf_y = Math.trunc(tile.y / (1 << level_diff));
|
const leafY = Math.trunc(tile.y / (1 << levelDiff));
|
||||||
return { z: leaf_level, x: leaf_x, y: leaf_y };
|
return { z: leafLevel, x: leafX, y: leafY };
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
@@ -202,57 +202,57 @@ async function getHeader(source: Source): Promise<Header> {
|
|||||||
|
|
||||||
const dataview = new DataView(resp.data);
|
const dataview = new DataView(resp.data);
|
||||||
|
|
||||||
const json_size = dataview.getUint32(4, true);
|
const jsonSize = dataview.getUint32(4, true);
|
||||||
const root_entries = dataview.getUint16(8, true);
|
const rootEntries = dataview.getUint16(8, true);
|
||||||
|
|
||||||
const dec = new TextDecoder("utf-8");
|
const dec = new TextDecoder("utf-8");
|
||||||
const json_metadata = JSON.parse(
|
const jsonMetadata = JSON.parse(
|
||||||
dec.decode(new DataView(resp.data, 10, json_size))
|
dec.decode(new DataView(resp.data, 10, jsonSize))
|
||||||
);
|
);
|
||||||
let tile_compression = Compression.Unknown;
|
let tileCompression = Compression.Unknown;
|
||||||
if (json_metadata.compression === "gzip") {
|
if (jsonMetadata.compression === "gzip") {
|
||||||
tile_compression = Compression.Gzip;
|
tileCompression = Compression.Gzip;
|
||||||
}
|
}
|
||||||
|
|
||||||
let minzoom = 0;
|
let minzoom = 0;
|
||||||
if ("minzoom" in json_metadata) {
|
if ("minzoom" in jsonMetadata) {
|
||||||
minzoom = +json_metadata.minzoom;
|
minzoom = +jsonMetadata.minzoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
let maxzoom = 0;
|
let maxzoom = 0;
|
||||||
if ("maxzoom" in json_metadata) {
|
if ("maxzoom" in jsonMetadata) {
|
||||||
maxzoom = +json_metadata.maxzoom;
|
maxzoom = +jsonMetadata.maxzoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
let center_lon = 0;
|
let centerLon = 0;
|
||||||
let center_lat = 0;
|
let centerLat = 0;
|
||||||
let center_zoom = 0;
|
let centerZoom = 0;
|
||||||
let min_lon = -180.0;
|
let minLon = -180.0;
|
||||||
let min_lat = -85.0;
|
let minLat = -85.0;
|
||||||
let max_lon = 180.0;
|
let maxLon = 180.0;
|
||||||
let max_lat = 85.0;
|
let maxLat = 85.0;
|
||||||
|
|
||||||
if (json_metadata.bounds) {
|
if (jsonMetadata.bounds) {
|
||||||
const split = json_metadata.bounds.split(",");
|
const split = jsonMetadata.bounds.split(",");
|
||||||
min_lon = +split[0];
|
minLon = +split[0];
|
||||||
min_lat = +split[1];
|
minLat = +split[1];
|
||||||
max_lon = +split[2];
|
maxLon = +split[2];
|
||||||
max_lat = +split[3];
|
maxLat = +split[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json_metadata.center) {
|
if (jsonMetadata.center) {
|
||||||
const split = json_metadata.center.split(",");
|
const split = jsonMetadata.center.split(",");
|
||||||
center_lon = +split[0];
|
centerLon = +split[0];
|
||||||
center_lat = +split[1];
|
centerLat = +split[1];
|
||||||
center_zoom = +split[2];
|
centerZoom = +split[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
const header = {
|
const header = {
|
||||||
specVersion: dataview.getUint16(2, true),
|
specVersion: dataview.getUint16(2, true),
|
||||||
rootDirectoryOffset: 10 + json_size,
|
rootDirectoryOffset: 10 + jsonSize,
|
||||||
rootDirectoryLength: root_entries * 17,
|
rootDirectoryLength: rootEntries * 17,
|
||||||
jsonMetadataOffset: 10,
|
jsonMetadataOffset: 10,
|
||||||
jsonMetadataLength: json_size,
|
jsonMetadataLength: jsonSize,
|
||||||
leafDirectoryOffset: 0,
|
leafDirectoryOffset: 0,
|
||||||
leafDirectoryLength: undefined,
|
leafDirectoryLength: undefined,
|
||||||
tileDataOffset: 0,
|
tileDataOffset: 0,
|
||||||
@@ -262,17 +262,17 @@ async function getHeader(source: Source): Promise<Header> {
|
|||||||
numTileContents: 0,
|
numTileContents: 0,
|
||||||
clustered: false,
|
clustered: false,
|
||||||
internalCompression: Compression.None,
|
internalCompression: Compression.None,
|
||||||
tileCompression: tile_compression,
|
tileCompression: tileCompression,
|
||||||
tileType: TileType.Mvt,
|
tileType: TileType.Mvt,
|
||||||
minZoom: minzoom,
|
minZoom: minzoom,
|
||||||
maxZoom: maxzoom,
|
maxZoom: maxzoom,
|
||||||
minLon: min_lon,
|
minLon: minLon,
|
||||||
minLat: min_lat,
|
minLat: minLat,
|
||||||
maxLon: max_lon,
|
maxLon: maxLon,
|
||||||
maxLat: max_lat,
|
maxLat: maxLat,
|
||||||
centerZoom: center_zoom,
|
centerZoom: centerZoom,
|
||||||
centerLon: center_lon,
|
centerLon: centerLon,
|
||||||
centerLat: center_lat,
|
centerLat: centerLat,
|
||||||
etag: resp.etag,
|
etag: resp.etag,
|
||||||
};
|
};
|
||||||
return header;
|
return header;
|
||||||
@@ -287,65 +287,65 @@ async function getZxy(
|
|||||||
y: number,
|
y: number,
|
||||||
signal?: AbortSignal
|
signal?: AbortSignal
|
||||||
): Promise<RangeResponse | undefined> {
|
): Promise<RangeResponse | undefined> {
|
||||||
let root_dir = await cache.getArrayBuffer(
|
let rootDir = await cache.getArrayBuffer(
|
||||||
source,
|
source,
|
||||||
header.rootDirectoryOffset,
|
header.rootDirectoryOffset,
|
||||||
header.rootDirectoryLength,
|
header.rootDirectoryLength,
|
||||||
header
|
header
|
||||||
);
|
);
|
||||||
if (header.specVersion === 1) {
|
if (header.specVersion === 1) {
|
||||||
root_dir = sortDir(root_dir);
|
rootDir = sortDir(rootDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry = queryTile(new DataView(root_dir), z, x, y);
|
const entry = queryTile(new DataView(rootDir), z, x, y);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
const resp = await source.getBytes(entry.offset, entry.length, signal);
|
const resp = await source.getBytes(entry.offset, entry.length, signal);
|
||||||
let tile_data = resp.data;
|
let tileData = resp.data;
|
||||||
|
|
||||||
const view = new DataView(tile_data);
|
const view = new DataView(tileData);
|
||||||
if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) {
|
if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) {
|
||||||
tile_data = decompressSync(new Uint8Array(tile_data));
|
tileData = decompressSync(new Uint8Array(tileData));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: tile_data,
|
data: tileData,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const leafcoords = deriveLeaf(new DataView(root_dir), { z: z, x: x, y: y });
|
const leafcoords = deriveLeaf(new DataView(rootDir), { z: z, x: x, y: y });
|
||||||
|
|
||||||
if (leafcoords) {
|
if (leafcoords) {
|
||||||
const leafdir_entry = queryLeafdir(
|
const leafdirEntry = queryLeafdir(
|
||||||
new DataView(root_dir),
|
new DataView(rootDir),
|
||||||
leafcoords.z,
|
leafcoords.z,
|
||||||
leafcoords.x,
|
leafcoords.x,
|
||||||
leafcoords.y
|
leafcoords.y
|
||||||
);
|
);
|
||||||
if (leafdir_entry) {
|
if (leafdirEntry) {
|
||||||
let leaf_dir = await cache.getArrayBuffer(
|
let leafDir = await cache.getArrayBuffer(
|
||||||
source,
|
source,
|
||||||
leafdir_entry.offset,
|
leafdirEntry.offset,
|
||||||
leafdir_entry.length,
|
leafdirEntry.length,
|
||||||
header
|
header
|
||||||
);
|
);
|
||||||
|
|
||||||
if (header.specVersion === 1) {
|
if (header.specVersion === 1) {
|
||||||
leaf_dir = sortDir(leaf_dir);
|
leafDir = sortDir(leafDir);
|
||||||
}
|
}
|
||||||
const tile_entry = queryTile(new DataView(leaf_dir), z, x, y);
|
const tileEntry = queryTile(new DataView(leafDir), z, x, y);
|
||||||
if (tile_entry) {
|
if (tileEntry) {
|
||||||
const resp = await source.getBytes(
|
const resp = await source.getBytes(
|
||||||
tile_entry.offset,
|
tileEntry.offset,
|
||||||
tile_entry.length,
|
tileEntry.length,
|
||||||
signal
|
signal
|
||||||
);
|
);
|
||||||
let tile_data = resp.data;
|
let tileData = resp.data;
|
||||||
|
|
||||||
const view = new DataView(tile_data);
|
const view = new DataView(tileData);
|
||||||
if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) {
|
if (view.getUint8(0) == 0x1f && view.getUint8(1) == 0x8b) {
|
||||||
tile_data = decompressSync(new Uint8Array(tile_data));
|
tileData = decompressSync(new Uint8Array(tileData));
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
data: tile_data,
|
data: tileData,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user