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

hono

Package Overview
Dependencies
Maintainers
1
Versions
338
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 0.4.0 to 0.4.1

dist/router.d.ts

2

dist/compose.d.ts

@@ -1,1 +0,1 @@

export declare const compose: <T>(middleware: Function[]) => (context: T, next?: Function) => Promise<void | object>;
export declare const compose: <T>(middleware: Function[], onError?: Function) => (context: T, next?: Function) => Promise<void | object>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compose = void 0;
const context_1 = require("./context");
// Based on the code in the MIT licensed `koa-compose` package.
const compose = (middleware) => {
const compose = (middleware, onError) => {
const errors = [];

@@ -22,3 +23,8 @@ return function (context, next) {

errors.push(e);
throw errors[0]; // XXX
if (onError && context instanceof context_1.Context) {
context.res = onError(errors[0], context);
}
else {
throw errors[0];
}
});

@@ -25,0 +31,0 @@ }

@@ -15,2 +15,3 @@ /// <reference types="@cloudflare/workers-types" />

render: (template: string, params?: object, options?: object) => Promise<Response>;
notFound: () => Response;
constructor(req: Request<RequestParamKeyType>, opts?: {

@@ -17,0 +18,0 @@ res: Response;

/// <reference types="@cloudflare/workers-types" />
import type { Result } from './node';
import { Node } from './node';
import { Context } from './context';
import type { Env } from './context';
import type { Result } from './router';
import { Router } from './router';
declare global {

@@ -19,3 +20,3 @@ interface Request<ParamKeyType = string> {

declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>;
export declare class Router<T> {
export declare class TrieRouter<T> extends Router<T> {
node: Node<T>;

@@ -26,23 +27,23 @@ constructor();

}
declare type Init = {
strict?: boolean;
};
export declare class Hono {
router: Router<Handler[]>;
routerClass: {
new (): Router<any>;
};
strict: boolean;
router: Router<Handler>;
middlewareRouters: Router<MiddlewareHandler>[];
tempPath: string;
strict: boolean;
constructor(init?: Init);
get<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
post<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
put<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
head<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
delete<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
options<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
patch<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
all<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
constructor(init?: Partial<Pick<Hono, 'routerClass' | 'strict'>>);
get<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
post<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
put<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
head<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
delete<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
options<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
patch<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
all<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
route(path: string): Hono;
use(path: string, middleware: MiddlewareHandler): void;
addRoute(method: string, path: string, ...args: Handler[]): Hono;
matchRoute(method: string, path: string): Promise<Result<Handler[]>>;
addRoute(method: string, path: string, handler: Handler): Hono;
matchRoute(method: string, path: string): Promise<Result<Handler>>;
dispatch(request: Request, env?: Env, event?: FetchEvent): Promise<Response>;

@@ -52,5 +53,5 @@ handleEvent(event: FetchEvent): Promise<Response>;

fire(): void;
onError(err: Error): Response;
notFound(): Response;
onError(err: Error, c: Context): Response;
notFound(c: Context): Response;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Hono = exports.Router = void 0;
exports.Hono = exports.TrieRouter = void 0;
const node_1 = require("./node");

@@ -8,4 +8,6 @@ const compose_1 = require("./compose");

const context_1 = require("./context");
class Router {
const router_1 = require("./router");
class TrieRouter extends router_1.Router {
constructor() {
super();
this.node = new node_1.Node();

@@ -20,33 +22,35 @@ }

}
exports.Router = Router;
exports.TrieRouter = TrieRouter;
class Hono {
constructor(init = { strict: true }) {
this.router = new Router();
constructor(init = {}) {
this.routerClass = TrieRouter;
this.strict = true; // strict routing - default is true
Object.assign(this, init);
this.router = new this.routerClass();
this.middlewareRouters = [];
this.tempPath = null;
this.strict = init.strict; // strict routing - default is true
}
get(path, ...args) {
return this.addRoute('get', path, ...args);
get(path, handler) {
return this.addRoute('get', path, handler);
}
post(path, ...args) {
return this.addRoute('post', path, ...args);
post(path, handler) {
return this.addRoute('post', path, handler);
}
put(path, ...args) {
return this.addRoute('put', path, ...args);
put(path, handler) {
return this.addRoute('put', path, handler);
}
head(path, ...args) {
return this.addRoute('head', path, ...args);
head(path, handler) {
return this.addRoute('head', path, handler);
}
delete(path, ...args) {
return this.addRoute('delete', path, ...args);
delete(path, handler) {
return this.addRoute('delete', path, handler);
}
options(path, ...args) {
return this.addRoute('options', path, ...args);
options(path, handler) {
return this.addRoute('options', path, handler);
}
patch(path, ...args) {
return this.addRoute('patch', path, ...args);
patch(path, handler) {
return this.addRoute('patch', path, handler);
}
all(path, ...args) {
return this.addRoute('all', path, ...args);
all(path, handler) {
return this.addRoute('all', path, handler);
}

@@ -63,8 +67,8 @@ route(path) {

}
const router = new Router();
router.add(node_1.METHOD_NAME_OF_ALL, path, middleware);
const router = new this.routerClass();
router.add(router_1.METHOD_NAME_OF_ALL, path, middleware);
this.middlewareRouters.push(router);
}
// addRoute('get', '/', handler)
addRoute(method, path, ...args) {
addRoute(method, path, handler) {
method = method.toUpperCase();

@@ -74,3 +78,3 @@ if (this.tempPath) {

}
this.router.add(method, path, args);
this.router.add(method, path, handler);
return this;

@@ -98,6 +102,6 @@ }

};
const handler = result ? result.handler[0] : this.notFound; // XXX
const handler = result ? result.handler : this.notFound;
const middleware = [];
for (const mr of this.middlewareRouters) {
const mwResult = mr.match(node_1.METHOD_NAME_OF_ALL, path);
const mwResult = mr.match(router_1.METHOD_NAME_OF_ALL, path);
if (mwResult) {

@@ -116,4 +120,5 @@ middleware.push(mwResult.handler);

middleware.push(wrappedHandler);
const composed = (0, compose_1.compose)(middleware);
const composed = (0, compose_1.compose)(middleware, this.onError);
const c = new context_1.Context(request, { env: env, event: event, res: null });
c.notFound = () => this.notFound(c);
await composed(c);

@@ -123,10 +128,6 @@ return c.res;

async handleEvent(event) {
return this.dispatch(event.request, {}, event).catch((err) => {
return this.onError(err);
});
return this.dispatch(event.request, {}, event);
}
async fetch(request, env, event) {
return this.dispatch(request, env, event).catch((err) => {
return this.onError(err);
});
return this.dispatch(request, env, event);
}

@@ -138,22 +139,14 @@ fire() {

}
onError(err) {
console.error(`${err}`);
// Default error Response
onError(err, c) {
console.error(`${err.message}`);
const message = 'Internal Server Error';
return new Response(message, {
status: 500,
headers: {
'Content-Length': message.length.toString(),
},
});
return c.text(message, 500);
}
notFound() {
// Default 404 not found Response
notFound(c) {
const message = 'Not Found';
return new Response(message, {
status: 404,
headers: {
'Content-Length': message.length.toString(),
},
});
return c.text(message, 404);
}
}
exports.Hono = Hono;

@@ -15,5 +15,3 @@ "use strict";

const delta = Date.now() - start;
return humanize([
delta < 10000 ? delta + 'ms' : Math.round(delta / 1000) + 's',
]);
return humanize([delta < 10000 ? delta + 'ms' : Math.round(delta / 1000) + 's']);
};

@@ -49,15 +47,5 @@ const LogPrefix = {

const start = Date.now();
try {
await next();
}
catch (e) {
log(fn, LogPrefix.Error, method, path, c.res.status || 500, time(start));
throw e;
}
await next();
const len = parseFloat(c.res.headers.get('Content-Length'));
const contentLength = isNaN(len)
? '0'
: len < 1024
? `${len}b`
: `${len / 1024}kB`;
const contentLength = isNaN(len) ? '0' : len < 1024 ? `${len}b` : `${len / 1024}kB`;
log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start), contentLength);

@@ -64,0 +52,0 @@ };

@@ -12,3 +12,7 @@ "use strict";

const url = new URL(c.req.url);
const path = (0, cloudflare_1.getKVFilePath)({ filename: url.pathname, root: opt.root, defaultDocument: DEFAULT_DOCUMENT });
const path = (0, cloudflare_1.getKVFilePath)({
filename: url.pathname,
root: opt.root,
defaultDocument: DEFAULT_DOCUMENT,
});
const content = await (0, cloudflare_1.getContentFromKVAsset)(path);

@@ -15,0 +19,0 @@ if (content) {

@@ -1,7 +0,3 @@

export declare const METHOD_NAME_OF_ALL = "ALL";
export declare class Result<T> {
handler: T;
params: Record<string, string>;
constructor(handler: T, params: Record<string, string>);
}
import type { Pattern } from './utils/url';
import { Result } from './router';
export declare class Node<T> {

@@ -12,2 +8,3 @@ method: Record<string, T>;

middlewares: [];
patterns: Pattern[];
constructor(method?: string, handler?: T, children?: Record<string, Node<T>>);

@@ -14,0 +11,0 @@ insert(method: string, path: string, handler: T): Node<T>;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Node = exports.Result = exports.METHOD_NAME_OF_ALL = void 0;
exports.Node = void 0;
const url_1 = require("./utils/url");
exports.METHOD_NAME_OF_ALL = 'ALL';
class Result {
constructor(handler, params) {
this.handler = handler;
this.params = params;
}
}
exports.Result = Result;
const router_1 = require("./router");
const noRoute = () => {

@@ -24,2 +17,3 @@ return null;

this.middlewares = [];
this.patterns = [];
}

@@ -37,2 +31,6 @@ insert(method, path, handler) {

curNode.children[p] = new Node();
const pattern = (0, url_1.getPattern)(p);
if (pattern) {
curNode.patterns.push(pattern);
}
curNode = curNode.children[p];

@@ -69,8 +67,7 @@ }

let isParamMatch = false;
const keys = Object.keys(curNode.children);
for (let j = 0, len = keys.length; j < len; j++) {
const key = keys[j];
for (let j = 0, len = curNode.patterns.length; j < len; j++) {
const pattern = curNode.patterns[j];
// Wildcard
// '/hello/*/foo' => match /hello/bar/foo
if (key === '*') {
if (pattern === '*') {
curNode = curNode.children['*'];

@@ -80,15 +77,11 @@ isWildcard = true;

}
const pattern = (0, url_1.getPattern)(key);
// Named match
if (pattern) {
const match = p.match(new RegExp(pattern[1]));
if (match) {
const k = pattern[0];
params[k] = match[1];
curNode = curNode.children[key];
isParamMatch = true;
break;
}
return noRoute();
const [key, name, matcher] = pattern;
if (p !== '' && (matcher === true || matcher.test(p))) {
params[name] = p;
curNode = curNode.children[key];
isParamMatch = true;
break;
}
return noRoute();
}

@@ -102,9 +95,9 @@ if (isWildcard && i === len - 1) {

}
const handler = curNode.method[exports.METHOD_NAME_OF_ALL] || curNode.method[method];
const handler = curNode.method[router_1.METHOD_NAME_OF_ALL] || curNode.method[method];
if (!handler) {
return noRoute();
}
return new Result(handler, params);
return new router_1.Result(handler, params);
}
}
exports.Node = Node;

@@ -49,3 +49,5 @@ "use strict";

}, new TextEncoder().encode(String(a)));
const hash = Array.prototype.map.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2)).join('');
const hash = Array.prototype.map
.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2))
.join('');
return hash;

@@ -52,0 +54,0 @@ }

@@ -0,3 +1,4 @@

export declare type Pattern = readonly [string, string, RegExp | true] | '*';
export declare const splitPath: (path: string) => string[];
export declare const getPattern: (label: string) => string[] | null;
export declare const getPattern: (label: string) => Pattern | null;
declare type Params = {

@@ -4,0 +5,0 @@ strict: boolean;

@@ -13,14 +13,22 @@ "use strict";

exports.splitPath = splitPath;
const patternCache = {};
const getPattern = (label) => {
// * => wildcard
// :id{[0-9]+} => ([0-9]+)
// :id => (.+)
//const name = ''
if (label === '*') {
return '*';
}
const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
if (match) {
if (match[2]) {
return [match[1], '(' + match[2] + ')'];
if (!patternCache[label]) {
if (match[2]) {
patternCache[label] = [label, match[1], new RegExp('^' + match[2] + '$')];
}
else {
patternCache[label] = [label, match[1], true];
}
}
else {
return [match[1], '(.+)'];
}
return patternCache[label];
}

@@ -27,0 +35,0 @@ return null;

{
"name": "hono",
"version": "0.4.0",
"version": "0.4.1",
"description": "[炎] Ultrafast web framework for Cloudflare Workers.",

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

"test": "jest",
"lint": "eslint --ext js,ts src .eslintrc.js test",
"lint": "eslint --ext js,ts src .eslintrc.js test && prettier --check src",
"build": "rimraf dist && tsc",

@@ -86,3 +86,3 @@ "watch": "tsc -w",

"eslint": "^7.26.0",
"eslint-config-prettier": "^8.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-define-config": "^1.2.1",

@@ -94,3 +94,2 @@ "eslint-import-resolver-typescript": "^2.0.0",

"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"form-data": "^4.0.0",

@@ -100,2 +99,3 @@ "jest": "^27.4.5",

"mustache": "^4.2.0",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",

@@ -102,0 +102,0 @@ "ts-jest": "^27.1.2",

@@ -26,8 +26,8 @@ # Hono

```plain
hono x 708,671 ops/sec ±2.58% (58 runs sampled)
itty-router x 159,610 ops/sec ±2.86% (87 runs sampled)
sunder x 322,846 ops/sec ±2.24% (86 runs sampled)
worktop x 223,625 ops/sec ±2.01% (95 runs sampled)
hono x 779,197 ops/sec ±6.55% (78 runs sampled)
itty-router x 161,813 ops/sec ±3.87% (87 runs sampled)
sunder x 334,096 ops/sec ±1.33% (93 runs sampled)
worktop x 212,661 ops/sec ±4.40% (81 runs sampled)
Fastest is hono
✨ Done in 57.83s.
✨ Done in 58.29s.
```

@@ -125,12 +125,2 @@

### Custom 404 Response
You can customize 404 Not Found response:
```js
app.get('*', (c) => {
return c.text('Custom 404 Error', 404)
})
```
### no strict

@@ -148,3 +138,3 @@

## async/await
### async/await

@@ -197,15 +187,2 @@ ```js

### Handling Error
```js
app.use('*', async (c, next) => {
try {
await next()
} catch (err) {
console.error(`${err}`)
c.res = c.text('Custom Error Message', { status: 500 })
}
})
```
## Context

@@ -298,2 +275,12 @@

### c.notFound()
Return the default `404 Not Found` Response:
```js
app.get('/notfound', (c) => {
return c.notFound()
})
```
### c.redirect()

@@ -340,2 +327,22 @@

## Not Found
If you want, you can set the default `404 Not Found` Response:
```js
app.notFound = (c) => {
return c.text('This is default 404 Not Found', 404)
}
```
## Error handling
You can handle errors in your way:
```js
app.onError = (err, c) => {
return c.text(`This is error message: ${err.mssage}`, 500)
}
```
## fire

@@ -342,0 +349,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