Comparing version 1.0.0 to 1.1.0
@@ -8,2 +8,3 @@ /// <reference types="@cloudflare/workers-types" /> | ||
export declare class Context<RequestParamKeyType = string> { | ||
#private; | ||
req: Request<RequestParamKeyType>; | ||
@@ -13,7 +14,2 @@ res: Response; | ||
event: FetchEvent; | ||
private _headers; | ||
private _status; | ||
private _statusText; | ||
private _pretty; | ||
private _prettySpace; | ||
render: (template: string, params?: object, options?: object) => Promise<Response>; | ||
@@ -20,0 +16,0 @@ notFound: () => Response | Promise<Response>; |
"use strict"; | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var _Context_headers, _Context_status, _Context_statusText, _Context_pretty, _Context_prettySpace; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -8,6 +20,10 @@ exports.Context = void 0; | ||
constructor(req, opts) { | ||
this._prettySpace = 2; | ||
_Context_headers.set(this, void 0); | ||
_Context_status.set(this, void 0); | ||
_Context_statusText.set(this, void 0); | ||
_Context_pretty.set(this, void 0); | ||
_Context_prettySpace.set(this, 2); | ||
this.req = this.initRequest(req); | ||
Object.assign(this, opts); | ||
this._headers = {}; | ||
__classPrivateFieldSet(this, _Context_headers, {}, "f"); | ||
} | ||
@@ -28,3 +44,3 @@ initRequest(req) { | ||
} | ||
this._headers[name] = value; | ||
__classPrivateFieldGet(this, _Context_headers, "f")[name] = value; | ||
} | ||
@@ -36,29 +52,17 @@ status(status) { | ||
} | ||
this._status = status; | ||
this._statusText = (0, http_status_1.getStatusText)(status); | ||
__classPrivateFieldSet(this, _Context_status, status, "f"); | ||
__classPrivateFieldSet(this, _Context_statusText, (0, http_status_1.getStatusText)(status), "f"); | ||
} | ||
pretty(prettyJSON, space = 2) { | ||
this._pretty = prettyJSON; | ||
this._prettySpace = space; | ||
__classPrivateFieldSet(this, _Context_pretty, prettyJSON, "f"); | ||
__classPrivateFieldSet(this, _Context_prettySpace, space, "f"); | ||
} | ||
newResponse(data, init = {}) { | ||
init.status = init.status || this._status || 200; | ||
init.status = init.status || __classPrivateFieldGet(this, _Context_status, "f") || 200; | ||
init.statusText = | ||
init.statusText || this._statusText || (0, http_status_1.getStatusText)(init.status); | ||
init.headers = Object.assign(Object.assign({}, this._headers), init.headers); | ||
// Content-Length | ||
let length = 0; | ||
if (data) { | ||
if (data instanceof ArrayBuffer) { | ||
length = data.byteLength; | ||
} | ||
else if (typeof data == 'string') { | ||
const Encoder = new TextEncoder(); | ||
length = Encoder.encode(data).byteLength || 0; | ||
} | ||
} | ||
init.headers = Object.assign(Object.assign({}, init.headers), { 'Content-Length': length.toString() }); | ||
init.statusText || __classPrivateFieldGet(this, _Context_statusText, "f") || (0, http_status_1.getStatusText)(init.status); | ||
init.headers = Object.assign(Object.assign({}, __classPrivateFieldGet(this, _Context_headers, "f")), init.headers); | ||
return new Response(data, init); | ||
} | ||
body(data, status = this._status, headers = this._headers) { | ||
body(data, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = __classPrivateFieldGet(this, _Context_headers, "f")) { | ||
return this.newResponse(data, { | ||
@@ -69,3 +73,3 @@ status: status, | ||
} | ||
text(text, status = this._status, headers = {}) { | ||
text(text, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = {}) { | ||
if (typeof text !== 'string') { | ||
@@ -77,8 +81,8 @@ throw new TypeError('text method arg must be a string!'); | ||
} | ||
json(object, status = this._status, headers = {}) { | ||
json(object, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = {}) { | ||
if (typeof object !== 'object') { | ||
throw new TypeError('json method arg must be an object!'); | ||
} | ||
const body = this._pretty | ||
? JSON.stringify(object, null, this._prettySpace) | ||
const body = __classPrivateFieldGet(this, _Context_pretty, "f") | ||
? JSON.stringify(object, null, __classPrivateFieldGet(this, _Context_prettySpace, "f")) | ||
: JSON.stringify(object); | ||
@@ -88,3 +92,3 @@ headers['Content-Type'] || (headers['Content-Type'] = 'application/json; charset=UTF-8'); | ||
} | ||
html(html, status = this._status, headers = {}) { | ||
html(html, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = {}) { | ||
if (typeof html !== 'string') { | ||
@@ -114,1 +118,2 @@ throw new TypeError('html method arg must be a string!'); | ||
exports.Context = Context; | ||
_Context_headers = new WeakMap(), _Context_status = new WeakMap(), _Context_statusText = new WeakMap(), _Context_pretty = new WeakMap(), _Context_prettySpace = new WeakMap(); |
@@ -10,6 +10,5 @@ /// <reference types="@cloudflare/workers-types" /> | ||
header: (name: string) => string; | ||
parsedBody: any; | ||
} | ||
} | ||
export declare type Handler<RequestParamKeyType = string> = (c: Context<RequestParamKeyType | string>, next?: Next) => Response | Promise<Response>; | ||
export declare type Handler<RequestParamKeyType = string> = (c: Context<RequestParamKeyType>, next?: Next) => Response | Promise<Response>; | ||
export declare type MiddlewareHandler = (c: Context, next: Next) => Promise<void>; | ||
@@ -22,15 +21,18 @@ export declare type NotFoundHandler = (c: Context) => Response | Promise<Response>; | ||
declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>; | ||
declare const Hono_base: new () => { | ||
delete: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono; | ||
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; | ||
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; | ||
} & { | ||
methods: ["get", "post", "put", "delete", "head", "options", "patch", "all"]; | ||
interface HandlerInterface<T extends string> { | ||
<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono<Path>; | ||
<Path extends T>(handler: Handler<ParamKeys<T>>): Hono<Path>; | ||
} | ||
declare const Hono_base: new <T extends string>() => { | ||
delete: HandlerInterface<T>; | ||
get: HandlerInterface<T>; | ||
post: HandlerInterface<T>; | ||
put: HandlerInterface<T>; | ||
head: HandlerInterface<T>; | ||
options: HandlerInterface<T>; | ||
patch: HandlerInterface<T>; | ||
all: HandlerInterface<T>; | ||
}; | ||
export declare class Hono extends Hono_base { | ||
export declare class Hono<P extends string> extends Hono_base<P> { | ||
#private; | ||
readonly routerClass: { | ||
@@ -40,12 +42,11 @@ new (): Router<any>; | ||
readonly strict: boolean; | ||
private router; | ||
private middlewareRouters; | ||
private tempPath; | ||
constructor(init?: Partial<Pick<Hono, 'routerClass' | 'strict'>>); | ||
private path; | ||
constructor(init?: Partial<Pick<Hono<P>, 'routerClass' | 'strict'>>); | ||
private notFoundHandler; | ||
private errorHandler; | ||
route(path: string): Hono; | ||
use(path: string, middleware: MiddlewareHandler): void; | ||
onError(handler: ErrorHandler): Hono; | ||
notFound(handler: NotFoundHandler): Hono; | ||
route(path: string): Hono<P>; | ||
use(path: string, middleware: MiddlewareHandler): Hono<P>; | ||
use(middleware: MiddlewareHandler): Hono<P>; | ||
onError(handler: ErrorHandler): Hono<P>; | ||
notFound(handler: NotFoundHandler): Hono<P>; | ||
private addRoute; | ||
@@ -52,0 +53,0 @@ private matchRoute; |
"use strict"; | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var _Hono_router, _Hono_middlewareRouters, _Hono_tempPath; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -9,10 +21,8 @@ exports.Hono = void 0; | ||
const url_1 = require("./utils/url"); | ||
function defineDynamicClass(...methods) { | ||
const methods = ['get', 'post', 'put', 'delete', 'head', 'options', 'patch', 'all']; | ||
function defineDynamicClass() { | ||
return class { | ||
get methods() { | ||
return methods; | ||
} | ||
}; | ||
} | ||
class Hono extends defineDynamicClass('get', 'post', 'put', 'delete', 'head', 'options', 'patch', 'all') { | ||
class Hono extends defineDynamicClass() { | ||
constructor(init = {}) { | ||
@@ -22,2 +32,5 @@ super(); | ||
this.strict = true; // strict routing - default is true | ||
_Hono_router.set(this, void 0); | ||
_Hono_middlewareRouters.set(this, void 0); | ||
_Hono_tempPath.set(this, void 0); | ||
this.notFoundHandler = (c) => { | ||
@@ -32,25 +45,38 @@ const message = '404 Not Found'; | ||
}; | ||
this.methods.map((method) => { | ||
this[method] = (path, handler) => { | ||
return this.addRoute(method, path, handler); | ||
methods.map((method) => { | ||
this[method] = (arg1, arg2) => { | ||
if (typeof arg1 === 'string') { | ||
this.path = arg1; | ||
return this.addRoute(method, this.path, arg2); | ||
} | ||
return this.addRoute(method, this.path, arg1); | ||
}; | ||
}); | ||
Object.assign(this, init); | ||
this.router = new this.routerClass(); | ||
this.middlewareRouters = []; | ||
this.tempPath = null; | ||
__classPrivateFieldSet(this, _Hono_router, new this.routerClass(), "f"); | ||
__classPrivateFieldSet(this, _Hono_middlewareRouters, [], "f"); | ||
__classPrivateFieldSet(this, _Hono_tempPath, null, "f"); | ||
} | ||
route(path) { | ||
const newHono = new Hono(); | ||
newHono.tempPath = path; | ||
newHono.router = this.router; | ||
__classPrivateFieldSet(newHono, _Hono_tempPath, path, "f"); | ||
__classPrivateFieldSet(newHono, _Hono_router, __classPrivateFieldGet(this, _Hono_router, "f"), "f"); | ||
return newHono; | ||
} | ||
use(path, middleware) { | ||
if (middleware.constructor.name !== 'AsyncFunction') { | ||
use(arg1, arg2) { | ||
let handler; | ||
if (typeof arg1 === 'string') { | ||
this.path = arg1; | ||
handler = arg2; | ||
} | ||
else { | ||
handler = arg1; | ||
} | ||
if (handler.constructor.name !== 'AsyncFunction') { | ||
throw new TypeError('middleware must be a async function!'); | ||
} | ||
const router = new this.routerClass(); | ||
router.add(router_1.METHOD_NAME_OF_ALL, path, middleware); | ||
this.middlewareRouters.push(router); | ||
router.add(router_1.METHOD_NAME_OF_ALL, this.path, handler); | ||
__classPrivateFieldGet(this, _Hono_middlewareRouters, "f").push(router); | ||
return this; | ||
} | ||
@@ -65,13 +91,12 @@ onError(handler) { | ||
} | ||
// addRoute('get', '/', handler) | ||
addRoute(method, path, handler) { | ||
method = method.toUpperCase(); | ||
if (this.tempPath) { | ||
path = (0, url_1.mergePath)(this.tempPath, path); | ||
if (__classPrivateFieldGet(this, _Hono_tempPath, "f")) { | ||
path = (0, url_1.mergePath)(__classPrivateFieldGet(this, _Hono_tempPath, "f"), path); | ||
} | ||
this.router.add(method, path, handler); | ||
__classPrivateFieldGet(this, _Hono_router, "f").add(method, path, handler); | ||
return this; | ||
} | ||
async matchRoute(method, path) { | ||
return this.router.match(method, path); | ||
return __classPrivateFieldGet(this, _Hono_router, "f").match(method, path); | ||
} | ||
@@ -89,3 +114,3 @@ async dispatch(request, env, event) { | ||
const middleware = []; | ||
for (const mr of this.middlewareRouters) { | ||
for (const mr of __classPrivateFieldGet(this, _Hono_middlewareRouters, "f")) { | ||
const mwResult = mr.match(router_1.METHOD_NAME_OF_ALL, path); | ||
@@ -127,1 +152,2 @@ if (mwResult) | ||
exports.Hono = Hono; | ||
_Hono_router = new WeakMap(), _Hono_middlewareRouters = new WeakMap(), _Hono_tempPath = new WeakMap(); |
@@ -5,3 +5,3 @@ "use strict"; | ||
const buffer_1 = require("../../utils/buffer"); | ||
const crypto_1 = require("../../utils/crypto"); | ||
const encode_1 = require("../../utils/encode"); | ||
const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/; | ||
@@ -23,3 +23,3 @@ const USER_PASS_REGEXP = /^([^:]*):(.*)$/; | ||
} | ||
const userPass = USER_PASS_REGEXP.exec((0, crypto_1.decodeBase64)(match[1])); | ||
const userPass = USER_PASS_REGEXP.exec((0, encode_1.decodeBase64)(match[1])); | ||
if (!userPass) { | ||
@@ -26,0 +26,0 @@ return undefined; |
import type { Context } from '../../context'; | ||
import type { Next } from '../../hono'; | ||
declare global { | ||
interface Request { | ||
parsedBody: any; | ||
} | ||
} | ||
export declare const bodyParse: () => (ctx: Context, next: Next) => Promise<void>; |
@@ -13,5 +13,3 @@ import type { Context } from '../../context'; | ||
} | ||
export declare type Cookie = { | ||
[key: string]: string; | ||
}; | ||
export declare type Cookie = Record<string, string>; | ||
export declare type CookieOptions = { | ||
@@ -18,0 +16,0 @@ domain?: string; |
@@ -1,3 +0,1 @@ | ||
export declare function parseBody(req: Request): Promise<{ | ||
[param: string]: unknown; | ||
}>; | ||
export declare function parseBody(req: Request): Promise<Record<string, unknown>>; |
@@ -34,6 +34,6 @@ "use strict"; | ||
}; | ||
function log(fn, prefix, method, path, status, elapsed, contentLength) { | ||
function log(fn, prefix, method, path, status, elapsed) { | ||
const out = prefix === LogPrefix.Incoming | ||
? ` ${prefix} ${method} ${path}` | ||
: ` ${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed} ${contentLength}`; | ||
: ` ${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}`; | ||
fn(out); | ||
@@ -48,7 +48,5 @@ } | ||
await next(); | ||
const len = parseFloat(c.res.headers.get('Content-Length')); | ||
const contentLength = isNaN(len) ? '0' : len < 1024 ? `${len}b` : `${len / 1024}kB`; | ||
log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start), contentLength); | ||
log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start)); | ||
}; | ||
}; | ||
exports.logger = logger; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.mustache = void 0; | ||
const buffer_1 = require("../../utils/buffer"); | ||
const cloudflare_1 = require("../../utils/cloudflare"); | ||
@@ -27,3 +28,3 @@ const EXTENSION = '.mustache'; | ||
} | ||
const content = bufferToString(buffer); | ||
const content = (0, buffer_1.bufferToString)(buffer); | ||
const partialArgs = {}; | ||
@@ -42,3 +43,3 @@ if (options) { | ||
} | ||
partialArgs[key] = bufferToString(partialBuffer); | ||
partialArgs[key] = (0, buffer_1.bufferToString)(partialBuffer); | ||
} | ||
@@ -53,8 +54,1 @@ } | ||
exports.mustache = mustache; | ||
const bufferToString = (buffer) => { | ||
if (buffer instanceof ArrayBuffer) { | ||
const enc = new TextDecoder('utf-8'); | ||
return enc.decode(buffer); | ||
} | ||
return buffer; | ||
}; |
export declare const equal: (a: ArrayBuffer, b: ArrayBuffer) => boolean; | ||
export declare const timingSafeEqual: (a: string | object | boolean, b: string | object | boolean, hashFunction?: Function) => Promise<boolean>; | ||
export declare const bufferToString: (buffer: ArrayBuffer) => string; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.timingSafeEqual = exports.equal = void 0; | ||
exports.bufferToString = exports.timingSafeEqual = exports.equal = void 0; | ||
const crypto_1 = require("../utils/crypto"); | ||
@@ -32,1 +32,9 @@ const equal = (a, b) => { | ||
exports.timingSafeEqual = timingSafeEqual; | ||
const bufferToString = (buffer) => { | ||
if (buffer instanceof ArrayBuffer) { | ||
const enc = new TextDecoder('utf-8'); | ||
return enc.decode(buffer); | ||
} | ||
return buffer; | ||
}; | ||
exports.bufferToString = bufferToString; |
@@ -9,4 +9,2 @@ declare type Algorithm = { | ||
export declare const createHash: (data: Data, algorithm: Algorithm) => Promise<string>; | ||
export declare const encodeBase64: (str: string) => string; | ||
export declare const decodeBase64: (str: string) => string; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.decodeBase64 = exports.encodeBase64 = exports.createHash = exports.sha1 = exports.sha256 = void 0; | ||
exports.createHash = exports.sha1 = exports.sha256 = void 0; | ||
const sha256 = async (data) => { | ||
@@ -37,51 +37,1 @@ const algorithm = { name: 'SHA-256', alias: 'sha256' }; | ||
exports.createHash = createHash; | ||
const encodeBase64 = (str) => { | ||
if (str === null) { | ||
throw new TypeError('1st argument of "encodeBase64" should not be null.'); | ||
} | ||
try { | ||
const encoder = new TextEncoder(); | ||
const bytes = encoder.encode(str); | ||
const length = bytes.byteLength; | ||
let binary = ''; | ||
for (let i = 0; i < length; i++) { | ||
binary += String.fromCharCode(bytes[i]); | ||
} | ||
return btoa(binary); | ||
} | ||
catch (_a) { } | ||
try { | ||
const { Buffer } = require('buffer'); | ||
return Buffer.from(str).toString('base64'); | ||
} | ||
catch (e) { | ||
console.error('If you want to do "encodeBase64", polyfill "buffer" module.'); | ||
throw e; | ||
} | ||
}; | ||
exports.encodeBase64 = encodeBase64; | ||
const decodeBase64 = (str) => { | ||
if (str === null) { | ||
throw new TypeError('1st argument of "decodeBase64" should not be null.'); | ||
} | ||
try { | ||
const text = atob(str); | ||
const length = text.length; | ||
const bytes = new Uint8Array(length); | ||
for (let i = 0; i < length; i++) { | ||
bytes[i] = text.charCodeAt(i); | ||
} | ||
const decoder = new TextDecoder(); | ||
return decoder.decode(bytes); | ||
} | ||
catch (_a) { } | ||
try { | ||
const { Buffer } = require('buffer'); | ||
return Buffer.from(str, 'base64').toString(); | ||
} | ||
catch (e) { | ||
console.error('If you want to do "decodeBase64", polyfill "buffer" module.'); | ||
throw e; | ||
} | ||
}; | ||
exports.decodeBase64 = decodeBase64; |
{ | ||
"name": "hono", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Ultrafast web framework for Cloudflare Workers.", | ||
@@ -26,2 +26,3 @@ "main": "dist/index.js", | ||
"./graphql-server": "./dist/middleware/graphql-server/index.js", | ||
"./jwt": "./dist/middleware/jwt/index.js", | ||
"./logger": "./dist/middleware/logger/index.js", | ||
@@ -56,2 +57,5 @@ "./mustache": "./dist/middleware/mustache/index.js", | ||
], | ||
"jwt": [ | ||
"./dist/middleware/jwt" | ||
], | ||
"logger": [ | ||
@@ -87,5 +91,5 @@ "./dist/middleware/logger" | ||
"type": "git", | ||
"url": "https://github.com/yusukebe/hono.git" | ||
"url": "https://github.com/honojs/hono.git" | ||
}, | ||
"homepage": "https://github.com/yusukebe/hono", | ||
"homepage": "https://github.com/honojs/hono", | ||
"keywords": [ | ||
@@ -104,29 +108,29 @@ "web", | ||
"devDependencies": { | ||
"@cloudflare/workers-types": "^3.3.0", | ||
"@cloudflare/workers-types": "^3.7.1", | ||
"@types/crypto-js": "^4.1.1", | ||
"@types/jest": "^27.4.0", | ||
"@types/jest": "^27.4.1", | ||
"@types/mustache": "^4.1.2", | ||
"@types/node": "^17.0.8", | ||
"@typescript-eslint/eslint-plugin": "^5.9.0", | ||
"@typescript-eslint/parser": "^5.9.0", | ||
"@types/node": "^17.0.29", | ||
"@typescript-eslint/eslint-plugin": "^5.21.0", | ||
"@typescript-eslint/parser": "^5.21.0", | ||
"crypto-js": "^4.1.1", | ||
"eslint": "^7.26.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-define-config": "^1.2.1", | ||
"eslint-import-resolver-typescript": "^2.0.0", | ||
"eslint": "^8.14.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-define-config": "^1.4.0", | ||
"eslint-import-resolver-typescript": "^2.7.1", | ||
"eslint-plugin-eslint-comments": "^3.2.0", | ||
"eslint-plugin-flowtype": "^5.7.2", | ||
"eslint-plugin-import": "^2.20.2", | ||
"eslint-plugin-flowtype": "^8.0.3", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
"form-data": "^4.0.0", | ||
"graphql": "^16.3.0", | ||
"jest": "^27.4.5", | ||
"jest-environment-miniflare": "^2.0.0", | ||
"graphql": "^16.4.0", | ||
"jest": "27.5.1", | ||
"jest-environment-miniflare": "^2.4.0", | ||
"mustache": "^4.2.0", | ||
"prettier": "^2.5.1", | ||
"prettier": "^2.6.2", | ||
"prettier-plugin-md-nocjsp": "^1.2.0", | ||
"rimraf": "^3.0.2", | ||
"ts-jest": "^27.1.2", | ||
"tsc-alias": "^1.6.6", | ||
"typescript": "^4.5.5" | ||
"ts-jest": "^27.1.4", | ||
"tsc-alias": "^1.6.7", | ||
"typescript": "^4.6.3" | ||
}, | ||
@@ -133,0 +137,0 @@ "engines": { |
113
README.md
<div align="center"> | ||
<a href="https://github.com/yusukebe/hono"> | ||
<img src="https://raw.githubusercontent.com/yusukebe/hono/master/docs/images/hono-title.png" width="500" height="auto" alt="Hono"/> | ||
<a href="https://github.com/honojs/hono"> | ||
<img src="https://raw.githubusercontent.com/honojs/hono/master/docs/images/hono-title.png" width="500" height="auto" alt="Hono"/> | ||
</a> | ||
@@ -10,16 +10,16 @@ </div> | ||
<p> | ||
<a href="https://github.com/yusukebe/hono/blob/master/README.md">English</a> | ||
<a href="https://github.com/honojs/hono/blob/master/README.md">English</a> | ||
· | ||
<a href="https://github.com/yusukebe/hono/blob/master/docs/README.ja.md">日本語</a> | ||
<a href="https://github.com/honojs/hono/blob/master/docs/README.ja.md">日本語</a> | ||
</p> | ||
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/yusukebe/hono/ci)](https://github.com/yusukebe/hono/actions) | ||
[![GitHub](https://img.shields.io/github/license/yusukebe/hono)](https://github.com/yusukebe/hono/blob/master/LICENSE) | ||
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/honojs/hono/ci)](https://github.com/honojs/hono/actions) | ||
[![GitHub](https://img.shields.io/github/license/honojs/hono)](https://github.com/honojs/hono/blob/master/LICENSE) | ||
[![npm](https://img.shields.io/npm/v/hono)](https://www.npmjs.com/package/hono) | ||
[![npm](https://img.shields.io/npm/dm/hono)](https://www.npmjs.com/package/hono) | ||
[![npm type definitions](https://img.shields.io/npm/types/hono)](https://www.npmjs.com/package/hono) | ||
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/yusukebe/hono)](https://github.com/yusukebe/hono/pulse) | ||
[![GitHub last commit](https://img.shields.io/github/last-commit/yusukebe/hono)](https://github.com/yusukebe/hono/commits/master) | ||
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/honojs/hono)](https://github.com/honojs/hono/pulse) | ||
[![GitHub last commit](https://img.shields.io/github/last-commit/honojs/hono)](https://github.com/honojs/hono/commits/master) | ||
Hono - _**[炎] means flame🔥 in Japanese**_ - is small, simple, and ultrafast web framework for Cloudflare Workers and Fastly Compute@Edge. | ||
Hono - _**[炎] means flame🔥 in Japanese**_ - is a small, simple, and ultrafast web framework for Cloudflare Workers and Service Worker based serverless such as Fastly Compute@Edge. | ||
@@ -41,3 +41,3 @@ ```js | ||
- **TypeScript** - first-class TypeScript support. | ||
- **Optimized** - for Cloudflare Workers. | ||
- **Optimized** - for Cloudflare Workers and Fastly Compute@Edge. | ||
@@ -63,4 +63,39 @@ ## Benchmark | ||
Now, the named path parameter has types. | ||
## Not only fast | ||
Hono is fast. But not only fast. | ||
### Write Less, do more | ||
Built-in middleware make _"**Write Less, do more**"_ in reality. You can use a lot of middleware without writing code from scratch. Below are examples. | ||
- [Basic Authentication](https://github.com/honojs/hono/tree/master/src/middleware/basic-auth/) | ||
- [Cookie parsing / serializing](https://github.com/honojs/hono/tree/master/src/middleware/cookie/) | ||
- [CORS](https://github.com/honojs/hono/tree/master/src/middleware/cors/) | ||
- [ETag](https://github.com/honojs/hono/tree/master/src/middleware/etag/) | ||
- [GraphQL Server](https://github.com/honojs/hono/tree/master/src/middleware/graphql-server/) | ||
- [JWT Authentication](https://github.com/honojs/hono/tree/master/src/middleware/jwt/) | ||
- [Logger](https://github.com/honojs/hono/tree/master/src/middleware/logger/) | ||
- [Mustache template engine](https://github.com/honojs/hono/tree/master/src/middleware/mustache/) (Only for Cloudflare Workers) | ||
- [JSON pretty printing](https://github.com/honojs/hono/tree/master/src/middleware/pretty-json/) | ||
- [Serving static files](https://github.com/honojs/hono/tree/master/src/middleware/serve-static/) (Only for Cloudflare Workers) | ||
You can enable logger and CORS middleware with just this code. | ||
```js | ||
import { Hono } from 'hono' | ||
import { cors } from 'hono/cors' | ||
import { logger } from 'hono/logger' | ||
const app = new Hono() | ||
app.use('*', cors()).use(logger()) | ||
``` | ||
### Developer Experience | ||
And Hono provides fine _"**Developer Experience**"_. Easy access to Request/Response thanks to the `Context` object. | ||
Above all, Hono is written in TypeScript. So, Hono has _"**Types**"_! | ||
For example, the named path parameters will be literal types. | ||
![Demo](https://user-images.githubusercontent.com/10682/154179671-9e491597-6778-44ac-a8e6-4483d7ad5393.png) | ||
@@ -86,6 +121,6 @@ | ||
- app.**HTTP_METHOD**(path, handler) | ||
- app.**all**(path, handler) | ||
- app.**HTTP_METHOD**(\[path,\] handler) | ||
- app.**all**(\[path,\] handler) | ||
- app.**route**(path) | ||
- app.**use**(path, middleware) | ||
- app.**use**(\[path,\] middleware) | ||
- app.**notFound**(handler) | ||
@@ -134,2 +169,17 @@ - app.**onError**(err, handler) | ||
### Chained route | ||
```js | ||
app | ||
.get('/endpoint', (c) => { | ||
return c.text('GET /endpoint') | ||
}) | ||
.post((c) => { | ||
return c.text('POST /endpoint') | ||
}) | ||
.delete((c) => { | ||
return c.text('DELETE /endpoint') | ||
}) | ||
``` | ||
### Nested route | ||
@@ -183,2 +233,5 @@ | ||
app.use('*', logger()) | ||
// Or you can write: | ||
// app.use('*', poweredBy()).use(logger()) | ||
app.use( | ||
@@ -193,3 +246,3 @@ '/auth/*', | ||
Available built-in middleware is listed on [src/middleware](https://github.com/yusukebe/hono/tree/master/src/middleware). | ||
Available built-in middleware is listed on [src/middleware](https://github.com/honojs/hono/tree/master/src/middleware). | ||
@@ -429,3 +482,3 @@ ### Custom Middleware | ||
1. Use [Wragler 2.0 Beta](https://github.com/cloudflare/wrangler2). | ||
2. Build without webpack 4.x. For example, you can use esbuild. See [the starter template](https://github.com/yusukebe/hono-minimal). | ||
2. Build without webpack 4.x. For example, you can use esbuild. See [the starter template](https://github.com/honojs/hono-minimal). | ||
@@ -500,3 +553,3 @@ --- | ||
You can start making your Cloudflare Workers application with [the starter template](https://github.com/yusukebe/hono-minimal). It is really minimal using TypeScript, esbuild, and Miniflare. | ||
You can start making your Cloudflare Workers application with [the starter template](https://github.com/honojs/hono-minimal). It is really minimal using TypeScript, esbuild, Miniflare, and Jest. | ||
@@ -506,5 +559,9 @@ To generate a project skelton, run this command. | ||
```sh | ||
wrangler generate my-app https://github.com/yusukebe/hono-minimal | ||
wrangler generate my-app https://github.com/honojs/hono-minimal | ||
``` | ||
## Examples | ||
- Hono Examples - <https://github.com/honojs/examples> | ||
## Related projects | ||
@@ -514,13 +571,13 @@ | ||
- express <https://github.com/expressjs/express> | ||
- koa <https://github.com/koajs/koa> | ||
- itty-router <https://github.com/kwhitley/itty-router> | ||
- Sunder <https://github.com/SunderJS/sunder> | ||
- goblin <https://github.com/bmf-san/goblin> | ||
- worktop <https://github.com/lukeed/worktop> | ||
- Router::Boom <https://github.com/tokuhirom/Router-Boom> | ||
- express - <https://github.com/expressjs/express> | ||
- koa - <https://github.com/koajs/koa> | ||
- itty-router - <https://github.com/kwhitley/itty-router> | ||
- Sunder - <https://github.com/SunderJS/sunder> | ||
- goblin - <https://github.com/bmf-san/goblin> | ||
- worktop - <https://github.com/lukeed/worktop> | ||
- Router::Boom - <https://github.com/tokuhirom/Router-Boom> | ||
## Contributing | ||
Contributions Welcome! You can contribute by the following way. | ||
Contributions Welcome! You can contribute in the following ways. | ||
@@ -533,7 +590,5 @@ - Write or fix documents | ||
Let's make Hono together! | ||
## Contributors | ||
Thanks to [all contributors](https://github.com/yusukebe/hono/graphs/contributors)! | ||
Thanks to [all contributors](https://github.com/honojs/hono/graphs/contributors)! | ||
@@ -540,0 +595,0 @@ ## Author |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
104302
75
2309
590