1
0

19 Commits

Author SHA1 Message Date
0dca90f4f9 3.1.2 2023-11-12 18:52:30 +01:00
cb8724edc4 clean up 2023-11-12 18:48:49 +01:00
08c329ff20 3.1.1 2023-10-31 16:45:35 +01:00
e9a0a2436d use body multiple times 2023-10-31 16:45:31 +01:00
76d7040a1b 3.1.0 2023-09-29 12:20:50 +02:00
0037fb64ea update readme 2023-09-29 12:20:23 +02:00
Toby
a5ccf0fc01 support Access-Control-Allow-Credentials and vary CORS headers, thanks @akreiling 2023-09-29 10:14:07 +00:00
Toby
e006d0a3b1 use a new buffer for every invocation of handle, thanks @akreiling 2023-09-29 10:12:15 +00:00
Andrew Kreiling
c7d7a642e6 support Access-Control-Allow-Credentials and vary CORS headers 2023-09-28 07:52:34 -05:00
Andrew Kreiling
49c7897bd0 use a new buffer for every invocation of handle 2023-09-28 07:52:14 -05:00
e28976a4b6 update migration 2023-08-22 21:04:44 +02:00
eea9e580f6 3.0.0 2023-08-19 18:10:11 +02:00
68e614b3fa prepare workflow for release 2023-08-19 18:00:13 +02:00
7a20454f79 update dependencies 2023-08-19 17:55:53 +02:00
101de4f5f6 3.0.0-16 2023-05-25 20:38:48 +02:00
9ee1182fa9 update node for dev 2023-05-25 20:37:41 +02:00
0309b0131f update migration guide 2023-05-25 20:34:55 +02:00
afd7ea662f 3.0.0-15 2023-05-25 20:01:45 +02:00
a742753cb7 update workflow 2023-05-25 20:01:36 +02:00
8 changed files with 115 additions and 70 deletions

View File

@@ -7,3 +7,7 @@ insert_final_newline = false
[src/**.ts]
charset = utf-8
indent_style = tab
[README.md]
indent_style = space
indent_size = 4

View File

@@ -1,4 +1,4 @@
name: Publish (pre)
name: Publish (main)
on:
release:
@@ -11,7 +11,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: latest
registry-url: https://registry.npmjs.org/
- name: Install dependencies
run: npm ci
@@ -20,11 +20,12 @@ jobs:
- name: Publish to npmjs
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
run: npm publish --tag pre --access public
- uses: actions/setup-node@v1
run: npm publish --tag latest --access public
- uses: actions/setup-node@v3
with:
node-version: latest
registry-url: https://npm.pkg.github.com/
- name: Publish to GPR
env:
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: npm publish --tag pre --access public
run: npm publish --tag latest --access public

1
.nvmrc
View File

@@ -1 +0,0 @@
v16

View File

@@ -7,7 +7,6 @@ From `v2.x.x` to `v3.x.x`.
- [Update Router](#update-router)
- [Handlers](#handlers)
- [Fetch](#fetch--routerhandle)
## Update Router
@@ -15,7 +14,7 @@ From `v2.x.x` to `v3.x.x`.
Update to the latest version version of the router.
```bash
npm i -D @tsndr/cloudflare-worker-router
npm i -D @tsndr/cloudflare-worker-router@^3
```

View File

@@ -33,6 +33,10 @@ Migrating from `v2.x.x`, check out the [Migration Guide](MIGRATION.md).
```typescript
import { Router } from '@tsndr/cloudflare-worker-router'
// Env Types
export type Var<T = string> = T
export type Secret<T = string> = T
export type Env = {
// Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
// MY_KV_NAMESPACE: KVNamespace
@@ -43,11 +47,23 @@ export type Env = {
// Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
// MY_BUCKET: R2Bucket
SECRET_TOKEN: string
ENVIRONMENT: Var<'dev' | 'prod'>
SECRET_TOKEN: Secret
}
// Initialize router
const router = new Router<Env>()
// Request Extension
export type ExtReq = {
userId?: number
}
// Context Extension
export type ExtCtx = {
//sentry?: Toucan
}
// Initialize Router
const router = new Router<Env, ExtCtx, ExtReq>()
// Enabling build in CORS support
router.cors()
@@ -211,10 +227,12 @@ If enabled will overwrite other `OPTIONS` requests.
#### `config` (object, optional)
Key | Type | Default Value
---------------------- | --------- | -------------
-------------------------- | ---------- | -------------
`allowOrigin` | `string` | `*`
`allowMethods` | `string` | `*`
`allowHeaders` | `string` | `*`
`allowCredentials` | `boolean` | `undefined`
`vary` | `string` | `undefined`
`maxAge` | `integer` | `86400`
`optionsSuccessStatus` | `integer` | `204`
@@ -287,6 +305,10 @@ npm i -D @tsndr/cloudflare-worker-router
```typescript
import { Router } from '@tsndr/cloudflare-worker-router'
// Env Types
export type Var<T = string> = T
export type Secret<T = string> = T
export type Env = {
// Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
// MY_KV_NAMESPACE: KVNamespace
@@ -296,9 +318,35 @@ export type Env = {
//
// Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
// MY_BUCKET: R2Bucket
//
// Example Variable
// ENVIRONMENT: Var<'dev' | 'prod'>
//
// Example Secret
// JWT_SECRET: Secret
}
const router = new Router<Env>()
// Request Extension
export type ExtReq = {
userId?: number
}
// Context Extension
export type ExtCtx = {
//sentry?: Toucan
}
// Handler Type
export type Handler = RouterHandler<Env, ExtCtx, ExtReq>
// Initialize Router
const router = new Router<Env, ExtCtx, ExtReq>()
// Enable Debug Mode
router.debug()
// Enabling build in CORS support
//router.cors()
/// Example Route
//
@@ -309,12 +357,11 @@ const router = new Router<Env>()
/// Example Route for splitting into multiple files
//
// const hiHandler: RouteHandler<Env> = async () => {
// const helloHandler: Handler = async () => {
// return new Response('Hello World')
// }
//
// router.get('/hi', hiHandler)
// router.get('/hellow', helloHandler)
// TODO: add your routes here
@@ -336,6 +383,12 @@ import { Router } from '@tsndr/cloudflare-worker-router'
const router = new Router()
// Enable Debug Mode
//router.debug()
// Enabling build in CORS support
//router.cors()
/// Example Route
//
// router.get('/hi', async () => {

40
package-lock.json generated
View File

@@ -1,50 +1,36 @@
{
"name": "@tsndr/cloudflare-worker-router",
"version": "3.0.0-14",
"lockfileVersion": 2,
"version": "3.1.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@tsndr/cloudflare-worker-router",
"version": "3.0.0-14",
"version": "3.1.2",
"license": "MIT",
"devDependencies": {
"@cloudflare/workers-types": "^4.20230518.0",
"typescript": "^5.0.4"
"@cloudflare/workers-types": "^4.20231025.0",
"typescript": "^5.2.2"
}
},
"node_modules/@cloudflare/workers-types": {
"version": "4.20230518.0",
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20230518.0.tgz",
"integrity": "sha512-A0w1V+5SUawGaaPRlhFhSC/SCDT9oQG8TMoWOKFLA4qbqagELqEAFD4KySBIkeVOvCBLT1DZSYBMCxbXddl0kw==",
"version": "4.20231025.0",
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20231025.0.tgz",
"integrity": "sha512-TkcZkntUTOcvJ4vgmwpNfLTclpMbmbClZCe62B25/VTukmyv91joRa4eKzSjzCZUXTbFHNmVdOpmGaaJU2U3+A==",
"dev": true
},
"node_modules/typescript": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=12.20"
}
}
},
"dependencies": {
"@cloudflare/workers-types": {
"version": "4.20230518.0",
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20230518.0.tgz",
"integrity": "sha512-A0w1V+5SUawGaaPRlhFhSC/SCDT9oQG8TMoWOKFLA4qbqagELqEAFD4KySBIkeVOvCBLT1DZSYBMCxbXddl0kw==",
"dev": true
},
"typescript": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
"dev": true
"node": ">=14.17"
}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@tsndr/cloudflare-worker-router",
"version": "3.0.0-14",
"version": "3.1.2",
"description": "",
"main": "index.js",
"types": "index.d.ts",
@@ -31,7 +31,7 @@
},
"homepage": "https://github.com/tsndr/cloudflare-worker-router#readme",
"devDependencies": {
"@cloudflare/workers-types": "^4.20230518.0",
"typescript": "^5.0.4"
"@cloudflare/workers-types": "^4.20231025.0",
"typescript": "^5.2.2"
}
}

View File

@@ -91,6 +91,8 @@ export type RouterHandler<TEnv = any, TCtx = any, TReq = any> = {
* @property {string} [allowOrigin="*"] Access-Control-Allow-Origin (default: `*`)
* @property {string} [allowMethods="*"] Access-Control-Allow-Methods (default: `*`)
* @property {string} [allowHeaders="*"] Access-Control-Allow-Headers (default: `*`)
* @property {boolean} [allowCredentials="true"] Access-Control-Allow-Credentials (default: undefined)
* @property {string} [vary="origin"] vary (default: undefined)
* @property {number} [maxAge=86400] Access-Control-Max-Age (default: `86400`)
* @property {number} [optionsSuccessStatus=204] Return status code for OPTIONS request (default: `204`)
*/
@@ -98,6 +100,8 @@ export type RouterCorsConfig = {
allowOrigin?: string
allowMethods?: string
allowHeaders?: string
allowCredentials?: boolean
vary?: string
maxAge?: number
optionsSuccessStatus?: number
}
@@ -150,14 +154,6 @@ export class Router<TEnv = any, TCtx = any, TReq = any> {
*/
protected corsConfig: RouterCorsConfig = {}
/**
* Buffer
*
* @protected
* @type {RouterBuffer}
*/
protected buffer: RouterBuffer = {}
/**
* CORS enabled
*
@@ -312,6 +308,8 @@ export class Router<TEnv = any, TCtx = any, TReq = any> {
allowOrigin: config?.allowOrigin ?? '*',
allowMethods: config?.allowMethods ?? '*',
allowHeaders: config?.allowHeaders ?? '*',
allowCredentials: config?.allowCredentials ?? undefined,
vary: config?.vary ?? undefined,
maxAge: config?.maxAge ?? 86400,
optionsSuccessStatus: config?.optionsSuccessStatus ?? 204
}
@@ -325,6 +323,10 @@ export class Router<TEnv = any, TCtx = any, TReq = any> {
headers.set('Access-Control-Allow-Methods', this.corsConfig.allowMethods)
if (this.corsConfig.allowHeaders && !headers.has('Access-Control-Allow-Headers'))
headers.set('Access-Control-Allow-Headers', this.corsConfig.allowHeaders)
if (this.corsConfig.allowCredentials && !headers.has('Access-Control-Allow-Credentials'))
headers.set('Access-Control-Allow-Credentials', this.corsConfig.allowCredentials.toString())
if (this.corsConfig.vary && !headers.has('vary'))
headers.set('vary', this.corsConfig.vary.toString())
if (this.corsConfig.maxAge && !headers.has('Access-Control-Max-Age'))
headers.set('Access-Control-Max-Age', this.corsConfig.maxAge.toString())
return headers
@@ -400,6 +402,7 @@ export class Router<TEnv = any, TCtx = any, TReq = any> {
* @returns {Promise<Response>}
*/
public async handle(request: Request, env: TEnv, ctx?: ExecutionContext, extCtx?: TCtx, extReq?: TReq): Promise<Response> {
const buffer: RouterBuffer = {};
const req = {
...(extReq ?? {}),
method: request.method,
@@ -409,11 +412,11 @@ export class Router<TEnv = any, TCtx = any, TReq = any> {
raw: request,
params: {},
query: {},
arrayBuffer: async (): Promise<ArrayBuffer> => this.buffer.arrayBuffer ? this.buffer.arrayBuffer : this.buffer.arrayBuffer = await request.arrayBuffer(),
text: async (): Promise<string> => this.buffer.text ? this.buffer.text : this.buffer.text = await request.text(),
json: async <T>(): Promise<T> => this.buffer.json ? this.buffer.json : this.buffer.json = await request.json<T>(),
formData: async (): Promise<FormData> => this.buffer.formData ? this.buffer.formData : this.buffer.formData = await request.formData(),
blob: async (): Promise<Blob> => this.buffer.blob ? this.buffer.blob : this.buffer.blob = await request.blob(),
arrayBuffer: async (): Promise<ArrayBuffer> => buffer.arrayBuffer ? buffer.arrayBuffer : buffer.arrayBuffer = await request.clone().arrayBuffer(),
text: async (): Promise<string> => buffer.text ? buffer.text : buffer.text = await request.clone().text(),
json: async <T>(): Promise<T> => buffer.json ? buffer.json : buffer.json = await request.clone().json<T>(),
formData: async (): Promise<FormData> => buffer.formData ? buffer.formData : buffer.formData = await request.clone().formData(),
blob: async (): Promise<Blob> => buffer.blob ? buffer.blob : buffer.blob = await request.clone().blob(),
bearer: () => request.headers.get('Authorization')?.replace(/^(B|b)earer /, '').trim()
} as RouterRequest<TReq>