@fastly/expressly 1.0.0-alpha.2 → 1.0.0-alpha.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/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.2
20
+ npm i @fastly/expressly
21
21
  ```
22
22
 
23
23
  ```shell
24
- yarn add @fastly/expressly@1.0.0-alpha.2
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,13 +1,10 @@
1
1
  /// <reference types="@fastly/js-compute" />
2
- import { ECommonObject } from "../common";
3
2
  import { CookieMap } from "./cookie-map";
4
3
  import { EConfig } from "..";
5
- export declare class ERequest extends ECommonObject {
4
+ declare class ERequestBase extends Request {
6
5
  private config;
7
- private event;
6
+ private readonly event;
8
7
  readonly clientInfo: ClientInfo;
9
- readonly method: string;
10
- headers: Headers;
11
8
  urlObj: URL;
12
9
  query: URLSearchParams;
13
10
  params: {
@@ -15,14 +12,23 @@ export declare class ERequest extends ECommonObject {
15
12
  };
16
13
  cookies: CookieMap;
17
14
  constructor(config: EConfig, event: FetchEvent);
18
- get url(): string;
19
15
  get path(): string;
20
16
  get ip(): string;
21
17
  get protocol(): string;
22
18
  get secure(): boolean;
23
19
  get subdomains(): Array<string>;
24
20
  get hostname(): string;
25
- json(): Promise<any>;
26
- text(): Promise<string>;
27
- arrayBuffer(): Promise<ArrayBuffer>;
28
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,25 +1,31 @@
1
- import { ECommonObject } from "../common";
1
+ import { addCommonMethods } from "../common";
2
2
  import { CookieMap } from "./cookie-map";
3
- export class ERequest extends ECommonObject {
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 {
4
6
  constructor(config, event) {
5
- super();
7
+ super(event.request, {
8
+ headers: event.request.headers,
9
+ method: event.request.method,
10
+ body: event.request.body,
11
+ });
6
12
  this.config = config;
7
13
  this.event = event;
8
14
  this.params = {};
9
- this.clientInfo = event.client;
10
- this.method = event.request.method;
11
- this.urlObj = new URL(event.request.url);
15
+ this.clientInfo = this.event.client;
16
+ this.urlObj = new URL(this.url);
12
17
  this.query = this.urlObj.searchParams;
13
- this.headers = event.request.headers;
18
+ Object.defineProperty(this, 'url', {
19
+ get() {
20
+ return this.urlObj.toString();
21
+ }
22
+ });
14
23
  // Parse cookies.
15
24
  if (this.config.parseCookie) {
16
25
  this.cookies = new CookieMap(this.headers);
17
26
  }
18
27
  }
19
28
  // Express-like URL helpers.
20
- get url() {
21
- return this.urlObj.toString();
22
- }
23
29
  get path() {
24
30
  return this.urlObj.pathname;
25
31
  }
@@ -38,13 +44,5 @@ export class ERequest extends ECommonObject {
38
44
  get hostname() {
39
45
  return this.urlObj.hostname;
40
46
  }
41
- async json() {
42
- return await this.event.request.json();
43
- }
44
- async text() {
45
- return await this.event.request.text();
46
- }
47
- async arrayBuffer() {
48
- return await this.event.request.arrayBuffer();
49
- }
50
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) {
@@ -99,3 +101,4 @@ export class EResponse extends ECommonObject {
99
101
  this.send(data);
100
102
  }
101
103
  }
104
+ export const EResponse = addCommonMethods(EResponseBase);
@@ -13,6 +13,7 @@ const defaultErrorHandler = (auto405) => async (err, req, res) => {
13
13
  res.headers.set("Allow", err.allow);
14
14
  return res.sendStatus(405);
15
15
  }
16
+ console.error(err);
16
17
  res.withStatus(500).json({ error: err });
17
18
  };
18
19
  export class Router {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastly/expressly",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.5",
4
4
  "description": "Express-style router for Fastly's Compute@Edge.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,10 +0,0 @@
1
- import ERequest from "./request";
2
- import EResponse from "./response";
3
- export declare type MiddlewareCallback = (req: ERequest, res: EResponse, next?: () => void) => Promise<any>;
4
- export declare class Middleware {
5
- private matchFn;
6
- private callback;
7
- constructor(matchFn: Function, callback: MiddlewareCallback);
8
- check(event: ERequest): 0 | 404 | 405;
9
- run(req: ERequest, res: EResponse): Promise<any>;
10
- }
@@ -1,13 +0,0 @@
1
- export class Middleware {
2
- constructor(matchFn, callback) {
3
- this.matchFn = matchFn;
4
- this.callback = callback;
5
- }
6
- check(event) {
7
- return this.matchFn(event);
8
- }
9
- async run(req, res) {
10
- // Supply an empty callback as an equivalent of next() in Express.js.
11
- await this.callback(req, res, () => { });
12
- }
13
- }
@@ -1,10 +0,0 @@
1
- import ERequest from "./request";
2
- import EResponse from "./response";
3
- export declare type RequestHandlerCallback = (req: ERequest, res: EResponse) => Promise<any>;
4
- export declare class Route {
5
- private matchFn;
6
- private callback;
7
- constructor(matchFn: Function, callback: RequestHandlerCallback);
8
- check(event: ERequest): 0 | 404 | 405;
9
- run(req: ERequest, res: EResponse): Promise<any>;
10
- }
@@ -1,12 +0,0 @@
1
- export class Route {
2
- constructor(matchFn, callback) {
3
- this.matchFn = matchFn;
4
- this.callback = callback;
5
- }
6
- check(event) {
7
- return this.matchFn(event);
8
- }
9
- async run(req, res) {
10
- await this.callback(req, res);
11
- }
12
- }