lint cloudflare implementation (#352)

Add linters to AWS and cloudflare implementations [#287]
This commit is contained in:
Brandon Liu
2024-02-05 16:59:06 +08:00
committed by GitHub
parent b229c1a8c7
commit e86dd554be
9 changed files with 598 additions and 126 deletions

View File

@@ -8,12 +8,168 @@
"name": "pmtiles-cloudflare",
"version": "0.0.1",
"devDependencies": {
"@biomejs/biome": "^1.5.3",
"@cloudflare/workers-types": "^4.20230518.0",
"tsx": "^4.7.0",
"typescript": "^4.8.4",
"wrangler": "3.19.0"
}
},
"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/@cloudflare/kv-asset-handler": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz",
@@ -1615,6 +1771,78 @@
}
},
"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
},
"@cloudflare/kv-asset-handler": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz",

View File

@@ -2,6 +2,7 @@
"name": "pmtiles-cloudflare",
"version": "0.0.1",
"devDependencies": {
"@biomejs/biome": "^1.5.3",
"@cloudflare/workers-types": "^4.20230518.0",
"tsx": "^4.7.0",
"typescript": "^4.8.4",
@@ -13,6 +14,8 @@
"deploy": "wrangler deploy",
"test": "tsx ../shared/index.test.ts",
"tsc": "tsc --watch",
"build": "wrangler publish --outdir dist --dry-run"
"build": "wrangler publish --outdir dist --dry-run",
"biome": "biome check --config-path=../../js/ src/index.ts --apply",
"biome-check": "biome check --config-path=../../js src/index.ts"
}
}

View File

@@ -1,26 +1,27 @@
import {
Compression,
PMTiles,
Source,
RangeResponse,
ResolvedValueCache,
Source,
TileType,
Compression,
} from "../../../js/index";
import { pmtiles_path, tile_path, tileJSON } from "../../shared/index";
import { pmtiles_path, tileJSON, tile_path } from "../../shared/index";
interface Env {
// biome-ignore lint: config name
ALLOWED_ORIGINS?: string;
// biome-ignore lint: config name
BUCKET: R2Bucket;
// biome-ignore lint: config name
CACHE_MAX_AGE?: number;
// biome-ignore lint: config name
PMTILES_PATH?: string;
// biome-ignore lint: config name
PUBLIC_HOSTNAME?: string;
}
class KeyNotFoundError extends Error {
constructor(message: string) {
super(message);
}
}
class KeyNotFoundError extends Error {}
async function nativeDecompress(
buf: ArrayBuffer,
@@ -28,33 +29,38 @@ async function nativeDecompress(
): Promise<ArrayBuffer> {
if (compression === Compression.None || compression === Compression.Unknown) {
return buf;
} else if (compression === Compression.Gzip) {
let stream = new Response(buf).body!;
let result = stream.pipeThrough(new DecompressionStream("gzip"));
return new Response(result).arrayBuffer();
} else {
throw Error("Compression method not supported");
}
if (compression === Compression.Gzip) {
const stream = new Response(buf).body;
const result = stream?.pipeThrough(new DecompressionStream("gzip"));
return new Response(result).arrayBuffer();
}
throw Error("Compression method not supported");
}
const CACHE = new ResolvedValueCache(25, undefined, nativeDecompress);
class R2Source implements Source {
env: Env;
archive_name: string;
archiveName: string;
constructor(env: Env, archive_name: string) {
constructor(env: Env, archiveName: string) {
this.env = env;
this.archive_name = archive_name;
this.archiveName = archiveName;
}
getKey() {
return this.archive_name;
return this.archiveName;
}
async getBytes(offset: number, length: number, signal?: AbortSignal, etag?: string): Promise<RangeResponse> {
async getBytes(
offset: number,
length: number,
signal?: AbortSignal,
etag?: string
): Promise<RangeResponse> {
const resp = await this.env.BUCKET.get(
pmtiles_path(this.archive_name, this.env.PMTILES_PATH),
pmtiles_path(this.archiveName, this.env.PMTILES_PATH),
{
range: { offset: offset, length: length },
}
@@ -88,73 +94,72 @@ export default {
const cache = caches.default;
if (ok) {
let allowed_origin = "";
let allowedOrigin = "";
if (typeof env.ALLOWED_ORIGINS !== "undefined") {
for (const o of env.ALLOWED_ORIGINS.split(",")) {
if (o === request.headers.get("Origin") || o === "*") {
allowed_origin = o;
allowedOrigin = o;
}
}
}
const cached = await cache.match(request.url);
if (cached) {
const resp_headers = new Headers(cached.headers);
if (allowed_origin)
resp_headers.set("Access-Control-Allow-Origin", allowed_origin);
resp_headers.set("Vary", "Origin");
const respHeaders = new Headers(cached.headers);
if (allowedOrigin)
respHeaders.set("Access-Control-Allow-Origin", allowedOrigin);
respHeaders.set("Vary", "Origin");
return new Response(cached.body, {
headers: resp_headers,
headers: respHeaders,
status: cached.status,
});
}
const cacheableResponse = (
body: ArrayBuffer | string | undefined,
cacheable_headers: Headers,
cacheableHeaders: Headers,
status: number
) => {
cacheable_headers.set(
cacheableHeaders.set(
"Cache-Control",
"max-age=" + (env.CACHE_MAX_AGE || 86400)
`max-age=${env.CACHE_MAX_AGE || 86400}`
);
const cacheable = new Response(body, {
headers: cacheable_headers,
headers: cacheableHeaders,
status: status,
});
// normalize HEAD requests
ctx.waitUntil(cache.put(request.url, cacheable));
const resp_headers = new Headers(cacheable_headers);
if (allowed_origin)
resp_headers.set("Access-Control-Allow-Origin", allowed_origin);
resp_headers.set("Vary", "Origin");
return new Response(body, { headers: resp_headers, status: status });
const respHeaders = new Headers(cacheableHeaders);
if (allowedOrigin)
respHeaders.set("Access-Control-Allow-Origin", allowedOrigin);
respHeaders.set("Vary", "Origin");
return new Response(body, { headers: respHeaders, status: status });
};
const cacheable_headers = new Headers();
const cacheableHeaders = new Headers();
const source = new R2Source(env, name);
const p = new PMTiles(source, CACHE, nativeDecompress);
try {
const p_header = await p.getHeader();
const pHeader = await p.getHeader();
if (!tile) {
cacheable_headers.set("Content-Type", "application/json");
cacheableHeaders.set("Content-Type", "application/json");
const t = tileJSON(
p_header,
pHeader,
await p.getMetadata(),
env.PUBLIC_HOSTNAME || url.hostname,
name
);
return cacheableResponse(JSON.stringify(t), cacheable_headers, 200);
return cacheableResponse(JSON.stringify(t), cacheableHeaders, 200);
}
if (tile[0] < p_header.minZoom || tile[0] > p_header.maxZoom) {
return cacheableResponse(undefined, cacheable_headers, 404);
if (tile[0] < pHeader.minZoom || tile[0] > pHeader.maxZoom) {
return cacheableResponse(undefined, cacheableHeaders, 404);
}
for (const pair of [
@@ -164,14 +169,14 @@ export default {
[TileType.Webp, "webp"],
[TileType.Avif, "avif"],
]) {
if (p_header.tileType === pair[0] && ext !== pair[1]) {
if (p_header.tileType == TileType.Mvt && ext === "pbf") {
if (pHeader.tileType === pair[0] && ext !== pair[1]) {
if (pHeader.tileType === TileType.Mvt && ext === "pbf") {
// allow this for now. Eventually we will delete this in favor of .mvt
continue;
}
return cacheableResponse(
`Bad request: requested .${ext} but archive has type .${pair[1]}`,
cacheable_headers,
cacheableHeaders,
400
);
}
@@ -179,32 +184,30 @@ export default {
const tiledata = await p.getZxy(tile[0], tile[1], tile[2]);
switch (p_header.tileType) {
switch (pHeader.tileType) {
case TileType.Mvt:
cacheable_headers.set("Content-Type", "application/x-protobuf");
cacheableHeaders.set("Content-Type", "application/x-protobuf");
break;
case TileType.Png:
cacheable_headers.set("Content-Type", "image/png");
cacheableHeaders.set("Content-Type", "image/png");
break;
case TileType.Jpeg:
cacheable_headers.set("Content-Type", "image/jpeg");
cacheableHeaders.set("Content-Type", "image/jpeg");
break;
case TileType.Webp:
cacheable_headers.set("Content-Type", "image/webp");
cacheableHeaders.set("Content-Type", "image/webp");
break;
}
if (tiledata) {
return cacheableResponse(tiledata.data, cacheable_headers, 200);
} else {
return cacheableResponse(undefined, cacheable_headers, 204);
return cacheableResponse(tiledata.data, cacheableHeaders, 200);
}
return cacheableResponse(undefined, cacheableHeaders, 204);
} catch (e) {
if (e instanceof KeyNotFoundError) {
return cacheableResponse("Archive not found", cacheable_headers, 404);
} else {
throw e;
return cacheableResponse("Archive not found", cacheableHeaders, 404);
}
throw e;
}
}