@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 ADDED
@@ -0,0 +1,3 @@
1
+ import FalconFrame from "./index.js";
2
+ import { FFRequest, ParseBody } from "./types.js";
3
+ export declare function parseBody(req: FFRequest, body: string, FF: FalconFrame): Promise<ParseBody>;
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 { Body, Cookies, RouteHandler } from "./types.js";
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 declare class FalconFrame extends Router {
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
- constructor(loggerOpts?: LoggerOptions);
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, RouteHandler, Router };
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
- constructor(loggerOpts) {
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 { FFRequest, FFResponse, PluginSystem, renderHTML, Router };
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 { parseBody, parseCookies } from "./helpers.js";
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 contentType = req.headers["content-type"] || "";
78
- req.body = parseBody(contentType, body);
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
@@ -1,7 +1,9 @@
1
1
  import http from "http";
2
2
  import { CookieOptions } from "./types.js";
3
+ import FalconFrame from "./index.js";
3
4
  export declare class FFResponse extends http.ServerResponse {
4
5
  _ended: boolean;
6
+ FF: FalconFrame;
5
7
  /**
6
8
  * bind end for compatibility
7
9
  */
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.20",
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": "^22.12.0",
16
- "tsc-alias": "^1.8.10",
17
- "typescript": "^5.7.3"
15
+ "@types/node": "*",
16
+ "tsc-alias": "*",
17
+ "typescript": "*"
18
18
  },
19
19
  "dependencies": {
20
- "@wxn0brp/lucerna-log": "^0.1.1"
20
+ "@wxn0brp/lucerna-log": "^0.2.0"
21
21
  },
22
22
  "files": [
23
23
  "dist"