hono 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,7 +35,7 @@ Fastest is hono
35
35
 
36
36
  Below is a demonstration to create an application of Cloudflare Workers with Hono.
37
37
 
38
- ![Demo](https://user-images.githubusercontent.com/10682/151102477-be0f950e-8d23-49c5-b6d8-d8ecb6b7484e.gif)
38
+ ![Demo](https://user-images.githubusercontent.com/10682/151973526-342644f9-71c5-4fee-81f4-64a7558bb192.gif)
39
39
 
40
40
  ## Install
41
41
 
@@ -138,19 +138,24 @@ app.get('/fetch-url', async (c) => {
138
138
  ### Builtin Middleware
139
139
 
140
140
  ```js
141
- import { Hono, Middleware } from 'hono'
141
+ import { Hono } from 'hono'
142
+ import { poweredBy } from 'hono/powered-by'
143
+ import { logger } from 'hono/logger'
144
+ import { basicAuth } from 'hono/basicAuth'
142
145
 
143
- ...
146
+ const app = new Hono()
144
147
 
145
- app.use('*', Middleware.poweredBy())
146
- app.use('*', Middleware.logger())
148
+ app.use('*', poweredBy())
149
+ app.use('*', logger())
147
150
  app.use(
148
151
  '/auth/*',
149
- Middleware.basicAuth({
152
+ basicAuth({
150
153
  username: 'hono',
151
154
  password: 'acoolproject',
152
155
  })
153
156
  )
157
+
158
+ ...
154
159
  ```
155
160
 
156
161
  Available builtin middleware are listed on [src/middleware](https://github.com/yusukebe/hono/tree/master/src/middleware).
@@ -358,6 +363,11 @@ export default {
358
363
  return app.fetch(request, env, event)
359
364
  },
360
365
  }
366
+
367
+ /*
368
+ or just do this:
369
+ export default app
370
+ */
361
371
  ```
362
372
 
363
373
  ## Cloudflare Workers with Hono
package/dist/context.js CHANGED
@@ -24,9 +24,22 @@ class Context {
24
24
  newResponse(data, init = {}) {
25
25
  init.status = init.status || this._status;
26
26
  init.statusText = init.statusText || this._statusText;
27
- const Encoder = new TextEncoder();
28
- const length = data ? data.bytelength || Encoder.encode(data).byteLength : 0;
29
- init.headers = Object.assign(Object.assign(Object.assign({}, this._headers), init.headers), { 'Content-Length': String(length) });
27
+ init.headers = Object.assign(Object.assign({}, this._headers), init.headers);
28
+ // Content-Length
29
+ let length = 0;
30
+ if (data) {
31
+ if (data instanceof ArrayBuffer) {
32
+ length = data.byteLength;
33
+ }
34
+ else if (typeof data == 'string') {
35
+ const Encoder = new TextEncoder();
36
+ length = Encoder.encode(data).byteLength || 0;
37
+ }
38
+ else {
39
+ length = data.bytelength;
40
+ }
41
+ }
42
+ init.headers = Object.assign(Object.assign({}, init.headers), { 'Content-Length': length.toString() });
30
43
  return new Response(data, init);
31
44
  }
32
45
  body(data, status = this._status, headers = this._headers) {
package/dist/hono.d.ts CHANGED
@@ -8,6 +8,7 @@ declare global {
8
8
  param: (key: string) => string;
9
9
  query: (key: string) => string | null;
10
10
  header: (name: string) => string;
11
+ parsedBody: any;
11
12
  }
12
13
  }
13
14
  export declare type Handler = (c: Context, next?: Function) => Response | Promise<Response>;
package/dist/hono.js CHANGED
@@ -48,6 +48,7 @@ class Hono {
48
48
  return this.addRoute('patch', arg, ...args);
49
49
  }
50
50
  /*
51
+ We may implement these HTTP methods:
51
52
  trace
52
53
  copy
53
54
  lock
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export { Hono } from './hono';
2
2
  export type { Handler, MiddlewareHandler } from './hono';
3
- export { Middleware } from './middleware';
4
3
  export { Context } from './context';
5
4
  export type { Env } from './context';
package/dist/index.js CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Context = exports.Middleware = exports.Hono = void 0;
3
+ exports.Context = exports.Hono = void 0;
4
4
  var hono_1 = require("./hono");
5
5
  Object.defineProperty(exports, "Hono", { enumerable: true, get: function () { return hono_1.Hono; } });
6
- var middleware_1 = require("./middleware");
7
- Object.defineProperty(exports, "Middleware", { enumerable: true, get: function () { return middleware_1.Middleware; } });
8
6
  var context_1 = require("./context");
9
7
  Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_1.Context; } });
@@ -1,7 +1,2 @@
1
1
  import type { Context } from '../../context';
2
- declare global {
3
- interface Request {
4
- parsedBody: any;
5
- }
6
- }
7
2
  export declare const bodyParse: () => (ctx: Context, next: Function) => Promise<void>;
@@ -1,51 +1,35 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
- Object.defineProperty(o, "default", { enumerable: true, value: v });
11
- }) : function(o, v) {
12
- o["default"] = v;
13
- });
14
- var __importStar = (this && this.__importStar) || function (mod) {
15
- if (mod && mod.__esModule) return mod;
16
- var result = {};
17
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
- __setModuleDefault(result, mod);
19
- return result;
20
- };
21
2
  Object.defineProperty(exports, "__esModule", { value: true });
22
3
  exports.mustache = void 0;
23
4
  const cloudflare_1 = require("../../utils/cloudflare");
24
5
  const EXTENSION = '.mustache';
25
6
  const mustache = () => {
7
+ let Mustache;
8
+ try {
9
+ Mustache = require('mustache');
10
+ }
11
+ catch (_a) {
12
+ // Do nothing.
13
+ }
26
14
  return async (c, next) => {
27
- let Mustache;
28
- try {
29
- Mustache = await Promise.resolve().then(() => __importStar(require('mustache')));
30
- }
31
- catch (e) {
32
- console.error(`Mustache is not found! ${e}`);
33
- throw new Error(`${e}`);
15
+ if (!Mustache) {
16
+ throw new Error('If you want to use Mustache Middleware, install mustache module.');
34
17
  }
35
18
  c.render = async (filename, view = {}, options) => {
36
- const content = await (0, cloudflare_1.getContentFromKVAsset)(`${filename}${EXTENSION}`);
37
- if (!content) {
38
- throw new Error(`Template "${filename}${EXTENSION}" is not found`);
19
+ const buffer = await (0, cloudflare_1.getContentFromKVAsset)(`${filename}${EXTENSION}`);
20
+ if (!buffer) {
21
+ throw new Error(`Template "${filename}${EXTENSION}" is not found or blank.`);
39
22
  }
23
+ const content = bufferToString(buffer);
40
24
  const partialArgs = {};
41
25
  if (options) {
42
26
  const partials = options;
43
27
  for (const key of Object.keys(partials)) {
44
- const partialContent = await (0, cloudflare_1.getContentFromKVAsset)(`${partials[key]}${EXTENSION}`);
45
- if (!partialContent) {
46
- throw new Error(`Partial Template "${partials[key]}${EXTENSION}" is not found`);
28
+ const partialBuffer = await (0, cloudflare_1.getContentFromKVAsset)(`${partials[key]}${EXTENSION}`);
29
+ if (!partialBuffer) {
30
+ throw new Error(`Partial Template "${partials[key]}${EXTENSION}" is not found or blank.`);
47
31
  }
48
- partialArgs[key] = partialContent;
32
+ partialArgs[key] = bufferToString(partialBuffer);
49
33
  }
50
34
  }
51
35
  const output = Mustache.render(content, view, partialArgs);
@@ -55,3 +39,10 @@ const mustache = () => {
55
39
  };
56
40
  };
57
41
  exports.mustache = mustache;
42
+ const bufferToString = (buffer) => {
43
+ if (buffer instanceof ArrayBuffer) {
44
+ const enc = new TextDecoder('utf-8');
45
+ return enc.decode(buffer);
46
+ }
47
+ return buffer;
48
+ };
@@ -0,0 +1,6 @@
1
+ import type { Context } from '../../context';
2
+ declare type Options = {
3
+ root: string;
4
+ };
5
+ export declare const serveStatic: (opt?: Options) => (c: Context, next: Function) => Promise<void>;
6
+ export {};
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serveStatic = void 0;
4
+ const cloudflare_1 = require("../../utils/cloudflare");
5
+ const mime_1 = require("../../utils/mime");
6
+ const DEFAULT_DOCUMENT = 'index.html';
7
+ // This middleware is available only on Cloudflare Workers.
8
+ const serveStatic = (opt = { root: '' }) => {
9
+ return async (c, next) => {
10
+ await next();
11
+ const url = new URL(c.req.url);
12
+ const path = getKVPath(url.pathname, opt.root);
13
+ const content = await (0, cloudflare_1.getContentFromKVAsset)(path);
14
+ if (content) {
15
+ const mimeType = (0, mime_1.getMimeType)(path);
16
+ if (mimeType) {
17
+ c.header('Content-Type', mimeType);
18
+ }
19
+ c.res = c.body(content);
20
+ }
21
+ else {
22
+ // console.debug(`Static file: ${path} is not found`)
23
+ }
24
+ };
25
+ };
26
+ exports.serveStatic = serveStatic;
27
+ const getKVPath = (filename, root) => {
28
+ if (filename.endsWith('/')) {
29
+ // /top/ => /top/index.html
30
+ filename = filename.concat(DEFAULT_DOCUMENT);
31
+ }
32
+ else if (!(0, mime_1.getMimeType)(filename)) {
33
+ // /top => /top/index.html
34
+ filename = filename.concat('/' + DEFAULT_DOCUMENT);
35
+ }
36
+ // /foo.html => foo.html
37
+ filename = filename.replace(/^\//, '');
38
+ // assets/ => assets
39
+ root = root.replace(/\/$/, '');
40
+ // ./assets/foo.html => assets/foo.html
41
+ let path = root + '/' + filename;
42
+ path = path.replace(/^\.?\//, '');
43
+ return path;
44
+ };
@@ -1,25 +1,3 @@
1
1
  export declare class Middleware {
2
2
  static default: (c: import("./context").Context, next: Function) => Promise<void>;
3
- static poweredBy: () => (c: import("./context").Context, next: Function) => Promise<void>;
4
- static logger: (fn?: {
5
- (...data: any[]): void;
6
- (...data: any[]): void;
7
- (message?: any, ...optionalParams: any[]): void;
8
- }) => (c: import("./context").Context, next: Function) => Promise<void>;
9
- static basicAuth: (options: {
10
- username: string;
11
- password: string;
12
- realm?: string;
13
- }) => (ctx: import("./context").Context, next: Function) => Promise<any>;
14
- static bodyParse: () => (ctx: import("./context").Context, next: Function) => Promise<void>;
15
- static cors: (options?: {
16
- origin: string;
17
- allowMethods?: string[];
18
- allowHeaders?: string[];
19
- maxAge?: number;
20
- credentials?: boolean;
21
- exposeHeaders?: string[];
22
- }) => (c: import("./context").Context, next: Function) => Promise<void>;
23
- static cookie: () => (c: import("./context").Context, next: Function) => Promise<void>;
24
- static mustache: () => (c: import("./context").Context, next: Function) => Promise<void>;
25
3
  }
@@ -2,21 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Middleware = void 0;
4
4
  const default_1 = require("./middleware/default");
5
- const powered_by_1 = require("./middleware/powered-by/powered-by");
6
- const logger_1 = require("./middleware/logger/logger");
7
- const basic_auth_1 = require("./middleware/basic-auth/basic-auth");
8
- const body_parse_1 = require("./middleware/body-parse/body-parse");
9
- const cors_1 = require("./middleware/cors/cors");
10
- const cookie_1 = require("./middleware/cookie/cookie");
11
- const mustache_1 = require("./middleware/mustache/mustache");
12
5
  class Middleware {
13
6
  }
14
7
  exports.Middleware = Middleware;
15
8
  Middleware.default = default_1.defaultMiddleware;
16
- Middleware.poweredBy = powered_by_1.poweredBy;
17
- Middleware.logger = logger_1.logger;
18
- Middleware.basicAuth = basic_auth_1.basicAuth;
19
- Middleware.bodyParse = body_parse_1.bodyParse;
20
- Middleware.cors = cors_1.cors;
21
- Middleware.cookie = cookie_1.cookie;
22
- Middleware.mustache = mustache_1.mustache;
@@ -1 +1 @@
1
- export declare const getContentFromKVAsset: (path: string) => Promise<string>;
1
+ export declare const getContentFromKVAsset: (path: string) => Promise<ArrayBuffer>;
@@ -14,8 +14,7 @@ const getContentFromKVAsset = async (path) => {
14
14
  if (!key) {
15
15
  return;
16
16
  }
17
- let content;
18
- content = await ASSET_NAMESPACE.get(key, { type: 'text' });
17
+ let content = await ASSET_NAMESPACE.get(key, { type: 'arrayBuffer' });
19
18
  if (content) {
20
19
  content = content;
21
20
  }
@@ -0,0 +1 @@
1
+ export declare const getMimeType: (filename: string) => string;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMimeType = void 0;
4
+ const getMimeType = (filename) => {
5
+ const regexp = /\.([a-zA-Z0-9]+?)$/;
6
+ const match = filename.match(regexp);
7
+ if (!match) {
8
+ return;
9
+ }
10
+ let mimeType = mimes[match[1]];
11
+ if (mimeType.startsWith('text') || mimeType === 'application/json') {
12
+ mimeType += '; charset=utf-8';
13
+ }
14
+ return mimeType;
15
+ };
16
+ exports.getMimeType = getMimeType;
17
+ const mimes = {
18
+ aac: 'audio/aac',
19
+ abw: 'application/x-abiword',
20
+ arc: 'application/x-freearc',
21
+ avi: 'video/x-msvideo',
22
+ azw: 'application/vnd.amazon.ebook',
23
+ bin: 'application/octet-stream',
24
+ bmp: 'image/bmp',
25
+ bz: 'application/x-bzip',
26
+ bz2: 'application/x-bzip2',
27
+ csh: 'application/x-csh',
28
+ css: 'text/css',
29
+ csv: 'text/csv',
30
+ doc: 'application/msword',
31
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
32
+ eot: 'application/vnd.ms-fontobject',
33
+ epub: 'application/epub+zip',
34
+ gz: 'application/gzip',
35
+ gif: 'image/gif',
36
+ htm: 'text/html',
37
+ html: 'text/html',
38
+ ico: 'image/vnd.microsoft.icon',
39
+ ics: 'text/calendar',
40
+ jar: 'application/java-archive',
41
+ jpeg: 'image/jpeg',
42
+ jpg: 'image/jpeg',
43
+ js: 'text/javascript',
44
+ json: 'application/json',
45
+ jsonld: 'application/ld+json',
46
+ mid: 'audio/x-midi',
47
+ midi: 'audio/x-midi',
48
+ mjs: 'text/javascript',
49
+ mp3: 'audio/mpeg',
50
+ mpeg: 'video/mpeg',
51
+ mpkg: 'application/vnd.apple.installer+xml',
52
+ odp: 'application/vnd.oasis.opendocument.presentation',
53
+ ods: 'application/vnd.oasis.opendocument.spreadsheet',
54
+ odt: 'application/vnd.oasis.opendocument.text',
55
+ oga: 'audio/ogg',
56
+ ogv: 'video/ogg',
57
+ ogx: 'application/ogg',
58
+ opus: 'audio/opus',
59
+ otf: 'font/otf',
60
+ png: 'image/png',
61
+ pdf: 'application/pdf',
62
+ php: 'application/php',
63
+ ppt: 'application/vnd.ms-powerpoint',
64
+ pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
65
+ rar: 'application/vnd.rar',
66
+ rtf: 'application/rtf',
67
+ sh: 'application/x-sh',
68
+ svg: 'image/svg+xml',
69
+ swf: 'application/x-shockwave-flash',
70
+ tar: 'application/x-tar',
71
+ tif: 'image/tiff',
72
+ tiff: 'image/tiff',
73
+ ts: 'video/mp2t',
74
+ ttf: 'font/ttf',
75
+ txt: 'text/plain',
76
+ vsd: 'application/vnd.visio',
77
+ wav: 'audio/wav',
78
+ weba: 'audio/webm',
79
+ webm: 'video/webm',
80
+ webp: 'image/webp',
81
+ woff: 'font/woff',
82
+ woff2: 'font/woff2',
83
+ xhtml: 'application/xhtml+xml',
84
+ xls: 'application/vnd.ms-excel',
85
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
86
+ xml: 'application/xml',
87
+ xul: 'application/vnd.mozilla.xul+xml',
88
+ zip: 'application/zip',
89
+ '3gp': 'video/3gpp',
90
+ '3g2': 'video/3gpp2',
91
+ '7z': 'application/x-7z-compressed',
92
+ };
package/package.json CHANGED
@@ -1,12 +1,51 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "[炎] Ultrafast web framework for Cloudflare Workers.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [
8
8
  "dist"
9
9
  ],
10
+ "exports": {
11
+ ".": "./dist/index.js",
12
+ "./basic-auth": "./dist/middleware/basic-auth/basic-auth.js",
13
+ "./body-parse": "./dist/middleware/body-parse/body-parse.js",
14
+ "./cookie": "./dist/middleware/cookie/cookie.js",
15
+ "./cors": "./dist/middleware/cors/cors.js",
16
+ "./logger": "./dist/middleware/logger/logger.js",
17
+ "./mustache": "./dist/middleware/mustache/mustache.js",
18
+ "./powered-by": "./dist/middleware/powered-by/powered-by.js",
19
+ "./serve-static": "./dist/middleware/serve-static/serve-static.js"
20
+ },
21
+ "typesVersions": {
22
+ "*": {
23
+ "basic-auth": [
24
+ "./dist/middleware/basic-auth/basic-auth.d.ts"
25
+ ],
26
+ "body-parse": [
27
+ "./dist/middleware/body-parse/body-parse.d.ts"
28
+ ],
29
+ "cookie": [
30
+ "./dist/middleware/cookie/cookie.d.ts"
31
+ ],
32
+ "cors": [
33
+ "./dist/middleware/cors/cors.d.ts"
34
+ ],
35
+ "logger": [
36
+ "./dist/middleware/logger/logger.d.ts"
37
+ ],
38
+ "mustache": [
39
+ "./dist/middleware/mustache/mustache.d.ts"
40
+ ],
41
+ "powered-by": [
42
+ "./dist/middleware/powered-by/powered-by.d.ts"
43
+ ],
44
+ "serve-static": [
45
+ "./dist/middleware/serve-static/serve-static.d.ts"
46
+ ]
47
+ }
48
+ },
10
49
  "scripts": {
11
50
  "test": "jest",
12
51
  "lint": "eslint --ext js,ts src .eslintrc.js test",
@@ -55,7 +94,7 @@
55
94
  "mustache": "^4.2.0",
56
95
  "rimraf": "^3.0.2",
57
96
  "ts-jest": "^27.1.2",
58
- "typescript": "^4.5.4"
97
+ "typescript": "^4.5.5"
59
98
  },
60
99
  "engines": {
61
100
  "node": ">=11.0.0"