Repository: protomaps/PMTiles (language: python)

Issue:
Cloudflare worker TileJSON endpoint
Would be nice if the cloudflare worker could return a TileJSON for each PMTiles file

https://github.com/protomaps/PMTiles/blob/main/serverless/cloudflare/src/index.ts#L241


Discussion / hints:

Fix patch:
diff --git a/serverless/aws/package-lock.json b/serverless/aws/package-lock.json
index f038f61..2990a60 100644
--- a/serverless/aws/package-lock.json
+++ b/serverless/aws/package-lock.json
@@ -15,6 +15,7 @@
         "@types/aws-lambda": "^8.10.108",
         "@types/node": "^18.11.2",
         "esbuild": "^0.15.11",
+        "esbuild-runner": "^2.2.2",
         "typescript": "^4.8.4"
       }
     },
@@ -1351,6 +1352,12 @@
       "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
       "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
     },
+    "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": {
       "version": "0.15.11",
       "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.11.tgz",
@@ -1644,6 +1651,28 @@
         "node": ">=12"
       }
     },
+    "node_modules/esbuild-runner": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/esbuild-runner/-/esbuild-runner-2.2.2.tgz",
+      "integrity": "sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==",
+      "dev": true,
+      "dependencies": {
+        "source-map-support": "0.5.21",
+        "tslib": "2.4.0"
+      },
+      "bin": {
+        "esr": "bin/esr.js"
+      },
+      "peerDependencies": {
+        "esbuild": "*"
+      }
+    },
+    "node_modules/esbuild-runner/node_modules/tslib": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+      "dev": true
+    },
     "node_modules/esbuild-sunos-64": {
       "version": "0.15.11",
       "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.11.tgz",
@@ -1723,6 +1752,25 @@
         "url": "https://paypal.me/naturalintelligence"
       }
     },
+    "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.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dev": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
     "node_modules/strnum": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
@@ -2870,6 +2918,12 @@
       "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
       "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
     },
+    "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": {
       "version": "0.15.11",
       "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.11.tgz",
@@ -3012,6 +3066,24 @@
       "dev": true,
       "optional": true
     },
+    "esbuild-runner": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/esbuild-runner/-/esbuild-runner-2.2.2.tgz",
+      "integrity": "sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==",
+      "dev": true,
+      "requires": {
+        "source-map-support": "0.5.21",
+        "tslib": "2.4.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.4.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+          "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+          "dev": true
+        }
+      }
+    },
     "esbuild-sunos-64": {
       "version": "0.15.11",
       "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.11.tgz",
@@ -3048,6 +3120,22 @@
         "strnum": "^1.0.5"
       }
     },
+    "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.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
     "strnum": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
diff --git a/serverless/aws/package.json b/serverless/aws/package.json
index 1436dd0..ae1e104 100644
--- a/serverless/aws/package.json
+++ b/serverless/aws/package.json
@@ -5,12 +5,14 @@
     "@types/aws-lambda": "^8.10.108",
     "@types/node": "^18.11.2",
     "esbuild": "^0.15.11",
+    "esbuild-runner": "^2.2.2",
     "typescript": "^4.8.4"
   },
   "private": true,
   "scripts": {
     "tsc": "tsc --noEmit --watch",
-    "build": "esbuild src/index.ts --target=es2020 --outfile=dist/index.mjs --format=esm --bundle --platform=node --target=node18 --external:@aws-sdk/client-s3 --external:@aws-sdk/node-http-handler --banner:js=//$(git describe --always) && cd dist && zip lambda_function.zip index.mjs"
+    "build": "esbuild src/index.ts --target=es2020 --outfile=dist/index.mjs --format=esm --bundle --platform=node --target=node18 --external:@aws-sdk/client-s3 --external:@aws-sdk/node-http-handler --banner:js=//$(git describe --always) && cd dist && zip lambda_function.zip index.mjs",
+    "test": "node -r esbuild-runner/register ../shared/index.test.ts"
   },
   "dependencies": {
     "@aws-sdk/client-s3": "^3.213.0",
diff --git a/serverless/aws/src/index.ts b/serverless/aws/src/index.ts
index 1d6629f..2130b4c 100644
--- a/serverless/aws/src/index.ts
+++ b/serverless/aws/src/index.ts
@@ -1,4 +1,3 @@
-import { Readable } from "stream";
 import {
   Context,
   APIGatewayProxyResult,
@@ -12,8 +11,8 @@ import {
   Compression,
   TileType,
 } from "../../../js/index";
+import { pmtiles_path, tile_path, tileJSON } from "../../shared/index";
 
-import https from "https";
 import zlib from "zlib";
 
 import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
@@ -43,47 +42,6 @@ async function nativeDecompress(
 // Lambda needs to run with 512MB, empty function takes about 70
 const CACHE = new ResolvedValueCache(undefined, undefined, nativeDecompress);
 
-// duplicated code below
-export const pmtiles_path = (name: string, setting?: string): string => {
-  if (setting) {
-    return setting.replaceAll("{name}", name);
-  }
-  return name + ".pmtiles";
-};
-
-const TILE =
-  /^\/(?<NAME>[0-9a-zA-Z\/!\-_\.\*\'\(\)]+)\/(?<Z>\d+)\/(?<X>\d+)\/(?<Y>\d+).(?<EXT>[a-z]+)$/;
-
-export const tile_path = (
-  path: string,
-  setting?: string
-): {
-  ok: boolean;
-  name: string;
-  tile: [number, number, number];
-  ext: string;
-} => {
-  let pattern = TILE;
-  if (setting) {
-    // escape regex
-    setting = setting.replace(/[.*+?^$()|[\]\\]/g, "\\$&");
-    setting = setting.replace("{name}", "(?<NAME>[0-9a-zA-Z/!-_.*'()]+)");
-    setting = setting.replace("{z}", "(?<Z>\\d+)");
-    setting = setting.replace("{x}", "(?<X>\\d+)");
-    setting = setting.replace("{y}", "(?<Y>\\d+)");
-    setting = setting.replace("{ext}", "(?<EXT>[a-z]+)");
-    pattern = new RegExp(setting);
-  }
-
-  let match = path.match(pattern);
-
-  if (match) {
-    const g = match.groups!;
-    return { ok: true, name: g.NAME, tile: [+g.Z, +g.X, +g.Y], ext: g.EXT };
-  }
-  return { ok: false, name: "", tile: [0, 0, 0], ext: "" };
-};
-
 class S3Source implements Source {
   archive_name: string;
 
@@ -138,11 +96,11 @@ const apiResp = (
 // Does not work with CloudFront events/Lambda@Edge; see README
 export const handlerRaw = async (
   event: APIGatewayProxyEventV2,
-  context: Context,
+  _context: Context,
   tilePostprocess?: (a: ArrayBuffer, t: TileType) => ArrayBuffer
 ): Promise<APIGatewayProxyResult> => {
-  var path;
-  var is_api_gateway;
+  let path;
+  let is_api_gateway;
   if (event.pathParameters) {
     is_api_gateway = true;
     if (event.pathParameters.proxy) {
@@ -158,14 +116,13 @@ export const handlerRaw = async (
     return apiResp(500, "Invalid event configuration");
   }
 
-  var headers: Headers = {};
-  // TODO: metadata and TileJSON
+  const headers: Headers = {};
 
   if (process.env.CORS) {
     headers["Access-Control-Allow-Origin"] = process.env.CORS;
   }
 
-  const { ok, name, tile, ext } = tile_path(path, process.env.TILE_PATH);
+  const { ok, name, tile, ext } = tile_path(path);
 
   if (!ok) {
     return apiResp(400, "Invalid tile URL", false, headers);
@@ -175,6 +132,28 @@ export const handlerRaw = async (
   const p = new PMTiles(source, CACHE, nativeDecompress);
   try {
     const header = await p.getHeader();
+
+    if (!tile) {
+      if (!process.env.PUBLIC_HOSTNAME) {
+        return apiResp(
+          400,
+          "PUBLIC_HOSTNAME must be set for TileJSON",
+          false,
+          headers
+        );
+      }
+      headers["Content-Type"] = "application/json";
+
+      const t = tileJSON(
+        header,
+        await p.getMetadata(),
+        process.env.PUBLIC_HOSTNAME,
+        name
+      );
+
+      return apiResp(200, JSON.stringify(t), false, headers);
+    }
+
     if (tile[0] < header.minZoom || tile[0] > header.maxZoom) {
       return apiResp(404, "", false, headers);
     }
@@ -259,5 +238,5 @@ export const handler = async (
   event: APIGatewayProxyEventV2,
   context: Context
 ): Promise<APIGatewayProxyResult> => {
-  return handlerRaw(event, context);
+  return await handlerRaw(event, context);
 };
diff --git a/serverless/cloudflare/package-lock.json b/serverless/cloudflare/package-lock.json
index e98f638..812b800 100644
--- a/serverless/cloudflare/package-lock.json
+++ b/serverless/cloudflare/package-lock.json
@@ -11,7 +11,7 @@
         "@cloudflare/workers-types": "^3.17.0",
         "esbuild-runner": "^2.2.2",
         "typescript": "^4.8.4",
-        "wrangler": "2.1.12"
+        "wrangler": "2.18.0"
       }
     },
     "node_modules/@cloudflare/kv-asset-handler": {
@@ -51,6 +51,358 @@
         "esbuild": "*"
       }
     },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.3.tgz",
+      "integrity": "sha512-mueuEoh+s1eRbSJqq9KNBQwI4QhQV6sRXIfTyLXSHGMpyew61rOK4qY21uKbXl1iBoMb0AdL1deWFCQVlN2qHA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.3.tgz",
+      "integrity": "sha512-RolFVeinkeraDvN/OoRf1F/lP0KUfGNb5jxy/vkIMeRRChkrX/HTYN6TYZosRJs3a1+8wqpxAo5PI5hFmxyPRg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.3.tgz",
+      "integrity": "sha512-SFpTUcIT1bIJuCCBMCQWq1bL2gPTjWoLZdjmIhjdcQHaUfV41OQfho6Ici5uvvkMmZRXIUGpM3GxysP/EU7ifQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.3.tgz",
+      "integrity": "sha512-DO8WykMyB+N9mIDfI/Hug70Dk1KipavlGAecxS3jDUwAbTpDXj0Lcwzw9svkhxfpCagDmpaTMgxWK8/C/XcXvw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.3.tgz",
+      "integrity": "sha512-uEqZQ2omc6BvWqdCiyZ5+XmxuHEi1SPzpVxXCSSV2+Sh7sbXbpeNhHIeFrIpRjAs0lI1FmA1iIOxFozKBhKgRQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.3.tgz",
+      "integrity": "sha512-nJansp3sSXakNkOD5i5mIz2Is/HjzIhFs49b1tjrPrpCmwgBmH9SSzhC/Z1UqlkivqMYkhfPwMw1dGFUuwmXhw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.3.tgz",
+      "integrity": "sha512-TfoDzLw+QHfc4a8aKtGSQ96Wa+6eimljjkq9HKR0rHlU83vw8aldMOUSJTUDxbcUdcgnJzPaX8/vGWm7vyV7ug==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.3.tgz",
+      "integrity": "sha512-VwswmSYwVAAq6LysV59Fyqk3UIjbhuc6wb3vEcJ7HEJUtFuLK9uXWuFoH1lulEbE4+5GjtHi3MHX+w1gNHdOWQ==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.3.tgz",
+      "integrity": "sha512-7I3RlsnxEFCHVZNBLb2w7unamgZ5sVwO0/ikE2GaYvYuUQs9Qte/w7TqWcXHtCwxvZx/2+F97ndiUQAWs47ZfQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.3.tgz",
+      "integrity": "sha512-X8FDDxM9cqda2rJE+iblQhIMYY49LfvW4kaEjoFbTTQ4Go8G96Smj2w3BRTwA8IHGoi9dPOPGAX63dhuv19UqA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.3.tgz",
+      "integrity": "sha512-hIbeejCOyO0X9ujfIIOKjBjNAs9XD/YdJ9JXAy1lHA+8UXuOqbFe4ErMCqMr8dhlMGBuvcQYGF7+kO7waj2KHw==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.3.tgz",
+      "integrity": "sha512-znFRzICT/V8VZQMt6rjb21MtAVJv/3dmKRMlohlShrbVXdBuOdDrGb+C2cZGQAR8RFyRe7HS6klmHq103WpmVw==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.3.tgz",
+      "integrity": "sha512-EV7LuEybxhXrVTDpbqWF2yehYRNz5e5p+u3oQUS2+ZFpknyi1NXxr8URk4ykR8Efm7iu04//4sBg249yNOwy5Q==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.3.tgz",
+      "integrity": "sha512-uDxqFOcLzFIJ+r/pkTTSE9lsCEaV/Y6rMlQjUI9BkzASEChYL/aSQjZjchtEmdnVxDKETnUAmsaZ4pqK1eE5BQ==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.3.tgz",
+      "integrity": "sha512-NbeREhzSxYwFhnCAQOQZmajsPYtX71Ufej3IQ8W2Gxskfz9DK58ENEju4SbpIj48VenktRASC52N5Fhyf/aliQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.3.tgz",
+      "integrity": "sha512-SDiG0nCixYO9JgpehoKgScwic7vXXndfasjnD5DLbp1xltANzqZ425l7LSdHynt19UWOcDjG9wJJzSElsPvk0w==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.3.tgz",
+      "integrity": "sha512-AzbsJqiHEq1I/tUvOfAzCY15h4/7Ivp3ff/o1GpP16n48JMNAtbW0qui2WCgoIZArEHD0SUQ95gvR0oSO7ZbdA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.3.tgz",
+      "integrity": "sha512-gSABi8qHl8k3Cbi/4toAzHiykuBuWLZs43JomTcXkjMZVkp0gj3gg9mO+9HJW/8GB5H89RX/V0QP4JGL7YEEVg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.3.tgz",
+      "integrity": "sha512-SF9Kch5Ete4reovvRO6yNjMxrvlfT0F0Flm+NPoUw5Z4Q3r1d23LFTgaLwm3Cp0iGbrU/MoUI+ZqwCv5XJijCw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.3.tgz",
+      "integrity": "sha512-u5aBonZIyGopAZyOnoPAA6fGsDeHByZ9CnEzyML9NqntK6D/xl5jteZUKm/p6nD09+v3pTM6TuUIqSPcChk5gg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.3.tgz",
+      "integrity": "sha512-GlgVq1WpvOEhNioh74TKelwla9KDuAaLZrdxuuUgsP2vayxeLgVc+rbpIv0IYF4+tlIzq2vRhofV+KGLD+37EQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.3.tgz",
+      "integrity": "sha512-5/JuTd8OWW8UzEtyf19fbrtMJENza+C9JoPIkvItgTBQ1FO2ZLvjbPO6Xs54vk0s5JB5QsfieUEshRQfu7ZHow==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/@iarna/toml": {
       "version": "2.2.5",
       "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
@@ -58,27 +410,27 @@
       "dev": true
     },
     "node_modules/@miniflare/cache": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.10.0.tgz",
-      "integrity": "sha512-nzEqFVPnD7Yf0HMDv7gCPpf4NSXfjhc+zg3gSwUS4Dad5bWV10B1ujTZW6HxQulW3CBHIg616mTjXIiaimVuEQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.13.0.tgz",
+      "integrity": "sha512-y3SdN3SVyPECWmLAEGkkrv0RB+LugEPs/FeXn8QtN9aE1vyj69clOAgmsDzoh1DpFfFsLKRiv05aWs4m79P8Xw==",
       "dev": true,
       "dependencies": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
         "http-cache-semantics": "^4.1.0",
-        "undici": "5.9.1"
+        "undici": "5.20.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/cli-parser": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.10.0.tgz",
-      "integrity": "sha512-NAiCtqlHTUKCmV+Jl9af+ixGmMhiGhIyIfr/vCdbismNEBxEsrQGg3sQYTNfvCkdHtODurQqayQreFq21OuEow==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.13.0.tgz",
+      "integrity": "sha512-Nx1PIfuMZ3mK9Dg/JojWZAjHR16h1pcdCFSqYln/ME7y5ifx+P1E5UkShWUQ1cBlibNaltjbJ2n/7stSAsIGPQ==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/shared": "2.13.0",
         "kleur": "^4.1.4"
       },
       "engines": {
@@ -86,20 +438,20 @@
       }
     },
     "node_modules/@miniflare/core": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.10.0.tgz",
-      "integrity": "sha512-Jx1M5oXQua0jzsJVdZSq07baVRmGC/6JkglrPQGAlZ7gQ1sunVZzq9fjxFqj0bqfEuYS0Wy6+lvK4rOAHISIjw==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.13.0.tgz",
+      "integrity": "sha512-YJ/C0J3k+7xn4gvlMpvePnM3xC8nOnkweW96cc0IA8kJ1JSmScOO2tZ7rrU1RyDgp6StkAtQBw4yC0wYeFycBw==",
       "dev": true,
       "dependencies": {
         "@iarna/toml": "^2.2.5",
-        "@miniflare/queues": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/watcher": "2.10.0",
+        "@miniflare/queues": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/watcher": "2.13.0",
         "busboy": "^1.6.0",
         "dotenv": "^10.0.0",
         "kleur": "^4.1.4",
         "set-cookie-parser": "^2.4.8",
-        "undici": "5.9.1",
+        "undici": "5.20.0",
         "urlpattern-polyfill": "^4.0.3"
       },
       "engines": {
@@ -107,60 +459,60 @@
       }
     },
     "node_modules/@miniflare/d1": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.10.0.tgz",
-      "integrity": "sha512-mOYZSmpTthH0tmFTQ+O9G0Q+iDAd7oiUtoIBianlKa9QiqYAoO7EBUPy6kUgDHXapOcN5Ri1u3J5UTpxXvw3qg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.13.0.tgz",
+      "integrity": "sha512-OslqjO8iTcvzyrC0spByftMboRmHJEyHyTHnlKkjWDGdQQztEOjso2Xj+3I4SZIeUYvbzDRhKLS2QXI9a8LS5A==",
       "dev": true,
       "dependencies": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0"
       },
       "engines": {
         "node": ">=16.7"
       }
     },
     "node_modules/@miniflare/durable-objects": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.10.0.tgz",
-      "integrity": "sha512-gU45f52gveFtCasm0ixYnt0mHI1lHrPomtmF+89oZGKBzOqUfO5diDs6wmoRSnovOWZCwtmwQGRoorAQN7AmoA==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.13.0.tgz",
+      "integrity": "sha512-CRGVBPO9vY4Fc3aV+pdPRVVeYIt64vQqvw+BJbyW+TQtqVP2CGQeziJGnCfcONNNKyooZxGyUkHewUypyH+Qhg==",
       "dev": true,
       "dependencies": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/storage-memory": "2.10.0",
-        "undici": "5.9.1"
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/storage-memory": "2.13.0",
+        "undici": "5.20.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/html-rewriter": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.10.0.tgz",
-      "integrity": "sha512-hCdG99L8+Ros4dn3B5H37PlQPBH0859EoRslzNTd4jzGIkwdiawpJvrvesL8056GjbUjeJN1zh7OPBRuMgyGLw==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.13.0.tgz",
+      "integrity": "sha512-XhN7Icyzvtvu+o/A0hrnSiSmla78seCaNwQ9M1TDHxt352I/ahPX4wtPXs6GbKqY0/i+V6yoG2KGFRQ/j59cQQ==",
       "dev": true,
       "dependencies": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
         "html-rewriter-wasm": "^0.4.1",
-        "undici": "5.9.1"
+        "undici": "5.20.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/http-server": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.10.0.tgz",
-      "integrity": "sha512-cm6hwkONucll93yoY8dteMp//Knvmb7n6zAgeHrtuNYKn//lAL6bRY//VLTttrMmfWxZFi1C7WpOeCv8Mn6/ug==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.13.0.tgz",
+      "integrity": "sha512-aMS/nUMTKP15hKnyZboeuWCiqmNrrCu+XRBY/TxDDl07iXcLpiHGf3oVv+yXxXkWlJHJVCbK7i/nXSNPllRMSw==",
       "dev": true,
       "dependencies": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/web-sockets": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/web-sockets": "2.13.0",
         "kleur": "^4.1.4",
         "selfsigned": "^2.0.0",
-        "undici": "5.9.1",
+        "undici": "5.20.0",
         "ws": "^8.2.2",
         "youch": "^2.2.2"
       },
@@ -169,62 +521,62 @@
       }
     },
     "node_modules/@miniflare/kv": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.10.0.tgz",
-      "integrity": "sha512-3+u1lO77FnlS0lQ6b1VgM1E/ZgQ/zy/FU+SdBG5LUOIiv3x522VYHOApeJLnSEo0KtZUB22Ni0fWQM6DgpaREg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.13.0.tgz",
+      "integrity": "sha512-J0AS5x3g/YVOmHMxMAZs07nRXRvSo9jyuC0eikTBf+4AABvBIyvVYmdTjYNjCmr8O5smcfWBX5S27HelD3aAAQ==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/queues": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.10.0.tgz",
-      "integrity": "sha512-WKdO6qI9rfS96KlCjazzPFf+qj6DPov4vONyf18+jzbRjRJh/xwWSk1/1h5A+gDPwVNG8TsNRPh9DW5OKBGNjw==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.13.0.tgz",
+      "integrity": "sha512-Gf/a6M1mJL03iOvNqh3JNahcBfvEMPHnO28n0gkCoyYWGvddIr9lwCdFIa0qwNJsC1fIDRxhPg8PZ5cQLBMwRA==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       },
       "engines": {
         "node": ">=16.7"
       }
     },
     "node_modules/@miniflare/r2": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.10.0.tgz",
-      "integrity": "sha512-uC1CCWbwM1t8DdpZgrveg6+CkZLfTq+wUMqs20BC5rCT8u8UyRv6ZVRQ7pTPiswLyt1oYDTXsZJK7tjV0U0zew==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.13.0.tgz",
+      "integrity": "sha512-/5k6GHOYMNV/oBtilV9HDXBkJUrx8oXVigG5vxbnzEGRXyVRmR+Glzu7mFT8JiE94XiEbXHk9Qvu1S5Dej3wBw==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0",
-        "undici": "5.9.1"
+        "@miniflare/shared": "2.13.0",
+        "undici": "5.20.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/runner-vm": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.10.0.tgz",
-      "integrity": "sha512-oTsHitQdQ1B1kT3G/6n9AEXsMd/sT1D8tLGzc7Xr79ZrxYxwRO0ATF3cdkxk4dUjUqg/RUqvOJV4YjJGyqvctg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.13.0.tgz",
+      "integrity": "sha512-VmKtF2cA8HmTuLXor1THWY0v+DmaobPct63iLcgWIaUdP3MIvL+9X8HDXFAviCR7bCTe6MKxckHkaOj0IE0aJQ==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/scheduler": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.10.0.tgz",
-      "integrity": "sha512-eGt2cZFE/yo585nT8xINQwdbTotZfeRIh6FUWmZkbva1i5SW0zTiOojr5a95vAGBF3TzwWGsUuzJpLhBB69a/g==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.13.0.tgz",
+      "integrity": "sha512-AOaQanoR4NjVEzVGWHnrL15A7aMx+d9AKLJhSDF7KaP+4NrT2Wo2BQuXCpn5oStx3itOdlQpMfqQ139e/I8WhQ==",
       "dev": true,
       "dependencies": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
         "cron-schedule": "^3.0.4"
       },
       "engines": {
@@ -232,14 +584,14 @@
       }
     },
     "node_modules/@miniflare/shared": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.10.0.tgz",
-      "integrity": "sha512-GDSweEhJ3nNtStGm6taZGUNytM0QTQ/sjZSedAKyF1/aHRaZUcD9cuKAMgIbSpKfvgGdLMNS7Bhd8jb249TO7g==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.13.0.tgz",
+      "integrity": "sha512-m8YFQzKmbjberrV9hPzNcQjNCXxjTjXUpuNrIGjAJO7g+BDztUHaZbdd26H9maBDlkeiWxA3hf0mDyCT/6MCMA==",
       "dev": true,
       "dependencies": {
         "@types/better-sqlite3": "^7.6.0",
         "kleur": "^4.1.4",
-        "npx-import": "^1.1.3",
+        "npx-import": "^1.1.4",
         "picomatch": "^2.3.1"
       },
       "engines": {
@@ -247,65 +599,65 @@
       }
     },
     "node_modules/@miniflare/sites": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.10.0.tgz",
-      "integrity": "sha512-1NVAT6+JS2OubL+pOOR5E/6MMddxQHWMi/yIDSumyyfXmj7Sm7n5dE1FvNPetggMP4f8+AjoyT9AYvdd1wkspQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.13.0.tgz",
+      "integrity": "sha512-/tuzIu00o6CF2tkSv01q02MgEShXBSKx85h9jwWvc+6u7prGacAOer0FA1YNRFbE+t9QIfutAkoPGMA9zYf8+Q==",
       "dev": true,
       "dependencies": {
-        "@miniflare/kv": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/storage-file": "2.10.0"
+        "@miniflare/kv": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/storage-file": "2.13.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/storage-file": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.10.0.tgz",
-      "integrity": "sha512-K/cRIWiTl4+Z+VO6tl4VfuYXA3NLJgvGPV+BCRYD7uTKuPYHqDMErtD1BI1I7nc3WJhwIXfzJrAR3XXhSKKWQQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.13.0.tgz",
+      "integrity": "sha512-LuAeAAY5046rq5U1eFLVkz+ppiFEWytWacpkQw92DvVKFFquZcXSj6WPxZF4rSs23WDk+rdcwuLekbb52aDR7A==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/storage-memory": "2.10.0"
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/storage-memory": "2.13.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/storage-memory": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.10.0.tgz",
-      "integrity": "sha512-ZATU+qZtJ9yG0umgTrOEUi9SU//YyDb8nYXMgqT4JHODYA3RTz1SyyiQSOOz589upJPdu1LN+0j8W24WGRwwxQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.13.0.tgz",
+      "integrity": "sha512-FnkYcBNXa/ym1ksNilNZycg9WYYKo6cWKplVBeSthRon3e8QY6t3n7/XRseBUo7O6mhDybVTy4wNCP1R2nBiEw==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/watcher": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.10.0.tgz",
-      "integrity": "sha512-X9CFYYyszfSYDzs07KhbWC2i08Dpyh3D60fPonYZcoZAfa5h9eATHUdRGvNCdax7awYp4b8bvU8upAI//OPlMg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.13.0.tgz",
+      "integrity": "sha512-teAacWcpMStoBLbLae95IUaL5lPzjPlXa9lhK9CbRaio/KRMibTMRGWrYos3IVGQRZvklvLwcms/nTvgcdb6yw==",
       "dev": true,
       "dependencies": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       },
       "engines": {
         "node": ">=16.13"
       }
     },
     "node_modules/@miniflare/web-sockets": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.10.0.tgz",
-      "integrity": "sha512-W+PrapdQqNEEFeD+amENgPQWcETGDp7OEh6JAoSzCRhHA0OoMe8DG0xb5a5+2FjGW/J7FFKsv84wkURpmFT4dQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.13.0.tgz",
+      "integrity": "sha512-+U2/HCf+BetRIgjAnNQjkuN6UeAjQmXifhQC+7CCaX834XJhrKXoR6z2xr2xkg1qj0qQs4D2jWG0KzrO5OUpug==",
       "dev": true,
       "dependencies": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "undici": "5.9.1",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "undici": "5.20.0",
         "ws": "^8.2.2"
       },
       "engines": {
@@ -313,18 +665,18 @@
       }
     },
     "node_modules/@types/better-sqlite3": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.2.tgz",
-      "integrity": "sha512-RgmaapusqTq6IMAr4McMyAsC6RshYTCjXCnzwVV59WctUxC8bNPyUfT9t5F81lKcU41lLurhjqjoMHfauzfqGg==",
+      "version": "7.6.4",
+      "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.4.tgz",
+      "integrity": "sha512-dzrRZCYPXIXfSR1/surNbJ/grU3scTaygS0OMzjlGf71i9sc2fGyHPXXiXmEvNIoE0cGwsanEFMVJxPXmco9Eg==",
       "dev": true,
       "dependencies": {
         "@types/node": "*"
       }
     },
     "node_modules/@types/node": {
-      "version": "18.11.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz",
-      "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==",
+      "version": "18.16.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz",
+      "integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==",
       "dev": true
     },
     "node_modules/@types/stack-trace": {
@@ -413,347 +765,93 @@
       ],
       "dependencies": {
         "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
-      },
-      "engines": {
-        "node": ">= 8.10.0"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
-      }
-    },
-    "node_modules/cookie": {
-      "version": "0.4.2",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
-      "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/cron-schedule": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz",
-      "integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==",
-      "dev": true
-    },
-    "node_modules/cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/dotenv": {
-      "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
-      "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/esbuild": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz",
-      "integrity": "sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==",
-      "dev": true,
-      "hasInstallScript": true,
-      "bin": {
-        "esbuild": "bin/esbuild"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "optionalDependencies": {
-        "esbuild-android-64": "0.14.51",
-        "esbuild-android-arm64": "0.14.51",
-        "esbuild-darwin-64": "0.14.51",
-        "esbuild-darwin-arm64": "0.14.51",
-        "esbuild-freebsd-64": "0.14.51",
-        "esbuild-freebsd-arm64": "0.14.51",
-        "esbuild-linux-32": "0.14.51",
-        "esbuild-linux-64": "0.14.51",
-        "esbuild-linux-arm": "0.14.51",
-        "esbuild-linux-arm64": "0.14.51",
-        "esbuild-linux-mips64le": "0.14.51",
-        "esbuild-linux-ppc64le": "0.14.51",
-        "esbuild-linux-riscv64": "0.14.51",
-        "esbuild-linux-s390x": "0.14.51",
-        "esbuild-netbsd-64": "0.14.51",
-        "esbuild-openbsd-64": "0.14.51",
-        "esbuild-sunos-64": "0.14.51",
-        "esbuild-windows-32": "0.14.51",
-        "esbuild-windows-64": "0.14.51",
-        "esbuild-windows-arm64": "0.14.51"
-      }
-    },
-    "node_modules/esbuild-android-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz",
-      "integrity": "sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-android-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz",
-      "integrity": "sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-darwin-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz",
-      "integrity": "sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-darwin-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz",
-      "integrity": "sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-freebsd-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz",
-      "integrity": "sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-freebsd-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz",
-      "integrity": "sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-linux-32": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz",
-      "integrity": "sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-linux-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz",
-      "integrity": "sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-linux-arm": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz",
-      "integrity": "sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-linux-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz",
-      "integrity": "sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-linux-mips64le": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz",
-      "integrity": "sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==",
-      "cpu": [
-        "mips64el"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-linux-ppc64le": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz",
-      "integrity": "sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">= 8.10.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
       }
     },
-    "node_modules/esbuild-linux-riscv64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz",
-      "integrity": "sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==",
-      "cpu": [
-        "riscv64"
-      ],
+    "node_modules/cookie": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
+      "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
       "engines": {
-        "node": ">=12"
+        "node": ">= 0.6"
       }
     },
-    "node_modules/esbuild-linux-s390x": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz",
-      "integrity": "sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==",
-      "cpu": [
-        "s390x"
-      ],
+    "node_modules/cron-schedule": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz",
+      "integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==",
+      "dev": true
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">= 8"
       }
     },
-    "node_modules/esbuild-netbsd-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz",
-      "integrity": "sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==",
-      "cpu": [
-        "x64"
-      ],
+    "node_modules/dotenv": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+      "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
       "dev": true,
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
       "engines": {
-        "node": ">=12"
+        "node": ">=10"
       }
     },
-    "node_modules/esbuild-openbsd-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz",
-      "integrity": "sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==",
-      "cpu": [
-        "x64"
-      ],
+    "node_modules/esbuild": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.3.tgz",
+      "integrity": "sha512-71f7EjPWTiSguen8X/kxEpkAS7BFHwtQKisCDDV3Y4GLGWBaoSCyD5uXkaUew6JDzA9FEN1W23mdnSwW9kqCeg==",
       "dev": true,
-      "optional": true,
-      "os": [
-        "openbsd"
-      ],
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
       "engines": {
         "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/android-arm": "0.16.3",
+        "@esbuild/android-arm64": "0.16.3",
+        "@esbuild/android-x64": "0.16.3",
+        "@esbuild/darwin-arm64": "0.16.3",
+        "@esbuild/darwin-x64": "0.16.3",
+        "@esbuild/freebsd-arm64": "0.16.3",
+        "@esbuild/freebsd-x64": "0.16.3",
+        "@esbuild/linux-arm": "0.16.3",
+        "@esbuild/linux-arm64": "0.16.3",
+        "@esbuild/linux-ia32": "0.16.3",
+        "@esbuild/linux-loong64": "0.16.3",
+        "@esbuild/linux-mips64el": "0.16.3",
+        "@esbuild/linux-ppc64": "0.16.3",
+        "@esbuild/linux-riscv64": "0.16.3",
+        "@esbuild/linux-s390x": "0.16.3",
+        "@esbuild/linux-x64": "0.16.3",
+        "@esbuild/netbsd-x64": "0.16.3",
+        "@esbuild/openbsd-x64": "0.16.3",
+        "@esbuild/sunos-x64": "0.16.3",
+        "@esbuild/win32-arm64": "0.16.3",
+        "@esbuild/win32-ia32": "0.16.3",
+        "@esbuild/win32-x64": "0.16.3"
       }
     },
     "node_modules/esbuild-runner": {
@@ -772,70 +870,6 @@
         "esbuild": "*"
       }
     },
-    "node_modules/esbuild-sunos-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz",
-      "integrity": "sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "sunos"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-windows-32": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz",
-      "integrity": "sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-windows-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz",
-      "integrity": "sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/esbuild-windows-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz",
-      "integrity": "sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
     "node_modules/escape-string-regexp": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -934,9 +968,9 @@
       "dev": true
     },
     "node_modules/http-cache-semantics": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
-      "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+      "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
       "dev": true
     },
     "node_modules/human-signals": {
@@ -1069,32 +1103,32 @@
       }
     },
     "node_modules/miniflare": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.10.0.tgz",
-      "integrity": "sha512-WPveqChVDdmDGv+wFqXjFqEZlZ5/aBlAKX37h/e4TAjl2XsK5nPfQATP8jZXwNDEC5iE29bYZymOqeZkp+t7OA==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.13.0.tgz",
+      "integrity": "sha512-ayNhVa4a6bZiOuHtrPmOt4BCYcmW1fBQ/+qGL85smq1m2OBBm3aUs6f4ISf38xH8tk+qewgmAywetyVtn6KHPw==",
       "dev": true,
       "dependencies": {
-        "@miniflare/cache": "2.10.0",
-        "@miniflare/cli-parser": "2.10.0",
-        "@miniflare/core": "2.10.0",
-        "@miniflare/d1": "2.10.0",
-        "@miniflare/durable-objects": "2.10.0",
-        "@miniflare/html-rewriter": "2.10.0",
-        "@miniflare/http-server": "2.10.0",
-        "@miniflare/kv": "2.10.0",
-        "@miniflare/queues": "2.10.0",
-        "@miniflare/r2": "2.10.0",
-        "@miniflare/runner-vm": "2.10.0",
-        "@miniflare/scheduler": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/sites": "2.10.0",
-        "@miniflare/storage-file": "2.10.0",
-        "@miniflare/storage-memory": "2.10.0",
-        "@miniflare/web-sockets": "2.10.0",
+        "@miniflare/cache": "2.13.0",
+        "@miniflare/cli-parser": "2.13.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/d1": "2.13.0",
+        "@miniflare/durable-objects": "2.13.0",
+        "@miniflare/html-rewriter": "2.13.0",
+        "@miniflare/http-server": "2.13.0",
+        "@miniflare/kv": "2.13.0",
+        "@miniflare/queues": "2.13.0",
+        "@miniflare/r2": "2.13.0",
+        "@miniflare/runner-vm": "2.13.0",
+        "@miniflare/scheduler": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/sites": "2.13.0",
+        "@miniflare/storage-file": "2.13.0",
+        "@miniflare/storage-memory": "2.13.0",
+        "@miniflare/web-sockets": "2.13.0",
         "kleur": "^4.1.4",
         "semiver": "^1.1.0",
         "source-map-support": "^0.5.20",
-        "undici": "5.9.1"
+        "undici": "5.20.0"
       },
       "bin": {
         "miniflare": "bootstrap.js"
@@ -1103,7 +1137,7 @@
         "node": ">=16.13"
       },
       "peerDependencies": {
-        "@miniflare/storage-redis": "2.10.0",
+        "@miniflare/storage-redis": "2.13.0",
         "cron-schedule": "^3.0.4",
         "ioredis": "^4.27.9"
       },
@@ -1309,9 +1343,9 @@
       }
     },
     "node_modules/semver": {
-      "version": "7.3.8",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
-      "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+      "version": "7.5.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
+      "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==",
       "dev": true,
       "dependencies": {
         "lru-cache": "^6.0.0"
@@ -1324,9 +1358,9 @@
       }
     },
     "node_modules/set-cookie-parser": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz",
-      "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==",
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
+      "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==",
       "dev": true
     },
     "node_modules/shebang-command": {
@@ -1452,10 +1486,13 @@
       }
     },
     "node_modules/undici": {
-      "version": "5.9.1",
-      "resolved": "https://registry.npmjs.org/undici/-/undici-5.9.1.tgz",
-      "integrity": "sha512-6fB3a+SNnWEm4CJbgo0/CWR8RGcOCQP68SF4X0mxtYTq2VNN8T88NYrWVBAeSX+zb7bny2dx2iYhP3XHi00omg==",
+      "version": "5.20.0",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz",
+      "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==",
       "dev": true,
+      "dependencies": {
+        "busboy": "^1.6.0"
+      },
       "engines": {
         "node": ">=12.18"
       }
@@ -1494,21 +1531,21 @@
       }
     },
     "node_modules/wrangler": {
-      "version": "2.1.12",
-      "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.1.12.tgz",
-      "integrity": "sha512-Oe3lBVR4b2o44A90S+3Bi6gOVw7pGA1qnkhSDkAFdxv1Ttsktb2B7yINRevCPm5wpPkwwpZXS8Dq3Gk0f3Ns8w==",
+      "version": "2.18.0",
+      "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.18.0.tgz",
+      "integrity": "sha512-e+WJ019AbioAf9u4YiOxjrfKqzOP8K3kDAM9v+lGQa+WKsae/UVcMb3Hn5iMIlIt2fc622WefZfuSNRpkAzrSA==",
       "dev": true,
       "dependencies": {
         "@cloudflare/kv-asset-handler": "^0.2.0",
         "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
         "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
-        "@miniflare/core": "2.10.0",
-        "@miniflare/d1": "2.10.0",
-        "@miniflare/durable-objects": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/d1": "2.13.0",
+        "@miniflare/durable-objects": "2.13.0",
         "blake3-wasm": "^2.1.5",
         "chokidar": "^3.5.3",
-        "esbuild": "0.14.51",
-        "miniflare": "2.10.0",
+        "esbuild": "0.16.3",
+        "miniflare": "2.13.0",
         "nanoid": "^3.3.3",
         "path-to-regexp": "^6.2.0",
         "selfsigned": "^2.0.1",
@@ -1527,16 +1564,16 @@
       }
     },
     "node_modules/ws": {
-      "version": "8.9.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
-      "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
+      "version": "8.13.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+      "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
       "dev": true,
       "engines": {
         "node": ">=10.0.0"
       },
       "peerDependencies": {
         "bufferutil": "^4.0.1",
-        "utf-8-validate": "^5.0.2"
+        "utf-8-validate": ">=5.0.2"
       },
       "peerDependenciesMeta": {
         "bufferutil": {
@@ -1605,6 +1642,160 @@
         "rollup-plugin-node-polyfills": "^0.2.1"
       }
     },
+    "@esbuild/android-arm": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.3.tgz",
+      "integrity": "sha512-mueuEoh+s1eRbSJqq9KNBQwI4QhQV6sRXIfTyLXSHGMpyew61rOK4qY21uKbXl1iBoMb0AdL1deWFCQVlN2qHA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.3.tgz",
+      "integrity": "sha512-RolFVeinkeraDvN/OoRf1F/lP0KUfGNb5jxy/vkIMeRRChkrX/HTYN6TYZosRJs3a1+8wqpxAo5PI5hFmxyPRg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.3.tgz",
+      "integrity": "sha512-SFpTUcIT1bIJuCCBMCQWq1bL2gPTjWoLZdjmIhjdcQHaUfV41OQfho6Ici5uvvkMmZRXIUGpM3GxysP/EU7ifQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.3.tgz",
+      "integrity": "sha512-DO8WykMyB+N9mIDfI/Hug70Dk1KipavlGAecxS3jDUwAbTpDXj0Lcwzw9svkhxfpCagDmpaTMgxWK8/C/XcXvw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.3.tgz",
+      "integrity": "sha512-uEqZQ2omc6BvWqdCiyZ5+XmxuHEi1SPzpVxXCSSV2+Sh7sbXbpeNhHIeFrIpRjAs0lI1FmA1iIOxFozKBhKgRQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.3.tgz",
+      "integrity": "sha512-nJansp3sSXakNkOD5i5mIz2Is/HjzIhFs49b1tjrPrpCmwgBmH9SSzhC/Z1UqlkivqMYkhfPwMw1dGFUuwmXhw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.3.tgz",
+      "integrity": "sha512-TfoDzLw+QHfc4a8aKtGSQ96Wa+6eimljjkq9HKR0rHlU83vw8aldMOUSJTUDxbcUdcgnJzPaX8/vGWm7vyV7ug==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.3.tgz",
+      "integrity": "sha512-VwswmSYwVAAq6LysV59Fyqk3UIjbhuc6wb3vEcJ7HEJUtFuLK9uXWuFoH1lulEbE4+5GjtHi3MHX+w1gNHdOWQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.3.tgz",
+      "integrity": "sha512-7I3RlsnxEFCHVZNBLb2w7unamgZ5sVwO0/ikE2GaYvYuUQs9Qte/w7TqWcXHtCwxvZx/2+F97ndiUQAWs47ZfQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ia32": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.3.tgz",
+      "integrity": "sha512-X8FDDxM9cqda2rJE+iblQhIMYY49LfvW4kaEjoFbTTQ4Go8G96Smj2w3BRTwA8IHGoi9dPOPGAX63dhuv19UqA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-loong64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.3.tgz",
+      "integrity": "sha512-hIbeejCOyO0X9ujfIIOKjBjNAs9XD/YdJ9JXAy1lHA+8UXuOqbFe4ErMCqMr8dhlMGBuvcQYGF7+kO7waj2KHw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-mips64el": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.3.tgz",
+      "integrity": "sha512-znFRzICT/V8VZQMt6rjb21MtAVJv/3dmKRMlohlShrbVXdBuOdDrGb+C2cZGQAR8RFyRe7HS6klmHq103WpmVw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ppc64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.3.tgz",
+      "integrity": "sha512-EV7LuEybxhXrVTDpbqWF2yehYRNz5e5p+u3oQUS2+ZFpknyi1NXxr8URk4ykR8Efm7iu04//4sBg249yNOwy5Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-riscv64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.3.tgz",
+      "integrity": "sha512-uDxqFOcLzFIJ+r/pkTTSE9lsCEaV/Y6rMlQjUI9BkzASEChYL/aSQjZjchtEmdnVxDKETnUAmsaZ4pqK1eE5BQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-s390x": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.3.tgz",
+      "integrity": "sha512-NbeREhzSxYwFhnCAQOQZmajsPYtX71Ufej3IQ8W2Gxskfz9DK58ENEju4SbpIj48VenktRASC52N5Fhyf/aliQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.3.tgz",
+      "integrity": "sha512-SDiG0nCixYO9JgpehoKgScwic7vXXndfasjnD5DLbp1xltANzqZ425l7LSdHynt19UWOcDjG9wJJzSElsPvk0w==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/netbsd-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.3.tgz",
+      "integrity": "sha512-AzbsJqiHEq1I/tUvOfAzCY15h4/7Ivp3ff/o1GpP16n48JMNAtbW0qui2WCgoIZArEHD0SUQ95gvR0oSO7ZbdA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.3.tgz",
+      "integrity": "sha512-gSABi8qHl8k3Cbi/4toAzHiykuBuWLZs43JomTcXkjMZVkp0gj3gg9mO+9HJW/8GB5H89RX/V0QP4JGL7YEEVg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/sunos-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.3.tgz",
+      "integrity": "sha512-SF9Kch5Ete4reovvRO6yNjMxrvlfT0F0Flm+NPoUw5Z4Q3r1d23LFTgaLwm3Cp0iGbrU/MoUI+ZqwCv5XJijCw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-arm64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.3.tgz",
+      "integrity": "sha512-u5aBonZIyGopAZyOnoPAA6fGsDeHByZ9CnEzyML9NqntK6D/xl5jteZUKm/p6nD09+v3pTM6TuUIqSPcChk5gg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-ia32": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.3.tgz",
+      "integrity": "sha512-GlgVq1WpvOEhNioh74TKelwla9KDuAaLZrdxuuUgsP2vayxeLgVc+rbpIv0IYF4+tlIzq2vRhofV+KGLD+37EQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-x64": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.3.tgz",
+      "integrity": "sha512-5/JuTd8OWW8UzEtyf19fbrtMJENza+C9JoPIkvItgTBQ1FO2ZLvjbPO6Xs54vk0s5JB5QsfieUEshRQfu7ZHow==",
+      "dev": true,
+      "optional": true
+    },
     "@iarna/toml": {
       "version": "2.2.5",
       "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
@@ -1612,219 +1803,219 @@
       "dev": true
     },
     "@miniflare/cache": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.10.0.tgz",
-      "integrity": "sha512-nzEqFVPnD7Yf0HMDv7gCPpf4NSXfjhc+zg3gSwUS4Dad5bWV10B1ujTZW6HxQulW3CBHIg616mTjXIiaimVuEQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.13.0.tgz",
+      "integrity": "sha512-y3SdN3SVyPECWmLAEGkkrv0RB+LugEPs/FeXn8QtN9aE1vyj69clOAgmsDzoh1DpFfFsLKRiv05aWs4m79P8Xw==",
       "dev": true,
       "requires": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
         "http-cache-semantics": "^4.1.0",
-        "undici": "5.9.1"
+        "undici": "5.20.0"
       }
     },
     "@miniflare/cli-parser": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.10.0.tgz",
-      "integrity": "sha512-NAiCtqlHTUKCmV+Jl9af+ixGmMhiGhIyIfr/vCdbismNEBxEsrQGg3sQYTNfvCkdHtODurQqayQreFq21OuEow==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.13.0.tgz",
+      "integrity": "sha512-Nx1PIfuMZ3mK9Dg/JojWZAjHR16h1pcdCFSqYln/ME7y5ifx+P1E5UkShWUQ1cBlibNaltjbJ2n/7stSAsIGPQ==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/shared": "2.13.0",
         "kleur": "^4.1.4"
       }
     },
     "@miniflare/core": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.10.0.tgz",
-      "integrity": "sha512-Jx1M5oXQua0jzsJVdZSq07baVRmGC/6JkglrPQGAlZ7gQ1sunVZzq9fjxFqj0bqfEuYS0Wy6+lvK4rOAHISIjw==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.13.0.tgz",
+      "integrity": "sha512-YJ/C0J3k+7xn4gvlMpvePnM3xC8nOnkweW96cc0IA8kJ1JSmScOO2tZ7rrU1RyDgp6StkAtQBw4yC0wYeFycBw==",
       "dev": true,
       "requires": {
         "@iarna/toml": "^2.2.5",
-        "@miniflare/queues": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/watcher": "2.10.0",
+        "@miniflare/queues": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/watcher": "2.13.0",
         "busboy": "^1.6.0",
         "dotenv": "^10.0.0",
         "kleur": "^4.1.4",
         "set-cookie-parser": "^2.4.8",
-        "undici": "5.9.1",
+        "undici": "5.20.0",
         "urlpattern-polyfill": "^4.0.3"
       }
     },
     "@miniflare/d1": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.10.0.tgz",
-      "integrity": "sha512-mOYZSmpTthH0tmFTQ+O9G0Q+iDAd7oiUtoIBianlKa9QiqYAoO7EBUPy6kUgDHXapOcN5Ri1u3J5UTpxXvw3qg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.13.0.tgz",
+      "integrity": "sha512-OslqjO8iTcvzyrC0spByftMboRmHJEyHyTHnlKkjWDGdQQztEOjso2Xj+3I4SZIeUYvbzDRhKLS2QXI9a8LS5A==",
       "dev": true,
       "requires": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0"
       }
     },
     "@miniflare/durable-objects": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.10.0.tgz",
-      "integrity": "sha512-gU45f52gveFtCasm0ixYnt0mHI1lHrPomtmF+89oZGKBzOqUfO5diDs6wmoRSnovOWZCwtmwQGRoorAQN7AmoA==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.13.0.tgz",
+      "integrity": "sha512-CRGVBPO9vY4Fc3aV+pdPRVVeYIt64vQqvw+BJbyW+TQtqVP2CGQeziJGnCfcONNNKyooZxGyUkHewUypyH+Qhg==",
       "dev": true,
       "requires": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/storage-memory": "2.10.0",
-        "undici": "5.9.1"
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/storage-memory": "2.13.0",
+        "undici": "5.20.0"
       }
     },
     "@miniflare/html-rewriter": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.10.0.tgz",
-      "integrity": "sha512-hCdG99L8+Ros4dn3B5H37PlQPBH0859EoRslzNTd4jzGIkwdiawpJvrvesL8056GjbUjeJN1zh7OPBRuMgyGLw==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.13.0.tgz",
+      "integrity": "sha512-XhN7Icyzvtvu+o/A0hrnSiSmla78seCaNwQ9M1TDHxt352I/ahPX4wtPXs6GbKqY0/i+V6yoG2KGFRQ/j59cQQ==",
       "dev": true,
       "requires": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
         "html-rewriter-wasm": "^0.4.1",
-        "undici": "5.9.1"
+        "undici": "5.20.0"
       }
     },
     "@miniflare/http-server": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.10.0.tgz",
-      "integrity": "sha512-cm6hwkONucll93yoY8dteMp//Knvmb7n6zAgeHrtuNYKn//lAL6bRY//VLTttrMmfWxZFi1C7WpOeCv8Mn6/ug==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.13.0.tgz",
+      "integrity": "sha512-aMS/nUMTKP15hKnyZboeuWCiqmNrrCu+XRBY/TxDDl07iXcLpiHGf3oVv+yXxXkWlJHJVCbK7i/nXSNPllRMSw==",
       "dev": true,
       "requires": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/web-sockets": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/web-sockets": "2.13.0",
         "kleur": "^4.1.4",
         "selfsigned": "^2.0.0",
-        "undici": "5.9.1",
+        "undici": "5.20.0",
         "ws": "^8.2.2",
         "youch": "^2.2.2"
       }
     },
     "@miniflare/kv": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.10.0.tgz",
-      "integrity": "sha512-3+u1lO77FnlS0lQ6b1VgM1E/ZgQ/zy/FU+SdBG5LUOIiv3x522VYHOApeJLnSEo0KtZUB22Ni0fWQM6DgpaREg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.13.0.tgz",
+      "integrity": "sha512-J0AS5x3g/YVOmHMxMAZs07nRXRvSo9jyuC0eikTBf+4AABvBIyvVYmdTjYNjCmr8O5smcfWBX5S27HelD3aAAQ==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       }
     },
     "@miniflare/queues": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.10.0.tgz",
-      "integrity": "sha512-WKdO6qI9rfS96KlCjazzPFf+qj6DPov4vONyf18+jzbRjRJh/xwWSk1/1h5A+gDPwVNG8TsNRPh9DW5OKBGNjw==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.13.0.tgz",
+      "integrity": "sha512-Gf/a6M1mJL03iOvNqh3JNahcBfvEMPHnO28n0gkCoyYWGvddIr9lwCdFIa0qwNJsC1fIDRxhPg8PZ5cQLBMwRA==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       }
     },
     "@miniflare/r2": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.10.0.tgz",
-      "integrity": "sha512-uC1CCWbwM1t8DdpZgrveg6+CkZLfTq+wUMqs20BC5rCT8u8UyRv6ZVRQ7pTPiswLyt1oYDTXsZJK7tjV0U0zew==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.13.0.tgz",
+      "integrity": "sha512-/5k6GHOYMNV/oBtilV9HDXBkJUrx8oXVigG5vxbnzEGRXyVRmR+Glzu7mFT8JiE94XiEbXHk9Qvu1S5Dej3wBw==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0",
-        "undici": "5.9.1"
+        "@miniflare/shared": "2.13.0",
+        "undici": "5.20.0"
       }
     },
     "@miniflare/runner-vm": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.10.0.tgz",
-      "integrity": "sha512-oTsHitQdQ1B1kT3G/6n9AEXsMd/sT1D8tLGzc7Xr79ZrxYxwRO0ATF3cdkxk4dUjUqg/RUqvOJV4YjJGyqvctg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.13.0.tgz",
+      "integrity": "sha512-VmKtF2cA8HmTuLXor1THWY0v+DmaobPct63iLcgWIaUdP3MIvL+9X8HDXFAviCR7bCTe6MKxckHkaOj0IE0aJQ==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       }
     },
     "@miniflare/scheduler": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.10.0.tgz",
-      "integrity": "sha512-eGt2cZFE/yo585nT8xINQwdbTotZfeRIh6FUWmZkbva1i5SW0zTiOojr5a95vAGBF3TzwWGsUuzJpLhBB69a/g==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.13.0.tgz",
+      "integrity": "sha512-AOaQanoR4NjVEzVGWHnrL15A7aMx+d9AKLJhSDF7KaP+4NrT2Wo2BQuXCpn5oStx3itOdlQpMfqQ139e/I8WhQ==",
       "dev": true,
       "requires": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
         "cron-schedule": "^3.0.4"
       }
     },
     "@miniflare/shared": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.10.0.tgz",
-      "integrity": "sha512-GDSweEhJ3nNtStGm6taZGUNytM0QTQ/sjZSedAKyF1/aHRaZUcD9cuKAMgIbSpKfvgGdLMNS7Bhd8jb249TO7g==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.13.0.tgz",
+      "integrity": "sha512-m8YFQzKmbjberrV9hPzNcQjNCXxjTjXUpuNrIGjAJO7g+BDztUHaZbdd26H9maBDlkeiWxA3hf0mDyCT/6MCMA==",
       "dev": true,
       "requires": {
         "@types/better-sqlite3": "^7.6.0",
         "kleur": "^4.1.4",
-        "npx-import": "^1.1.3",
+        "npx-import": "^1.1.4",
         "picomatch": "^2.3.1"
       }
     },
     "@miniflare/sites": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.10.0.tgz",
-      "integrity": "sha512-1NVAT6+JS2OubL+pOOR5E/6MMddxQHWMi/yIDSumyyfXmj7Sm7n5dE1FvNPetggMP4f8+AjoyT9AYvdd1wkspQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.13.0.tgz",
+      "integrity": "sha512-/tuzIu00o6CF2tkSv01q02MgEShXBSKx85h9jwWvc+6u7prGacAOer0FA1YNRFbE+t9QIfutAkoPGMA9zYf8+Q==",
       "dev": true,
       "requires": {
-        "@miniflare/kv": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/storage-file": "2.10.0"
+        "@miniflare/kv": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/storage-file": "2.13.0"
       }
     },
     "@miniflare/storage-file": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.10.0.tgz",
-      "integrity": "sha512-K/cRIWiTl4+Z+VO6tl4VfuYXA3NLJgvGPV+BCRYD7uTKuPYHqDMErtD1BI1I7nc3WJhwIXfzJrAR3XXhSKKWQQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.13.0.tgz",
+      "integrity": "sha512-LuAeAAY5046rq5U1eFLVkz+ppiFEWytWacpkQw92DvVKFFquZcXSj6WPxZF4rSs23WDk+rdcwuLekbb52aDR7A==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/storage-memory": "2.10.0"
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/storage-memory": "2.13.0"
       }
     },
     "@miniflare/storage-memory": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.10.0.tgz",
-      "integrity": "sha512-ZATU+qZtJ9yG0umgTrOEUi9SU//YyDb8nYXMgqT4JHODYA3RTz1SyyiQSOOz589upJPdu1LN+0j8W24WGRwwxQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.13.0.tgz",
+      "integrity": "sha512-FnkYcBNXa/ym1ksNilNZycg9WYYKo6cWKplVBeSthRon3e8QY6t3n7/XRseBUo7O6mhDybVTy4wNCP1R2nBiEw==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       }
     },
     "@miniflare/watcher": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.10.0.tgz",
-      "integrity": "sha512-X9CFYYyszfSYDzs07KhbWC2i08Dpyh3D60fPonYZcoZAfa5h9eATHUdRGvNCdax7awYp4b8bvU8upAI//OPlMg==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.13.0.tgz",
+      "integrity": "sha512-teAacWcpMStoBLbLae95IUaL5lPzjPlXa9lhK9CbRaio/KRMibTMRGWrYos3IVGQRZvklvLwcms/nTvgcdb6yw==",
       "dev": true,
       "requires": {
-        "@miniflare/shared": "2.10.0"
+        "@miniflare/shared": "2.13.0"
       }
     },
     "@miniflare/web-sockets": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.10.0.tgz",
-      "integrity": "sha512-W+PrapdQqNEEFeD+amENgPQWcETGDp7OEh6JAoSzCRhHA0OoMe8DG0xb5a5+2FjGW/J7FFKsv84wkURpmFT4dQ==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.13.0.tgz",
+      "integrity": "sha512-+U2/HCf+BetRIgjAnNQjkuN6UeAjQmXifhQC+7CCaX834XJhrKXoR6z2xr2xkg1qj0qQs4D2jWG0KzrO5OUpug==",
       "dev": true,
       "requires": {
-        "@miniflare/core": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "undici": "5.9.1",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "undici": "5.20.0",
         "ws": "^8.2.2"
       }
     },
     "@types/better-sqlite3": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.2.tgz",
-      "integrity": "sha512-RgmaapusqTq6IMAr4McMyAsC6RshYTCjXCnzwVV59WctUxC8bNPyUfT9t5F81lKcU41lLurhjqjoMHfauzfqGg==",
+      "version": "7.6.4",
+      "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.4.tgz",
+      "integrity": "sha512-dzrRZCYPXIXfSR1/surNbJ/grU3scTaygS0OMzjlGf71i9sc2fGyHPXXiXmEvNIoE0cGwsanEFMVJxPXmco9Eg==",
       "dev": true,
       "requires": {
         "@types/node": "*"
       }
     },
     "@types/node": {
-      "version": "18.11.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz",
-      "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==",
+      "version": "18.16.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz",
+      "integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==",
       "dev": true
     },
     "@types/stack-trace": {
@@ -1934,144 +2125,34 @@
       "dev": true
     },
     "esbuild": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz",
-      "integrity": "sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==",
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.3.tgz",
+      "integrity": "sha512-71f7EjPWTiSguen8X/kxEpkAS7BFHwtQKisCDDV3Y4GLGWBaoSCyD5uXkaUew6JDzA9FEN1W23mdnSwW9kqCeg==",
       "dev": true,
       "requires": {
-        "esbuild-android-64": "0.14.51",
-        "esbuild-android-arm64": "0.14.51",
-        "esbuild-darwin-64": "0.14.51",
-        "esbuild-darwin-arm64": "0.14.51",
-        "esbuild-freebsd-64": "0.14.51",
-        "esbuild-freebsd-arm64": "0.14.51",
-        "esbuild-linux-32": "0.14.51",
-        "esbuild-linux-64": "0.14.51",
-        "esbuild-linux-arm": "0.14.51",
-        "esbuild-linux-arm64": "0.14.51",
-        "esbuild-linux-mips64le": "0.14.51",
-        "esbuild-linux-ppc64le": "0.14.51",
-        "esbuild-linux-riscv64": "0.14.51",
-        "esbuild-linux-s390x": "0.14.51",
-        "esbuild-netbsd-64": "0.14.51",
-        "esbuild-openbsd-64": "0.14.51",
-        "esbuild-sunos-64": "0.14.51",
-        "esbuild-windows-32": "0.14.51",
-        "esbuild-windows-64": "0.14.51",
-        "esbuild-windows-arm64": "0.14.51"
-      }
-    },
-    "esbuild-android-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz",
-      "integrity": "sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-android-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz",
-      "integrity": "sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-darwin-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz",
-      "integrity": "sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-darwin-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz",
-      "integrity": "sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-freebsd-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz",
-      "integrity": "sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-freebsd-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz",
-      "integrity": "sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-32": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz",
-      "integrity": "sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz",
-      "integrity": "sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-arm": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz",
-      "integrity": "sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz",
-      "integrity": "sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-mips64le": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz",
-      "integrity": "sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-ppc64le": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz",
-      "integrity": "sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-riscv64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz",
-      "integrity": "sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-s390x": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz",
-      "integrity": "sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-netbsd-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz",
-      "integrity": "sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-openbsd-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz",
-      "integrity": "sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==",
-      "dev": true,
-      "optional": true
+        "@esbuild/android-arm": "0.16.3",
+        "@esbuild/android-arm64": "0.16.3",
+        "@esbuild/android-x64": "0.16.3",
+        "@esbuild/darwin-arm64": "0.16.3",
+        "@esbuild/darwin-x64": "0.16.3",
+        "@esbuild/freebsd-arm64": "0.16.3",
+        "@esbuild/freebsd-x64": "0.16.3",
+        "@esbuild/linux-arm": "0.16.3",
+        "@esbuild/linux-arm64": "0.16.3",
+        "@esbuild/linux-ia32": "0.16.3",
+        "@esbuild/linux-loong64": "0.16.3",
+        "@esbuild/linux-mips64el": "0.16.3",
+        "@esbuild/linux-ppc64": "0.16.3",
+        "@esbuild/linux-riscv64": "0.16.3",
+        "@esbuild/linux-s390x": "0.16.3",
+        "@esbuild/linux-x64": "0.16.3",
+        "@esbuild/netbsd-x64": "0.16.3",
+        "@esbuild/openbsd-x64": "0.16.3",
+        "@esbuild/sunos-x64": "0.16.3",
+        "@esbuild/win32-arm64": "0.16.3",
+        "@esbuild/win32-ia32": "0.16.3",
+        "@esbuild/win32-x64": "0.16.3"
+      }
     },
     "esbuild-runner": {
       "version": "2.2.2",
@@ -2083,34 +2164,6 @@
         "tslib": "2.4.0"
       }
     },
-    "esbuild-sunos-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz",
-      "integrity": "sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-windows-32": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz",
-      "integrity": "sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-windows-64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz",
-      "integrity": "sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-windows-arm64": {
-      "version": "0.14.51",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz",
-      "integrity": "sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==",
-      "dev": true,
-      "optional": true
-    },
     "escape-string-regexp": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -2178,9 +2231,9 @@
       "dev": true
     },
     "http-cache-semantics": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
-      "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+      "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
       "dev": true
     },
     "human-signals": {
@@ -2274,32 +2327,32 @@
       "dev": true
     },
     "miniflare": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.10.0.tgz",
-      "integrity": "sha512-WPveqChVDdmDGv+wFqXjFqEZlZ5/aBlAKX37h/e4TAjl2XsK5nPfQATP8jZXwNDEC5iE29bYZymOqeZkp+t7OA==",
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.13.0.tgz",
+      "integrity": "sha512-ayNhVa4a6bZiOuHtrPmOt4BCYcmW1fBQ/+qGL85smq1m2OBBm3aUs6f4ISf38xH8tk+qewgmAywetyVtn6KHPw==",
       "dev": true,
       "requires": {
-        "@miniflare/cache": "2.10.0",
-        "@miniflare/cli-parser": "2.10.0",
-        "@miniflare/core": "2.10.0",
-        "@miniflare/d1": "2.10.0",
-        "@miniflare/durable-objects": "2.10.0",
-        "@miniflare/html-rewriter": "2.10.0",
-        "@miniflare/http-server": "2.10.0",
-        "@miniflare/kv": "2.10.0",
-        "@miniflare/queues": "2.10.0",
-        "@miniflare/r2": "2.10.0",
-        "@miniflare/runner-vm": "2.10.0",
-        "@miniflare/scheduler": "2.10.0",
-        "@miniflare/shared": "2.10.0",
-        "@miniflare/sites": "2.10.0",
-        "@miniflare/storage-file": "2.10.0",
-        "@miniflare/storage-memory": "2.10.0",
-        "@miniflare/web-sockets": "2.10.0",
+        "@miniflare/cache": "2.13.0",
+        "@miniflare/cli-parser": "2.13.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/d1": "2.13.0",
+        "@miniflare/durable-objects": "2.13.0",
+        "@miniflare/html-rewriter": "2.13.0",
+        "@miniflare/http-server": "2.13.0",
+        "@miniflare/kv": "2.13.0",
+        "@miniflare/queues": "2.13.0",
+        "@miniflare/r2": "2.13.0",
+        "@miniflare/runner-vm": "2.13.0",
+        "@miniflare/scheduler": "2.13.0",
+        "@miniflare/shared": "2.13.0",
+        "@miniflare/sites": "2.13.0",
+        "@miniflare/storage-file": "2.13.0",
+        "@miniflare/storage-memory": "2.13.0",
+        "@miniflare/web-sockets": "2.13.0",
         "kleur": "^4.1.4",
         "semiver": "^1.1.0",
         "source-map-support": "^0.5.20",
-        "undici": "5.9.1"
+        "undici": "5.20.0"
       }
     },
     "mustache": {
@@ -2442,18 +2495,18 @@
       "dev": true
     },
     "semver": {
-      "version": "7.3.8",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
-      "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+      "version": "7.5.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
+      "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==",
       "dev": true,
       "requires": {
         "lru-cache": "^6.0.0"
       }
     },
     "set-cookie-parser": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz",
-      "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==",
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
+      "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==",
       "dev": true
     },
     "shebang-command": {
@@ -2547,10 +2600,13 @@
       "dev": true
     },
     "undici": {
-      "version": "5.9.1",
-      "resolved": "https://registry.npmjs.org/undici/-/undici-5.9.1.tgz",
-      "integrity": "sha512-6fB3a+SNnWEm4CJbgo0/CWR8RGcOCQP68SF4X0mxtYTq2VNN8T88NYrWVBAeSX+zb7bny2dx2iYhP3XHi00omg==",
-      "dev": true
+      "version": "5.20.0",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz",
+      "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==",
+      "dev": true,
+      "requires": {
+        "busboy": "^1.6.0"
+      }
     },
     "urlpattern-polyfill": {
       "version": "4.0.3",
@@ -2577,22 +2633,22 @@
       }
     },
     "wrangler": {
-      "version": "2.1.12",
-      "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.1.12.tgz",
-      "integrity": "sha512-Oe3lBVR4b2o44A90S+3Bi6gOVw7pGA1qnkhSDkAFdxv1Ttsktb2B7yINRevCPm5wpPkwwpZXS8Dq3Gk0f3Ns8w==",
+      "version": "2.18.0",
+      "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.18.0.tgz",
+      "integrity": "sha512-e+WJ019AbioAf9u4YiOxjrfKqzOP8K3kDAM9v+lGQa+WKsae/UVcMb3Hn5iMIlIt2fc622WefZfuSNRpkAzrSA==",
       "dev": true,
       "requires": {
         "@cloudflare/kv-asset-handler": "^0.2.0",
         "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
         "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
-        "@miniflare/core": "2.10.0",
-        "@miniflare/d1": "2.10.0",
-        "@miniflare/durable-objects": "2.10.0",
+        "@miniflare/core": "2.13.0",
+        "@miniflare/d1": "2.13.0",
+        "@miniflare/durable-objects": "2.13.0",
         "blake3-wasm": "^2.1.5",
         "chokidar": "^3.5.3",
-        "esbuild": "0.14.51",
+        "esbuild": "0.16.3",
         "fsevents": "~2.3.2",
-        "miniflare": "2.10.0",
+        "miniflare": "2.13.0",
         "nanoid": "^3.3.3",
         "path-to-regexp": "^6.2.0",
         "selfsigned": "^2.0.1",
@@ -2601,9 +2657,9 @@
       }
     },
     "ws": {
-      "version": "8.9.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
-      "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
+      "version": "8.13.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+      "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
       "dev": true,
       "requires": {}
     },
diff --git a/serverless/cloudflare/package.json b/serverless/cloudflare/package.json
index c06ad60..fa2f315 100644
--- a/serverless/cloudflare/package.json
+++ b/serverless/cloudflare/package.json
@@ -5,13 +5,13 @@
     "@cloudflare/workers-types": "^3.17.0",
     "esbuild-runner": "^2.2.2",
     "typescript": "^4.8.4",
-    "wrangler": "2.1.12"
+    "wrangler": "2.18.0"
   },
   "private": true,
   "scripts": {
     "start": "wrangler dev",
     "deploy": "wrangler publish",
-    "test": "node -r esbuild-runner/register src/index.test.ts",
+    "test": "node -r esbuild-runner/register ../shared/index.test.ts",
     "tsc": "tsc --watch",
     "build": "wrangler publish --outdir dist --dry-run"
   }
diff --git a/serverless/cloudflare/src/index.ts b/serverless/cloudflare/src/index.ts
index 2a33f45..7a0f1d4 100644
--- a/serverless/cloudflare/src/index.ts
+++ b/serverless/cloudflare/src/index.ts
@@ -1,24 +1,18 @@
-/**
- * - Run `wrangler dev src/index.ts` in your terminal to start a development server
- * - Open a browser tab at http://localhost:8787/ to see your worker in action
- * - Run `wrangler publish src/index.ts --name my-worker` to publish your worker
- */
-
 import {
   PMTiles,
   Source,
   RangeResponse,
   ResolvedValueCache,
   TileType,
-  Compression,
 } from "../../../js/index";
+import { pmtiles_path, tile_path, tileJSON } from "../../shared/index";
 
 interface Env {
-  BUCKET: R2Bucket;
   ALLOWED_ORIGINS?: string;
-  PMTILES_PATH?: string;
-  TILE_PATH?: string;
+  BUCKET: R2Bucket;
   CACHE_MAX_AGE?: number;
+  PMTILES_PATH?: string;
+  PUBLIC_HOSTNAME?: string;
 }
 
 class KeyNotFoundError extends Error {
@@ -27,62 +21,7 @@ class KeyNotFoundError extends Error {
   }
 }
 
-export const pmtiles_path = (name: string, setting?: string): string => {
-  if (setting) {
-    return setting.replaceAll("{name}", name);
-  }
-  return name + ".pmtiles";
-};
-
-const TILE =
-  /^\/(?<NAME>[0-9a-zA-Z\/!\-_\.\*\'\(\)]+)\/(?<Z>\d+)\/(?<X>\d+)\/(?<Y>\d+).(?<EXT>[a-z]+)$/;
-
-export const tile_path = (
-  path: string,
-  setting?: string
-): {
-  ok: boolean;
-  name: string;
-  tile: [number, number, number];
-  ext: string;
-} => {
-  let pattern = TILE;
-  if (setting) {
-    // escape regex
-    setting = setting.replace(/[.*+?^$()|[\]\\]/g, "\\$&");
-    setting = setting.replace("{name}", "(?<NAME>[0-9a-zA-Z/!-_.*'()]+)");
-    setting = setting.replace("{z}", "(?<Z>\\d+)");
-    setting = setting.replace("{x}", "(?<X>\\d+)");
-    setting = setting.replace("{y}", "(?<Y>\\d+)");
-    setting = setting.replace("{ext}", "(?<EXT>[a-z]+)");
-    pattern = new RegExp(setting);
-  }
-
-  let match = path.match(pattern);
-
-  if (match) {
-    const g = match.groups!;
-    return { ok: true, name: g.NAME, tile: [+g.Z, +g.X, +g.Y], ext: g.EXT };
-  }
-  return { ok: false, name: "", tile: [0, 0, 0], ext: "" };
-};
-
-async function nativeDecompress(
-  buf: ArrayBuffer,
-  compression: Compression
-): 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");
-  }
-}
-
-const CACHE = new ResolvedValueCache(25, undefined, nativeDecompress);
+const CACHE = new ResolvedValueCache(25, undefined);
 
 class R2Source implements Source {
   env: Env;
@@ -128,23 +67,23 @@ export default {
       return new Response(undefined, { status: 405 });
 
     const url = new URL(request.url);
-    const { ok, name, tile, ext } = tile_path(url.pathname, env.TILE_PATH);
+    const { ok, name, tile, ext } = tile_path(url.pathname);
 
     const cache = caches.default;
 
     if (ok) {
       let allowed_origin = "";
       if (typeof env.ALLOWED_ORIGINS !== "undefined") {
-        for (let o of env.ALLOWED_ORIGINS.split(",")) {
+        for (const o of env.ALLOWED_ORIGINS.split(",")) {
           if (o === request.headers.get("Origin") || o === "*") {
             allowed_origin = o;
           }
         }
       }
 
-      let cached = await cache.match(request.url);
+      const cached = await cache.match(request.url);
       if (cached) {
-        let resp_headers = new Headers(cached.headers);
+        const resp_headers = new Headers(cached.headers);
         if (allowed_origin)
           resp_headers.set("Access-Control-Allow-Origin", allowed_origin);
         resp_headers.set("Vary", "Origin");
@@ -162,9 +101,9 @@ export default {
       ) => {
         cacheable_headers.set(
           "Cache-Control",
-          "max-age=" + (env.CACHE_MAX_AGE | 86400)
+          "max-age=" + (env.CACHE_MAX_AGE || 86400)
         );
-        let cacheable = new Response(body, {
+        const cacheable = new Response(body, {
           headers: cacheable_headers,
           status: status,
         });
@@ -172,7 +111,7 @@ export default {
         // normalize HEAD requests
         ctx.waitUntil(cache.put(request.url, cacheable));
 
-        let resp_headers = new Headers(cacheable_headers);
+        const resp_headers = new Headers(cacheable_headers);
         if (allowed_origin)
           resp_headers.set("Access-Control-Allow-Origin", allowed_origin);
         resp_headers.set("Vary", "Origin");
@@ -181,9 +120,23 @@ export default {
 
       const cacheable_headers = new Headers();
       const source = new R2Source(env, name);
-      const p = new PMTiles(source, CACHE, nativeDecompress);
+      const p = new PMTiles(source, CACHE);
       try {
         const p_header = await p.getHeader();
+
+        if (!tile) {
+          cacheable_headers.set("Content-Type", "application/json");
+
+          const t = tileJSON(
+            p_header,
+            await p.getMetadata(),
+            env.PUBLIC_HOSTNAME || url.hostname,
+            name
+          );
+
+          return cacheableResponse(JSON.stringify(t), cacheable_headers, 200);
+        }
+
         if (tile[0] < p_header.minZoom || tile[0] > p_header.maxZoom) {
           return cacheableResponse(undefined, cacheable_headers, 404);
         }
@@ -238,7 +191,6 @@ export default {
       }
     }
 
-    // TODO: metadata responses, tileJSON
     return new Response("Invalid URL", { status: 404 });
   },
 };
diff --git a/serverless/shared/index.ts b/serverless/shared/index.ts
new file mode 100644
index 0000000..ad03d3d
--- /dev/null
+++ b/serverless/shared/index.ts
@@ -0,0 +1,71 @@
+import { Header, TileType } from "../../js/index";
+
+export const pmtiles_path = (name: string, setting?: string): string => {
+  if (setting) {
+    return setting.replaceAll("{name}", name);
+  }
+  return name + ".pmtiles";
+};
+
+const TILE =
+  /^\/(?<NAME>[0-9a-zA-Z\/!\-_\.\*\'\(\)]+)\/(?<Z>\d+)\/(?<X>\d+)\/(?<Y>\d+).(?<EXT>[a-z]+)$/;
+
+const TILESET = /^\/(?<NAME>[0-9a-zA-Z\/!\-_\.\*\'\(\)]+).json$/;
+
+export const tile_path = (
+  path: string
+): {
+  ok: boolean;
+  name: string;
+  tile?: [number, number, number];
+  ext: string;
+} => {
+  const tile_match = path.match(TILE);
+
+  if (tile_match) {
+    const g = tile_match.groups!;
+    return { ok: true, name: g.NAME, tile: [+g.Z, +g.X, +g.Y], ext: g.EXT };
+  }
+
+  const tileset_match = path.match(TILESET);
+
+  if (tileset_match) {
+    const g = tileset_match.groups!;
+    return { ok: true, name: g.NAME, ext: "json" };
+  }
+
+  return { ok: false, name: "", tile: [0, 0, 0], ext: "" };
+};
+
+export const tileJSON = (
+  header: Header,
+  metadata: unknown,
+  hostname: string,
+  tileset_name: string
+) => {
+  let ext = "";
+  if (header.tileType === TileType.Mvt) {
+    ext = ".mvt";
+  } else if (header.tileType === TileType.Png) {
+    ext = ".png";
+  } else if (header.tileType === TileType.Jpeg) {
+    ext = ".jpg";
+  } else if (header.tileType === TileType.Webp) {
+    ext = ".webp";
+  }
+
+  return {
+    tilejson: "3.0.0",
+    scheme: "xyz",
+    tiles: ["https://" + hostname + "/" + tileset_name + "/{z}/{x}/{y}" + ext],
+    vector_layers: metadata.vector_layers,
+    attribution: metadata.attribution,
+    description: metadata.description,
+    name: metadata.name,
+    version: metadata.version,
+    bounds: [header.minLon, header.minLat, header.maxLon, header.maxLat],
+    center: [header.centerLon, header.centerLat, header.centerZoom],
+    minzoom: header.minZoom,
+    maxzoom: header.maxZoom,
+  };
+};


Test patch:
diff --git a/serverless/cloudflare/src/index.test.ts b/serverless/cloudflare/src/index.test.ts
deleted file mode 100644
index 64fe012..0000000
--- a/serverless/cloudflare/src/index.test.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { test } from "node:test";
-import assert from "node:assert";
-
-import { pmtiles_path, tile_path } from "./index";
-
-test("pmtiles path", () => {
-  let result = pmtiles_path("foo", undefined);
-  assert.strictEqual(result, "foo.pmtiles");
-});
-
-test("pmtiles path", () => {
-  let result = pmtiles_path("foo", "folder/{name}/file.pmtiles");
-  assert.strictEqual(result, "folder/foo/file.pmtiles");
-});
-
-test("pmtiles path with slash", () => {
-  let result = pmtiles_path("foo/bar", "folder/{name}/file.pmtiles");
-  assert.strictEqual(result, "folder/foo/bar/file.pmtiles");
-});
-
-test("pmtiles path with multiple names", () => {
-  let result = pmtiles_path("slug", "folder/{name}/{name}.pmtiles");
-  assert.strictEqual(result, "folder/slug/slug.pmtiles");
-  result = pmtiles_path("foo/bar", "folder/{name}/{name}.pmtiles");
-  assert.strictEqual(result, "folder/foo/bar/foo/bar.pmtiles");
-});
-
-test("parse tile default", () => {
-  let { ok, name, tile, ext } = tile_path("abcd");
-  assert.strictEqual(ok, false);
-
-  ({ name, tile } = tile_path("/foo/11/22/33.pbf"));
-  assert.strictEqual(name, "foo");
-  assert.strictEqual(tile[0], 11);
-  assert.strictEqual(tile[1], 22);
-  assert.strictEqual(tile[2], 33);
-});
-
-test("parse tile path setting", () => {
-  let { ok, name, tile, ext } = tile_path(
-    "/foo/11/22/33.pbf",
-    "/{name}/{z}/{y}/{x}.{ext}"
-  );
-  assert.strictEqual(tile[1], 33);
-  assert.strictEqual(tile[2], 22);
-  assert.strictEqual(ext, "pbf");
-  ({ ok, name, tile, ext } = tile_path(
-    "/tiles/foo/4/2/3.mvt",
-    "/tiles/{name}/{z}/{x}/{y}.{ext}"
-  ));
-  assert.strictEqual(name, "foo");
-  assert.strictEqual(tile[0], 4);
-  assert.strictEqual(tile[1], 2);
-  assert.strictEqual(tile[2], 3);
-  assert.strictEqual(ext, "mvt");
-});
-
-test("parse tile path setting special chars", () => {
-  let { ok, name, tile, ext } = tile_path(
-    "/folder(new/foo/11/22/33.pbf",
-    "/folder(new/{name}/{z}/{y}/{x}.{ext}"
-  );
-  assert.strictEqual(name, "foo");
-});
-
-test("parse tile path setting slash", () => {
-  let { ok, name, tile, ext } = tile_path(
-    "/foo/bar/11/22/33.pbf",
-    "/{name}/{z}/{y}/{x}.{ext}"
-  );
-  assert.strictEqual(name, "foo/bar");
-});
diff --git a/serverless/shared/index.test.ts b/serverless/shared/index.test.ts
new file mode 100644
index 0000000..1427f6d
--- /dev/null
+++ b/serverless/shared/index.test.ts
@@ -0,0 +1,27 @@
+import { test } from "node:test";
+import assert from "node:assert";
+
+import { pmtiles_path, tile_path } from "./index";
+
+test("pmtiles path", () => {
+  let result = pmtiles_path("foo", undefined);
+  assert.strictEqual(result, "foo.pmtiles");
+});
+
+test("pmtiles path", () => {
+  let result = pmtiles_path("foo", "folder/{name}/file.pmtiles");
+  assert.strictEqual(result, "folder/foo/file.pmtiles");
+});
+
+test("pmtiles path with slash", () => {
+  let result = pmtiles_path("foo/bar", "folder/{name}/file.pmtiles");
+  assert.strictEqual(result, "folder/foo/bar/file.pmtiles");
+});
+
+test("pmtiles path with multiple names", () => {
+  let result = pmtiles_path("slug", "folder/{name}/{name}.pmtiles");
+  assert.strictEqual(result, "folder/slug/slug.pmtiles");
+  result = pmtiles_path("foo/bar", "folder/{name}/{name}.pmtiles");
+  assert.strictEqual(result, "folder/foo/bar/foo/bar.pmtiles");
+});
+