@basmilius/worker 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/error.d.ts +9 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +13 -0
- package/dist/request.d.ts +5 -0
- package/dist/response.d.ts +2 -0
- package/package.json +57 -0
- package/src/error.ts +17 -0
- package/src/index.ts +52 -0
- package/src/request.ts +55 -0
- package/src/response.ts +27 -0
- package/src/types.ts +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<a href="https://bas.dev" target="_blank" rel="noopener">
|
|
2
|
+
<img src="https://bmcdn.nl/assets/branding/logo.svg" alt="Bas-logo" height="48"/>
|
|
3
|
+
</a>
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# `@basmilius/utils`
|
|
8
|
+
|
|
9
|
+
Various utilities that are commonly used throughout personal Vue-related projects.
|
|
10
|
+
|
|
11
|
+
## ⭐️ Prerequisites
|
|
12
|
+
|
|
13
|
+
- Bun >= 1.2.11
|
|
14
|
+
- Node >= 23
|
|
15
|
+
|
|
16
|
+
## 🚀 Getting started
|
|
17
|
+
|
|
18
|
+
1. Run `bun install` in the root of the project.
|
|
19
|
+
2. Run `bun --cwd packages/utils build` to build the project.
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class MissingParameterError extends Error {
|
|
2
|
+
constructor(param: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class InvalidValueError extends Error {
|
|
5
|
+
constructor(param: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class NotFoundError extends Error {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Routes, Worker } from "./types";
|
|
2
|
+
export { cloudflare } from "@cloudflare/vite-plugin";
|
|
3
|
+
export { InvalidValueError, MissingParameterError, NotFoundError } from "./error";
|
|
4
|
+
export { queryDate, queryInteger, queryPosition } from "./request";
|
|
5
|
+
export { error, json } from "./response";
|
|
6
|
+
export declare const createWorker: (routes: Routes) => Worker;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
class s extends Error{constructor(e){super(`Missing required parameter ${e}.`)}}class i extends Error{constructor(e){super(`Invalid value for parameter ${e}.`)}}class u extends Error{constructor(e){super(e)}}function a(e,r,o,t){return c({code:e,error:r,error_description:o},{},t)}function c(e,r={},o=200){let t=new Date,n=new Date(t.getFullYear(),t.getMonth()+1,t.getDate());if(r=r||{},r["Access-Control-Allow-Origin"]="*",r["Content-Type"]="application/json",o===200)r["Cache-Control"]="public, max-age=2628000, immutable",r.Date=t.toISOString(),r.Expires=n.toISOString();return new Response(JSON.stringify(e),{headers:r,status:o})}import{cloudflare as v}from"@cloudflare/vite-plugin";import{DateTime as l}from"luxon";function p(e,r="date"){let{searchParams:o}=new URL(e.url);if(!o.has(r))throw new s(r);let t=l.fromFormat(o.get(r),"yyyy-MM-dd");if(!t.isValid)throw new i(r);return t}function f(e,r){let{searchParams:o}=new URL(e.url);if(!o.has(r))throw new s(r);let t=parseInt(o.get(r));if(isNaN(t))throw new i(r);return t}function m(e){let{searchParams:r}=new URL(e.url);if(!r.has("latitude")||!r.has("longitude"))throw new s("latitude or longitude");let o=parseFloat(r.get("latitude")),t=parseFloat(r.get("longitude"));if(isNaN(o)||isNaN(t))throw new i("latitude or longitude");return{latitude:o,longitude:t}}var h=(e)=>({async fetch(r){let{pathname:o}=new URL(r.url);if(!e[o])return a(404,"not_found","The requested endpoint could not be found.",404);let t=e[o];return t(r).catch((n)=>{if(n instanceof i)return a(406,"invalid_value",n.message,406);if(n instanceof s)return a(400,"missing_parameter",n.message,400);if(n instanceof u)return a(404,"not_found",n.message,404);return a(500,"internal_server_error","An unexpected error occurred.",500)})}});export{m as queryPosition,f as queryInteger,p as queryDate,c as json,a as error,h as createWorker,v as cloudflare,u as NotFoundError,s as MissingParameterError,i as InvalidValueError};
|
|
2
|
+
|
|
3
|
+
//# debugId=E5477CA28CE6A9D264756E2164756E21
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/error.ts", "../src/response.ts", "../src/index.ts", "../src/request.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"export class MissingParameterError extends Error {\n constructor(param: string) {\n super(`Missing required parameter ${param}.`);\n }\n}\n\nexport class InvalidValueError extends Error {\n constructor(param: string) {\n super(`Invalid value for parameter ${param}.`);\n }\n}\n\nexport class NotFoundError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n",
|
|
6
|
+
"export function error(code: number, error: string, errorDescription: string, status: number): Response {\n return json({\n code,\n error,\n error_description: errorDescription\n }, {}, status);\n}\n\nexport function json(json: object, headers: HeadersInit = {}, status: number = 200): Response {\n const date = new Date();\n const expires = new Date(date.getFullYear(), date.getMonth() + 1, date.getDate());\n\n headers = headers || {};\n headers['Access-Control-Allow-Origin'] = '*';\n headers['Content-Type'] = 'application/json';\n\n if (status === 200) {\n headers['Cache-Control'] = 'public, max-age=2628000, immutable';\n headers['Date'] = date.toISOString();\n headers['Expires'] = expires.toISOString();\n }\n\n return new Response(JSON.stringify(json), {\n headers,\n status\n });\n}\n",
|
|
7
|
+
"import { InvalidValueError, MissingParameterError, NotFoundError } from './error';\nimport type { Routes, Worker } from './types';\nimport { error } from './response';\n\nexport {\n cloudflare\n} from '@cloudflare/vite-plugin';\n\nexport {\n InvalidValueError,\n MissingParameterError,\n NotFoundError\n} from './error';\n\nexport {\n queryDate,\n queryInteger,\n queryPosition\n} from './request';\n\nexport {\n error,\n json\n} from './response';\n\nexport const createWorker = (routes: Routes): Worker => ({\n async fetch(req: Request): Promise<Response> {\n const {pathname} = new URL(req.url);\n\n if (!routes[pathname]) {\n return error(404, 'not_found', 'The requested endpoint could not be found.', 404);\n }\n\n const route = routes[pathname];\n\n return route(req).catch(err => {\n if (err instanceof InvalidValueError) {\n return error(406, 'invalid_value', err.message, 406);\n }\n\n if (err instanceof MissingParameterError) {\n return error(400, 'missing_parameter', err.message, 400);\n }\n\n if (err instanceof NotFoundError) {\n return error(404, 'not_found', err.message, 404);\n }\n\n return error(500, 'internal_server_error', 'An unexpected error occurred.', 500);\n });\n }\n});\n",
|
|
8
|
+
"import { DateTime } from 'luxon';\nimport { InvalidValueError, MissingParameterError } from './error';\nimport type { Coords } from './types';\n\nexport function queryDate(req: Request, name: string = 'date'): DateTime {\n const {searchParams} = new URL(req.url);\n\n if (!searchParams.has(name)) {\n throw new MissingParameterError(name);\n }\n\n const date = DateTime.fromFormat(searchParams.get(name)!, 'yyyy-MM-dd');\n\n if (!date.isValid) {\n throw new InvalidValueError(name);\n }\n\n return date;\n}\n\nexport function queryInteger(req: Request, name: string): number {\n const {searchParams} = new URL(req.url);\n\n if (!searchParams.has(name)) {\n throw new MissingParameterError(name);\n }\n\n const value = parseInt(searchParams.get(name)!);\n\n if (isNaN(value)) {\n throw new InvalidValueError(name);\n }\n\n return value;\n}\n\nexport function queryPosition(req: Request): Coords {\n const {searchParams} = new URL(req.url);\n\n if (!searchParams.has('latitude') || !searchParams.has('longitude')) {\n throw new MissingParameterError('latitude or longitude');\n }\n\n const latitude = parseFloat(searchParams.get('latitude')!);\n const longitude = parseFloat(searchParams.get('longitude')!);\n\n if (isNaN(latitude) || isNaN(longitude)) {\n throw new InvalidValueError('latitude or longitude');\n }\n\n return {\n latitude,\n longitude\n };\n}\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "AAAO,MAAM,UAA8B,KAAM,CAC7C,WAAW,CAAC,EAAe,CACvB,MAAM,8BAA8B,IAAQ,EAEpD,CAEO,MAAM,UAA0B,KAAM,CACzC,WAAW,CAAC,EAAe,CACvB,MAAM,+BAA+B,IAAQ,EAErD,CAEO,MAAM,UAAsB,KAAM,CACrC,WAAW,CAAC,EAAiB,CACzB,MAAM,CAAO,EAErB,CChBO,SAAS,CAAK,CAAC,EAAc,EAAe,EAA0B,EAA0B,CACnG,OAAO,EAAK,CACR,OACA,QACA,kBAAmB,CACvB,EAAG,CAAC,EAAG,CAAM,EAGV,SAAS,CAAI,CAAC,EAAc,EAAuB,CAAC,EAAG,EAAiB,IAAe,CAC1F,IAAM,EAAO,IAAI,KACX,EAAU,IAAI,KAAK,EAAK,YAAY,EAAG,EAAK,SAAS,EAAI,EAAG,EAAK,QAAQ,CAAC,EAMhF,GAJA,EAAU,GAAW,CAAC,EACtB,EAAQ,+BAAiC,IACzC,EAAQ,gBAAkB,mBAEtB,IAAW,IACX,EAAQ,iBAAmB,qCAC3B,EAAQ,KAAU,EAAK,YAAY,EACnC,EAAQ,QAAa,EAAQ,YAAY,EAG7C,OAAO,IAAI,SAAS,KAAK,UAAU,CAAI,EAAG,CACtC,UACA,QACJ,CAAC,ECrBL,qBACI,gCCLJ,mBAAS,cAIF,SAAS,CAAS,CAAC,EAAc,EAAe,OAAkB,CACrE,IAAO,gBAAgB,IAAI,IAAI,EAAI,GAAG,EAEtC,GAAI,CAAC,EAAa,IAAI,CAAI,EACtB,MAAM,IAAI,EAAsB,CAAI,EAGxC,IAAM,EAAO,EAAS,WAAW,EAAa,IAAI,CAAI,EAAI,YAAY,EAEtE,GAAI,CAAC,EAAK,QACN,MAAM,IAAI,EAAkB,CAAI,EAGpC,OAAO,EAGJ,SAAS,CAAY,CAAC,EAAc,EAAsB,CAC7D,IAAO,gBAAgB,IAAI,IAAI,EAAI,GAAG,EAEtC,GAAI,CAAC,EAAa,IAAI,CAAI,EACtB,MAAM,IAAI,EAAsB,CAAI,EAGxC,IAAM,EAAQ,SAAS,EAAa,IAAI,CAAI,CAAE,EAE9C,GAAI,MAAM,CAAK,EACX,MAAM,IAAI,EAAkB,CAAI,EAGpC,OAAO,EAGJ,SAAS,CAAa,CAAC,EAAsB,CAChD,IAAO,gBAAgB,IAAI,IAAI,EAAI,GAAG,EAEtC,GAAI,CAAC,EAAa,IAAI,UAAU,GAAK,CAAC,EAAa,IAAI,WAAW,EAC9D,MAAM,IAAI,EAAsB,uBAAuB,EAG3D,IAAM,EAAW,WAAW,EAAa,IAAI,UAAU,CAAE,EACnD,EAAY,WAAW,EAAa,IAAI,WAAW,CAAE,EAE3D,GAAI,MAAM,CAAQ,GAAK,MAAM,CAAS,EAClC,MAAM,IAAI,EAAkB,uBAAuB,EAGvD,MAAO,CACH,WACA,WACJ,ED5BG,IAAM,EAAe,CAAC,KAA4B,MAC/C,MAAK,CAAC,EAAiC,CACzC,IAAO,YAAY,IAAI,IAAI,EAAI,GAAG,EAElC,GAAI,CAAC,EAAO,GACR,OAAO,EAAM,IAAK,YAAa,6CAA8C,GAAG,EAGpF,IAAM,EAAQ,EAAO,GAErB,OAAO,EAAM,CAAG,EAAE,MAAM,KAAO,CAC3B,GAAI,aAAe,EACf,OAAO,EAAM,IAAK,gBAAiB,EAAI,QAAS,GAAG,EAGvD,GAAI,aAAe,EACf,OAAO,EAAM,IAAK,oBAAqB,EAAI,QAAS,GAAG,EAG3D,GAAI,aAAe,EACf,OAAO,EAAM,IAAK,YAAa,EAAI,QAAS,GAAG,EAGnD,OAAO,EAAM,IAAK,wBAAyB,gCAAiC,GAAG,EAClF,EAET",
|
|
11
|
+
"debugId": "E5477CA28CE6A9D264756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
|
+
import type { Coords } from "./types";
|
|
3
|
+
export declare function queryDate(req: Request, name?: string): DateTime;
|
|
4
|
+
export declare function queryInteger(req: Request, name: string): number;
|
|
5
|
+
export declare function queryPosition(req: Request): Coords;
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@basmilius/worker",
|
|
3
|
+
"description": "Various utilities that are used in workers.",
|
|
4
|
+
"version": "2.21.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"funding": "https://github.com/sponsors/basmilius",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "Bas Milius",
|
|
10
|
+
"email": "bas@mili.us",
|
|
11
|
+
"url": "https://bas.dev"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/basmilius/packages.git",
|
|
16
|
+
"directory": "packages/worker"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"cloudflare",
|
|
20
|
+
"worker",
|
|
21
|
+
"api"
|
|
22
|
+
],
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"src",
|
|
26
|
+
"CODEOWNERS",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"provenance": true
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "bun -b build.ts"
|
|
35
|
+
},
|
|
36
|
+
"main": "./dist/index.js",
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"typings": "./dist/index.d.ts",
|
|
39
|
+
"sideEffects": false,
|
|
40
|
+
"exports": {
|
|
41
|
+
".": {
|
|
42
|
+
"types": "./dist/index.d.ts",
|
|
43
|
+
"default": "./dist/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./*": "./*"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"luxon": "^3.7.2"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@basmilius/tools": "2.21.0",
|
|
52
|
+
"@cloudflare/vite-plugin": "^1.19.0",
|
|
53
|
+
"@types/bun": "^1.3.5",
|
|
54
|
+
"@types/cloudflare": "^3.0.0",
|
|
55
|
+
"@types/luxon": "^3.7.1"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/error.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class MissingParameterError extends Error {
|
|
2
|
+
constructor(param: string) {
|
|
3
|
+
super(`Missing required parameter ${param}.`);
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class InvalidValueError extends Error {
|
|
8
|
+
constructor(param: string) {
|
|
9
|
+
super(`Invalid value for parameter ${param}.`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class NotFoundError extends Error {
|
|
14
|
+
constructor(message: string) {
|
|
15
|
+
super(message);
|
|
16
|
+
}
|
|
17
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { InvalidValueError, MissingParameterError, NotFoundError } from './error';
|
|
2
|
+
import type { Routes, Worker } from './types';
|
|
3
|
+
import { error } from './response';
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
cloudflare
|
|
7
|
+
} from '@cloudflare/vite-plugin';
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
InvalidValueError,
|
|
11
|
+
MissingParameterError,
|
|
12
|
+
NotFoundError
|
|
13
|
+
} from './error';
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
queryDate,
|
|
17
|
+
queryInteger,
|
|
18
|
+
queryPosition
|
|
19
|
+
} from './request';
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
error,
|
|
23
|
+
json
|
|
24
|
+
} from './response';
|
|
25
|
+
|
|
26
|
+
export const createWorker = (routes: Routes): Worker => ({
|
|
27
|
+
async fetch(req: Request): Promise<Response> {
|
|
28
|
+
const {pathname} = new URL(req.url);
|
|
29
|
+
|
|
30
|
+
if (!routes[pathname]) {
|
|
31
|
+
return error(404, 'not_found', 'The requested endpoint could not be found.', 404);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const route = routes[pathname];
|
|
35
|
+
|
|
36
|
+
return route(req).catch(err => {
|
|
37
|
+
if (err instanceof InvalidValueError) {
|
|
38
|
+
return error(406, 'invalid_value', err.message, 406);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (err instanceof MissingParameterError) {
|
|
42
|
+
return error(400, 'missing_parameter', err.message, 400);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (err instanceof NotFoundError) {
|
|
46
|
+
return error(404, 'not_found', err.message, 404);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return error(500, 'internal_server_error', 'An unexpected error occurred.', 500);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
package/src/request.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
import { InvalidValueError, MissingParameterError } from './error';
|
|
3
|
+
import type { Coords } from './types';
|
|
4
|
+
|
|
5
|
+
export function queryDate(req: Request, name: string = 'date'): DateTime {
|
|
6
|
+
const {searchParams} = new URL(req.url);
|
|
7
|
+
|
|
8
|
+
if (!searchParams.has(name)) {
|
|
9
|
+
throw new MissingParameterError(name);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const date = DateTime.fromFormat(searchParams.get(name)!, 'yyyy-MM-dd');
|
|
13
|
+
|
|
14
|
+
if (!date.isValid) {
|
|
15
|
+
throw new InvalidValueError(name);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return date;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function queryInteger(req: Request, name: string): number {
|
|
22
|
+
const {searchParams} = new URL(req.url);
|
|
23
|
+
|
|
24
|
+
if (!searchParams.has(name)) {
|
|
25
|
+
throw new MissingParameterError(name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const value = parseInt(searchParams.get(name)!);
|
|
29
|
+
|
|
30
|
+
if (isNaN(value)) {
|
|
31
|
+
throw new InvalidValueError(name);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function queryPosition(req: Request): Coords {
|
|
38
|
+
const {searchParams} = new URL(req.url);
|
|
39
|
+
|
|
40
|
+
if (!searchParams.has('latitude') || !searchParams.has('longitude')) {
|
|
41
|
+
throw new MissingParameterError('latitude or longitude');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const latitude = parseFloat(searchParams.get('latitude')!);
|
|
45
|
+
const longitude = parseFloat(searchParams.get('longitude')!);
|
|
46
|
+
|
|
47
|
+
if (isNaN(latitude) || isNaN(longitude)) {
|
|
48
|
+
throw new InvalidValueError('latitude or longitude');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
latitude,
|
|
53
|
+
longitude
|
|
54
|
+
};
|
|
55
|
+
}
|
package/src/response.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function error(code: number, error: string, errorDescription: string, status: number): Response {
|
|
2
|
+
return json({
|
|
3
|
+
code,
|
|
4
|
+
error,
|
|
5
|
+
error_description: errorDescription
|
|
6
|
+
}, {}, status);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function json(json: object, headers: HeadersInit = {}, status: number = 200): Response {
|
|
10
|
+
const date = new Date();
|
|
11
|
+
const expires = new Date(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
12
|
+
|
|
13
|
+
headers = headers || {};
|
|
14
|
+
headers['Access-Control-Allow-Origin'] = '*';
|
|
15
|
+
headers['Content-Type'] = 'application/json';
|
|
16
|
+
|
|
17
|
+
if (status === 200) {
|
|
18
|
+
headers['Cache-Control'] = 'public, max-age=2628000, immutable';
|
|
19
|
+
headers['Date'] = date.toISOString();
|
|
20
|
+
headers['Expires'] = expires.toISOString();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return new Response(JSON.stringify(json), {
|
|
24
|
+
headers,
|
|
25
|
+
status
|
|
26
|
+
});
|
|
27
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type Worker = {
|
|
2
|
+
fetch(req: Request): Promise<Response>;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export type Route = (req: Request) => Promise<Response>;
|
|
6
|
+
export type Routes = Record<string, Route>;
|
|
7
|
+
|
|
8
|
+
export type Coords = {
|
|
9
|
+
readonly latitude: number;
|
|
10
|
+
readonly longitude: number;
|
|
11
|
+
};
|