From fdb79d28751f6d91ab0eb76a192c23029d2efcba Mon Sep 17 00:00:00 2001 From: tada5hi Date: Wed, 8 Apr 2026 12:10:49 +0200 Subject: [PATCH 1/2] feat(cookie): update @routup/cookie for routup v5 --- package-lock.json | 60 ++++++++++---- packages/assets/package.json | 4 +- packages/cookie/package.json | 6 +- packages/cookie/src/handler.ts | 13 ++-- packages/cookie/src/request.ts | 28 +++---- packages/cookie/src/response.ts | 12 +-- packages/cookie/src/utils.ts | 7 +- packages/cookie/test/unit/module.spec.ts | 99 ++++++++++-------------- packages/swagger/package.json | 4 +- 9 files changed, 119 insertions(+), 114 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38d4f792..2af7d2a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9162,10 +9162,10 @@ "version": "3.4.2", "license": "MIT", "devDependencies": { - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" }, "peerDependencies": { - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" } }, "packages/assets/node_modules/@ebec/http": { @@ -9179,9 +9179,9 @@ } }, "packages/assets/node_modules/routup": { - "version": "5.0.0-beta.2", - "resolved": "https://registry.npmjs.org/routup/-/routup-5.0.0-beta.2.tgz", - "integrity": "sha512-lu4xfXZmRv7qStbz3OfvbqA53+bSBi6FufXlCSAwkWYJaFYieqPGNKfm3JcNIrqTZEs1o/2SIOMlc/H4QLQRWg==", + "version": "5.0.0-beta.3", + "resolved": "https://registry.npmjs.org/routup/-/routup-5.0.0-beta.3.tgz", + "integrity": "sha512-DyBIIalGQAOW+1O7jLhEaBnJ7ZIrTK8DUVeE5pmKtUOYSpcz1vQ8zhzlwnR7EoEM49iE/GA+25ZSQNgPPwszqw==", "dev": true, "license": "MIT", "dependencies": { @@ -9191,7 +9191,7 @@ "path-to-regexp": "^8.4.2", "proxy-addr": "^2.0.7", "smob": "^1.5.0", - "srvx": "^0.11.14", + "srvx": "^0.11.15", "uncrypto": "^0.1.3" }, "engines": { @@ -9242,12 +9242,40 @@ "cookie-es": "^3.1.1" }, "devDependencies": { - "@types/supertest": "^7.2.0", - "routup": "^4.0.1", - "supertest": "^7.1.4" + "routup": "^5.0.0-beta.3" }, "peerDependencies": { - "routup": "^4.0.1" + "routup": "^5.0.0-beta.3" + } + }, + "packages/cookie/node_modules/@ebec/http": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@ebec/http/-/http-3.0.3.tgz", + "integrity": "sha512-GSs7yOLfZzZAJ6jYfRlL64ORgQcu2NCj2V6IfQStU+n5+QMiLU9V+lBR7PKJuqt66kFSLC++iLlChPU/w/a/Lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ebec/core": "^1.0.1" + } + }, + "packages/cookie/node_modules/routup": { + "version": "5.0.0-beta.3", + "resolved": "https://registry.npmjs.org/routup/-/routup-5.0.0-beta.3.tgz", + "integrity": "sha512-DyBIIalGQAOW+1O7jLhEaBnJ7ZIrTK8DUVeE5pmKtUOYSpcz1vQ8zhzlwnR7EoEM49iE/GA+25ZSQNgPPwszqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ebec/http": "^3.0.3", + "mime-explorer": "^1.1.0", + "negotiator": "^1.0.0", + "path-to-regexp": "^8.4.2", + "proxy-addr": "^2.0.7", + "smob": "^1.5.0", + "srvx": "^0.11.15", + "uncrypto": "^0.1.3" + }, + "engines": { + "node": ">=22.0.0" } }, "packages/decorators": { @@ -9363,10 +9391,10 @@ "devDependencies": { "@routup/decorators": "^3.4.3", "jsonata": "^2.1.0", - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" }, "peerDependencies": { - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" } }, "packages/swagger-preset": { @@ -9391,9 +9419,9 @@ } }, "packages/swagger/node_modules/routup": { - "version": "5.0.0-beta.2", - "resolved": "https://registry.npmjs.org/routup/-/routup-5.0.0-beta.2.tgz", - "integrity": "sha512-lu4xfXZmRv7qStbz3OfvbqA53+bSBi6FufXlCSAwkWYJaFYieqPGNKfm3JcNIrqTZEs1o/2SIOMlc/H4QLQRWg==", + "version": "5.0.0-beta.3", + "resolved": "https://registry.npmjs.org/routup/-/routup-5.0.0-beta.3.tgz", + "integrity": "sha512-DyBIIalGQAOW+1O7jLhEaBnJ7ZIrTK8DUVeE5pmKtUOYSpcz1vQ8zhzlwnR7EoEM49iE/GA+25ZSQNgPPwszqw==", "dev": true, "license": "MIT", "dependencies": { @@ -9403,7 +9431,7 @@ "path-to-regexp": "^8.4.2", "proxy-addr": "^2.0.7", "smob": "^1.5.0", - "srvx": "^0.11.14", + "srvx": "^0.11.15", "uncrypto": "^0.1.3" }, "engines": { diff --git a/packages/assets/package.json b/packages/assets/package.json index e06e3ea5..cfaedbcd 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -52,10 +52,10 @@ }, "homepage": "https://github.com/routup/plugins#readme", "peerDependencies": { - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" }, "devDependencies": { - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" }, "publishConfig": { "access": "public" diff --git a/packages/cookie/package.json b/packages/cookie/package.json index 83ff5fed..56859b38 100644 --- a/packages/cookie/package.json +++ b/packages/cookie/package.json @@ -51,15 +51,13 @@ }, "homepage": "https://github.com/routup/plugins#readme", "peerDependencies": { - "routup": "^4.0.1" + "routup": "^5.0.0-beta.3" }, "dependencies": { "cookie-es": "^3.1.1" }, "devDependencies": { - "@types/supertest": "^7.2.0", - "routup": "^4.0.1", - "supertest": "^7.1.4" + "routup": "^5.0.0-beta.3" }, "gitHead": "94d729e309c1eec0401afb4d8083f65ce3aa8e0b", "publishConfig": { diff --git a/packages/cookie/src/handler.ts b/packages/cookie/src/handler.ts index b59cf12f..fe96e6ac 100644 --- a/packages/cookie/src/handler.ts +++ b/packages/cookie/src/handler.ts @@ -1,5 +1,5 @@ import { - coreHandler, + defineCoreHandler, } from 'routup'; import { @@ -11,14 +11,13 @@ import type { ParseOptions } from './types'; import { parseRequestCookies } from './utils'; export function createHandler(options?: ParseOptions) { - return coreHandler((req, res, next) => { - if (hasRequestCookies(req)) { - next(); - return; + return defineCoreHandler((event) => { + if (hasRequestCookies(event)) { + return event.next(); } - setRequestCookies(req, parseRequestCookies(req, options)); + setRequestCookies(event, parseRequestCookies(event, options)); - next(); + return event.next(); }); } diff --git a/packages/cookie/src/request.ts b/packages/cookie/src/request.ts index 22ef2557..87fdb7f1 100644 --- a/packages/cookie/src/request.ts +++ b/packages/cookie/src/request.ts @@ -1,34 +1,34 @@ -import type { Request } from 'routup'; +import type { IRoutupEvent } from 'routup'; import { isObject } from './utils'; const CookieSymbol = Symbol.for('ReqCookie'); export function useRequestCookies( - req: Request, + event: IRoutupEvent, ) : Record { - if (CookieSymbol in req) { - return (req as any)[CookieSymbol]; + if (CookieSymbol in event.store) { + return event.store[CookieSymbol] as Record; } return {}; } -export function hasRequestCookies(req: Request) { - return CookieSymbol in req && - isObject((req as any)[CookieSymbol]); +export function hasRequestCookies(event: IRoutupEvent) { + return CookieSymbol in event.store && + isObject(event.store[CookieSymbol]); } -export function useRequestCookie(req: Request, name: string) : string | undefined { - return useRequestCookies(req)[name]; +export function useRequestCookie(event: IRoutupEvent, name: string) : string | undefined { + return useRequestCookies(event)[name]; } -export function setRequestCookies(req: Request, key: string, value: unknown) : void; -export function setRequestCookies(req: Request, record: Record) : void; -export function setRequestCookies(req: Request, key: Record | string, value?: unknown) : void { +export function setRequestCookies(event: IRoutupEvent, key: string, value: unknown) : void; +export function setRequestCookies(event: IRoutupEvent, record: Record) : void; +export function setRequestCookies(event: IRoutupEvent, key: Record | string, value?: unknown) : void { if (isObject(key)) { - (req as any)[CookieSymbol] = key; + event.store[CookieSymbol] = key; return; } - (req as any)[CookieSymbol] = { [key]: value }; + event.store[CookieSymbol] = { [key]: value }; } diff --git a/packages/cookie/src/response.ts b/packages/cookie/src/response.ts index fdcf5ecc..73907a75 100644 --- a/packages/cookie/src/response.ts +++ b/packages/cookie/src/response.ts @@ -1,18 +1,18 @@ -import type { Response } from 'routup'; -import { HeaderName, appendResponseHeader } from 'routup'; +import type { IRoutupEvent } from 'routup'; +import { appendResponseHeader } from 'routup'; import { serialize } from 'cookie-es'; import type { SerializeOptions } from './types'; -export function setResponseCookie(res: Response, name: string, value: string, options?: SerializeOptions) { - appendResponseHeader(res, HeaderName.SET_COOKIE, serialize(name, value, { +export function setResponseCookie(event: IRoutupEvent, name: string, value: string, options?: SerializeOptions) { + appendResponseHeader(event, 'set-cookie', serialize(name, value, { path: '/', ...(options || {}), })); } /* istanbul ignore next */ -export function unsetResponseCookie(res: Response, name: string, options?: SerializeOptions) { - setResponseCookie(res, name, '', { +export function unsetResponseCookie(event: IRoutupEvent, name: string, options?: SerializeOptions) { + setResponseCookie(event, name, '', { ...(options || {}), maxAge: 0, }); diff --git a/packages/cookie/src/utils.ts b/packages/cookie/src/utils.ts index 227a4c5b..7e5f9be0 100644 --- a/packages/cookie/src/utils.ts +++ b/packages/cookie/src/utils.ts @@ -1,10 +1,9 @@ -import type { Request } from 'routup'; -import { HeaderName } from 'routup'; +import type { IRoutupEvent } from 'routup'; import { parse } from 'cookie-es'; import type { ParseOptions } from './types'; -export function parseRequestCookies(req: Request, options?: ParseOptions) { - return parse(req.headers[HeaderName.COOKIE] || '', options || {}); +export function parseRequestCookies(event: IRoutupEvent, options?: ParseOptions) { + return parse(event.headers.get('cookie') || '', options || {}); } export function isObject(item: unknown) : item is Record { diff --git a/packages/cookie/test/unit/module.spec.ts b/packages/cookie/test/unit/module.spec.ts index 8b0fbac2..29b8a981 100644 --- a/packages/cookie/test/unit/module.spec.ts +++ b/packages/cookie/test/unit/module.spec.ts @@ -1,11 +1,7 @@ import { describe, expect, it } from 'vitest'; -import supertest from 'supertest'; import { - HeaderName, - Router, - coreHandler, - createNodeDispatcher, - send, + Router, + defineCoreHandler, } from 'routup'; import { cookie, @@ -15,27 +11,28 @@ import { useRequestCookies, } from '../../src'; +function createTestRequest(url: string, options?: RequestInit): Request { + const fullUrl = url.startsWith('http') ? url : `http://localhost${url}`; + return new Request(fullUrl, options); +} + describe('src/module', () => { it('should parse cookie', async () => { const router = new Router(); router.use(cookie()); - router.get('/', coreHandler((req, res) => { - useRequestCookies(req); + router.get('/', defineCoreHandler((event) => { + useRequestCookies(event); - const foo = useRequestCookie(req, 'foo'); - send(res, foo); + const foo = useRequestCookie(event, 'foo'); + return foo; })); - const server = supertest(createNodeDispatcher(router)); - - const response = await server - .get('/') - .set('Cookie', ['foo=bar']); + const response = await router.fetch(createTestRequest('/', { headers: { cookie: 'foo=bar' } })); - expect(response.statusCode).toEqual(200); - expect(response.text).toEqual('bar'); + expect(response.status).toEqual(200); + expect(await response.text()).toEqual('bar'); }); it('should parse cookie with middleware', async () => { @@ -43,74 +40,58 @@ describe('src/module', () => { router.use(cookie()); - router.get('/', coreHandler((req, res) => { - useRequestCookies(req); + router.get('/', defineCoreHandler((event) => { + useRequestCookies(event); - const foo = useRequestCookie(req, 'bar'); - send(res, foo); + const foo = useRequestCookie(event, 'bar'); + return foo; })); - const server = supertest(createNodeDispatcher(router)); - - const response = await server - .get('/') - .set('Cookie', ['bar=baz']); + const response = await router.fetch(createTestRequest('/', { headers: { cookie: 'bar=baz' } })); - expect(response.statusCode).toEqual(200); - expect(response.text).toEqual('baz'); + expect(response.status).toEqual(200); + expect(await response.text()).toEqual('baz'); }); it('should set (multiple) cookie', async () => { const router = new Router(); - router.get('/', coreHandler((req, res) => { - setResponseCookie(res, 'bar', 'baz'); + router.get('/', defineCoreHandler((event) => { + setResponseCookie(event, 'bar', 'baz'); - send(res); + return null; })); - router.get('/multiple', coreHandler((req, res) => { - setResponseCookie(res, 'foo', 'bar'); - setResponseCookie(res, 'bar', 'baz'); + router.get('/multiple', defineCoreHandler((event) => { + setResponseCookie(event, 'foo', 'bar'); + setResponseCookie(event, 'bar', 'baz'); - send(res); + return null; })); - const server = supertest(createNodeDispatcher(router)); + let response = await router.fetch(createTestRequest('/', { headers: { cookie: 'foo=bar' } })); - let response = await server - .get('/') - .set('Cookie', ['foo=bar']); + expect(response.status).toEqual(200); + expect(response.headers.get('set-cookie')).toEqual('bar=baz; Path=/'); - expect(response.statusCode).toEqual(200); - expect(response.headers[HeaderName.SET_COOKIE]).toEqual(['bar=baz; Path=/']); + response = await router.fetch(createTestRequest('/multiple')); - response = await server - .get('/multiple'); - - expect(response.statusCode).toEqual(200); - expect(response.headers[HeaderName.SET_COOKIE]).toEqual([ - 'foo=bar; Path=/', - 'bar=baz; Path=/', - ]); + expect(response.status).toEqual(200); + expect(response.headers.get('set-cookie')).toEqual('foo=bar; Path=/, bar=baz; Path=/'); }); it('should unset cookie', async () => { const router = new Router(); - router.get('/', coreHandler((req, res) => { - unsetResponseCookie(res, 'foo'); + router.get('/', defineCoreHandler((event) => { + unsetResponseCookie(event, 'foo'); - send(res); + return null; })); - const server = supertest(createNodeDispatcher(router)); - - const response = await server - .get('/') - .set('Cookie', ['foo=bar']); + const response = await router.fetch(createTestRequest('/', { headers: { cookie: 'foo=bar' } })); - expect(response.statusCode).toEqual(200); - expect(response.headers[HeaderName.SET_COOKIE]).toEqual(['foo=; Max-Age=0; Path=/']); + expect(response.status).toEqual(200); + expect(response.headers.get('set-cookie')).toEqual('foo=; Max-Age=0; Path=/'); }); }); diff --git a/packages/swagger/package.json b/packages/swagger/package.json index 95964600..fe9dd20f 100644 --- a/packages/swagger/package.json +++ b/packages/swagger/package.json @@ -52,7 +52,7 @@ }, "homepage": "https://github.com/routup/plugins#readme", "peerDependencies": { - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" }, "dependencies": { "@routup/assets": "^3.4.2", @@ -65,7 +65,7 @@ "devDependencies": { "@routup/decorators": "^3.4.3", "jsonata": "^2.1.0", - "routup": "^5.0.0-beta.2" + "routup": "^5.0.0-beta.3" }, "publishConfig": { "access": "public" From e2937ca4fa82e50449ed5185d8b3d22c13bc6b3b Mon Sep 17 00:00:00 2001 From: tada5hi Date: Wed, 8 Apr 2026 12:13:52 +0200 Subject: [PATCH 2/2] docs: updated documentation --- packages/cookie/README.md | 57 ++++++++++++++++++++++++++++---------- packages/swagger/README.md | 11 ++------ 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/packages/cookie/README.md b/packages/cookie/README.md index b73c8f8f..6431d7ea 100644 --- a/packages/cookie/README.md +++ b/packages/cookie/README.md @@ -19,6 +19,8 @@ response. - [setRequestCookies](#setrequestcookies) - [useRequestCookies](#userequestcookies) - [useRequestCookie](#userequestcookie) + - [setResponseCookie](#setresponsecookie) + - [unsetResponseCookie](#unsetresponsecookie) - [License](#license) ## Installation @@ -37,33 +39,33 @@ It is important to invoke the request middleware, to parse the cookies of the request header. ```typescript -import { createServer } from 'node:http'; import { - createNodeDispatcher, - coreHandler, - Router + Router, + defineCoreHandler, + serve, } from 'routup'; import { cookie, useRequestCookie, - useRequestCookies + useRequestCookies, } from '@routup/cookie'; const router = new Router(); router.use(cookie()); -router.get('/', coreHandler((req, res) => { - const cookies = useRequestCookies(req); +router.get('/', defineCoreHandler((event) => { + const cookies = useRequestCookies(event); console.log(cookies); // { key: value, ... } - const cookie = useRequestCookie(req, 'key'); + const value = useRequestCookie(event, 'key'); // value + + return value; })); -const server = createServer(createNodeDispatcher(router)); -server.listen(3000); +serve(router, { port: 3000 }); ``` ## Options @@ -93,13 +95,13 @@ This function sets the parsed request cookies for the current request. ```typescript declare function setRequestCookies( - req: Request, + event: IRoutupEvent, key: string, value: unknown ) : void; declare function setRequestCookies( - req: Request, + event: IRoutupEvent, record: Record ) : void; ``` @@ -110,21 +112,46 @@ This function returns the parsed request cookies. ```typescript declare function useRequestCookies( - req: IncomingMessage, + event: IRoutupEvent, ) : Record; ``` ### `useRequestCookie` -This function returns a **single** parsed request cookies. +This function returns a **single** parsed request cookie. ```typescript declare function useRequestCookie( - req: IncomingMessage, + event: IRoutupEvent, name: string ) : string | undefined; ``` +### `setResponseCookie` + +This function sets a cookie on the response. + +```typescript +declare function setResponseCookie( + event: IRoutupEvent, + name: string, + value: string, + options?: SerializeOptions +) : void; +``` + +### `unsetResponseCookie` + +This function removes a cookie by setting its `maxAge` to `0`. + +```typescript +declare function unsetResponseCookie( + event: IRoutupEvent, + name: string, + options?: SerializeOptions +) : void; +``` + ## License Made with 💚 diff --git a/packages/swagger/README.md b/packages/swagger/README.md index 091713e7..98d10663 100644 --- a/packages/swagger/README.md +++ b/packages/swagger/README.md @@ -6,7 +6,7 @@ [![Known Vulnerabilities](https://snyk.io/test/github/Tada5hi/routup/badge.svg)](https://snyk.io/test/github/Tada5hi/routup) [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white)](https://conventionalcommits.org) -This is a plugin for reading and parsing the request payload. +This is a plugin for serving Swagger UI and OpenAPI documentation. **Table of Contents** @@ -88,19 +88,14 @@ The function call will save the file under the location: `./writable/swagger.jso Serve generated docs from (file- / web-) URL or based on a JSON file with [swagger-ui](https://www.npmjs.com/package/swagger-ui-dist). ```typescript -import { createServer } from 'node:http'; -import { - createNodeDispatcher, - Router -} from 'routup'; +import { Router, serve } from 'routup'; import { swaggerUI } from '@routup/swagger'; const router = new Router(); router.use('/docs', swaggerUI('test/data/swagger.json')); -const server = createServer(createNodeDispatcher(router)); -server.listen(3000); +serve(router, { port: 3000 }); ``` Now open the browser and visit: