@fastly/expressly 1.0.0-alpha.4 → 1.0.0-alpha.7

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/README.md CHANGED
@@ -17,11 +17,11 @@ First, head over to [developer.fastly.com](https://developer.fastly.com) to get
17
17
  Install expressly from the [npm registry](https://www.npmjs.com/package/@fastly/expressly):
18
18
 
19
19
  ```shell
20
- npm i @fastly/expressly@1.0.0-alpha.4
20
+ npm i @fastly/expressly
21
21
  ```
22
22
 
23
23
  ```shell
24
- yarn add @fastly/expressly@1.0.0-alpha.4
24
+ yarn add @fastly/expressly
25
25
  ```
26
26
 
27
27
  ### Your first expressly app
@@ -1,11 +1,11 @@
1
- /// <reference types="@fastly/js-compute" />
2
- export declare class ECommonObject {
3
- headers: Headers;
4
- set(headerNameOrObject: string | {
5
- [key: string]: string;
6
- }, value?: string): void;
7
- private appendHeader;
8
- append(headerNameOrObject: string | {
9
- [key: string]: string | string[];
10
- }, value?: string | string[]): void;
11
- }
1
+ export declare function addCommonMethods<T extends new (...args: any[]) => any>(Base: T): {
2
+ new (...args: any[]): {
3
+ [x: string]: any;
4
+ set(headerNameOrObject: string | {
5
+ [key: string]: string;
6
+ }, value?: string): void;
7
+ append(headerNameOrObject: string | {
8
+ [key: string]: string | string[];
9
+ }, value?: string | string[]): void;
10
+ };
11
+ } & T;
@@ -1,36 +1,35 @@
1
- export class ECommonObject {
2
- constructor() {
3
- this.headers = new Headers();
4
- }
5
- // Header helpers.
6
- set(headerNameOrObject, value) {
7
- if (typeof headerNameOrObject === "string") {
8
- this.headers.set(headerNameOrObject, value);
1
+ export function addCommonMethods(Base) {
2
+ return class extends Base {
3
+ // Header helpers.
4
+ set(headerNameOrObject, value) {
5
+ if (typeof headerNameOrObject === "string") {
6
+ this.headers.set(headerNameOrObject, value);
7
+ }
8
+ else {
9
+ Object.keys(headerNameOrObject).forEach((headerName) => {
10
+ this.headers.set(headerName, headerNameOrObject[headerName]);
11
+ });
12
+ }
9
13
  }
10
- else {
11
- Object.keys(headerNameOrObject).forEach((headerName) => {
12
- this.headers.set(headerName, headerNameOrObject[headerName]);
13
- });
14
+ append(headerNameOrObject, value) {
15
+ const appendHeader = (headerName, headerValue) => {
16
+ if (typeof headerValue === "string") {
17
+ this.headers.append(headerName, headerValue);
18
+ }
19
+ else if (Array.isArray(headerValue)) {
20
+ headerValue.forEach((v) => {
21
+ this.headers.append(headerName, v);
22
+ });
23
+ }
24
+ };
25
+ if (typeof headerNameOrObject === "string") {
26
+ appendHeader(headerNameOrObject, value);
27
+ }
28
+ else {
29
+ Object.keys(headerNameOrObject).forEach((headerName) => {
30
+ appendHeader(headerName, headerNameOrObject[headerName]);
31
+ });
32
+ }
14
33
  }
15
- }
16
- appendHeader(headerName, headerValue) {
17
- if (typeof headerValue === "string") {
18
- this.headers.append(headerName, headerValue);
19
- }
20
- else if (Array.isArray(headerValue)) {
21
- headerValue.forEach((v) => {
22
- this.headers.append(headerName, v);
23
- });
24
- }
25
- }
26
- append(headerNameOrObject, value) {
27
- if (typeof headerNameOrObject === "string") {
28
- this.appendHeader(headerNameOrObject, value);
29
- }
30
- else {
31
- Object.keys(headerNameOrObject).forEach((headerName) => {
32
- this.appendHeader(headerName, headerNameOrObject[headerName]);
33
- });
34
- }
35
- }
34
+ };
36
35
  }
@@ -1,10 +1,10 @@
1
- import { ERequest } from "./request";
2
- import { EResponse } from "./response";
3
- export declare type ErrorMiddlewareCallback = (err: Error, req: ERequest, res: EResponse) => Promise<any>;
1
+ import { EReq } from "./request";
2
+ import { ERes } from "./response";
3
+ export declare type ErrorMiddlewareCallback = (err: Error, req: EReq, res: ERes) => Promise<any>;
4
4
  export declare class ErrorMiddleware {
5
5
  private matchFn;
6
6
  private callback;
7
7
  constructor(matchFn: Function, callback: ErrorMiddlewareCallback);
8
- check(event: ERequest): 0 | 404 | string[];
9
- run(err: Error, req: ERequest, res: EResponse): Promise<any>;
8
+ check(event: EReq): 0 | 404 | string[];
9
+ run(err: Error, req: EReq, res: ERes): Promise<any>;
10
10
  }
@@ -0,0 +1 @@
1
+ export declare function applyMixins(derivedConstructor: any, baseConstructors: any[]): void;
@@ -0,0 +1,9 @@
1
+ export function applyMixins(derivedConstructor, baseConstructors) {
2
+ baseConstructors.forEach(baseConstructor => {
3
+ Object.getOwnPropertyNames(baseConstructor.prototype).forEach(name => {
4
+ if (name !== 'constructor') {
5
+ derivedConstructor.prototype[name] = baseConstructor.prototype[name];
6
+ }
7
+ });
8
+ });
9
+ }
@@ -1,12 +1,10 @@
1
1
  /// <reference types="@fastly/js-compute" />
2
2
  import { CookieMap } from "./cookie-map";
3
3
  import { EConfig } from "..";
4
- export declare class ERequest extends Request {
4
+ declare class ERequestBase extends Request {
5
5
  private config;
6
- private event;
6
+ private readonly event;
7
7
  readonly clientInfo: ClientInfo;
8
- readonly method: string;
9
- headers: Headers;
10
8
  urlObj: URL;
11
9
  query: URLSearchParams;
12
10
  params: {
@@ -20,11 +18,17 @@ export declare class ERequest extends Request {
20
18
  get secure(): boolean;
21
19
  get subdomains(): Array<string>;
22
20
  get hostname(): string;
23
- set(headerNameOrObject: string | {
24
- [key: string]: string;
25
- }, value?: string): void;
26
- private appendHeader;
27
- append(headerNameOrObject: string | {
28
- [key: string]: string | string[];
29
- }, value?: string | string[]): void;
30
21
  }
22
+ export declare const ERequest: {
23
+ new (...args: any[]): {
24
+ [x: string]: any;
25
+ set(headerNameOrObject: string | {
26
+ [key: string]: string;
27
+ }, value?: string): void;
28
+ append(headerNameOrObject: string | {
29
+ [key: string]: string | string[];
30
+ }, value?: string | string[]): void;
31
+ };
32
+ } & typeof ERequestBase;
33
+ export declare type EReq = InstanceType<typeof ERequest>;
34
+ export {};
@@ -1,23 +1,31 @@
1
+ import { addCommonMethods } from "../common";
1
2
  import { CookieMap } from "./cookie-map";
2
- export class ERequest extends Request {
3
+ // Will extend Request correctly after https://github.com/fastly/js-compute-runtime/pull/116 is merged
4
+ // See: https://github.com/fastly/js-compute-runtime/issues/113
5
+ class ERequestBase extends Request {
3
6
  constructor(config, event) {
4
- super(event.request);
7
+ super(event.request, {
8
+ headers: event.request.headers,
9
+ method: event.request.method,
10
+ body: event.request.body,
11
+ });
5
12
  this.config = config;
6
13
  this.event = event;
7
14
  this.params = {};
8
- this.clientInfo = event.client;
9
- this.urlObj = new URL(event.request.url);
15
+ this.clientInfo = this.event.client;
16
+ this.urlObj = new URL(this.url);
10
17
  this.query = this.urlObj.searchParams;
18
+ Object.defineProperty(this, 'url', {
19
+ get() {
20
+ return this.urlObj.toString();
21
+ }
22
+ });
11
23
  // Parse cookies.
12
24
  if (this.config.parseCookie) {
13
25
  this.cookies = new CookieMap(this.headers);
14
26
  }
15
27
  }
16
28
  // Express-like URL helpers.
17
- // get url(): string {
18
- // console.log("custom getter");
19
- // return this.urlObj.toString();
20
- // }
21
29
  get path() {
22
30
  return this.urlObj.pathname;
23
31
  }
@@ -36,35 +44,5 @@ export class ERequest extends Request {
36
44
  get hostname() {
37
45
  return this.urlObj.hostname;
38
46
  }
39
- // Header helpers.
40
- set(headerNameOrObject, value) {
41
- if (typeof headerNameOrObject === "string") {
42
- this.headers.set(headerNameOrObject, value);
43
- }
44
- else {
45
- Object.keys(headerNameOrObject).forEach((headerName) => {
46
- this.headers.set(headerName, headerNameOrObject[headerName]);
47
- });
48
- }
49
- }
50
- appendHeader(headerName, headerValue) {
51
- if (typeof headerValue === "string") {
52
- this.headers.append(headerName, headerValue);
53
- }
54
- else if (Array.isArray(headerValue)) {
55
- headerValue.forEach((v) => {
56
- this.headers.append(headerName, v);
57
- });
58
- }
59
- }
60
- append(headerNameOrObject, value) {
61
- if (typeof headerNameOrObject === "string") {
62
- this.appendHeader(headerNameOrObject, value);
63
- }
64
- else {
65
- Object.keys(headerNameOrObject).forEach((headerName) => {
66
- this.appendHeader(headerName, headerNameOrObject[headerName]);
67
- });
68
- }
69
- }
70
47
  }
48
+ export const ERequest = addCommonMethods(ERequestBase);
@@ -0,0 +1,9 @@
1
+ /// <reference types="@fastly/js-compute" />
2
+ export declare class CookieMap extends Map {
3
+ private headers;
4
+ constructor(headers: Headers);
5
+ clear(): void;
6
+ set(key: string, value: string): this;
7
+ delete(key: string): boolean;
8
+ private serialize;
9
+ }
@@ -0,0 +1,37 @@
1
+ import cookie from "cookie";
2
+ export class CookieMap extends Map {
3
+ constructor(headers) {
4
+ super();
5
+ this.headers = headers;
6
+ if (Boolean(this.headers.get("Cookie"))) {
7
+ for (const [key, value] of Object.entries(cookie.parse(this.headers.get("Cookie")))) {
8
+ if (typeof value === "string") {
9
+ super.set(key, value);
10
+ }
11
+ }
12
+ }
13
+ }
14
+ clear() {
15
+ this.headers.delete("Cookie");
16
+ super.clear();
17
+ }
18
+ set(key, value) {
19
+ super.set(key, value);
20
+ this.serialize();
21
+ return this;
22
+ }
23
+ delete(key) {
24
+ const deleteResult = super.delete(key);
25
+ this.serialize();
26
+ return deleteResult;
27
+ }
28
+ serialize() {
29
+ if (this.size) {
30
+ const cookies = [];
31
+ for (const [key, value] of this.entries()) {
32
+ cookies.push(cookie.serialize(key, value));
33
+ }
34
+ this.headers.set("Cookie", cookies.join("; "));
35
+ }
36
+ }
37
+ }
@@ -1,10 +1,10 @@
1
- import { ERequest } from "./request";
2
- import { EResponse } from "./response";
3
- export declare type RequestHandlerCallback = (req: ERequest, res: EResponse) => Promise<any>;
1
+ import { EReq } from "./request";
2
+ import { ERes } from "./response";
3
+ export declare type RequestHandlerCallback = (req: EReq, res: ERes) => Promise<any>;
4
4
  export declare class RequestHandler {
5
5
  private matchFn;
6
6
  private callback;
7
7
  constructor(matchFn: Function, callback: RequestHandlerCallback);
8
- check(event: ERequest): 0 | 404 | string[];
9
- run(req: ERequest, res: EResponse): Promise<any>;
8
+ check(event: EReq): 0 | 404 | string[];
9
+ run(req: EReq, res: ERes): Promise<any>;
10
10
  }
@@ -1,8 +1,7 @@
1
1
  /// <reference types="@fastly/js-compute" />
2
- import { ECommonObject } from "../common";
3
2
  import { SurrogateKeys } from "./surrogate-keys";
4
3
  import { CookieOptions, EConfig } from "..";
5
- export declare class EResponse extends ECommonObject {
4
+ declare class EResponseBase {
6
5
  private config;
7
6
  headers: Headers;
8
7
  status: number;
@@ -22,3 +21,16 @@ export declare class EResponse extends ECommonObject {
22
21
  text(data: string): void;
23
22
  html(data: string, charset?: string): void;
24
23
  }
24
+ export declare const EResponse: {
25
+ new (...args: any[]): {
26
+ [x: string]: any;
27
+ set(headerNameOrObject: string | {
28
+ [key: string]: string;
29
+ }, value?: string): void;
30
+ append(headerNameOrObject: string | {
31
+ [key: string]: string | string[];
32
+ }, value?: string | string[]): void;
33
+ };
34
+ } & typeof EResponseBase;
35
+ export declare type ERes = InstanceType<typeof EResponse>;
36
+ export {};
@@ -1,16 +1,18 @@
1
1
  import cookie from "cookie";
2
- import { ECommonObject } from "../common";
2
+ import { addCommonMethods } from "../common";
3
3
  import { statusText } from "./status-codes";
4
4
  import { SurrogateKeys } from "./surrogate-keys";
5
- export class EResponse extends ECommonObject {
5
+ // TODO: extends Response
6
+ // See: https://github.com/fastly/js-compute-runtime/issues/113
7
+ class EResponseBase {
6
8
  constructor(config) {
7
- super();
8
9
  this.config = config;
9
10
  this.headers = new Headers();
10
11
  this.status = 0;
11
12
  this.body = null;
12
13
  this.hasEnded = false;
13
14
  this.surrogateKeys = new SurrogateKeys(this.headers);
15
+ // super();
14
16
  }
15
17
  // Header helpers.
16
18
  vary(field) {
@@ -33,8 +35,10 @@ export class EResponse extends ECommonObject {
33
35
  return;
34
36
  if (response instanceof Response) {
35
37
  this.body = response.body;
36
- this.headers = response.headers;
37
- this.status = response.status;
38
+ // Append, rather than overwrite headers.
39
+ response.headers.forEach((value, key) => this.headers.append(key, value));
40
+ // Do not overwrite user-defined status.
41
+ this.status = this.status || response.status;
38
42
  }
39
43
  else {
40
44
  this.body = response;
@@ -99,3 +103,4 @@ export class EResponse extends ECommonObject {
99
103
  this.send(data);
100
104
  }
101
105
  }
106
+ export const EResponse = addCommonMethods(EResponseBase);
@@ -13,7 +13,8 @@ const defaultErrorHandler = (auto405) => async (err, req, res) => {
13
13
  res.headers.set("Allow", err.allow);
14
14
  return res.sendStatus(405);
15
15
  }
16
- res.withStatus(500).json({ error: err });
16
+ console.error(err);
17
+ res.withStatus(500).json({ error: err.message });
17
18
  };
18
19
  export class Router {
19
20
  constructor(config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastly/expressly",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.7",
4
4
  "description": "Express-style router for Fastly's Compute@Edge.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",