@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 +2 -2
- package/dist/lib/routing/common.d.ts +11 -11
- package/dist/lib/routing/common.js +32 -33
- package/dist/lib/routing/error-middleware.d.ts +5 -5
- package/dist/lib/routing/mixin.d.ts +1 -0
- package/dist/lib/routing/mixin.js +9 -0
- package/dist/lib/routing/request/index.d.ts +15 -11
- package/dist/lib/routing/request/index.js +17 -39
- package/dist/lib/routing/request/request-url.d.ts +9 -0
- package/dist/lib/routing/request/request-url.js +37 -0
- package/dist/lib/routing/request-handler.d.ts +5 -5
- package/dist/lib/routing/response/index.d.ts +14 -2
- package/dist/lib/routing/response/index.js +10 -5
- package/dist/lib/routing/router.js +2 -1
- package/package.json +1 -1
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
|
|
20
|
+
npm i @fastly/expressly
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
```shell
|
|
24
|
-
yarn add @fastly/expressly
|
|
24
|
+
yarn add @fastly/expressly
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
### Your first expressly app
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
export declare type ErrorMiddlewareCallback = (err: Error, req:
|
|
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:
|
|
9
|
-
run(err: Error, req:
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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,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 {
|
|
2
|
-
import {
|
|
3
|
-
export declare type RequestHandlerCallback = (req:
|
|
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:
|
|
9
|
-
run(req:
|
|
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
|
-
|
|
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 {
|
|
2
|
+
import { addCommonMethods } from "../common";
|
|
3
3
|
import { statusText } from "./status-codes";
|
|
4
4
|
import { SurrogateKeys } from "./surrogate-keys";
|
|
5
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
|
|
16
|
+
console.error(err);
|
|
17
|
+
res.withStatus(500).json({ error: err.message });
|
|
17
18
|
};
|
|
18
19
|
export class Router {
|
|
19
20
|
constructor(config) {
|