@fastly/expressly 2.1.0 → 2.2.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/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # v2.1.1 (Thu Oct 19 2023)
2
+
3
+ #### ⚠️ Pushed to `main`
4
+
5
+ - Delete src/.DS_Store ([@doramatadora](https://github.com/doramatadora))
6
+
7
+ #### Authors: 1
8
+
9
+ - Dora Militaru ([@doramatadora](https://github.com/doramatadora))
@@ -1,10 +1,11 @@
1
1
  import { EReq } from "./request";
2
2
  import { ERes } from "./response";
3
- export type ErrorMiddlewareCallback = (err: Error, req: EReq, res: ERes) => Promise<any>;
4
- export declare class ErrorMiddleware {
3
+ import { EErr } from "./errors";
4
+ export type ErrorMiddlewareCallback<Err extends EErr = EErr, Req extends EReq = EReq, Res extends ERes = ERes> = (err: Err, req: Req, res: Res) => Promise<any> | void;
5
+ export declare class ErrorMiddleware<Err extends EErr = EErr, Req extends EReq = EReq, Res extends ERes = ERes> {
5
6
  private matchFn;
6
7
  private callback;
7
8
  constructor(matchFn: Function, callback: ErrorMiddlewareCallback);
8
- check(event: EReq): 0 | 404 | string[];
9
- run(err: Error, req: EReq, res: ERes): Promise<any>;
9
+ check(event: Req): 0 | 404 | string[];
10
+ run(err: Err, req: Req, res: Res): Promise<any>;
10
11
  }
@@ -1,8 +1,12 @@
1
- export declare class ErrorNotFound extends Error {
1
+ export declare class EErr extends Error {
2
+ status: number;
3
+ constructor(message?: string);
4
+ }
5
+ export declare class ErrorNotFound extends EErr {
2
6
  status: number;
3
7
  constructor();
4
8
  }
5
- export declare class ErrorMethodNotAllowed extends Error {
9
+ export declare class ErrorMethodNotAllowed extends EErr {
6
10
  status: number;
7
11
  allow: string;
8
12
  constructor(allowedMethods: string[]);
@@ -1,11 +1,18 @@
1
- export class ErrorNotFound extends Error {
1
+ export class EErr extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.status = 500;
5
+ Object.setPrototypeOf(this, EErr.prototype);
6
+ }
7
+ }
8
+ export class ErrorNotFound extends EErr {
2
9
  constructor() {
3
10
  super("Not Found");
4
11
  this.status = 404;
5
12
  Object.setPrototypeOf(this, ErrorNotFound.prototype);
6
13
  }
7
14
  }
8
- export class ErrorMethodNotAllowed extends Error {
15
+ export class ErrorMethodNotAllowed extends EErr {
9
16
  constructor(allowedMethods) {
10
17
  super("Method Not Allowed");
11
18
  this.status = 405;
@@ -1,16 +1,25 @@
1
1
  import { EConfig, Method } from ".";
2
2
  import { RequestHandler, RequestHandlerCallback } from "./request-handler";
3
3
  import { ErrorMiddleware, ErrorMiddlewareCallback } from "./error-middleware";
4
+ import { EErr } from "./errors";
4
5
  import { EReq } from "./request";
5
6
  import { ERes } from "./response";
6
- export declare class Router<Req extends EReq = EReq, Res extends ERes = ERes> {
7
- requestHandlers: Array<RequestHandler>;
8
- errorHandlers: Array<ErrorMiddleware>;
7
+ export declare class Router<Req extends EReq = EReq, Res extends ERes = ERes, Err extends EErr = EErr> {
8
+ requestHandlers: Array<RequestHandler<Req, Res>>;
9
+ errorHandlers: Array<ErrorMiddleware<Err, Req, Res>>;
9
10
  config: EConfig;
10
11
  constructor(config?: EConfig);
11
12
  listen(): void;
12
13
  private handler;
13
- use(path: string | RequestHandlerCallback<Req, Res> | ErrorMiddlewareCallback, callback?: RequestHandlerCallback<Req, Res> | ErrorMiddlewareCallback): void;
14
+ private defaultErrorHandler;
15
+ /**
16
+ * Handles preflight requests from trusted origins configured by the user when initializing a router.
17
+ * Note that the wildcard value "*" will fail if the request is sent with credentials (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#directives)
18
+ * @param autoCorsPreflight the object containing CORS preflight option of trustedOrigins, an array of trusted origins.
19
+ * @returns 200 if the preflight request succeeds, 403 if it fails
20
+ */
21
+ private preflightHandler;
22
+ use(path: string | RequestHandlerCallback<Req, Res> | ErrorMiddlewareCallback<Err, Req, Res>, callback?: RequestHandlerCallback<Req, Res> | ErrorMiddlewareCallback<Err, Req, Res>): void;
14
23
  route(methods: Method[], pattern: string, callback: RequestHandlerCallback<Req, Res>): void;
15
24
  all(pattern: string, callback: RequestHandlerCallback<Req, Res>): void;
16
25
  get(pattern: string, callback: RequestHandlerCallback<Req, Res>): void;
@@ -5,49 +5,6 @@ import { ErrorNotFound, ErrorMethodNotAllowed } from "./errors";
5
5
  import { ERequest } from "./request";
6
6
  import { EResponse } from "./response";
7
7
  const pathMatcherCache = new Map();
8
- const defaultErrorHandler = (auto405) => async (err, req, res) => {
9
- if (err instanceof ErrorNotFound || (err instanceof ErrorMethodNotAllowed && !auto405)) {
10
- return res.sendStatus(404);
11
- }
12
- else if (err instanceof ErrorMethodNotAllowed) {
13
- res.headers.set("Allow", err.allow);
14
- return res.sendStatus(405);
15
- }
16
- console.error(err);
17
- res.withStatus(500).json({ error: err.message });
18
- };
19
- /**
20
- * Handles preflight requests from trusted origins configured by the user when initializing a router.
21
- * Note that the wildcard value "*" will fail if the request is sent with credentials (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#directives)
22
- * @param autoCorsPreflight the object containing CORS preflight option of trustedOrigins, an array of trusted origins.
23
- * @returns 200 if the preflight request succeeds, 403 if it fails
24
- */
25
- const preflightHandler = (autoCorsPreflight) => async (req, res) => {
26
- if (autoCorsPreflight.trustedOrigins.length === 0) {
27
- return res.sendStatus(403);
28
- }
29
- let originHeaderValue = null;
30
- if (autoCorsPreflight.trustedOrigins.length === 1 && autoCorsPreflight.trustedOrigins[0] === "*") {
31
- originHeaderValue = "*";
32
- }
33
- else if (req.headers.has("origin")) {
34
- const origin = req.headers.get("origin").toLowerCase();
35
- if (autoCorsPreflight.trustedOrigins.some((trustedOrigin) => trustedOrigin.toLowerCase() === origin)) {
36
- originHeaderValue = origin;
37
- }
38
- }
39
- if (!originHeaderValue) {
40
- return res.sendStatus(403);
41
- }
42
- if (req.headers.has("access-control-request-method")) {
43
- res.headers.set("access-control-allow-methods", req.headers.get("access-control-request-method"));
44
- }
45
- if (req.headers.has("access-control-request-headers")) {
46
- res.headers.set("access-control-allow-headers", req.headers.get("access-control-request-headers"));
47
- }
48
- res.headers.set("access-control-allow-origin", originHeaderValue);
49
- return res.sendStatus(200);
50
- };
51
8
  export class Router {
52
9
  constructor(config) {
53
10
  this.requestHandlers = [];
@@ -63,7 +20,7 @@ export class Router {
63
20
  ...config
64
21
  };
65
22
  if (this.config.autoCorsPreflight) {
66
- this.options("*", preflightHandler(this.config.autoCorsPreflight));
23
+ this.options("*", this.preflightHandler);
67
24
  }
68
25
  }
69
26
  listen() {
@@ -78,12 +35,55 @@ export class Router {
78
35
  }
79
36
  catch (err) {
80
37
  // Add default error handler.
81
- this.use(defaultErrorHandler(this.config.auto405));
38
+ this.use(this.defaultErrorHandler);
82
39
  // Run error handler stack.
83
40
  await this.runErrorHandlers(err, req, res);
84
41
  }
85
42
  return Router.serializeResponse(res);
86
43
  }
44
+ async defaultErrorHandler(err, req, res) {
45
+ if (err instanceof ErrorNotFound || (err instanceof ErrorMethodNotAllowed && !this.config.auto405)) {
46
+ return res.sendStatus(404);
47
+ }
48
+ else if (err instanceof ErrorMethodNotAllowed) {
49
+ res.headers.set("Allow", err.allow);
50
+ return res.sendStatus(405);
51
+ }
52
+ console.error(err);
53
+ res.withStatus(500).json({ error: err.message });
54
+ }
55
+ /**
56
+ * Handles preflight requests from trusted origins configured by the user when initializing a router.
57
+ * Note that the wildcard value "*" will fail if the request is sent with credentials (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#directives)
58
+ * @param autoCorsPreflight the object containing CORS preflight option of trustedOrigins, an array of trusted origins.
59
+ * @returns 200 if the preflight request succeeds, 403 if it fails
60
+ */
61
+ async preflightHandler(req, res) {
62
+ if (this.config.autoCorsPreflight.trustedOrigins.length === 0) {
63
+ return res.sendStatus(403);
64
+ }
65
+ let originHeaderValue = null;
66
+ if (this.config.autoCorsPreflight.trustedOrigins.includes("*")) {
67
+ originHeaderValue = "*";
68
+ }
69
+ else if (req.headers.has("origin")) {
70
+ const origin = req.headers.get("origin").toLowerCase();
71
+ if (this.config.autoCorsPreflight.trustedOrigins.some((trustedOrigin) => trustedOrigin.toLowerCase() === origin)) {
72
+ originHeaderValue = origin;
73
+ }
74
+ }
75
+ if (!originHeaderValue) {
76
+ return res.sendStatus(403);
77
+ }
78
+ if (req.headers.has("access-control-request-method")) {
79
+ res.headers.set("access-control-allow-methods", req.headers.get("access-control-request-method"));
80
+ }
81
+ if (req.headers.has("access-control-request-headers")) {
82
+ res.headers.set("access-control-allow-headers", req.headers.get("access-control-request-headers"));
83
+ }
84
+ res.headers.set("access-control-allow-origin", originHeaderValue);
85
+ return res.sendStatus(200);
86
+ }
87
87
  // Middleware attach point.
88
88
  use(path, callback) {
89
89
  const cb = path instanceof Function ? path : callback;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastly/expressly",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Express-style router for Fastly's Compute@Edge.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,34 @@
1
+ import { expectType } from 'tsd';
2
+ import { Router } from "../dist";
3
+ import { EReq } from "../dist/lib/routing/request";
4
+ import { ERes } from '../dist/lib/routing/response';
5
+ import { EErr } from "../dist/lib/routing/errors";
6
+
7
+ // Default Err types
8
+ {
9
+ const router = new Router();
10
+ router.use(async (err, _, res) => {
11
+ expectType<EErr>(err)
12
+ });
13
+ }
14
+
15
+ // Custom Req and Res types
16
+ {
17
+ interface MeowErr extends EErr {
18
+ meow(): string
19
+ }
20
+
21
+ interface WoofErr extends EErr {
22
+ woof(): string
23
+ }
24
+
25
+ interface MyErr extends MeowErr, WoofErr { }
26
+
27
+ const router = new Router<EReq,ERes,MyErr>();
28
+ router.use(async (err, _, res) => {
29
+ expectType<MyErr>(err)
30
+ err.meow()
31
+ err.woof()
32
+ });
33
+
34
+ }