@tinyhttp/app 2.1.4 → 2.2.1
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/dist/app.d.ts +25 -42
- package/dist/extend.d.ts +2 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +160 -87
- package/dist/index.js.map +1 -1
- package/dist/request.d.ts +2 -4
- package/dist/response.d.ts +25 -30
- package/dist/types.d.ts +39 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/view.d.ts +37 -0
- package/package.json +4 -4
package/dist/app.d.ts
CHANGED
|
@@ -3,29 +3,10 @@ import { Server } from 'node:http';
|
|
|
3
3
|
import type { Request } from './request.js';
|
|
4
4
|
import type { Response } from './response.js';
|
|
5
5
|
import type { ErrorHandler } from './onError.js';
|
|
6
|
-
import { Middleware, Handler, NextFunction,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export type AppSettings = Partial<{
|
|
11
|
-
networkExtensions: boolean;
|
|
12
|
-
subdomainOffset: number;
|
|
13
|
-
bindAppToReqRes: boolean;
|
|
14
|
-
xPoweredBy: string | boolean;
|
|
15
|
-
enableReqRoute: boolean;
|
|
16
|
-
views: string;
|
|
17
|
-
}>;
|
|
18
|
-
/**
|
|
19
|
-
* Function that processes the template
|
|
20
|
-
*/
|
|
21
|
-
export type TemplateFunc<O> = (path: string, locals: Record<string, any>, opts: TemplateEngineOptions<O>, cb: (err: Error | null, html: unknown) => void) => void;
|
|
22
|
-
export type TemplateEngineOptions<O> = Partial<{
|
|
23
|
-
cache: boolean;
|
|
24
|
-
ext: string;
|
|
25
|
-
renderOptions: Partial<O>;
|
|
26
|
-
viewsFolder: string;
|
|
27
|
-
_locals: Record<string, any>;
|
|
28
|
-
}>;
|
|
6
|
+
import type { Middleware, Handler, NextFunction, UseMethodParams } from '@tinyhttp/router';
|
|
7
|
+
import { Router } from '@tinyhttp/router';
|
|
8
|
+
import { AppConstructor, AppRenderOptions, AppSettings, TemplateEngine } from './types.js';
|
|
9
|
+
import { TemplateEngineOptions } from './index.js';
|
|
29
10
|
/**
|
|
30
11
|
* `App` class - the starting point of tinyhttp app.
|
|
31
12
|
*
|
|
@@ -48,33 +29,40 @@ export type TemplateEngineOptions<O> = Partial<{
|
|
|
48
29
|
* const app = App<any, CoolReq, Response>()
|
|
49
30
|
* ```
|
|
50
31
|
*/
|
|
51
|
-
export declare class App<
|
|
32
|
+
export declare class App<Req extends Request = Request, Res extends Response = Response> extends Router<App, Req, Res> {
|
|
52
33
|
#private;
|
|
53
34
|
middleware: Middleware<Req, Res>[];
|
|
54
35
|
locals: Record<string, unknown>;
|
|
55
36
|
noMatchHandler: Handler;
|
|
56
37
|
onError: ErrorHandler;
|
|
57
38
|
settings: AppSettings;
|
|
58
|
-
engines: Record<string,
|
|
39
|
+
engines: Record<string, TemplateEngine>;
|
|
59
40
|
applyExtensions: (req: Request, res: Response, next: NextFunction) => void;
|
|
60
41
|
attach: (req: Req, res: Res) => void;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
onError: ErrorHandler;
|
|
64
|
-
settings: AppSettings;
|
|
65
|
-
applyExtensions: (req: Request, res: Response, next: NextFunction) => void;
|
|
66
|
-
}>);
|
|
42
|
+
cache: Record<string, unknown>;
|
|
43
|
+
constructor(options?: AppConstructor<Req, Res>);
|
|
67
44
|
/**
|
|
68
45
|
* Set app setting
|
|
69
46
|
* @param setting setting name
|
|
70
47
|
* @param value setting value
|
|
71
48
|
*/
|
|
72
|
-
set<
|
|
49
|
+
set<K extends keyof AppSettings>(setting: K, value: AppSettings[K]): this;
|
|
73
50
|
/**
|
|
74
51
|
* Enable app setting
|
|
75
52
|
* @param setting Setting name
|
|
76
53
|
*/
|
|
77
|
-
enable(setting:
|
|
54
|
+
enable<K extends keyof AppSettings>(setting: K): this;
|
|
55
|
+
/**
|
|
56
|
+
* Check if setting is enabled
|
|
57
|
+
* @param setting Setting name
|
|
58
|
+
* @returns
|
|
59
|
+
*/
|
|
60
|
+
enabled<K extends keyof AppSettings>(setting: K): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Disable app setting
|
|
63
|
+
* @param setting Setting name
|
|
64
|
+
*/
|
|
65
|
+
disable<K extends keyof AppSettings>(setting: K): this;
|
|
78
66
|
/**
|
|
79
67
|
* Return the app's absolute pathname
|
|
80
68
|
* based on the parent(s) that have
|
|
@@ -88,10 +76,9 @@ export declare class App<RenderOptions = any, Req extends Request = Request, Res
|
|
|
88
76
|
*/
|
|
89
77
|
path(): string;
|
|
90
78
|
/**
|
|
91
|
-
*
|
|
92
|
-
* @param setting
|
|
79
|
+
* Register a template engine with extension
|
|
93
80
|
*/
|
|
94
|
-
|
|
81
|
+
engine<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions>(ext: string, fn: TemplateEngine<RenderOptions>): this;
|
|
95
82
|
/**
|
|
96
83
|
* Render a template
|
|
97
84
|
* @param file What to render
|
|
@@ -99,19 +86,15 @@ export declare class App<RenderOptions = any, Req extends Request = Request, Res
|
|
|
99
86
|
* @param options Template engine options
|
|
100
87
|
* @param cb Callback that consumes error and html
|
|
101
88
|
*/
|
|
102
|
-
render(
|
|
89
|
+
render<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions>(name: string, data: Record<string, unknown>, options: AppRenderOptions<RenderOptions>, cb: (err: unknown, html?: unknown) => void): void;
|
|
103
90
|
use(...args: UseMethodParams<Req, Res, App>): this;
|
|
104
|
-
/**
|
|
105
|
-
* Register a template engine with extension
|
|
106
|
-
*/
|
|
107
|
-
engine(ext: string, fn: TemplateFunc<RenderOptions>): this;
|
|
108
91
|
route(path: string): App;
|
|
109
92
|
/**
|
|
110
93
|
* Extends Req / Res objects, pushes 404 and 500 handlers, dispatches middleware
|
|
111
94
|
* @param req Req object
|
|
112
95
|
* @param res Res object
|
|
113
96
|
*/
|
|
114
|
-
handler(req: Req, res: Res, next?: NextFunction): void;
|
|
97
|
+
handler<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions>(req: Req, res: Res, next?: NextFunction): void;
|
|
115
98
|
/**
|
|
116
99
|
* Creates HTTP server and dispatches middleware
|
|
117
100
|
* @param port server listening port
|
package/dist/extend.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { Request } from './request.js';
|
|
|
2
2
|
import type { NextFunction } from '@tinyhttp/router';
|
|
3
3
|
import type { Response } from './response.js';
|
|
4
4
|
import { App } from './app.js';
|
|
5
|
+
import { TemplateEngineOptions } from './types.js';
|
|
5
6
|
/**
|
|
6
7
|
* Extends Request and Response objects with custom properties and methods
|
|
7
8
|
*/
|
|
8
|
-
export declare const extendMiddleware: <EngineOptions>(app: App) => (req: Request, res: Response<EngineOptions
|
|
9
|
+
export declare const extendMiddleware: <EngineOptions extends TemplateEngineOptions = TemplateEngineOptions>(app: App) => (req: Request, res: Response<EngineOptions>, next: NextFunction) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { App } from './app.js';
|
|
2
|
-
export type { AppSettings, TemplateEngineOptions, TemplateFunc } from './app.js';
|
|
3
2
|
export * from './request.js';
|
|
4
|
-
import type { Request } from './request.js';
|
|
5
3
|
export * from './response.js';
|
|
6
|
-
import type { Response } from './response.js';
|
|
7
4
|
export { extendMiddleware } from './extend.js';
|
|
8
|
-
export { onErrorHandler } from './onError.js';
|
|
9
|
-
export
|
|
5
|
+
export { onErrorHandler, type ErrorHandler } from './onError.js';
|
|
6
|
+
export { View } from './view.js';
|
|
7
|
+
export type { AppSettings, TemplateEngineOptions, TemplateEngine, AppConstructor } from './types.js';
|
|
8
|
+
import type { Request } from './request.js';
|
|
9
|
+
import type { Response } from './response.js';
|
|
10
10
|
import type { NextFunction, Handler as RHandler, AsyncHandler as RAsyncHandler, SyncHandler as RSyncHandler, Middleware } from '@tinyhttp/router';
|
|
11
11
|
export type Handler = RHandler<Request, Response>;
|
|
12
12
|
export type AsyncHandler = RAsyncHandler<Request, Response>;
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
|
-
var __accessCheck = (obj, member, msg) => {
|
|
2
|
-
if (!member.has(obj))
|
|
3
|
-
throw TypeError("Cannot " + msg);
|
|
4
|
-
};
|
|
5
|
-
var __privateAdd = (obj, member, value) => {
|
|
6
|
-
if (member.has(obj))
|
|
7
|
-
throw TypeError("Cannot add the same private member more than once");
|
|
8
|
-
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
9
|
-
};
|
|
10
|
-
var __privateMethod = (obj, member, method) => {
|
|
11
|
-
__accessCheck(obj, member, "access private method");
|
|
12
|
-
return method;
|
|
13
|
-
};
|
|
14
|
-
var _find, find_fn;
|
|
15
1
|
import { STATUS_CODES, createServer } from "node:http";
|
|
16
|
-
import path from "node:path";
|
|
17
2
|
import { proxyaddr, all, compile } from "@tinyhttp/proxy-addr";
|
|
18
3
|
import { isIP } from "node:net";
|
|
19
4
|
import { getRequestHeader, getQueryParams, getRangeFromHeader, getAccepts, getAcceptsCharsets, getAcceptsEncodings, getAcceptsLanguages, checkIfXMLHttpRequest, getFreshOrStale, getPathname, getURLParams } from "@tinyhttp/req";
|
|
@@ -21,13 +6,14 @@ import { getURLParams as getURLParams2 } from "@tinyhttp/req";
|
|
|
21
6
|
import { Router, pushMiddleware } from "@tinyhttp/router";
|
|
22
7
|
import { getResponseHeader, setHeader, send, json, status, sendStatus, sendFile, setContentType, setLocationHeader, setLinksHeader, setVaryHeader, setCookie, clearCookie, formatResponse, redirect, attachment, download, append } from "@tinyhttp/res";
|
|
23
8
|
import { parse } from "regexparam";
|
|
9
|
+
import { extname, resolve, dirname, basename, join } from "node:path";
|
|
10
|
+
import { statSync } from "node:fs";
|
|
24
11
|
const trustRemoteAddress = ({ socket }) => {
|
|
25
12
|
const val = socket.remoteAddress;
|
|
26
13
|
if (typeof val === "string")
|
|
27
14
|
return compile(val.split(",").map((x) => x.trim()));
|
|
28
15
|
return compile(val || []);
|
|
29
16
|
};
|
|
30
|
-
const getRouteFromApp = ({ middleware }, h) => middleware.find(({ handler }) => typeof handler === "function" && handler.name === h.name);
|
|
31
17
|
const getProtocol = (req) => {
|
|
32
18
|
const proto = `http${req.secure ? "s" : ""}`;
|
|
33
19
|
if (!trustRemoteAddress(req))
|
|
@@ -68,16 +54,11 @@ const onErrorHandler = function(err, _req, res) {
|
|
|
68
54
|
res.writeHead(500).end(err.message);
|
|
69
55
|
};
|
|
70
56
|
const renderTemplate = (_req, res, app) => (file, data, options) => {
|
|
71
|
-
app.render(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
throw err;
|
|
77
|
-
res.send(html);
|
|
78
|
-
},
|
|
79
|
-
options
|
|
80
|
-
);
|
|
57
|
+
app.render(file, data ? { ...res.locals, ...data } : res.locals, options, (err, html) => {
|
|
58
|
+
if (err)
|
|
59
|
+
throw err;
|
|
60
|
+
res.send(html);
|
|
61
|
+
});
|
|
81
62
|
return res;
|
|
82
63
|
};
|
|
83
64
|
const extendMiddleware = (app) => (req, res, next) => {
|
|
@@ -126,6 +107,60 @@ const extendMiddleware = (app) => (req, res, next) => {
|
|
|
126
107
|
req.stale = !req.fresh;
|
|
127
108
|
next();
|
|
128
109
|
};
|
|
110
|
+
function tryStat(path) {
|
|
111
|
+
try {
|
|
112
|
+
return statSync(path);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
class View {
|
|
118
|
+
constructor(name, opts = {}) {
|
|
119
|
+
this.ext = extname(name);
|
|
120
|
+
this.name = name;
|
|
121
|
+
this.root = opts.root;
|
|
122
|
+
this.defaultEngine = opts.defaultEngine;
|
|
123
|
+
if (!this.ext && !this.defaultEngine)
|
|
124
|
+
throw new Error("No default engine was specified and no extension was provided.");
|
|
125
|
+
let fileName = name;
|
|
126
|
+
if (!this.ext) {
|
|
127
|
+
this.ext = this.defaultEngine[0] !== "." ? "." + this.defaultEngine : this.defaultEngine;
|
|
128
|
+
fileName += this.ext;
|
|
129
|
+
}
|
|
130
|
+
if (!opts.engines[this.ext])
|
|
131
|
+
throw new Error(`No engine was found for ${this.ext}`);
|
|
132
|
+
this.engine = opts.engines[this.ext];
|
|
133
|
+
this.path = this.#lookup(fileName);
|
|
134
|
+
}
|
|
135
|
+
#lookup(name) {
|
|
136
|
+
let path;
|
|
137
|
+
const roots = [].concat(this.root);
|
|
138
|
+
for (let i = 0; i < roots.length && !path; i++) {
|
|
139
|
+
const root = roots[i];
|
|
140
|
+
const loc = resolve(root, name);
|
|
141
|
+
const dir = dirname(loc);
|
|
142
|
+
const file = basename(loc);
|
|
143
|
+
path = this.#resolve(dir, file);
|
|
144
|
+
}
|
|
145
|
+
return path;
|
|
146
|
+
}
|
|
147
|
+
#resolve(dir, file) {
|
|
148
|
+
const ext = this.ext;
|
|
149
|
+
let path = join(dir, file);
|
|
150
|
+
let stat = tryStat(path);
|
|
151
|
+
if (stat && stat.isFile()) {
|
|
152
|
+
return path;
|
|
153
|
+
}
|
|
154
|
+
path = join(dir, basename(file, ext), "index" + ext);
|
|
155
|
+
stat = tryStat(path);
|
|
156
|
+
if (stat && stat.isFile()) {
|
|
157
|
+
return path;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
render(options, data, cb) {
|
|
161
|
+
this.engine(this.path, data, options, cb);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
129
164
|
const lead = (x) => x.charCodeAt(0) === 47 ? x : "/" + x;
|
|
130
165
|
const mount = (fn) => fn instanceof App ? fn.attach : fn;
|
|
131
166
|
const applyHandler = (h) => async (req, res, next) => {
|
|
@@ -138,18 +173,24 @@ const applyHandler = (h) => async (req, res, next) => {
|
|
|
138
173
|
next(e);
|
|
139
174
|
}
|
|
140
175
|
};
|
|
141
|
-
|
|
176
|
+
class App extends Router {
|
|
142
177
|
constructor(options = {}) {
|
|
143
178
|
super();
|
|
144
|
-
__privateAdd(this, _find);
|
|
145
179
|
this.middleware = [];
|
|
146
180
|
this.locals = {};
|
|
147
181
|
this.engines = {};
|
|
148
182
|
this.onError = (options == null ? void 0 : options.onError) || onErrorHandler;
|
|
149
183
|
this.noMatchHandler = (options == null ? void 0 : options.noMatchHandler) || this.onError.bind(this, { code: 404 });
|
|
150
|
-
this.settings =
|
|
184
|
+
this.settings = {
|
|
185
|
+
view: View,
|
|
186
|
+
xPoweredBy: true,
|
|
187
|
+
views: `${process.cwd()}/views`,
|
|
188
|
+
"view cache": process.env.NODE_ENV === "production",
|
|
189
|
+
...options.settings
|
|
190
|
+
};
|
|
151
191
|
this.applyExtensions = options == null ? void 0 : options.applyExtensions;
|
|
152
192
|
this.attach = (req, res) => setImmediate(this.handler.bind(this, req, res, void 0), req, res);
|
|
193
|
+
this.cache = {};
|
|
153
194
|
}
|
|
154
195
|
/**
|
|
155
196
|
* Set app setting
|
|
@@ -168,6 +209,22 @@ const _App = class _App extends Router {
|
|
|
168
209
|
this.settings[setting] = true;
|
|
169
210
|
return this;
|
|
170
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if setting is enabled
|
|
214
|
+
* @param setting Setting name
|
|
215
|
+
* @returns
|
|
216
|
+
*/
|
|
217
|
+
enabled(setting) {
|
|
218
|
+
return Boolean(this.settings[setting]);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Disable app setting
|
|
222
|
+
* @param setting Setting name
|
|
223
|
+
*/
|
|
224
|
+
disable(setting) {
|
|
225
|
+
this.settings[setting] = false;
|
|
226
|
+
return this;
|
|
227
|
+
}
|
|
171
228
|
/**
|
|
172
229
|
* Return the app's absolute pathname
|
|
173
230
|
* based on the parent(s) that have
|
|
@@ -183,11 +240,10 @@ const _App = class _App extends Router {
|
|
|
183
240
|
return this.parent ? this.parent.path() + this.mountpath : "";
|
|
184
241
|
}
|
|
185
242
|
/**
|
|
186
|
-
*
|
|
187
|
-
* @param setting
|
|
243
|
+
* Register a template engine with extension
|
|
188
244
|
*/
|
|
189
|
-
|
|
190
|
-
this.
|
|
245
|
+
engine(ext, fn) {
|
|
246
|
+
this.engines[ext[0] === "." ? ext : `.${ext}`] = fn;
|
|
191
247
|
return this;
|
|
192
248
|
}
|
|
193
249
|
/**
|
|
@@ -197,25 +253,45 @@ const _App = class _App extends Router {
|
|
|
197
253
|
* @param options Template engine options
|
|
198
254
|
* @param cb Callback that consumes error and html
|
|
199
255
|
*/
|
|
200
|
-
render(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
256
|
+
render(name, data = {}, options = {}, cb) {
|
|
257
|
+
let view;
|
|
258
|
+
const { _locals, ...opts } = options;
|
|
259
|
+
let locals = this.locals;
|
|
260
|
+
if (_locals)
|
|
261
|
+
locals = { ...locals, ..._locals };
|
|
262
|
+
locals = { ...locals, ...data };
|
|
263
|
+
if (opts.cache == null)
|
|
264
|
+
opts.cache = this.enabled("view cache");
|
|
265
|
+
if (opts.cache) {
|
|
266
|
+
view = this.cache[name];
|
|
267
|
+
}
|
|
268
|
+
if (!view) {
|
|
269
|
+
const View2 = this.settings["view"];
|
|
270
|
+
view = new View2(name, {
|
|
271
|
+
defaultEngine: this.settings["view engine"],
|
|
272
|
+
root: this.settings.views,
|
|
273
|
+
engines: this.engines
|
|
274
|
+
});
|
|
275
|
+
if (!view.path) {
|
|
276
|
+
const dirs = Array.isArray(view.root) && view.root.length > 1 ? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"' : 'directory "' + view.root + '"';
|
|
277
|
+
const err = new Error('Failed to lookup view "' + name + '" in views ' + dirs);
|
|
278
|
+
return cb(err);
|
|
279
|
+
}
|
|
280
|
+
if (opts.cache) {
|
|
281
|
+
this.cache[name] = view;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
view.render(opts, locals, cb);
|
|
286
|
+
} catch (err) {
|
|
287
|
+
cb(err);
|
|
288
|
+
}
|
|
213
289
|
}
|
|
214
290
|
use(...args) {
|
|
215
291
|
const base = args[0];
|
|
216
292
|
const fns = args.slice(1).flat();
|
|
217
293
|
let pathArray = [];
|
|
218
|
-
if (typeof base === "function" || base instanceof
|
|
294
|
+
if (typeof base === "function" || base instanceof App) {
|
|
219
295
|
fns.unshift(base);
|
|
220
296
|
} else {
|
|
221
297
|
let basePaths = [];
|
|
@@ -232,26 +308,26 @@ const _App = class _App extends Router {
|
|
|
232
308
|
});
|
|
233
309
|
fns.unshift(...basePaths);
|
|
234
310
|
}
|
|
235
|
-
pathArray = pathArray.length ? pathArray : ["/"];
|
|
311
|
+
pathArray = pathArray.length ? pathArray.map((path) => lead(path)) : ["/"];
|
|
236
312
|
const mountpath = pathArray.join(", ");
|
|
237
313
|
let regex;
|
|
238
314
|
for (const fn of fns) {
|
|
239
|
-
if (fn instanceof
|
|
240
|
-
pathArray.forEach((
|
|
241
|
-
regex = parse(
|
|
315
|
+
if (fn instanceof App) {
|
|
316
|
+
pathArray.forEach((path) => {
|
|
317
|
+
regex = parse(path, true);
|
|
242
318
|
fn.mountpath = mountpath;
|
|
243
|
-
this.apps[
|
|
319
|
+
this.apps[path] = fn;
|
|
244
320
|
fn.parent = this;
|
|
245
321
|
});
|
|
246
322
|
}
|
|
247
323
|
}
|
|
248
|
-
pathArray.forEach((
|
|
324
|
+
pathArray.forEach((path) => {
|
|
249
325
|
var _a;
|
|
250
326
|
const handlerPaths = [];
|
|
251
327
|
const handlerFunctions = [];
|
|
252
|
-
const handlerPathBase =
|
|
328
|
+
const handlerPathBase = path === "/" ? "" : lead(path);
|
|
253
329
|
for (const fn of fns) {
|
|
254
|
-
if (fn instanceof
|
|
330
|
+
if (fn instanceof App && ((_a = fn.middleware) == null ? void 0 : _a.length)) {
|
|
255
331
|
for (const mw of fn.middleware) {
|
|
256
332
|
handlerPaths.push(handlerPathBase + lead(mw.path));
|
|
257
333
|
handlerFunctions.push(fn);
|
|
@@ -262,7 +338,7 @@ const _App = class _App extends Router {
|
|
|
262
338
|
}
|
|
263
339
|
}
|
|
264
340
|
pushMiddleware(this.middleware)({
|
|
265
|
-
path
|
|
341
|
+
path,
|
|
266
342
|
regex,
|
|
267
343
|
type: "mw",
|
|
268
344
|
handler: mount(handlerFunctions[0]),
|
|
@@ -272,18 +348,19 @@ const _App = class _App extends Router {
|
|
|
272
348
|
});
|
|
273
349
|
return this;
|
|
274
350
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
engine(ext, fn) {
|
|
279
|
-
this.engines[ext] = fn;
|
|
280
|
-
return this;
|
|
281
|
-
}
|
|
282
|
-
route(path2) {
|
|
283
|
-
const app = new _App();
|
|
284
|
-
this.use(path2, app);
|
|
351
|
+
route(path) {
|
|
352
|
+
const app = new App({ settings: this.settings });
|
|
353
|
+
this.use(path, app);
|
|
285
354
|
return app;
|
|
286
355
|
}
|
|
356
|
+
#find(url) {
|
|
357
|
+
return this.middleware.filter((m) => {
|
|
358
|
+
m.regex = m.regex || parse(m.path, m.type === "mw");
|
|
359
|
+
let fullPathRegex;
|
|
360
|
+
m.fullPath && typeof m.fullPath === "string" ? fullPathRegex = parse(m.fullPath, m.type === "mw") : fullPathRegex = null;
|
|
361
|
+
return m.regex.pattern.test(url) && (m.type === "mw" && fullPathRegex ? fullPathRegex.pattern.test(url) : true);
|
|
362
|
+
});
|
|
363
|
+
}
|
|
287
364
|
/**
|
|
288
365
|
* Extends Req / Res objects, pushes 404 and 500 handlers, dispatches middleware
|
|
289
366
|
* @param req Req object
|
|
@@ -296,7 +373,7 @@ const _App = class _App extends Router {
|
|
|
296
373
|
const exts = this.applyExtensions || extendMiddleware(this);
|
|
297
374
|
req.originalUrl = req.url || req.originalUrl;
|
|
298
375
|
const pathname = getPathname(req.originalUrl);
|
|
299
|
-
const matched =
|
|
376
|
+
const matched = this.#find(pathname);
|
|
300
377
|
const mw = [
|
|
301
378
|
{
|
|
302
379
|
handler: exts,
|
|
@@ -325,7 +402,7 @@ const _App = class _App extends Router {
|
|
|
325
402
|
});
|
|
326
403
|
const handle = (mw2) => async (req2, res2, next2) => {
|
|
327
404
|
var _a;
|
|
328
|
-
const { path
|
|
405
|
+
const { path, handler, regex } = mw2;
|
|
329
406
|
let params;
|
|
330
407
|
try {
|
|
331
408
|
params = regex ? getURLParams(regex, pathname) : {};
|
|
@@ -336,18 +413,24 @@ const _App = class _App extends Router {
|
|
|
336
413
|
else
|
|
337
414
|
throw e;
|
|
338
415
|
}
|
|
416
|
+
let prefix = path;
|
|
417
|
+
if (regex) {
|
|
418
|
+
for (const key of regex.keys) {
|
|
419
|
+
if (key === "wild") {
|
|
420
|
+
prefix = prefix.replace("*", params.wild);
|
|
421
|
+
} else {
|
|
422
|
+
prefix = prefix.replace(`:${key}`, params[key]);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
339
426
|
req2.params = { ...req2.params, ...params };
|
|
340
|
-
if (
|
|
341
|
-
|
|
342
|
-
const url = req2.url.slice(req2.url.indexOf(first) + (first == null ? void 0 : first.length));
|
|
343
|
-
req2.url = lead(url);
|
|
344
|
-
} else {
|
|
345
|
-
req2.url = lead(req2.url.substring(path2.length));
|
|
427
|
+
if (mw2.type === "mw") {
|
|
428
|
+
req2.url = lead(req2.originalUrl.substring(prefix.length));
|
|
346
429
|
}
|
|
347
430
|
if (!req2.path)
|
|
348
431
|
req2.path = getPathname(req2.url);
|
|
349
432
|
if ((_a = this.settings) == null ? void 0 : _a.enableReqRoute)
|
|
350
|
-
req2.route =
|
|
433
|
+
req2.route = mw2;
|
|
351
434
|
await applyHandler(handler)(req2, res2, next2);
|
|
352
435
|
};
|
|
353
436
|
let idx = 0;
|
|
@@ -364,25 +447,15 @@ const _App = class _App extends Router {
|
|
|
364
447
|
listen(port, cb, host) {
|
|
365
448
|
return createServer().on("request", this.attach).listen(port, host, cb);
|
|
366
449
|
}
|
|
367
|
-
}
|
|
368
|
-
_find = new WeakSet();
|
|
369
|
-
find_fn = function(url) {
|
|
370
|
-
return this.middleware.filter((m) => {
|
|
371
|
-
m.regex = m.regex || parse(m.path, m.type === "mw");
|
|
372
|
-
let fullPathRegex;
|
|
373
|
-
m.fullPath && typeof m.fullPath === "string" ? fullPathRegex = parse(m.fullPath, m.type === "mw") : fullPathRegex = null;
|
|
374
|
-
return m.regex.pattern.test(url) && (m.type === "mw" && fullPathRegex ? fullPathRegex.pattern.test(url) : true);
|
|
375
|
-
});
|
|
376
|
-
};
|
|
377
|
-
let App = _App;
|
|
450
|
+
}
|
|
378
451
|
export {
|
|
379
452
|
App,
|
|
453
|
+
View,
|
|
380
454
|
extendMiddleware,
|
|
381
455
|
getHostname,
|
|
382
456
|
getIP,
|
|
383
457
|
getIPs,
|
|
384
458
|
getProtocol,
|
|
385
|
-
getRouteFromApp,
|
|
386
459
|
getSubdomains,
|
|
387
460
|
getURLParams2 as getURLParams,
|
|
388
461
|
onErrorHandler,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/request.ts","../src/onError.ts","../src/response.ts","../src/extend.ts","../src/app.ts"],"sourcesContent":["import { IncomingMessage } from 'node:http'\nimport type { ParsedUrlQuery } from 'node:querystring'\n\nimport { Options, Ranges } from 'header-range-parser'\nimport { proxyaddr as proxyAddr, all, compile } from '@tinyhttp/proxy-addr'\n\nimport { App } from './app.js'\nimport type { Middleware, Handler } from '@tinyhttp/router'\nimport type { Response } from './response.js'\n\nimport type { URLParams } from '@tinyhttp/req'\nimport { isIP } from 'node:net'\nimport type { Socket } from 'node:net'\nimport type { TLSSocket } from 'node:tls'\n\nexport { getURLParams } from '@tinyhttp/req'\n\nconst trustRemoteAddress = ({ socket }: Pick<Request, 'headers' | 'socket'>) => {\n const val = socket.remoteAddress\n\n if (typeof val === 'string') return compile(val.split(',').map((x) => x.trim()))\n\n return compile(val || [])\n}\n\nexport const getRouteFromApp = ({ middleware }: App, h: Handler<Request, Response>): Middleware<Request, Response> =>\n middleware.find(({ handler }) => typeof handler === 'function' && handler.name === h.name)\n\nexport const getProtocol = (req: Request): Protocol => {\n const proto = `http${req.secure ? 's' : ''}`\n\n if (!trustRemoteAddress(req)) return proto\n\n const header = (req.headers['X-Forwarded-Proto'] as string) || proto\n\n const index = header.indexOf(',')\n\n return index !== -1 ? header.substring(0, index).trim() : header.trim()\n}\n\nexport const getHostname = (req: Request): string | undefined => {\n let host: string = req.get('X-Forwarded-Host') as string\n\n if (!host || !trustRemoteAddress(req)) host = req.get('Host') as string\n\n if (!host) return\n\n // IPv6 literal support\n const index = host.indexOf(':', host[0] === '[' ? host.indexOf(']') + 1 : 0)\n\n return index !== -1 ? host.substring(0, index) : host\n}\n\nexport const getIP = (req: Pick<Request, 'headers' | 'connection' | 'socket'>): string | undefined =>\n proxyAddr(req, trustRemoteAddress(req)).replace(/^.*:/, '') // striping the redundant prefix addeded by OS to IPv4 address\n\nexport const getIPs = (req: Pick<Request, 'headers' | 'connection' | 'socket'>): string[] | undefined =>\n all(req, trustRemoteAddress(req))\n\nexport const getSubdomains = (req: Request, subdomainOffset = 2): string[] => {\n const hostname = getHostname(req)\n\n if (!hostname) return []\n\n const subdomains = isIP(hostname) ? [hostname] : hostname.split('.').reverse()\n\n return subdomains.slice(subdomainOffset)\n}\n\nexport type Connection = IncomingMessage['socket'] & {\n encrypted: boolean\n}\n\nexport type Protocol = 'node:http' | 'https' | string\n\nexport type { URLParams }\n\ntype AcceptsReturns = string | boolean | string[]\n\nexport interface Request extends IncomingMessage {\n originalUrl: string\n path: string\n url: string\n query: ParsedUrlQuery\n params: URLParams\n connection: Connection\n socket: TLSSocket | Socket\n route?: Middleware\n protocol: Protocol\n secure: boolean\n xhr: boolean\n hostname?: string\n ip?: string\n ips?: string[]\n subdomains?: string[]\n get: (header: string) => string | string[] | undefined\n range: (size: number, options?: Options) => -1 | -2 | -3 | Ranges | undefined\n accepts: (...types: string[]) => AcceptsReturns\n acceptsEncodings: (...encodings: string[]) => AcceptsReturns\n acceptsCharsets: (...charsets: string[]) => AcceptsReturns\n acceptsLanguages: (...languages: string[]) => AcceptsReturns\n is: (...types: string[]) => boolean\n cookies?: any\n signedCookies?: any\n secret?: string | string[]\n fresh?: boolean\n stale?: boolean\n body?: any\n app?: App\n}\n","import type { NextFunction } from '@tinyhttp/router'\nimport { STATUS_CODES } from 'node:http'\nimport type { Request } from './request.js'\nimport type { Response } from './response.js'\nimport type { App } from './app.js'\n\nexport type ErrorHandler = (this: App, err: any, req: Request, res: Response, next?: NextFunction) => void\n\nexport const onErrorHandler: ErrorHandler = function (this: App, err: any, _req: Request, res: Response) {\n if (this.onError === onErrorHandler && this.parent) return this.parent.onError(err, _req, res)\n\n if (err instanceof Error) console.error(err)\n\n const code = err.code in STATUS_CODES ? err.code : err.status\n\n if (typeof err === 'string' || Buffer.isBuffer(err)) res.writeHead(500).end(err)\n else if (code in STATUS_CODES) res.writeHead(code).end(STATUS_CODES[code])\n else res.writeHead(500).end(err.message)\n}\n","import { ServerResponse } from 'node:http'\nimport type { SerializeOptions } from '@tinyhttp/cookie'\nimport { Request } from './request.js'\nimport { App, TemplateEngineOptions } from './app.js'\nimport type { ReadStreamOptions, FormatProps, DownloadOptions } from '@tinyhttp/res'\n\nexport const renderTemplate =\n <O>(_req: Request, res: Response, app: App) =>\n (file: string, data?: Record<string, any>, options?: TemplateEngineOptions<O>): Response => {\n app.render(\n file,\n data ? { ...data, ...res.locals } : res.locals,\n (err: unknown, html: unknown) => {\n if (err) throw err\n res.send(html)\n },\n options\n )\n return res\n }\n\nexport interface Response<O = any, B = any> extends ServerResponse {\n header(field: string | Record<string, unknown>, val?: string | any[]): Response<O, B>\n set(field: string | Record<string, unknown>, val?: string | any[]): Response<O, B>\n get(field: string): string | number | string[]\n send(body: B): Response<O, B>\n sendFile(path: string, options?: ReadStreamOptions, cb?: (err?: any) => void): Response<O, B>\n json(body: B): Response<O, B>\n status(status: number): Response<O, B>\n sendStatus(statusCode: number): Response<O, B>\n cookie(\n name: string,\n value: string | Record<string, unknown>,\n options?: SerializeOptions & Partial<{ signed: boolean }>\n ): Response<O, B>\n clearCookie(name: string, options?: SerializeOptions): Response<O, B>\n location(url: string): Response<O, B>\n links(links: { [key: string]: string }): Response<O, B>\n render(file: string, data?: Record<string, any>, options?: TemplateEngineOptions<O>): Response<O, B>\n vary(field: string): Response<O, B>\n format(obj: FormatProps): Response<O, B>\n redirect(url: string, status?: number): Response<O, B>\n type(type: string): Response<O, B>\n download(path: string, filename: string, options?: DownloadOptions, cb?: (err?: any) => void): Response<O, B>\n attachment(filename?: string): Response<O, B>\n app?: App\n locals?: Record<string, any>\n /**\n * Send JSON response with JSONP callback support.\n *\n * To enable this method, install the `@tinyhttp/jsonp` package and attach the method to `res.jsonp` property.\n *\n * @param obj Response object\n */\n jsonp(obj: any): Response<O, B>\n\n append(field: string, value: any): Response<O, B>\n}\n","import { getSubdomains, Request } from './request.js'\nimport type { NextFunction } from '@tinyhttp/router'\nimport type { Response } from './response.js'\nimport {\n getFreshOrStale,\n getRangeFromHeader,\n getRequestHeader,\n checkIfXMLHttpRequest,\n getQueryParams,\n getAccepts,\n getAcceptsCharsets,\n getAcceptsEncodings,\n getAcceptsLanguages\n} from '@tinyhttp/req'\nimport { getProtocol, getHostname, getIP, getIPs } from './request.js'\nimport {\n send,\n json,\n status,\n setCookie,\n clearCookie,\n setHeader,\n getResponseHeader,\n setLocationHeader,\n setLinksHeader,\n sendStatus,\n setVaryHeader,\n sendFile,\n formatResponse,\n redirect,\n setContentType,\n attachment,\n download,\n append\n} from '@tinyhttp/res'\nimport { renderTemplate } from './response.js'\nimport { App } from './app.js'\n\n/**\n * Extends Request and Response objects with custom properties and methods\n */\nexport const extendMiddleware =\n <EngineOptions>(app: App) =>\n (req: Request, res: Response<EngineOptions>, next: NextFunction): void => {\n const { settings } = app\n\n res.get = getResponseHeader(res)\n req.get = getRequestHeader(req)\n\n if (settings?.bindAppToReqRes) {\n req.app = app\n res.app = app\n }\n\n if (settings?.networkExtensions) {\n req.protocol = getProtocol(req)\n req.secure = req.protocol === 'https'\n req.hostname = getHostname(req)\n req.subdomains = getSubdomains(req, settings.subdomainOffset)\n req.ip = getIP(req)\n req.ips = getIPs(req)\n }\n\n req.query = getQueryParams(req.url)\n\n req.range = getRangeFromHeader(req)\n req.accepts = getAccepts(req)\n req.acceptsCharsets = getAcceptsCharsets(req)\n req.acceptsEncodings = getAcceptsEncodings(req)\n req.acceptsLanguages = getAcceptsLanguages(req)\n\n req.xhr = checkIfXMLHttpRequest(req)\n\n res.header = res.set = setHeader<Response>(res)\n res.send = send<Request, Response>(req, res)\n res.json = json<Response>(res)\n res.status = status<Response>(res)\n res.sendStatus = sendStatus<Request, Response>(req, res)\n res.sendFile = sendFile<Request, Response>(req, res)\n res.type = setContentType<Response>(res)\n res.location = setLocationHeader<Request, Response>(req, res)\n res.links = setLinksHeader<Response>(res)\n res.vary = setVaryHeader<Response>(res)\n res.cookie = setCookie<Request, Response>(req, res)\n res.clearCookie = clearCookie<Request, Response>(req, res)\n res.render = renderTemplate<EngineOptions>(req, res, app)\n res.format = formatResponse(req, res, next)\n res.redirect = redirect(req, res, next)\n res.attachment = attachment<Response>(res)\n res.download = download<Request, Response>(req, res)\n res.append = append<Response>(res)\n res.locals = res.locals || Object.create(null)\n\n Object.defineProperty(req, 'fresh', { get: getFreshOrStale.bind(null, req, res), configurable: true })\n req.stale = !req.fresh\n\n next()\n }\n","import { createServer, Server } from 'node:http'\nimport path from 'node:path'\nimport { getRouteFromApp, getURLParams } from './request.js'\nimport type { Request, URLParams } from './request.js'\nimport type { Response } from './response.js'\nimport type { ErrorHandler } from './onError.js'\nimport { onErrorHandler } from './onError.js'\nimport { Middleware, Handler, NextFunction, Router, UseMethodParams, pushMiddleware } from '@tinyhttp/router'\nimport { extendMiddleware } from './extend.js'\nimport { parse as rg } from 'regexparam'\nimport { getPathname } from '@tinyhttp/req'\n\n/**\n * Add leading slash if not present (e.g. path -> /path, /path -> /path)\n * @param x\n */\nconst lead = (x: string) => (x.charCodeAt(0) === 47 ? x : '/' + x)\n\nconst mount = (fn: App | Handler) => (fn instanceof App ? fn.attach : fn)\n\nconst applyHandler =\n <Req, Res>(h: Handler<Req, Res>) =>\n async (req: Req, res: Res, next?: NextFunction) => {\n try {\n if (h[Symbol.toStringTag] === 'AsyncFunction') {\n await h(req, res, next)\n } else h(req, res, next)\n } catch (e) {\n next(e)\n }\n }\n/**\n * tinyhttp App has a few settings for toggling features\n */\nexport type AppSettings = Partial<{\n networkExtensions: boolean\n subdomainOffset: number\n bindAppToReqRes: boolean\n xPoweredBy: string | boolean\n enableReqRoute: boolean\n views: string\n}>\n\n/**\n * Function that processes the template\n */\nexport type TemplateFunc<O> = (\n path: string,\n locals: Record<string, any>,\n opts: TemplateEngineOptions<O>,\n cb: (err: Error | null, html: unknown) => void\n) => void\n\nexport type TemplateEngineOptions<O> = Partial<{\n cache: boolean\n ext: string\n renderOptions: Partial<O>\n viewsFolder: string\n _locals: Record<string, any>\n}>\n\n/**\n * `App` class - the starting point of tinyhttp app.\n *\n * With the `App` you can:\n * * use routing methods and `.use(...)`\n * * set no match (404) and error (500) handlers\n * * configure template engines\n * * store data in locals\n * * listen the http server on a specified port\n *\n * In case you use TypeScript, you can pass custom types to this class because it is also a generic class.\n *\n * Example:\n *\n * ```ts\n * interface CoolReq extends Request {\n * genericsAreDope: boolean\n * }\n *\n * const app = App<any, CoolReq, Response>()\n * ```\n */\nexport class App<\n RenderOptions = any,\n Req extends Request = Request,\n Res extends Response<RenderOptions> = Response<RenderOptions>\n> extends Router<App, Req, Res> {\n middleware: Middleware<Req, Res>[] = []\n locals: Record<string, unknown> = {}\n noMatchHandler: Handler\n onError: ErrorHandler\n settings: AppSettings\n engines: Record<string, TemplateFunc<RenderOptions>> = {}\n applyExtensions: (req: Request, res: Response, next: NextFunction) => void\n attach: (req: Req, res: Res) => void\n\n constructor(\n options: Partial<{\n noMatchHandler: Handler<Req, Res>\n onError: ErrorHandler\n settings: AppSettings\n applyExtensions: (req: Request, res: Response, next: NextFunction) => void\n }> = {}\n ) {\n super()\n this.onError = options?.onError || onErrorHandler\n this.noMatchHandler = options?.noMatchHandler || this.onError.bind(this, { code: 404 })\n this.settings = options.settings || { xPoweredBy: true, views: `${process.cwd()}/views` }\n this.applyExtensions = options?.applyExtensions\n this.attach = (req, res) => setImmediate(this.handler.bind(this, req, res, undefined), req, res)\n }\n /**\n * Set app setting\n * @param setting setting name\n * @param value setting value\n */\n set<T = unknown>(setting: string, value: T): this {\n this.settings[setting] = value\n\n return this\n }\n\n /**\n * Enable app setting\n * @param setting Setting name\n */\n enable(setting: string): this {\n this.settings[setting] = true\n\n return this\n }\n\n /**\n * Return the app's absolute pathname\n * based on the parent(s) that have\n * mounted it.\n *\n * For example if the application was\n * mounted as `\"/admin\"`, which itself\n * was mounted as `\"/blog\"` then the\n * return value would be `\"/blog/admin\"`.\n *\n */\n path(): string {\n return this.parent ? this.parent.path() + this.mountpath : ''\n }\n\n /**\n * Disable app setting\n * @param setting\n */\n disable(setting: string): this {\n this.settings[setting] = false\n\n return this\n }\n\n /**\n * Render a template\n * @param file What to render\n * @param data data that is passed to a template\n * @param options Template engine options\n * @param cb Callback that consumes error and html\n */\n render(\n file: string,\n data: Record<string, unknown> = {},\n cb: (err: unknown, html: unknown) => void,\n options: TemplateEngineOptions<RenderOptions> = {}\n ): this {\n options.viewsFolder = options.viewsFolder || this.settings.views || `${process.cwd()}/views`\n options.ext = options.ext || file.slice(file.lastIndexOf('.') + 1) || 'ejs'\n\n options._locals = options._locals || {}\n\n options.cache = options.cache || process.env.NODE_ENV === 'production'\n\n let locals = { ...data, ...this.locals }\n\n if (options._locals) locals = { ...locals, ...options._locals }\n\n if (!file.endsWith(`.${options.ext}`)) file = `${file}.${options.ext}`\n\n const dest = options.viewsFolder ? path.join(options.viewsFolder, file) : file\n\n this.engines[options.ext](dest, locals, options.renderOptions, cb)\n\n return this\n }\n use(...args: UseMethodParams<Req, Res, App>): this {\n const base = args[0]\n\n const fns = args.slice(1).flat()\n\n let pathArray = []\n if (typeof base === 'function' || base instanceof App) {\n fns.unshift(base)\n } else {\n // if base is not an array of paths, then convert it to an array.\n let basePaths = []\n if (Array.isArray(base)) basePaths = [...base]\n else if (typeof base === 'string') basePaths = [base]\n\n basePaths = basePaths.filter((element) => {\n if (typeof element === 'string') {\n pathArray.push(element)\n return false\n }\n return true\n })\n fns.unshift(...basePaths)\n }\n pathArray = pathArray.length ? pathArray : ['/']\n\n const mountpath = pathArray.join(', ')\n let regex: { keys: string[]; pattern: RegExp }\n\n for (const fn of fns) {\n if (fn instanceof App) {\n pathArray.forEach((path) => {\n regex = rg(path, true)\n fn.mountpath = mountpath\n this.apps[path] = fn\n fn.parent = this\n })\n }\n }\n pathArray.forEach((path) => {\n const handlerPaths = []\n const handlerFunctions = []\n const handlerPathBase = path === '/' ? '' : lead(path)\n for (const fn of fns) {\n if (fn instanceof App && fn.middleware?.length) {\n for (const mw of fn.middleware) {\n handlerPaths.push(handlerPathBase + lead(mw.path))\n handlerFunctions.push(fn)\n }\n } else {\n handlerPaths.push('')\n handlerFunctions.push(fn)\n }\n }\n pushMiddleware(this.middleware)({\n path,\n regex,\n type: 'mw',\n handler: mount(handlerFunctions[0] as Handler),\n handlers: handlerFunctions.slice(1).map(mount),\n fullPaths: handlerPaths\n })\n })\n return this\n }\n /**\n * Register a template engine with extension\n */\n engine(ext: string, fn: TemplateFunc<RenderOptions>): this {\n this.engines[ext] = fn\n\n return this\n }\n\n route(path: string): App {\n const app = new App()\n\n this.use(path, app)\n\n return app\n }\n\n #find(url: string): Middleware<Req, Res>[] {\n return this.middleware.filter((m) => {\n m.regex = m.regex || rg(m.path, m.type === 'mw')\n\n let fullPathRegex: { keys: string[]; pattern: RegExp }\n\n m.fullPath && typeof m.fullPath === 'string'\n ? (fullPathRegex = rg(m.fullPath, m.type === 'mw'))\n : (fullPathRegex = null)\n\n return m.regex.pattern.test(url) && (m.type === 'mw' && fullPathRegex ? fullPathRegex.pattern.test(url) : true)\n })\n }\n\n /**\n * Extends Req / Res objects, pushes 404 and 500 handlers, dispatches middleware\n * @param req Req object\n * @param res Res object\n */\n handler(req: Req, res: Res, next?: NextFunction): void {\n /* Set X-Powered-By header */\n const { xPoweredBy } = this.settings\n if (xPoweredBy) res.setHeader('X-Powered-By', typeof xPoweredBy === 'string' ? xPoweredBy : 'tinyhttp')\n\n const exts = this.applyExtensions || extendMiddleware<RenderOptions>(this)\n\n req.originalUrl = req.url || req.originalUrl\n\n const pathname = getPathname(req.originalUrl)\n\n const matched = this.#find(pathname)\n\n const mw: Middleware[] = [\n {\n handler: exts,\n type: 'mw',\n path: '/'\n },\n ...matched.filter((x) => req.method === 'HEAD' || (x.method ? x.method === req.method : true))\n ]\n\n if (matched[0] != null) {\n mw.push({\n type: 'mw',\n handler: (req, res, next) => {\n if (req.method === 'HEAD') {\n res.statusCode = 204\n return res.end('')\n }\n next()\n },\n path: '/'\n })\n }\n\n mw.push({\n handler: this.noMatchHandler,\n type: 'mw',\n path: '/'\n })\n\n const handle = (mw: Middleware) => async (req: Req, res: Res, next?: NextFunction) => {\n const { path, handler, regex } = mw\n\n let params: URLParams\n\n try {\n params = regex ? getURLParams(regex, pathname) : {}\n } catch (e) {\n console.error(e)\n if (e instanceof URIError) return res.sendStatus(400) // Handle malformed URI\n else throw e\n }\n\n req.params = { ...req.params, ...params }\n\n if (path.includes(':')) {\n const first = Object.values(params)[0]\n const url = req.url.slice(req.url.indexOf(first) + first?.length)\n req.url = lead(url)\n } else {\n req.url = lead(req.url.substring(path.length))\n }\n\n if (!req.path) req.path = getPathname(req.url)\n\n if (this.settings?.enableReqRoute) req.route = getRouteFromApp(this, handler)\n\n await applyHandler<Req, Res>(handler as unknown as Handler<Req, Res>)(req, res, next)\n }\n\n let idx = 0\n\n const loop = () => res.writableEnded || (idx < mw.length && handle(mw[idx++])(req, res, next))\n\n next = next || ((err) => (err ? this.onError(err, req, res) : loop()))\n\n loop()\n }\n\n /**\n * Creates HTTP server and dispatches middleware\n * @param port server listening port\n * @param Server callback after server starts listening\n * @param host server listening host\n */\n listen(port?: number, cb?: () => void, host?: string): Server {\n return createServer().on('request', this.attach).listen(port, host, cb)\n }\n}\n"],"names":["proxyAddr","path","rg","req","res","next","mw"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/request.ts","../src/onError.ts","../src/response.ts","../src/extend.ts","../src/view.ts","../src/app.ts"],"sourcesContent":["import { IncomingMessage } from 'node:http'\nimport type { ParsedUrlQuery } from 'node:querystring'\n\nimport { Options, Ranges } from 'header-range-parser'\nimport { proxyaddr as proxyAddr, all, compile } from '@tinyhttp/proxy-addr'\n\nimport { App } from './app.js'\nimport type { Middleware } from '@tinyhttp/router'\n\nimport type { URLParams } from '@tinyhttp/req'\nimport { isIP } from 'node:net'\nimport type { Socket } from 'node:net'\nimport type { TLSSocket } from 'node:tls'\n\nexport { getURLParams } from '@tinyhttp/req'\n\nconst trustRemoteAddress = ({ socket }: Pick<Request, 'headers' | 'socket'>) => {\n const val = socket.remoteAddress\n if (typeof val === 'string') return compile(val.split(',').map((x) => x.trim()))\n return compile(val || [])\n}\n\nexport const getProtocol = (req: Request): Protocol => {\n const proto = `http${req.secure ? 's' : ''}`\n\n if (!trustRemoteAddress(req)) return proto\n\n const header = (req.headers['X-Forwarded-Proto'] as string) || proto\n\n const index = header.indexOf(',')\n\n return index !== -1 ? header.substring(0, index).trim() : header.trim()\n}\n\nexport const getHostname = (req: Request): string | undefined => {\n let host: string = req.get('X-Forwarded-Host') as string\n\n if (!host || !trustRemoteAddress(req)) host = req.get('Host') as string\n\n if (!host) return\n\n // IPv6 literal support\n const index = host.indexOf(':', host[0] === '[' ? host.indexOf(']') + 1 : 0)\n\n return index !== -1 ? host.substring(0, index) : host\n}\n\nexport const getIP = (req: Pick<Request, 'headers' | 'connection' | 'socket'>): string | undefined =>\n proxyAddr(req, trustRemoteAddress(req)).replace(/^.*:/, '') // striping the redundant prefix addeded by OS to IPv4 address\n\nexport const getIPs = (req: Pick<Request, 'headers' | 'connection' | 'socket'>): string[] | undefined =>\n all(req, trustRemoteAddress(req))\n\nexport const getSubdomains = (req: Request, subdomainOffset = 2): string[] => {\n const hostname = getHostname(req)\n\n if (!hostname) return []\n\n const subdomains = isIP(hostname) ? [hostname] : hostname.split('.').reverse()\n\n return subdomains.slice(subdomainOffset)\n}\n\nexport type Connection = IncomingMessage['socket'] & {\n encrypted: boolean\n}\n\nexport type Protocol = 'http' | 'https' | string\n\nexport type { URLParams }\n\ntype AcceptsReturns = string | boolean | string[]\n\nexport interface Request extends IncomingMessage {\n originalUrl: string\n path: string\n url: string\n query: ParsedUrlQuery\n params: URLParams\n connection: Connection\n socket: TLSSocket | Socket\n route?: Middleware\n protocol: Protocol\n secure: boolean\n xhr: boolean\n hostname?: string\n ip?: string\n ips?: string[]\n subdomains?: string[]\n get: (header: string) => string | string[] | undefined\n range: (size: number, options?: Options) => -1 | -2 | -3 | Ranges | undefined\n accepts: (...types: string[]) => AcceptsReturns\n acceptsEncodings: (...encodings: string[]) => AcceptsReturns\n acceptsCharsets: (...charsets: string[]) => AcceptsReturns\n acceptsLanguages: (...languages: string[]) => AcceptsReturns\n is: (...types: string[]) => boolean\n cookies?: any\n signedCookies?: any\n secret?: string | string[]\n fresh?: boolean\n stale?: boolean\n body?: any\n app?: App\n}\n","import type { NextFunction } from '@tinyhttp/router'\nimport { STATUS_CODES } from 'node:http'\nimport type { Request } from './request.js'\nimport type { Response } from './response.js'\nimport type { App } from './app.js'\n\nexport type ErrorHandler = (this: App, err: any, req: Request, res: Response, next?: NextFunction) => void\n\nexport const onErrorHandler: ErrorHandler = function (this: App, err: any, _req: Request, res: Response) {\n if (this.onError === onErrorHandler && this.parent) return this.parent.onError(err, _req, res)\n\n if (err instanceof Error) console.error(err)\n\n const code = err.code in STATUS_CODES ? err.code : err.status\n\n if (typeof err === 'string' || Buffer.isBuffer(err)) res.writeHead(500).end(err)\n else if (code in STATUS_CODES) res.writeHead(code).end(STATUS_CODES[code])\n else res.writeHead(500).end(err.message)\n}\n","import { ServerResponse } from 'node:http'\nimport type { SerializeOptions } from '@tinyhttp/cookie'\nimport { Request } from './request.js'\nimport { App } from './app.js'\nimport type { ReadStreamOptions, FormatProps, DownloadOptions } from '@tinyhttp/res'\nimport type { AppRenderOptions, TemplateEngineOptions } from './types.js'\n\nexport const renderTemplate =\n <O extends TemplateEngineOptions = TemplateEngineOptions>(_req: Request, res: Response, app: App) =>\n (file: string, data?: Record<string, unknown>, options?: AppRenderOptions<O>): Response => {\n app.render(file, data ? { ...res.locals, ...data } : res.locals, options, (err: unknown, html: unknown) => {\n if (err) throw err\n res.send(html)\n })\n return res\n }\n\nexport interface Response<B = unknown> extends ServerResponse {\n header(field: string | Record<string, unknown>, val?: string | any[]): Response<B>\n set(field: string | Record<string, unknown>, val?: string | any[]): Response<B>\n get(field: string): string | number | string[]\n send(body: B): Response<B>\n sendFile(path: string, options?: ReadStreamOptions, cb?: (err?: unknown) => void): Response<B>\n json(body: B): Response<B>\n status(status: number): Response<B>\n sendStatus(statusCode: number): Response<B>\n cookie(\n name: string,\n value: string | Record<string, unknown>,\n options?: SerializeOptions & Partial<{ signed: boolean }>\n ): Response<B>\n clearCookie(name: string, options?: SerializeOptions): Response<B>\n location(url: string): Response<B>\n links(links: { [key: string]: string }): Response<B>\n render<O extends TemplateEngineOptions = TemplateEngineOptions>(\n file: string,\n data?: Record<string, any>,\n options?: AppRenderOptions<O>\n ): Response<B>\n vary(field: string): Response<B>\n format(obj: FormatProps): Response<B>\n redirect(url: string, status?: number): Response<B>\n type(type: string): Response<B>\n download(path: string, filename: string, options?: DownloadOptions, cb?: (err?: unknown) => void): Response<B>\n attachment(filename?: string): Response<B>\n app?: App\n locals: Record<string, any>\n /**\n * Send JSON response with JSONP callback support.\n *\n * To enable this method, install the `@tinyhttp/jsonp` package and attach the method to `res.jsonp` property.\n *\n * @param obj Response object\n */\n jsonp(obj: any): Response<B>\n\n append(field: string, value: any): Response<B>\n}\n","import { getSubdomains, Request } from './request.js'\nimport type { NextFunction } from '@tinyhttp/router'\nimport type { Response } from './response.js'\nimport {\n getFreshOrStale,\n getRangeFromHeader,\n getRequestHeader,\n checkIfXMLHttpRequest,\n getQueryParams,\n getAccepts,\n getAcceptsCharsets,\n getAcceptsEncodings,\n getAcceptsLanguages\n} from '@tinyhttp/req'\nimport { getProtocol, getHostname, getIP, getIPs } from './request.js'\nimport {\n send,\n json,\n status,\n setCookie,\n clearCookie,\n setHeader,\n getResponseHeader,\n setLocationHeader,\n setLinksHeader,\n sendStatus,\n setVaryHeader,\n sendFile,\n formatResponse,\n redirect,\n setContentType,\n attachment,\n download,\n append\n} from '@tinyhttp/res'\nimport { renderTemplate } from './response.js'\nimport { App } from './app.js'\nimport { TemplateEngineOptions } from './types.js'\n\n/**\n * Extends Request and Response objects with custom properties and methods\n */\nexport const extendMiddleware =\n <EngineOptions extends TemplateEngineOptions = TemplateEngineOptions>(app: App) =>\n (req: Request, res: Response<EngineOptions>, next: NextFunction): void => {\n const { settings } = app\n\n res.get = getResponseHeader(res)\n req.get = getRequestHeader(req)\n\n if (settings?.bindAppToReqRes) {\n req.app = app\n res.app = app\n }\n\n if (settings?.networkExtensions) {\n req.protocol = getProtocol(req)\n req.secure = req.protocol === 'https'\n req.hostname = getHostname(req)\n req.subdomains = getSubdomains(req, settings.subdomainOffset)\n req.ip = getIP(req)\n req.ips = getIPs(req)\n }\n\n req.query = getQueryParams(req.url)\n\n req.range = getRangeFromHeader(req)\n req.accepts = getAccepts(req)\n req.acceptsCharsets = getAcceptsCharsets(req)\n req.acceptsEncodings = getAcceptsEncodings(req)\n req.acceptsLanguages = getAcceptsLanguages(req)\n\n req.xhr = checkIfXMLHttpRequest(req)\n\n res.header = res.set = setHeader<Response>(res)\n res.send = send<Request, Response>(req, res)\n res.json = json<Response>(res)\n res.status = status<Response>(res)\n res.sendStatus = sendStatus<Request, Response>(req, res)\n res.sendFile = sendFile<Request, Response>(req, res)\n res.type = setContentType<Response>(res)\n res.location = setLocationHeader<Request, Response>(req, res)\n res.links = setLinksHeader<Response>(res)\n res.vary = setVaryHeader<Response>(res)\n res.cookie = setCookie<Request, Response>(req, res)\n res.clearCookie = clearCookie<Request, Response>(req, res)\n res.render = renderTemplate(req, res, app)\n res.format = formatResponse(req, res, next)\n res.redirect = redirect(req, res, next)\n res.attachment = attachment<Response>(res)\n res.download = download<Request, Response>(req, res)\n res.append = append<Response>(res)\n res.locals = res.locals || Object.create(null)\n\n Object.defineProperty(req, 'fresh', { get: getFreshOrStale.bind(null, req, res), configurable: true })\n req.stale = !req.fresh\n\n next()\n }\n","/*!\n * Ported from https://github.com/expressjs/express/blob/master/lib/view.js\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2013 Roman Shtylman\n * Copyright(c) 2014-2015 Douglas Christopher Wilson\n * MIT Licensed\n */\n\nimport { extname, resolve, dirname, basename, join } from 'node:path'\nimport { TemplateEngineOptions, TemplateEngine } from './types.js'\nimport { statSync } from 'node:fs'\n\nfunction tryStat(path: string) {\n try {\n return statSync(path)\n } catch (e) {\n return undefined\n }\n}\n\n/**\n * Initialize a new `View` with the given `name`.\n *\n * Options:\n *\n * - `defaultEngine` the default template engine name\n * - `engines` template engine require() cache\n * - `root` root path for view lookup\n *\n * @param name\n * @param options\n * @public\n */\n\nexport class View<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions> {\n ext: string\n defaultEngine: string\n name: string\n engine: TemplateEngine<RenderOptions>\n path: string\n root: string | string[]\n constructor(\n name: string,\n opts: Partial<{\n defaultEngine: string\n root: string | string[]\n engines: Record<string, TemplateEngine<RenderOptions>>\n }> = {}\n ) {\n this.ext = extname(name)\n this.name = name\n this.root = opts.root\n this.defaultEngine = opts.defaultEngine\n\n if (!this.ext && !this.defaultEngine)\n throw new Error('No default engine was specified and no extension was provided.')\n\n let fileName = name\n\n if (!this.ext) {\n // get extension from default engine name\n this.ext = this.defaultEngine[0] !== '.' ? '.' + this.defaultEngine : this.defaultEngine\n\n fileName += this.ext\n }\n\n if (!opts.engines[this.ext]) throw new Error(`No engine was found for ${this.ext}`)\n\n this.engine = opts.engines[this.ext]\n this.path = this.#lookup(fileName)\n }\n #lookup(name: string) {\n let path: string\n const roots = [].concat(this.root)\n\n for (let i = 0; i < roots.length && !path; i++) {\n const root = roots[i]\n // resolve the path\n const loc = resolve(root, name)\n const dir = dirname(loc)\n const file = basename(loc)\n\n // resolve the file\n path = this.#resolve(dir, file)\n }\n\n return path\n }\n #resolve(dir: string, file: string) {\n const ext = this.ext\n\n // <path>.<ext>\n let path = join(dir, file)\n let stat = tryStat(path)\n\n if (stat && stat.isFile()) {\n return path\n }\n\n // <path>/index.<ext>\n path = join(dir, basename(file, ext), 'index' + ext)\n stat = tryStat(path)\n\n if (stat && stat.isFile()) {\n return path\n }\n }\n render(options: RenderOptions, data: Record<string, unknown>, cb: (err: Error | null, html: unknown) => void) {\n this.engine(this.path, data, options, cb)\n }\n}\n","import { createServer, Server } from 'node:http'\nimport { getURLParams } from './request.js'\nimport type { Request, URLParams } from './request.js'\nimport type { Response } from './response.js'\nimport type { ErrorHandler } from './onError.js'\nimport { onErrorHandler } from './onError.js'\nimport type { Middleware, Handler, NextFunction, UseMethodParams } from '@tinyhttp/router'\nimport { Router, pushMiddleware } from '@tinyhttp/router'\nimport { extendMiddleware } from './extend.js'\nimport { parse as rg } from 'regexparam'\nimport { getPathname } from '@tinyhttp/req'\nimport { AppConstructor, AppRenderOptions, AppSettings, TemplateEngine } from './types.js'\nimport { TemplateEngineOptions } from './index.js'\nimport { View } from './view.js'\n\n/**\n * Add leading slash if not present (e.g. path -> /path, /path -> /path)\n * @param x\n */\nconst lead = (x: string) => (x.charCodeAt(0) === 47 ? x : '/' + x)\n\nconst mount = (fn: App | Handler) => (fn instanceof App ? fn.attach : fn)\n\nconst applyHandler =\n <Req, Res>(h: Handler<Req, Res>) =>\n async (req: Req, res: Res, next?: NextFunction) => {\n try {\n if (h[Symbol.toStringTag] === 'AsyncFunction') {\n await h(req, res, next)\n } else h(req, res, next)\n } catch (e) {\n next(e)\n }\n }\n\n/**\n * `App` class - the starting point of tinyhttp app.\n *\n * With the `App` you can:\n * * use routing methods and `.use(...)`\n * * set no match (404) and error (500) handlers\n * * configure template engines\n * * store data in locals\n * * listen the http server on a specified port\n *\n * In case you use TypeScript, you can pass custom types to this class because it is also a generic class.\n *\n * Example:\n *\n * ```ts\n * interface CoolReq extends Request {\n * genericsAreDope: boolean\n * }\n *\n * const app = App<any, CoolReq, Response>()\n * ```\n */\nexport class App<Req extends Request = Request, Res extends Response = Response> extends Router<App, Req, Res> {\n middleware: Middleware<Req, Res>[] = []\n locals: Record<string, unknown> = {}\n noMatchHandler: Handler\n onError: ErrorHandler\n settings: AppSettings\n engines: Record<string, TemplateEngine> = {}\n applyExtensions: (req: Request, res: Response, next: NextFunction) => void\n attach: (req: Req, res: Res) => void\n cache: Record<string, unknown>\n\n constructor(options: AppConstructor<Req, Res> = {}) {\n super()\n this.onError = options?.onError || onErrorHandler\n this.noMatchHandler = options?.noMatchHandler || this.onError.bind(this, { code: 404 })\n this.settings = {\n view: View,\n xPoweredBy: true,\n views: `${process.cwd()}/views`,\n 'view cache': process.env.NODE_ENV === 'production',\n ...options.settings\n }\n this.applyExtensions = options?.applyExtensions\n this.attach = (req, res) => setImmediate(this.handler.bind(this, req, res, undefined), req, res)\n this.cache = {}\n }\n\n /**\n * Set app setting\n * @param setting setting name\n * @param value setting value\n */\n set<K extends keyof AppSettings>(setting: K, value: AppSettings[K]): this {\n this.settings[setting] = value\n\n return this\n }\n\n /**\n * Enable app setting\n * @param setting Setting name\n */\n enable<K extends keyof AppSettings>(setting: K): this {\n this.settings[setting] = true as AppSettings[K]\n\n return this\n }\n\n /**\n * Check if setting is enabled\n * @param setting Setting name\n * @returns\n */\n enabled<K extends keyof AppSettings>(setting: K): boolean {\n return Boolean(this.settings[setting])\n }\n\n /**\n * Disable app setting\n * @param setting Setting name\n */\n disable<K extends keyof AppSettings>(setting: K): this {\n this.settings[setting] = false as AppSettings[K]\n\n return this\n }\n\n /**\n * Return the app's absolute pathname\n * based on the parent(s) that have\n * mounted it.\n *\n * For example if the application was\n * mounted as `\"/admin\"`, which itself\n * was mounted as `\"/blog\"` then the\n * return value would be `\"/blog/admin\"`.\n *\n */\n path(): string {\n return this.parent ? this.parent.path() + this.mountpath : ''\n }\n\n /**\n * Register a template engine with extension\n */\n engine<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions>(\n ext: string,\n fn: TemplateEngine<RenderOptions>\n ): this {\n this.engines[ext[0] === '.' ? ext : `.${ext}`] = fn\n\n return this\n }\n\n /**\n * Render a template\n * @param file What to render\n * @param data data that is passed to a template\n * @param options Template engine options\n * @param cb Callback that consumes error and html\n */\n render<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions>(\n name: string,\n data: Record<string, unknown> = {},\n options: AppRenderOptions<RenderOptions> = {} as AppRenderOptions<RenderOptions>,\n cb: (err: unknown, html?: unknown) => void\n ): void {\n let view: View | undefined\n\n const { _locals, ...opts } = options\n\n let locals = this.locals\n\n if (_locals) locals = { ...locals, ..._locals }\n\n locals = { ...locals, ...data }\n\n if (opts.cache == null) (opts.cache as boolean) = this.enabled('view cache')\n\n if (opts.cache) {\n view = this.cache[name] as View\n }\n\n if (!view) {\n const View = this.settings['view']\n view = new View(name, {\n defaultEngine: this.settings['view engine'],\n root: this.settings.views,\n engines: this.engines\n })\n\n if (!view.path) {\n const dirs =\n Array.isArray(view.root) && view.root.length > 1\n ? 'directories \"' + view.root.slice(0, -1).join('\", \"') + '\" or \"' + view.root[view.root.length - 1] + '\"'\n : 'directory \"' + view.root + '\"'\n const err = new Error('Failed to lookup view \"' + name + '\" in views ' + dirs)\n\n return cb(err)\n }\n\n if (opts.cache) {\n this.cache[name] = view\n }\n }\n\n try {\n view.render(opts, locals, cb)\n } catch (err) {\n cb(err)\n }\n }\n use(...args: UseMethodParams<Req, Res, App>): this {\n const base = args[0]\n\n const fns = args.slice(1).flat()\n\n let pathArray = []\n if (typeof base === 'function' || base instanceof App) {\n fns.unshift(base)\n } else {\n // if base is not an array of paths, then convert it to an array.\n let basePaths = []\n if (Array.isArray(base)) basePaths = [...base]\n else if (typeof base === 'string') basePaths = [base]\n\n basePaths = basePaths.filter((element) => {\n if (typeof element === 'string') {\n pathArray.push(element)\n return false\n }\n return true\n })\n fns.unshift(...basePaths)\n }\n pathArray = pathArray.length ? pathArray.map((path) => lead(path)) : ['/']\n\n const mountpath = pathArray.join(', ')\n let regex: { keys: string[]; pattern: RegExp }\n\n for (const fn of fns) {\n if (fn instanceof App) {\n pathArray.forEach((path) => {\n regex = rg(path, true)\n fn.mountpath = mountpath\n this.apps[path] = fn\n fn.parent = this\n })\n }\n }\n pathArray.forEach((path) => {\n const handlerPaths = []\n const handlerFunctions = []\n const handlerPathBase = path === '/' ? '' : lead(path)\n for (const fn of fns) {\n if (fn instanceof App && fn.middleware?.length) {\n for (const mw of fn.middleware) {\n handlerPaths.push(handlerPathBase + lead(mw.path))\n handlerFunctions.push(fn)\n }\n } else {\n handlerPaths.push('')\n handlerFunctions.push(fn)\n }\n }\n pushMiddleware(this.middleware)({\n path,\n regex,\n type: 'mw',\n handler: mount(handlerFunctions[0] as Handler),\n handlers: handlerFunctions.slice(1).map(mount),\n fullPaths: handlerPaths\n })\n })\n return this\n }\n\n route(path: string): App {\n const app = new App({ settings: this.settings })\n\n this.use(path, app)\n\n return app\n }\n\n #find(url: string): Middleware<Req, Res>[] {\n return this.middleware.filter((m) => {\n m.regex = m.regex || rg(m.path, m.type === 'mw')\n\n let fullPathRegex: { keys: string[]; pattern: RegExp }\n\n m.fullPath && typeof m.fullPath === 'string'\n ? (fullPathRegex = rg(m.fullPath, m.type === 'mw'))\n : (fullPathRegex = null)\n\n return m.regex.pattern.test(url) && (m.type === 'mw' && fullPathRegex ? fullPathRegex.pattern.test(url) : true)\n })\n }\n\n /**\n * Extends Req / Res objects, pushes 404 and 500 handlers, dispatches middleware\n * @param req Req object\n * @param res Res object\n */\n handler<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions>(\n req: Req,\n res: Res,\n next?: NextFunction\n ): void {\n /* Set X-Powered-By header */\n const { xPoweredBy } = this.settings\n if (xPoweredBy) res.setHeader('X-Powered-By', typeof xPoweredBy === 'string' ? xPoweredBy : 'tinyhttp')\n\n const exts = this.applyExtensions || extendMiddleware<RenderOptions>(this)\n\n req.originalUrl = req.url || req.originalUrl\n\n const pathname = getPathname(req.originalUrl)\n\n const matched = this.#find(pathname)\n\n const mw: Middleware[] = [\n {\n handler: exts,\n type: 'mw',\n path: '/'\n },\n ...matched.filter((x) => req.method === 'HEAD' || (x.method ? x.method === req.method : true))\n ]\n\n if (matched[0] != null) {\n mw.push({\n type: 'mw',\n handler: (req, res, next) => {\n if (req.method === 'HEAD') {\n res.statusCode = 204\n return res.end('')\n }\n next()\n },\n path: '/'\n })\n }\n\n mw.push({\n handler: this.noMatchHandler,\n type: 'mw',\n path: '/'\n })\n\n const handle = (mw: Middleware) => async (req: Req, res: Res, next?: NextFunction) => {\n const { path, handler, regex } = mw\n\n let params: URLParams\n\n try {\n params = regex ? getURLParams(regex, pathname) : {}\n } catch (e) {\n console.error(e)\n if (e instanceof URIError) return res.sendStatus(400) // Handle malformed URI\n else throw e\n }\n\n // Warning: users should not use :wild as a pattern\n let prefix = path\n if (regex) {\n for (const key of regex.keys) {\n if (key === 'wild') {\n prefix = prefix.replace('*', params.wild)\n } else {\n prefix = prefix.replace(`:${key}`, params[key])\n }\n }\n }\n\n req.params = { ...req.params, ...params }\n\n if (mw.type === 'mw') {\n req.url = lead(req.originalUrl.substring(prefix.length))\n }\n\n if (!req.path) req.path = getPathname(req.url)\n\n if (this.settings?.enableReqRoute) req.route = mw\n\n await applyHandler<Req, Res>(handler as unknown as Handler<Req, Res>)(req, res, next)\n }\n\n let idx = 0\n\n const loop = () => res.writableEnded || (idx < mw.length && handle(mw[idx++])(req, res, next))\n\n next = next || ((err) => (err ? this.onError(err, req, res) : loop()))\n\n loop()\n }\n\n /**\n * Creates HTTP server and dispatches middleware\n * @param port server listening port\n * @param Server callback after server starts listening\n * @param host server listening host\n */\n listen(port?: number, cb?: () => void, host?: string): Server {\n return createServer().on('request', this.attach).listen(port, host, cb)\n }\n}\n"],"names":["proxyAddr","View","rg","req","res","next","mw"],"mappings":"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"}
|
package/dist/request.d.ts
CHANGED
|
@@ -6,13 +6,11 @@ import { IncomingMessage } from 'node:http';
|
|
|
6
6
|
import type { ParsedUrlQuery } from 'node:querystring';
|
|
7
7
|
import { Options, Ranges } from 'header-range-parser';
|
|
8
8
|
import { App } from './app.js';
|
|
9
|
-
import type { Middleware
|
|
10
|
-
import type { Response } from './response.js';
|
|
9
|
+
import type { Middleware } from '@tinyhttp/router';
|
|
11
10
|
import type { URLParams } from '@tinyhttp/req';
|
|
12
11
|
import type { Socket } from 'node:net';
|
|
13
12
|
import type { TLSSocket } from 'node:tls';
|
|
14
13
|
export { getURLParams } from '@tinyhttp/req';
|
|
15
|
-
export declare const getRouteFromApp: ({ middleware }: App, h: Handler<Request, Response>) => Middleware<Request, Response>;
|
|
16
14
|
export declare const getProtocol: (req: Request) => Protocol;
|
|
17
15
|
export declare const getHostname: (req: Request) => string | undefined;
|
|
18
16
|
export declare const getIP: (req: Pick<Request, 'headers' | 'connection' | 'socket'>) => string | undefined;
|
|
@@ -21,7 +19,7 @@ export declare const getSubdomains: (req: Request, subdomainOffset?: number) =>
|
|
|
21
19
|
export type Connection = IncomingMessage['socket'] & {
|
|
22
20
|
encrypted: boolean;
|
|
23
21
|
};
|
|
24
|
-
export type Protocol = '
|
|
22
|
+
export type Protocol = 'http' | 'https' | string;
|
|
25
23
|
export type { URLParams };
|
|
26
24
|
type AcceptsReturns = string | boolean | string[];
|
|
27
25
|
export interface Request extends IncomingMessage {
|
package/dist/response.d.ts
CHANGED
|
@@ -2,41 +2,36 @@
|
|
|
2
2
|
import { ServerResponse } from 'node:http';
|
|
3
3
|
import type { SerializeOptions } from '@tinyhttp/cookie';
|
|
4
4
|
import { Request } from './request.js';
|
|
5
|
-
import { App
|
|
5
|
+
import { App } from './app.js';
|
|
6
6
|
import type { ReadStreamOptions, FormatProps, DownloadOptions } from '@tinyhttp/res';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
_locals: Record<string, any>;
|
|
13
|
-
}>) => Response;
|
|
14
|
-
export interface Response<O = any, B = any> extends ServerResponse {
|
|
15
|
-
header(field: string | Record<string, unknown>, val?: string | any[]): Response<O, B>;
|
|
16
|
-
set(field: string | Record<string, unknown>, val?: string | any[]): Response<O, B>;
|
|
7
|
+
import type { AppRenderOptions, TemplateEngineOptions } from './types.js';
|
|
8
|
+
export declare const renderTemplate: <O extends TemplateEngineOptions = TemplateEngineOptions>(_req: Request, res: Response, app: App) => (file: string, data?: Record<string, unknown>, options?: AppRenderOptions<O>) => Response;
|
|
9
|
+
export interface Response<B = unknown> extends ServerResponse {
|
|
10
|
+
header(field: string | Record<string, unknown>, val?: string | any[]): Response<B>;
|
|
11
|
+
set(field: string | Record<string, unknown>, val?: string | any[]): Response<B>;
|
|
17
12
|
get(field: string): string | number | string[];
|
|
18
|
-
send(body: B): Response<
|
|
19
|
-
sendFile(path: string, options?: ReadStreamOptions, cb?: (err?:
|
|
20
|
-
json(body: B): Response<
|
|
21
|
-
status(status: number): Response<
|
|
22
|
-
sendStatus(statusCode: number): Response<
|
|
13
|
+
send(body: B): Response<B>;
|
|
14
|
+
sendFile(path: string, options?: ReadStreamOptions, cb?: (err?: unknown) => void): Response<B>;
|
|
15
|
+
json(body: B): Response<B>;
|
|
16
|
+
status(status: number): Response<B>;
|
|
17
|
+
sendStatus(statusCode: number): Response<B>;
|
|
23
18
|
cookie(name: string, value: string | Record<string, unknown>, options?: SerializeOptions & Partial<{
|
|
24
19
|
signed: boolean;
|
|
25
|
-
}>): Response<
|
|
26
|
-
clearCookie(name: string, options?: SerializeOptions): Response<
|
|
27
|
-
location(url: string): Response<
|
|
20
|
+
}>): Response<B>;
|
|
21
|
+
clearCookie(name: string, options?: SerializeOptions): Response<B>;
|
|
22
|
+
location(url: string): Response<B>;
|
|
28
23
|
links(links: {
|
|
29
24
|
[key: string]: string;
|
|
30
|
-
}): Response<
|
|
31
|
-
render(file: string, data?: Record<string, any>, options?:
|
|
32
|
-
vary(field: string): Response<
|
|
33
|
-
format(obj: FormatProps): Response<
|
|
34
|
-
redirect(url: string, status?: number): Response<
|
|
35
|
-
type(type: string): Response<
|
|
36
|
-
download(path: string, filename: string, options?: DownloadOptions, cb?: (err?:
|
|
37
|
-
attachment(filename?: string): Response<
|
|
25
|
+
}): Response<B>;
|
|
26
|
+
render<O extends TemplateEngineOptions = TemplateEngineOptions>(file: string, data?: Record<string, any>, options?: AppRenderOptions<O>): Response<B>;
|
|
27
|
+
vary(field: string): Response<B>;
|
|
28
|
+
format(obj: FormatProps): Response<B>;
|
|
29
|
+
redirect(url: string, status?: number): Response<B>;
|
|
30
|
+
type(type: string): Response<B>;
|
|
31
|
+
download(path: string, filename: string, options?: DownloadOptions, cb?: (err?: unknown) => void): Response<B>;
|
|
32
|
+
attachment(filename?: string): Response<B>;
|
|
38
33
|
app?: App;
|
|
39
|
-
locals
|
|
34
|
+
locals: Record<string, any>;
|
|
40
35
|
/**
|
|
41
36
|
* Send JSON response with JSONP callback support.
|
|
42
37
|
*
|
|
@@ -44,6 +39,6 @@ export interface Response<O = any, B = any> extends ServerResponse {
|
|
|
44
39
|
*
|
|
45
40
|
* @param obj Response object
|
|
46
41
|
*/
|
|
47
|
-
jsonp(obj: any): Response<
|
|
48
|
-
append(field: string, value: any): Response<
|
|
42
|
+
jsonp(obj: any): Response<B>;
|
|
43
|
+
append(field: string, value: any): Response<B>;
|
|
49
44
|
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Handler, NextFunction } from '@tinyhttp/router';
|
|
2
|
+
import type { ErrorHandler } from './onError.js';
|
|
3
|
+
import type { Request } from './request.js';
|
|
4
|
+
import type { Response } from './response.js';
|
|
5
|
+
import type { View } from './view.js';
|
|
6
|
+
/**
|
|
7
|
+
* tinyhttp App has a few settings for toggling features
|
|
8
|
+
*/
|
|
9
|
+
export type AppSettings = Partial<{
|
|
10
|
+
networkExtensions: boolean;
|
|
11
|
+
subdomainOffset: number;
|
|
12
|
+
bindAppToReqRes: boolean;
|
|
13
|
+
xPoweredBy: string | boolean;
|
|
14
|
+
enableReqRoute: boolean;
|
|
15
|
+
views: string | string[];
|
|
16
|
+
view: typeof View;
|
|
17
|
+
'view cache': boolean;
|
|
18
|
+
'view engine': string;
|
|
19
|
+
}>;
|
|
20
|
+
export type TemplateEngineOptions = {
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Function that processes the template
|
|
25
|
+
*/
|
|
26
|
+
export type TemplateEngine<O extends TemplateEngineOptions = TemplateEngineOptions> = (path: string, locals: Record<string, unknown>, opts: AppRenderOptions<O>, cb: (err: Error | null, html: unknown) => void) => void;
|
|
27
|
+
export type AppRenderOptions<O extends TemplateEngineOptions = TemplateEngineOptions> = O & Partial<{
|
|
28
|
+
cache: boolean;
|
|
29
|
+
ext: string;
|
|
30
|
+
viewsFolder: string;
|
|
31
|
+
_locals: Record<string, unknown>;
|
|
32
|
+
}>;
|
|
33
|
+
export type AppConstructor<Req extends Request = Request, Res extends Response = Response> = Partial<{
|
|
34
|
+
noMatchHandler: Handler<Req, Res>;
|
|
35
|
+
onError: ErrorHandler;
|
|
36
|
+
settings: AppSettings;
|
|
37
|
+
applyExtensions: (req: Request, res: Response, next: NextFunction) => void;
|
|
38
|
+
}>;
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;IAChC,iBAAiB,EAAE,OAAO,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,OAAO,CAAA;IACxB,UAAU,EAAE,MAAM,GAAG,OAAO,CAAA;IAC5B,cAAc,EAAE,OAAO,CAAA;IACvB,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACxB,IAAI,EAAE,OAAO,IAAI,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAC,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,qBAAqB,GAAG,qBAAqB,IAAI,CACpF,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,EACzB,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,KAC3C,IAAI,CAAA;AAET,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,qBAAqB,GAAG,qBAAqB,IAAI,CAAC,GACvF,OAAO,CAAC;IACN,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAC,CAAA;AAEJ,MAAM,MAAM,cAAc,CAAC,GAAG,SAAS,OAAO,GAAG,OAAO,EAAE,GAAG,SAAS,QAAQ,GAAG,QAAQ,IAAI,OAAO,CAAC;IACnG,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACjC,OAAO,EAAE,YAAY,CAAA;IACrB,QAAQ,EAAE,WAAW,CAAA;IACrB,eAAe,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;CAC3E,CAAC,CAAA"}
|
package/dist/view.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Ported from https://github.com/expressjs/express/blob/master/lib/view.js
|
|
3
|
+
* express
|
|
4
|
+
* Copyright(c) 2009-2013 TJ Holowaychuk
|
|
5
|
+
* Copyright(c) 2013 Roman Shtylman
|
|
6
|
+
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
|
7
|
+
* MIT Licensed
|
|
8
|
+
*/
|
|
9
|
+
import { TemplateEngineOptions, TemplateEngine } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Initialize a new `View` with the given `name`.
|
|
12
|
+
*
|
|
13
|
+
* Options:
|
|
14
|
+
*
|
|
15
|
+
* - `defaultEngine` the default template engine name
|
|
16
|
+
* - `engines` template engine require() cache
|
|
17
|
+
* - `root` root path for view lookup
|
|
18
|
+
*
|
|
19
|
+
* @param name
|
|
20
|
+
* @param options
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export declare class View<RenderOptions extends TemplateEngineOptions = TemplateEngineOptions> {
|
|
24
|
+
#private;
|
|
25
|
+
ext: string;
|
|
26
|
+
defaultEngine: string;
|
|
27
|
+
name: string;
|
|
28
|
+
engine: TemplateEngine<RenderOptions>;
|
|
29
|
+
path: string;
|
|
30
|
+
root: string | string[];
|
|
31
|
+
constructor(name: string, opts?: Partial<{
|
|
32
|
+
defaultEngine: string;
|
|
33
|
+
root: string | string[];
|
|
34
|
+
engines: Record<string, TemplateEngine<RenderOptions>>;
|
|
35
|
+
}>);
|
|
36
|
+
render(options: RenderOptions, data: Record<string, unknown>, cb: (err: Error | null, html: unknown) => void): void;
|
|
37
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinyhttp/app",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "0-legacy, tiny & fast web framework as a replacement of Express",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://tinyhttp.v1rtl.site",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"regexparam": "^2.0.1",
|
|
37
37
|
"@tinyhttp/cookie": "2.1.0",
|
|
38
38
|
"@tinyhttp/proxy-addr": "2.1.2",
|
|
39
|
-
"@tinyhttp/
|
|
40
|
-
"@tinyhttp/
|
|
41
|
-
"@tinyhttp/
|
|
39
|
+
"@tinyhttp/req": "2.2.0",
|
|
40
|
+
"@tinyhttp/router": "2.2.1",
|
|
41
|
+
"@tinyhttp/res": "2.2.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"dev": "vite",
|