@wxn0brp/falcon-frame 0.9.3 → 0.9.5

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/index.d.ts CHANGED
@@ -43,7 +43,8 @@ export declare class FalconFrame<Vars extends Record<string, any> = {}> extends
43
43
  set500(handler: ErrorHandler): void;
44
44
  }
45
45
  export default FalconFrame;
46
- export { OfflineEngine, OfflineRequest, OfflineResponse } from "./engine.js";
46
+ export { OfflineEngine } from "./engine.js";
47
+ export type { OfflineRequest, OfflineResponse } from "./engine.js";
47
48
  export * as Helpers from "./helpers.js";
48
49
  export type { FFOpts as Opts } from "./types.js";
49
50
  export { validateBody } from "./valid.js";
package/dist/res.d.ts CHANGED
@@ -83,4 +83,11 @@ export declare class FFResponse extends http.ServerResponse {
83
83
  * @returns The response object
84
84
  */
85
85
  sseSend(data: string | object): this;
86
+ /**
87
+ * Sends a Server-Sent Event with an event type to the client.
88
+ * @param event The event type
89
+ * @param data The data to be sent. If an object, it will be JSON.stringified.
90
+ * @returns The response object
91
+ */
92
+ sseEventSend(event: string, data: string | object): this;
86
93
  }
package/dist/res.js CHANGED
@@ -180,4 +180,16 @@ export class FFResponse extends http.ServerResponse {
180
180
  this.write(`data: ${data}\n\n`);
181
181
  return this;
182
182
  }
183
+ /**
184
+ * Sends a Server-Sent Event with an event type to the client.
185
+ * @param event The event type
186
+ * @param data The data to be sent. If an object, it will be JSON.stringified.
187
+ * @returns The response object
188
+ */
189
+ sseEventSend(event, data) {
190
+ if (typeof data === "object")
191
+ data = JSON.stringify(data);
192
+ this.write(`event: ${event}\ndata: ${data}\n\n`);
193
+ return this;
194
+ }
183
195
  }
package/dist/router.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SSEManager } from "./sse.js";
2
- import { Method, Middleware, RouteHandler, StaticServeOptions } from "./types.js";
2
+ import { Method, Middleware, RouteHandler, StaticFileOptions, StaticServeOptions } from "./types.js";
3
3
  export type MiddlewareFn = RouteHandler | Router | {
4
4
  getRouteHandler(): RouteHandler;
5
5
  };
@@ -14,7 +14,8 @@ export declare class Router {
14
14
  patch(path: string, ...handlers: RouteHandler[]): this;
15
15
  all(path: string, ...handlers: RouteHandler[]): this;
16
16
  static(apiPath: string, dirPath?: string, opts?: StaticServeOptions): this;
17
+ file(routePath: string, filePath: string, opts?: StaticFileOptions): this;
17
18
  sse(path: string, ...handlers: RouteHandler[]): SSEManager;
18
19
  customParser(path: string, handler: RouteHandler, method?: Method): this;
19
- router(path: string): Router;
20
+ router(path?: string): Router;
20
21
  }
package/dist/router.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SSEManager } from "./sse.js";
2
- import { handleStaticFiles } from "./static.js";
2
+ import { handleSingleFile, handleStaticFiles } from "./static.js";
3
3
  export class Router {
4
4
  middlewares = [];
5
5
  addRoute(method, path, ...handlers) {
@@ -68,6 +68,10 @@ export class Router {
68
68
  this.use(apiPath, handleStaticFiles(dirPath, opts));
69
69
  return this;
70
70
  }
71
+ file(routePath, filePath, opts = {}) {
72
+ this.use(routePath, handleSingleFile(filePath, opts));
73
+ return this;
74
+ }
71
75
  sse(path, ...handlers) {
72
76
  const lastHandler = handlers.pop() || (() => { });
73
77
  const manager = new SSEManager();
@@ -80,7 +84,7 @@ export class Router {
80
84
  this.middlewares[index - 1].customParser = true;
81
85
  return this;
82
86
  }
83
- router(path) {
87
+ router(path = "/") {
84
88
  const router = new Router();
85
89
  this.use(path, router);
86
90
  return router;
package/dist/sse.d.ts CHANGED
@@ -12,5 +12,7 @@ export declare class SSEManager {
12
12
  }>;
13
13
  sendAll(data: any): void;
14
14
  sendTo(id: string, data: any): void;
15
+ sendEventAll(event: string, data: any): void;
16
+ sendEventTo(id: string, event: string, data: any): void;
15
17
  disconnect(id: string): void;
16
18
  }
package/dist/sse.js CHANGED
@@ -20,21 +20,30 @@ export class SSEManager {
20
20
  return this._clients;
21
21
  }
22
22
  sendAll(data) {
23
- for (const { res } of this._clients.values()) {
23
+ for (const { res } of this._clients.values())
24
24
  res.sseSend(data);
25
- }
26
25
  }
27
26
  sendTo(id, data) {
28
27
  const client = this._clients.get(id);
29
- if (client) {
30
- client.res.sseSend(data);
31
- }
28
+ if (!client)
29
+ return;
30
+ client.res.sseSend(data);
31
+ }
32
+ sendEventAll(event, data) {
33
+ for (const { res } of this._clients.values())
34
+ res.sseEventSend(event, data);
35
+ }
36
+ sendEventTo(id, event, data) {
37
+ const client = this._clients.get(id);
38
+ if (!client)
39
+ return;
40
+ client.res.sseEventSend(event, data);
32
41
  }
33
42
  disconnect(id) {
34
43
  const client = this._clients.get(id);
35
- if (client) {
36
- client.res.end();
37
- this._clients.delete(id);
38
- }
44
+ if (!client)
45
+ return;
46
+ client.res.end();
47
+ this._clients.delete(id);
39
48
  }
40
49
  }
package/dist/static.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- import { RouteHandler, StaticServeOptions } from "./types.js";
1
+ import { RouteHandler, StaticFileOptions, StaticServeOptions } from "./types.js";
2
+ export declare function handleSingleFile(filePath: string, opts: StaticFileOptions): RouteHandler;
2
3
  export declare function handleStaticFiles(dirPath: string, opts: StaticServeOptions): RouteHandler;
package/dist/static.js CHANGED
@@ -1,6 +1,44 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import { ensureLeadingDot, getContentType } from "./helpers.js";
4
+ export function handleSingleFile(filePath, opts) {
5
+ opts = {
6
+ utf8: true,
7
+ etag: true,
8
+ errorIfFileNotFound: true,
9
+ ...opts,
10
+ };
11
+ if (opts.errorIfFileNotFound && !fs.existsSync(filePath))
12
+ throw new Error(`File ${filePath} does not exist`);
13
+ return (req, res, next) => {
14
+ if (req.method !== "GET" && req.method !== "HEAD")
15
+ return next();
16
+ let stats;
17
+ try {
18
+ stats = fs.statSync(filePath);
19
+ }
20
+ catch (e) {
21
+ res.statusCode = 404;
22
+ res.FF._404(req, res);
23
+ return;
24
+ }
25
+ if (opts.etag) {
26
+ const etag = `W/"${stats.size}-${stats.mtime.getTime()}"`;
27
+ if (req.headers["if-none-match"] === etag) {
28
+ res.status(304).end();
29
+ return;
30
+ }
31
+ res.setHeader("ETag", etag);
32
+ }
33
+ res.ct(getContentType(filePath, opts.utf8));
34
+ if (req.method === "HEAD") {
35
+ res.setHeader("Content-Length", stats.size);
36
+ res.end();
37
+ return;
38
+ }
39
+ fs.createReadStream(filePath).pipe(res);
40
+ };
41
+ }
4
42
  export function handleStaticFiles(dirPath, opts) {
5
43
  opts = {
6
44
  utf8: true,
package/dist/types.d.ts CHANGED
@@ -76,6 +76,11 @@ export interface StaticServeOptions {
76
76
  errorIfDirNotFound?: boolean;
77
77
  notRenderHtml?: boolean;
78
78
  }
79
+ export interface StaticFileOptions {
80
+ utf8?: boolean;
81
+ etag?: boolean;
82
+ errorIfFileNotFound?: boolean;
83
+ }
79
84
  export type EngineCallback = (path: string, data: any, callback: (e: any, rendered?: string) => void, FF?: FalconFrame) => void;
80
85
  export interface RenderOptions {
81
86
  notUseViews?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wxn0brp/falcon-frame",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "author": "wxn0brP",