Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hono

Package Overview
Dependencies
Maintainers
1
Versions
343
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hono - npm Package Compare versions

Comparing version 1.4.2 to 1.4.3

dist/request.d.ts

7

dist/compose.js

@@ -19,9 +19,8 @@ "use strict";

if (!handler) {
if (context instanceof context_1.Context && context.res._finalized === false && onNotFound) {
if (context instanceof context_1.Context && context.finalized === false && onNotFound) {
context.res = onNotFound(context);
context.res._finalized = true;
}
return Promise.resolve(context);
}
return Promise.resolve(handler(context, dispatch.bind(null, i + 1)))
return Promise.resolve(handler(context, () => dispatch(i + 1)))
.then(async (res) => {

@@ -31,3 +30,2 @@ // If handler return Response like `return c.text('foo')`

context.res = res;
context.res._finalized = true;
}

@@ -40,3 +38,2 @@ return context;

context.res = onError(err, context);
context.res._finalized = true;
}

@@ -43,0 +40,0 @@ return context;

/// <reference types="@cloudflare/workers-types" />
import { HonoResponse } from './response';
import type { StatusCode } from './utils/http-status';

@@ -9,5 +8,5 @@ declare type Headers = Record<string, string>;

req: Request<RequestParamKeyType>;
res: Response;
env: E;
event: FetchEvent | undefined;
finalized: boolean;
private _status;

@@ -17,10 +16,9 @@ private _pretty;

private _map;
private _headers;
private _res;
private notFoundHandler;
render: (template: string, params?: object, options?: object) => Promise<Response>;
notFound: () => Response | Promise<Response>;
constructor(req: Request<RequestParamKeyType>, opts?: {
env?: Env;
event?: FetchEvent;
res?: Response | HonoResponse;
});
private initRequest;
constructor(req: Request<RequestParamKeyType>, env?: E | undefined, event?: FetchEvent | undefined, notFoundHandler?: (c: Context<string, E>) => Response);
get res(): Response;
set res(_res: Response);
header(name: string, value: string): void;

@@ -31,3 +29,3 @@ status(status: StatusCode): void;

pretty(prettyJSON: boolean, space?: number): void;
newResponse(data: Data | null, init?: ResponseInit): Response;
newResponse(data: Data | null, status: StatusCode, headers?: Headers): Response;
body(data: Data | null, status?: StatusCode, headers?: Headers): Response;

@@ -38,3 +36,4 @@ text(text: string, status?: StatusCode, headers?: Headers): Response;

redirect(location: string, status?: StatusCode): Response;
notFound(): Response | Promise<Response>;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Context = void 0;
const response_1 = require("./response");
const url_1 = require("./utils/url");
class Context {
constructor(req, opts = {
env: {},
event: undefined,
res: undefined,
}) {
constructor(req, env = undefined, event = undefined, notFoundHandler = () => new Response()) {
this._status = 200;
this._pretty = false;
this._prettySpace = 2;
this.req = this.initRequest(req);
this._map = {};
Object.assign(this, opts);
if (!this.res) {
const res = new response_1.HonoResponse(null, { status: 404 });
res._finalized = false;
this.res = res;
this.req = req;
if (env) {
this.env = env;
}
this.event = event;
this.notFoundHandler = notFoundHandler;
this.finalized = false;
}
initRequest(req) {
req.header = ((name) => {
if (name) {
return req.headers.get(name);
}
else {
const result = {};
for (const [key, value] of req.headers) {
result[key] = value;
}
return result;
}
});
req.query = ((key) => {
const url = new URL(req.url);
if (key) {
return url.searchParams.get(key);
}
else {
const result = {};
for (const key of url.searchParams.keys()) {
result[key] = url.searchParams.get(key) || '';
}
return result;
}
});
req.queries = ((key) => {
const url = new URL(req.url);
if (key) {
return url.searchParams.getAll(key);
}
else {
const result = {};
for (const key of url.searchParams.keys()) {
result[key] = url.searchParams.getAll(key);
}
return result;
}
});
return req;
get res() {
return (this._res || (this._res = new Response()));
}
set res(_res) {
this._res = _res;
this.finalized = true;
}
header(name, value) {
this.res.headers.set(name, value);
this._headers || (this._headers = {});
this._headers[name] = value;
if (this.finalized) {
this.res.headers.set(name, value);
}
}

@@ -72,5 +36,9 @@ status(status) {

set(key, value) {
this._map || (this._map = {});
this._map[key] = value;
}
get(key) {
if (!this._map) {
return undefined;
}
return this._map[key];

@@ -82,21 +50,18 @@ }

}
newResponse(data, init = {}) {
init.status = init.status || this._status || 200;
const headers = {};
this.res.headers.forEach((v, k) => {
headers[k] = v;
newResponse(data, status, headers = {}) {
const _headers = { ...this._headers, ...headers };
if (this._res) {
this._res.headers.forEach((v, k) => {
_headers[k] = v;
});
}
return new Response(data, {
status: status || this._status || 200,
headers: _headers,
});
init.headers = Object.assign(headers, init.headers);
return new Response(data, init);
}
body(data, status = this._status, headers = {}) {
return this.newResponse(data, {
status: status,
headers: headers,
});
return this.newResponse(data, status, headers);
}
text(text, status = this._status, headers = {}) {
if (typeof text !== 'string') {
throw new TypeError('text method arg must be a string!');
}
headers['Content-Type'] || (headers['Content-Type'] = 'text/plain; charset=UTF-8');

@@ -106,5 +71,2 @@ return this.body(text, status, headers);

json(object, status = this._status, headers = {}) {
if (typeof object !== 'object') {
throw new TypeError('json method arg must be an object!');
}
const body = this._pretty

@@ -117,5 +79,2 @@ ? JSON.stringify(object, null, this._prettySpace)

html(html, status = this._status, headers = {}) {
if (typeof html !== 'string') {
throw new TypeError('html method arg must be a string!');
}
headers['Content-Type'] || (headers['Content-Type'] = 'text/html; charset=UTF-8');

@@ -125,5 +84,2 @@ return this.body(html, status, headers);

redirect(location, status = 302) {
if (typeof location !== 'string') {
throw new TypeError('location must be a string!');
}
if (!(0, url_1.isAbsoluteURL)(location)) {

@@ -134,10 +90,10 @@ const url = new URL(this.req.url);

}
return this.newResponse(null, {
status: status,
headers: {
Location: location,
},
return this.newResponse(null, status, {
Location: location,
});
}
notFound() {
return this.notFoundHandler(this);
}
}
exports.Context = Context;

@@ -5,25 +5,2 @@ /// <reference types="@cloudflare/workers-types" />

import type { Router } from './router';
declare global {
interface Request<ParamKeyType extends string = string> {
param: {
(key: ParamKeyType): string;
(): Record<ParamKeyType, string>;
};
query: {
(key: string): string;
(): Record<string, string>;
};
queries: {
(key: string): string[];
(): Record<string, string[]>;
};
header: {
(name: string): string;
(): Record<string, string>;
};
}
interface Response {
_finalized: boolean;
}
}
export declare type Handler<RequestParamKeyType extends string = string, E = Env> = (c: Context<RequestParamKeyType, E>, next: Next) => Response | Promise<Response> | Promise<void> | Promise<Response | undefined>;

@@ -36,3 +13,3 @@ export declare type NotFoundHandler<E = Env> = (c: Context<string, E>) => Response;

declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>;
interface HandlerInterface<T extends string, E = Env, U = Hono<E, T>> {
interface HandlerInterface<T extends string, E extends Env = Env, U = Hono<E, T>> {
<Path extends string>(path: Path, ...handlers: Handler<ParamKeys<Path> extends never ? string : ParamKeys<Path>, E>[]): U;

@@ -58,3 +35,3 @@ (path: string, ...handlers: Handler<string, E>[]): U;

};
export declare class Hono<E = Env, P extends string = '/'> extends Hono_base<E, P, Hono<E, P>> {
export declare class Hono<E extends Env = Env, P extends string = '/'> extends Hono_base<E, P, Hono<E, P>> {
readonly router: Router<Handler<string, E>>;

@@ -61,0 +38,0 @@ readonly strict: boolean;

@@ -6,2 +6,3 @@ "use strict";

const context_1 = require("./context");
const request_1 = require("./request");
const router_1 = require("./router");

@@ -32,2 +33,3 @@ const trie_router_1 = require("./router/trie-router"); // Default Router

};
(0, request_1.extendRequestPrototype)(); // FIXME: should be executed at a better timing
const allMethods = [...methods, router_1.METHOD_NAME_ALL_LOWERCASE];

@@ -91,26 +93,12 @@ allMethods.map((method) => {

}
async matchRoute(method, path) {
matchRoute(method, path) {
return this.router.match(method, path);
}
async dispatch(request, event, env) {
const path = (0, url_1.getPathFromURL)(request.url, { strict: this.strict });
const path = (0, url_1.getPathFromURL)(request.url, this.strict);
const method = request.method;
const result = await this.matchRoute(method, path);
request.param = ((key) => {
if (result) {
if (key) {
return result.params[key];
}
else {
return result.params;
}
}
return null;
});
const result = this.matchRoute(method, path);
request.paramData = result?.params;
const handlers = result ? result.handlers : [this.notFoundHandler];
const c = new context_1.Context(request, {
env: env,
event: event,
});
c.notFound = () => this.notFoundHandler(c);
const c = new context_1.Context(request, env, event, this.notFoundHandler);
const composed = (0, compose_1.compose)(handlers, this.errorHandler, this.notFoundHandler);

@@ -127,4 +115,2 @@ let context;

}
if (!context.res)
return context.notFound();
return context.res;

@@ -131,0 +117,0 @@ }

@@ -37,3 +37,2 @@ "use strict";

return async (ctx, next) => {
var _a;
const requestUser = auth(ctx.req);

@@ -54,3 +53,3 @@ if (requestUser) {

headers: {
'WWW-Authenticate': 'Basic realm="' + ((_a = options.realm) === null || _a === void 0 ? void 0 : _a.replace(/"/g, '\\"')) + '"',
'WWW-Authenticate': 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"',
},

@@ -57,0 +56,0 @@ });

@@ -11,5 +11,7 @@ "use strict";

};
const opts = Object.assign(Object.assign({}, defaults), options);
const opts = {
...defaults,
...options,
};
return async (c, next) => {
var _a, _b;
await next();

@@ -28,3 +30,3 @@ function set(key, value) {

}
if ((_a = opts.exposeHeaders) === null || _a === void 0 ? void 0 : _a.length) {
if (opts.exposeHeaders?.length) {
set('Access-Control-Expose-Headers', opts.exposeHeaders.join(','));

@@ -37,7 +39,7 @@ }

}
if ((_b = opts.allowMethods) === null || _b === void 0 ? void 0 : _b.length) {
if (opts.allowMethods?.length) {
set('Access-Control-Allow-Methods', opts.allowMethods.join(','));
}
let headers = opts.allowHeaders;
if (!(headers === null || headers === void 0 ? void 0 : headers.length)) {
if (!headers?.length) {
const requestHeaders = c.req.headers.get('Access-Control-Request-Headers');

@@ -48,3 +50,3 @@ if (requestHeaders) {

}
if (headers === null || headers === void 0 ? void 0 : headers.length) {
if (headers?.length) {
set('Access-Control-Allow-Headers', headers.join(','));

@@ -51,0 +53,0 @@ set('Vary', 'Access-Control-Request-Headers');

@@ -9,7 +9,6 @@ "use strict";

const graphqlServer = (options) => {
var _a, _b;
const schema = options.schema;
const rootValue = options.rootValue;
const pretty = (_a = options.pretty) !== null && _a !== void 0 ? _a : false;
const validationRules = (_b = options.validationRules) !== null && _b !== void 0 ? _b : [];
const pretty = options.pretty ?? false;
const validationRules = options.validationRules ?? [];
// const showGraphiQL = options.graphiql ?? false

@@ -126,7 +125,6 @@ return async (c, next) => {

const getGraphQLParams = async (request) => {
var _a, _b, _c;
const urlData = new URLSearchParams(request.url.split('?')[1]);
const bodyData = await (0, parse_body_1.parseBody)(request);
// GraphQL Query string.
let query = (_a = urlData.get('query')) !== null && _a !== void 0 ? _a : bodyData.query;
let query = urlData.get('query') ?? bodyData.query;
if (typeof query !== 'string') {

@@ -136,3 +134,3 @@ query = null;

// Parse the variables if needed.
let variables = ((_b = urlData.get('variables')) !== null && _b !== void 0 ? _b : bodyData.variables);
let variables = (urlData.get('variables') ?? bodyData.variables);
if (typeof variables === 'string') {

@@ -142,3 +140,3 @@ try {

}
catch (_d) {
catch {
throw Error('Variables are invalid JSON.');

@@ -151,3 +149,3 @@ }

// Name of GraphQL operation to execute.
let operationName = (_c = urlData.get('operationName')) !== null && _c !== void 0 ? _c : bodyData.operationName;
let operationName = urlData.get('operationName') ?? bodyData.operationName;
if (typeof operationName !== 'string') {

@@ -154,0 +152,0 @@ operationName = null;

@@ -13,5 +13,5 @@ "use strict";

ctx.res = new Response('Unauthorized', {
status: 401,
status: 400,
headers: {
'WWW-Authenticate': 'Basic ${options.secret}',
'WWW-Authenticate': `Bearer realm="${ctx.req.url}",error="invalid_request",error_description="no authorization included in request"`,
},

@@ -24,5 +24,5 @@ });

ctx.res = new Response('Unauthorized', {
status: 401,
status: 400,
headers: {
'WWW-Authenticate': 'Basic ${options.secret}',
'WWW-Authenticate': `Bearer realm="${ctx.req.url}",error="invalid_request",error_description="no authorization included in request"`,
},

@@ -45,3 +45,3 @@ });

headers: {
'WWW-Authenticate': 'Bearer ${options.secret}',
'WWW-Authenticate': `Bearer realm="${ctx.req.url}",error="invalid_token",error_description="token verification failure"`,
},

@@ -48,0 +48,0 @@ });

@@ -11,3 +11,3 @@ "use strict";

// Do nothing if Response is already set
if (c.res && c.res._finalized) {
if (c.res && c.finalized) {
await next();

@@ -14,0 +14,0 @@ }

@@ -14,8 +14,8 @@ import type { Result } from '../../router';

name: string;
handlerSetCache: Record<string, HandlerSet<T>[]>;
constructor(method?: string, handler?: T, children?: Record<string, Node<T>>);
insert(method: string, path: string, handler: T): Node<T>;
private getHandlerSets;
private next;
search(method: string, path: string): Result<T> | null;
}
export {};

@@ -31,2 +31,3 @@ "use strict";

this.patterns = [];
this.handlerSetCache = {};
}

@@ -86,69 +87,22 @@ insert(method, path, handler) {

getHandlerSets(node, method, wildcard) {
const handlerSets = [];
node.methods.map((m) => {
const handlerSet = m[method] || m[router_1.METHOD_NAME_ALL];
if (handlerSet !== undefined) {
const hs = Object.assign({}, handlerSet);
if (wildcard) {
hs.score = handlerSet.score - 1;
}
handlerSets.push(hs);
return;
}
});
return handlerSets;
}
next(node, part, method, isLast) {
const handlerSets = [];
const nextNodes = [];
const params = {};
for (let j = 0, len = node.patterns.length; j < len; j++) {
const pattern = node.patterns[j];
// Wildcard
// '/hello/*/foo' => match /hello/bar/foo
if (pattern === '*') {
const astNode = node.children['*'];
if (astNode) {
handlerSets.push(...this.getHandlerSets(astNode, method));
nextNodes.push(astNode);
}
}
if (part === '')
continue;
// Named match
// `/posts/:id` => match /posts/123
const [key, name, matcher] = pattern;
if (matcher === true || (matcher instanceof RegExp && matcher.test(part))) {
if (typeof key === 'string') {
if (isLast === true) {
handlerSets.push(...this.getHandlerSets(node.children[key], method));
var _a, _b;
return ((_a = node.handlerSetCache)[_b = `${method}:${wildcard ? '1' : '0'}`] || (_a[_b] = (() => {
const handlerSets = [];
node.methods.map((m) => {
const handlerSet = m[method] || m[router_1.METHOD_NAME_ALL];
if (handlerSet !== undefined) {
const hs = { ...handlerSet };
if (wildcard) {
hs.score = handlerSet.score - 1;
}
nextNodes.push(node.children[key]);
handlerSets.push(hs);
return;
}
if (typeof name === 'string') {
params[name] = part;
}
}
}
const nextNode = node.children[part];
if (nextNode) {
if (isLast === true) {
// '/hello/*' => match '/hello'
if (nextNode.children['*']) {
handlerSets.push(...this.getHandlerSets(nextNode.children['*'], method, true));
}
handlerSets.push(...this.getHandlerSets(nextNode, method));
}
nextNodes.push(nextNode);
}
const next = {
nodes: nextNodes,
handlerSets: handlerSets,
params: params,
};
return next;
});
return handlerSets;
})()));
}
search(method, path) {
const handlerSets = [];
let params = {};
const params = {};
// eslint-disable-next-line @typescript-eslint/no-this-alias

@@ -159,13 +113,47 @@ const curNode = this;

for (let i = 0, len = parts.length; i < len; i++) {
const p = parts[i];
const part = parts[i];
const isLast = i === len - 1;
const tempNodes = [];
for (let j = 0, len2 = curNodes.length; j < len2; j++) {
const res = this.next(curNodes[j], p, method, isLast);
if (res.nodes.length === 0) {
continue;
const node = curNodes[j];
for (let k = 0, len3 = node.patterns.length; k < len3; k++) {
const pattern = node.patterns[k];
// Wildcard
// '/hello/*/foo' => match /hello/bar/foo
if (pattern === '*') {
const astNode = node.children['*'];
if (astNode) {
handlerSets.push(...this.getHandlerSets(astNode, method));
tempNodes.push(astNode);
}
continue;
}
if (part === '')
continue;
// Named match
// `/posts/:id` => match /posts/123
const [key, name, matcher] = pattern;
if (matcher === true || (matcher instanceof RegExp && matcher.test(part))) {
if (typeof key === 'string') {
if (isLast === true) {
handlerSets.push(...this.getHandlerSets(node.children[key], method));
}
tempNodes.push(node.children[key]);
}
if (typeof name === 'string') {
params[name] = part;
}
}
}
handlerSets.push(...res.handlerSets);
params = Object.assign(params, res.params);
tempNodes.push(...res.nodes);
const nextNode = node.children[part];
if (nextNode) {
if (isLast === true) {
// '/hello/*' => match '/hello'
if (nextNode.children['*']) {
handlerSets.push(...this.getHandlerSets(nextNode.children['*'], method, true));
}
handlerSets.push(...this.getHandlerSets(nextNode, method));
}
tempNodes.push(nextNode);
}
}

@@ -172,0 +160,0 @@ curNodes = tempNodes;

@@ -13,3 +13,3 @@ "use strict";

}
catch (_a) { }
catch { }
try {

@@ -34,3 +34,3 @@ return Buffer.from(str).toString('base64');

}
catch (_a) { }
catch { }
try {

@@ -37,0 +37,0 @@ return Buffer.from(str, 'base64').toString();

export declare type Pattern = readonly [string, string, RegExp | true] | '*';
export declare const splitPath: (path: string) => string[];
export declare const getPattern: (label: string) => Pattern | null;
declare type Params = {
strict: boolean;
};
export declare const getPathFromURL: (url: string, params?: Params) => string;
export declare const getPathFromURL: (url: string, strict?: boolean) => string;
export declare const isAbsoluteURL: (url: string) => boolean;
export declare const mergePath: (...paths: string[]) => string;
export {};

@@ -37,13 +37,11 @@ "use strict";

exports.getPattern = getPattern;
const getPathFromURL = (url, params = { strict: true }) => {
const getPathFromURL = (url, strict = true) => {
const queryIndex = url.indexOf('?');
const result = url.substring(url.indexOf('/', 8), queryIndex === -1 ? url.length : queryIndex);
// if strict routing is false => `/hello/hey/` and `/hello/hey` are treated the same
// default is true
if (params.strict === false && url.endsWith('/')) {
url = url.slice(0, -1);
if (strict === false && result.endsWith('/')) {
return result.slice(0, -1);
}
const match = url.match(URL_REGEXP);
if (match) {
return match[1];
}
return '';
return result;
};

@@ -50,0 +48,0 @@ exports.getPathFromURL = getPathFromURL;

{
"name": "hono",
"version": "1.4.2",
"version": "1.4.3",
"description": "Ultrafast web framework for Cloudflare Workers.",

@@ -136,3 +136,3 @@ "main": "dist/index.js",

"jest": "27.5.1",
"jest-environment-miniflare": "^2.4.0",
"jest-environment-miniflare": "^2.5.0",
"mustache": "^4.2.0",

@@ -139,0 +139,0 @@ "prettier": "^2.6.2",

@@ -41,9 +41,9 @@ <div align="center">

```plain
hono - trie-router(default) x 724,143 ops/sec ±3.63% (80 runs sampled)
hono - regexp-router x 1,236,810 ops/sec ±6.77% (72 runs sampled)
itty-router x 161,786 ops/sec ±2.28% (97 runs sampled)
sunder x 312,262 ops/sec ±2.59% (85 runs sampled)
worktop x 224,979 ops/sec ±1.13% (96 runs sampled)
hono - trie-router(default) x 389,510 ops/sec ±3.16% (85 runs sampled)
hono - regexp-router x 452,290 ops/sec ±2.64% (84 runs sampled)
itty-router x 206,013 ops/sec ±3.39% (90 runs sampled)
sunder x 323,131 ops/sec ±0.75% (97 runs sampled)
worktop x 191,218 ops/sec ±2.70% (91 runs sampled)
Fastest is hono - regexp-router
✨ Done in 95.05s.
✨ Done in 43.56s.
```

@@ -102,3 +102,3 @@

v1.get('/posts', (c) => {
return c.text('list pots')
return c.text('list posts')
})

@@ -649,3 +649,3 @@ .post(basicAuth({ username, password }), (c) => {

To generate a project skelton, run this command.
To generate a project skeleton, run this command.

@@ -652,0 +652,0 @@ ```

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc