@wxn0brp/falcon-frame 0.0.20 → 0.1.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/dist/body.d.ts +3 -0
- package/dist/body.js +46 -0
- package/dist/helpers.d.ts +1 -2
- package/dist/helpers.js +6 -15
- package/dist/index.d.ts +13 -4
- package/dist/index.js +18 -4
- package/dist/req.js +6 -4
- package/dist/res.d.ts +2 -0
- package/dist/res.js +5 -0
- package/dist/types.d.ts +6 -0
- package/package.json +5 -5
package/dist/body.d.ts
ADDED
package/dist/body.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import querystring from "querystring";
|
|
2
|
+
const parseBodyFunctions = {
|
|
3
|
+
"application/json": async (body) => ({ body: JSON.parse(body) }),
|
|
4
|
+
"application/x-www-form-urlencoded": async (body) => ({ body: querystring.parse(body) }),
|
|
5
|
+
};
|
|
6
|
+
export async function parseBody(req, body, FF) {
|
|
7
|
+
const funcs = Object.assign({}, parseBodyFunctions, FF.customParsers || {});
|
|
8
|
+
const limit = parseLimit(FF.opts.bodyLimit);
|
|
9
|
+
try {
|
|
10
|
+
if (limit && body.length > limit) {
|
|
11
|
+
await FF.logger.warn(`Body size exceeds limit of ${limit} bytes`);
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
const type = req.headers["content-type"] || "";
|
|
15
|
+
const func = funcs[type];
|
|
16
|
+
if (!func)
|
|
17
|
+
return {};
|
|
18
|
+
const data = await func(body, req, FF);
|
|
19
|
+
if (!data || typeof data !== "object")
|
|
20
|
+
return {};
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
await FF.logger.warn(`Error parsing body: ${e}`);
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function parseLimit(limit) {
|
|
29
|
+
if (!limit)
|
|
30
|
+
return 0;
|
|
31
|
+
if (typeof limit === "number")
|
|
32
|
+
return limit;
|
|
33
|
+
if (typeof limit !== "string")
|
|
34
|
+
return 0;
|
|
35
|
+
const match = limit.match(/^(\d+)([kmg])?$/i);
|
|
36
|
+
if (!match)
|
|
37
|
+
return 0;
|
|
38
|
+
const num = parseInt(match[1], 10);
|
|
39
|
+
const unit = match[2]?.toLowerCase();
|
|
40
|
+
switch (unit) {
|
|
41
|
+
case "k": return num * 1024;
|
|
42
|
+
case "m": return num * 1024 * 1024;
|
|
43
|
+
case "g": return num * 1024 * 1024 * 1024;
|
|
44
|
+
default: return num;
|
|
45
|
+
}
|
|
46
|
+
}
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Cookies, RouteHandler } from "./types.js";
|
|
2
2
|
export declare function parseCookies(cookieHeader: string): Cookies;
|
|
3
|
-
export declare function parseBody(contentType: string, body: string): Body;
|
|
4
3
|
export declare function getContentType(filePath: string, utf8?: boolean): string;
|
|
5
4
|
export declare function handleStaticFiles(dirPath: string, utf8?: boolean): RouteHandler;
|
package/dist/helpers.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import querystring from "querystring";
|
|
4
3
|
export function parseCookies(cookieHeader) {
|
|
5
4
|
const cookies = {};
|
|
6
5
|
cookieHeader.split(";").forEach(cookie => {
|
|
@@ -10,20 +9,6 @@ export function parseCookies(cookieHeader) {
|
|
|
10
9
|
});
|
|
11
10
|
return cookies;
|
|
12
11
|
}
|
|
13
|
-
export function parseBody(contentType, body) {
|
|
14
|
-
if (contentType.includes("application/json")) {
|
|
15
|
-
try {
|
|
16
|
-
return JSON.parse(body);
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return {};
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
else if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
23
|
-
return querystring.parse(body);
|
|
24
|
-
}
|
|
25
|
-
return {};
|
|
26
|
-
}
|
|
27
12
|
function _getContentType(filePath) {
|
|
28
13
|
const ext = path.extname(filePath).toLowerCase();
|
|
29
14
|
switch (ext) {
|
|
@@ -83,6 +68,12 @@ export function handleStaticFiles(dirPath, utf8 = true) {
|
|
|
83
68
|
return true;
|
|
84
69
|
}
|
|
85
70
|
}
|
|
71
|
+
const htmlPath = filePath + ".html";
|
|
72
|
+
if (fs.existsSync(htmlPath) && fs.statSync(htmlPath).isFile()) {
|
|
73
|
+
res.ct(getContentType(htmlPath, utf8));
|
|
74
|
+
fs.createReadStream(htmlPath).pipe(res);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
86
77
|
next();
|
|
87
78
|
};
|
|
88
79
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,15 +4,24 @@ import { PluginSystem } from "./plugins.js";
|
|
|
4
4
|
import { renderHTML } from "./render.js";
|
|
5
5
|
import { FFResponse } from "./res.js";
|
|
6
6
|
import { Router } from "./router.js";
|
|
7
|
-
import { BeforeHandleRequest, FFRequest, RouteHandler } from "./types.js";
|
|
8
|
-
export
|
|
7
|
+
import type { BeforeHandleRequest, FFRequest, ParseBodyFunction, RouteHandler } from "./types.js";
|
|
8
|
+
export interface Opts {
|
|
9
|
+
loggerOpts?: LoggerOptions;
|
|
10
|
+
bodyLimit?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class FalconFrame<Vars extends Record<string, any> = any> extends Router {
|
|
9
13
|
logger: Logger;
|
|
10
|
-
|
|
14
|
+
customParsers: Record<string, ParseBodyFunction>;
|
|
15
|
+
vars: Vars;
|
|
16
|
+
opts: Opts;
|
|
17
|
+
constructor(opts?: Partial<Opts>);
|
|
11
18
|
listen(port: number, callback?: (() => void) | boolean, beforeHandleRequest?: BeforeHandleRequest): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
12
19
|
getApp(beforeHandleRequest?: BeforeHandleRequest): (req: any, res: any) => Promise<void>;
|
|
20
|
+
setVar(key: keyof Vars, value: typeof this.vars[keyof Vars]): void;
|
|
21
|
+
getVar(key: string): typeof this.vars[keyof Vars];
|
|
13
22
|
}
|
|
14
23
|
export default FalconFrame;
|
|
15
|
-
export { FFRequest, FFResponse, PluginSystem, renderHTML,
|
|
24
|
+
export { FFRequest, FFResponse, PluginSystem, renderHTML, Router, RouteHandler };
|
|
16
25
|
export * as Plugins from "./plugins/index.js";
|
|
17
26
|
export * as PluginsEngine from "./plugins.js";
|
|
18
27
|
export * as Helpers from "./helpers.js";
|
package/dist/index.js
CHANGED
|
@@ -5,15 +5,21 @@ import { renderHTML } from "./render.js";
|
|
|
5
5
|
import { handleRequest } from "./req.js";
|
|
6
6
|
import { FFResponse } from "./res.js";
|
|
7
7
|
import { Router } from "./router.js";
|
|
8
|
-
import { FFRequest } from "./types.js";
|
|
9
8
|
export class FalconFrame extends Router {
|
|
10
9
|
logger;
|
|
11
|
-
|
|
10
|
+
customParsers = {};
|
|
11
|
+
vars = {};
|
|
12
|
+
opts = {};
|
|
13
|
+
constructor(opts = {}) {
|
|
12
14
|
super();
|
|
13
15
|
this.logger = new Logger({
|
|
14
16
|
loggerName: "falcon-frame",
|
|
15
|
-
...loggerOpts
|
|
17
|
+
...[opts?.loggerOpts || {}],
|
|
16
18
|
});
|
|
19
|
+
this.opts = {
|
|
20
|
+
bodyLimit: "10m",
|
|
21
|
+
...opts,
|
|
22
|
+
};
|
|
17
23
|
}
|
|
18
24
|
listen(port, callback, beforeHandleRequest) {
|
|
19
25
|
const server = http.createServer(this.getApp(beforeHandleRequest));
|
|
@@ -38,9 +44,17 @@ export class FalconFrame extends Router {
|
|
|
38
44
|
await handleRequest(req, res, this);
|
|
39
45
|
};
|
|
40
46
|
}
|
|
47
|
+
setVar(key, value) {
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
this.vars[key] = value;
|
|
50
|
+
}
|
|
51
|
+
getVar(key) {
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
return this.vars[key];
|
|
54
|
+
}
|
|
41
55
|
}
|
|
42
56
|
export default FalconFrame;
|
|
43
|
-
export {
|
|
57
|
+
export { FFResponse, PluginSystem, renderHTML, Router };
|
|
44
58
|
export * as Plugins from "./plugins/index.js";
|
|
45
59
|
export * as PluginsEngine from "./plugins.js";
|
|
46
60
|
export * as Helpers from "./helpers.js";
|
package/dist/req.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { URL } from "url";
|
|
2
|
-
import {
|
|
2
|
+
import { parseCookies } from "./helpers.js";
|
|
3
3
|
import { FFResponse } from "./res.js";
|
|
4
4
|
import { validate } from "./valid.js";
|
|
5
5
|
import { getMiddlewares, matchMiddleware } from "./middleware.js";
|
|
6
|
+
import { parseBody } from "./body.js";
|
|
6
7
|
export function handleRequest(req, res, FF) {
|
|
7
8
|
Object.setPrototypeOf(res, FFResponse.prototype);
|
|
9
|
+
res.FF = FF;
|
|
8
10
|
const originalEnd = res.end;
|
|
9
11
|
res.end = function (...any) {
|
|
10
12
|
res._ended = true;
|
|
@@ -73,9 +75,9 @@ export function handleRequest(req, res, FF) {
|
|
|
73
75
|
}
|
|
74
76
|
let body = "";
|
|
75
77
|
req.on("data", chunk => (body += chunk.toString()));
|
|
76
|
-
req.on("end", () => {
|
|
77
|
-
const
|
|
78
|
-
|
|
78
|
+
req.on("end", async () => {
|
|
79
|
+
const parsedBody = await parseBody(req, body, FF);
|
|
80
|
+
Object.assign(req, parsedBody);
|
|
79
81
|
logger.debug(`Request body: ${JSON.stringify(req.body)}`);
|
|
80
82
|
next();
|
|
81
83
|
});
|
package/dist/res.d.ts
CHANGED
package/dist/res.js
CHANGED
|
@@ -2,8 +2,10 @@ import http from "http";
|
|
|
2
2
|
import { getContentType } from "./helpers.js";
|
|
3
3
|
import { createReadStream } from "fs";
|
|
4
4
|
import { renderHTML } from "./render.js";
|
|
5
|
+
import { resolve } from "path";
|
|
5
6
|
export class FFResponse extends http.ServerResponse {
|
|
6
7
|
_ended = false;
|
|
8
|
+
FF;
|
|
7
9
|
/**
|
|
8
10
|
* bind end for compatibility
|
|
9
11
|
*/
|
|
@@ -105,6 +107,9 @@ export class FFResponse extends http.ServerResponse {
|
|
|
105
107
|
*/
|
|
106
108
|
render(templatePath, data = {}) {
|
|
107
109
|
this.setHeader("Content-Type", "text/html");
|
|
110
|
+
if (this.FF.vars["views"] && !templatePath.endsWith(".html")) {
|
|
111
|
+
templatePath = resolve(this.FF.vars["views"] + "/" + templatePath + ".html");
|
|
112
|
+
}
|
|
108
113
|
this.end(renderHTML(templatePath, data));
|
|
109
114
|
return this;
|
|
110
115
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import FalconFrame from "./index.js";
|
|
1
2
|
import { FFResponse } from "./res.js";
|
|
2
3
|
import http from "http";
|
|
3
4
|
export type RouteHandler = (req: FFRequest, res: FFResponse, next?: () => void) => void | any;
|
|
@@ -14,6 +15,11 @@ export interface Query {
|
|
|
14
15
|
export interface Body {
|
|
15
16
|
[key: string]: any;
|
|
16
17
|
}
|
|
18
|
+
export interface ParseBody {
|
|
19
|
+
body?: Body;
|
|
20
|
+
files?: Record<string, Buffer>;
|
|
21
|
+
}
|
|
22
|
+
export type ParseBodyFunction = (body: string, req: FFRequest, FF: FalconFrame) => Promise<ParseBody>;
|
|
17
23
|
export declare class FFRequest extends http.IncomingMessage {
|
|
18
24
|
path: string;
|
|
19
25
|
query: Query;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wxn0brp/falcon-frame",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"author": "wxn0brP",
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
"url": "https://github.com/wxn0brP/FalconFrame.git"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@types/node": "
|
|
16
|
-
"tsc-alias": "
|
|
17
|
-
"typescript": "
|
|
15
|
+
"@types/node": "*",
|
|
16
|
+
"tsc-alias": "*",
|
|
17
|
+
"typescript": "*"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@wxn0brp/lucerna-log": "^0.
|
|
20
|
+
"@wxn0brp/lucerna-log": "^0.2.0"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist"
|