@goldstack/utils-aws-http-api-local 0.1.43 → 0.3.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.
@@ -1,18 +1,18 @@
1
- import { Request, Response } from 'express';
2
- import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2, Context } from 'aws-lambda';
3
- import { LambdaConfig } from '@goldstack/utils-aws-lambda';
4
- export interface CovertToGatewayEventParams {
5
- req: Request;
6
- lambdaConfig: LambdaConfig;
7
- }
8
- export interface StringMap {
9
- [key: string]: string;
10
- }
11
- export declare const sortPropertiesByAppearanceInPath: (params: CovertToGatewayEventParams, pathParams: StringMap) => [string, string][];
12
- export declare const convertToGatewayEvent: (params: CovertToGatewayEventParams) => APIGatewayProxyEventV2;
13
- export interface CreateContextParams {
14
- functionName: string;
15
- }
16
- export declare const createContext: (params: CreateContextParams) => Context;
17
- export declare const injectGatewayResultIntoResponse: (result: APIGatewayProxyStructuredResultV2 | string | any, resp: Response) => void;
1
+ import { Request, Response } from 'express';
2
+ import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2, Context } from 'aws-lambda';
3
+ import { LambdaConfig } from '@goldstack/utils-aws-lambda';
4
+ export interface CovertToGatewayEventParams {
5
+ req: Request;
6
+ lambdaConfig: LambdaConfig;
7
+ }
8
+ export interface StringMap {
9
+ [key: string]: string;
10
+ }
11
+ export declare const sortPropertiesByAppearanceInPath: (params: CovertToGatewayEventParams, pathParams: StringMap) => [string, string][];
12
+ export declare const convertToGatewayEvent: (params: CovertToGatewayEventParams) => APIGatewayProxyEventV2;
13
+ export interface CreateContextParams {
14
+ functionName: string;
15
+ }
16
+ export declare const createContext: (params: CreateContextParams) => Context;
17
+ export declare const injectGatewayResultIntoResponse: (result: APIGatewayProxyStructuredResultV2 | string | any, resp: Response) => void;
18
18
  //# sourceMappingURL=expressRequestToHttpApiGatewayEvent.d.ts.map
@@ -1,187 +1,187 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.injectGatewayResultIntoResponse = exports.createContext = exports.convertToGatewayEvent = exports.sortPropertiesByAppearanceInPath = void 0;
7
- const cookie_1 = __importDefault(require("cookie"));
8
- const sortPropertiesByAppearanceInPath = (params, pathParams) => {
9
- const pathElements = Object.entries(pathParams)
10
- .filter((e) => e[0] !== '0')
11
- .sort((a, b) => {
12
- return (params.lambdaConfig.path.indexOf(a[0]) -
13
- params.lambdaConfig.path.indexOf(b[0]));
14
- });
15
- return pathElements;
16
- };
17
- exports.sortPropertiesByAppearanceInPath = sortPropertiesByAppearanceInPath;
18
- const convertToGatewayEvent = (params) => {
19
- const incomingHeaders = params.req.headers;
20
- const normalisedHeaders = Object.entries(incomingHeaders).reduce((prev, curr) => {
21
- if (typeof curr[1] === 'string') {
22
- prev[curr[0]] = curr[1];
23
- return prev;
24
- }
25
- else if (curr[1]) {
26
- prev[curr[0]] = curr[1].join(',');
27
- return prev;
28
- }
29
- return prev;
30
- }, {});
31
- const expressQuery = params.req.query;
32
- const lambdaQuery = Object.entries(expressQuery)
33
- .map((e) => `${e[0]}=${e[1]}`)
34
- .join('&');
35
- const queryStringParameters = Object.entries(expressQuery).reduce((prev, curr) => {
36
- if (typeof curr[1] === 'string') {
37
- prev[curr[0]] = curr[1];
38
- }
39
- else {
40
- prev[curr[0]] = curr[1].join(',');
41
- }
42
- return prev;
43
- }, {});
44
- const pathParams = { ...params.req.params };
45
- // some complicated stuff happening
46
- // if there was a regex/ greedy path match
47
- // since express does not provide the full path
48
- // but rather the 'matches' of the regex
49
- if (pathParams['0']) {
50
- const sortedPathParams = (0, exports.sortPropertiesByAppearanceInPath)(params, pathParams);
51
- if (sortedPathParams.length > 0) {
52
- const lastPathParam = sortedPathParams[sortedPathParams.length - 1];
53
- const lastPathParamObject = Object.entries(pathParams).find((e) => {
54
- return e[0].indexOf(lastPathParam[0]) === 0;
55
- });
56
- if (lastPathParamObject) {
57
- // here we append the regex match to the path
58
- // so the path is the full path that was matched
59
- pathParams[lastPathParamObject[0]] = `${lastPathParamObject[1]}${pathParams['0']}`;
60
- }
61
- }
62
- }
63
- return {
64
- version: '2.0',
65
- routeKey: params.lambdaConfig.route,
66
- rawPath: params.req.url.split('?')[0],
67
- rawQueryString: lambdaQuery,
68
- queryStringParameters,
69
- pathParameters: pathParams,
70
- cookies: params.req.cookies,
71
- headers: {
72
- accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
73
- 'accept-encoding': 'gzip, deflate, br',
74
- 'accept-language': 'en-US,en;q=0.9,de;q=0.8',
75
- 'content-length': '0',
76
- dnt: '1',
77
- 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
78
- 'sec-ch-ua-mobile': '?0',
79
- 'sec-ch-ua-platform': '"Windows"',
80
- 'sec-fetch-dest': 'document',
81
- 'sec-fetch-mode': 'navigate',
82
- 'sec-fetch-site': 'none',
83
- 'sec-fetch-user': '?1',
84
- 'upgrade-insecure-requests': '1',
85
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
86
- 'x-amzn-trace-id': 'Root=1-61ce5e14-5d8a4b4e22d2e69f3af9eb20',
87
- 'x-forwarded-for': '120.148.16.26',
88
- 'x-forwarded-port': '443',
89
- 'x-forwarded-proto': 'https',
90
- ...normalisedHeaders,
91
- },
92
- requestContext: {
93
- accountId: '111111128371',
94
- apiId: 'd5811h14p0',
95
- domainName: 'localhost',
96
- domainPrefix: 'localhost',
97
- http: {
98
- method: params.req.method,
99
- path: params.req.url,
100
- protocol: 'HTTP/1.1',
101
- sourceIp: '120.148.16.26',
102
- userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
103
- },
104
- requestId: 'LMOjOiBiPHcEMkQ=',
105
- routeKey: params.lambdaConfig.route,
106
- stage: '$default',
107
- time: '31/Dec/2021:01:34:12 +0000',
108
- timeEpoch: new Date().getTime(),
109
- },
110
- isBase64Encoded: false,
111
- body: JSON.stringify(params.req.body),
112
- };
113
- };
114
- exports.convertToGatewayEvent = convertToGatewayEvent;
115
- const createContext = (params) => {
116
- return {
117
- callbackWaitsForEmptyEventLoop: true,
118
- getRemainingTimeInMillis: () => {
119
- return 0;
120
- },
121
- done: () => { },
122
- fail: () => { },
123
- succeed: () => { },
124
- functionVersion: '$LATEST',
125
- functionName: params.functionName,
126
- memoryLimitInMB: '2048',
127
- logGroupName: `/aws/lambda/${params.functionName}`,
128
- logStreamName: '2021/12/31/[$LATEST]11f0a4a770034f1c822a5c4c69490bb1',
129
- invokedFunctionArn: `arn:aws:lambda:us-west-2:475629728374:function:${params.functionName}`,
130
- awsRequestId: '8bb853aa-6c00-42cb-9877-0963bd56ae01',
131
- };
132
- };
133
- exports.createContext = createContext;
134
- const injectGatewayResultIntoResponse = (result, resp) => {
135
- // result can have three different structures https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
136
- var _a, _b;
137
- // 1: string
138
- if (typeof result === 'string') {
139
- resp.status(200);
140
- resp.contentType('application/json');
141
- resp.json(JSON.parse(result));
142
- return;
143
- }
144
- // 2: structured output
145
- if (result.statusCode) {
146
- const structuredResult = result;
147
- resp.status(structuredResult.statusCode || 200);
148
- if (structuredResult.headers) {
149
- resp.set(structuredResult.headers);
150
- }
151
- const contentType = ((_a = structuredResult.headers) === null || _a === void 0 ? void 0 : _a['content-type']) ||
152
- ((_b = structuredResult.headers) === null || _b === void 0 ? void 0 : _b['Content-Type']);
153
- if (!contentType) {
154
- resp.contentType('application/json');
155
- }
156
- else {
157
- // content type would be set by headers above
158
- }
159
- if (structuredResult.cookies) {
160
- structuredResult.cookies.forEach((val) => {
161
- const obj = cookie_1.default.parse(val);
162
- Object.entries(obj).forEach((element) => {
163
- resp.cookie(element[0], element[1]);
164
- });
165
- });
166
- }
167
- if (structuredResult.body) {
168
- if (!structuredResult.isBase64Encoded) {
169
- resp.send(structuredResult.body);
170
- }
171
- else {
172
- resp.send(Buffer.from(structuredResult.body, 'base64'));
173
- }
174
- }
175
- else {
176
- resp.end();
177
- }
178
- return;
179
- }
180
- // 3: json object
181
- resp.status(200);
182
- resp.contentType('application/json');
183
- resp.json(result);
184
- return;
185
- };
186
- exports.injectGatewayResultIntoResponse = injectGatewayResultIntoResponse;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.injectGatewayResultIntoResponse = exports.createContext = exports.convertToGatewayEvent = exports.sortPropertiesByAppearanceInPath = void 0;
7
+ const cookie_1 = __importDefault(require("cookie"));
8
+ const sortPropertiesByAppearanceInPath = (params, pathParams) => {
9
+ const pathElements = Object.entries(pathParams)
10
+ .filter((e) => e[0] !== '0')
11
+ .sort((a, b) => {
12
+ return (params.lambdaConfig.path.indexOf(a[0]) -
13
+ params.lambdaConfig.path.indexOf(b[0]));
14
+ });
15
+ return pathElements;
16
+ };
17
+ exports.sortPropertiesByAppearanceInPath = sortPropertiesByAppearanceInPath;
18
+ const convertToGatewayEvent = (params) => {
19
+ const incomingHeaders = params.req.headers;
20
+ const normalisedHeaders = Object.entries(incomingHeaders).reduce((prev, curr) => {
21
+ if (typeof curr[1] === 'string') {
22
+ prev[curr[0]] = curr[1];
23
+ return prev;
24
+ }
25
+ else if (curr[1]) {
26
+ prev[curr[0]] = curr[1].join(',');
27
+ return prev;
28
+ }
29
+ return prev;
30
+ }, {});
31
+ const expressQuery = params.req.query;
32
+ const lambdaQuery = Object.entries(expressQuery)
33
+ .map((e) => `${e[0]}=${e[1]}`)
34
+ .join('&');
35
+ const queryStringParameters = Object.entries(expressQuery).reduce((prev, curr) => {
36
+ if (typeof curr[1] === 'string') {
37
+ prev[curr[0]] = curr[1];
38
+ }
39
+ else {
40
+ prev[curr[0]] = curr[1].join(',');
41
+ }
42
+ return prev;
43
+ }, {});
44
+ const pathParams = { ...params.req.params };
45
+ // some complicated stuff happening
46
+ // if there was a regex/ greedy path match
47
+ // since express does not provide the full path
48
+ // but rather the 'matches' of the regex
49
+ if (pathParams['0']) {
50
+ const sortedPathParams = (0, exports.sortPropertiesByAppearanceInPath)(params, pathParams);
51
+ if (sortedPathParams.length > 0) {
52
+ const lastPathParam = sortedPathParams[sortedPathParams.length - 1];
53
+ const lastPathParamObject = Object.entries(pathParams).find((e) => {
54
+ return e[0].indexOf(lastPathParam[0]) === 0;
55
+ });
56
+ if (lastPathParamObject) {
57
+ // here we append the regex match to the path
58
+ // so the path is the full path that was matched
59
+ pathParams[lastPathParamObject[0]] = `${lastPathParamObject[1]}${pathParams['0']}`;
60
+ }
61
+ }
62
+ }
63
+ return {
64
+ version: '2.0',
65
+ routeKey: params.lambdaConfig.route,
66
+ rawPath: params.req.url.split('?')[0],
67
+ rawQueryString: lambdaQuery,
68
+ queryStringParameters,
69
+ pathParameters: pathParams,
70
+ cookies: params.req.cookies,
71
+ headers: {
72
+ accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
73
+ 'accept-encoding': 'gzip, deflate, br',
74
+ 'accept-language': 'en-US,en;q=0.9,de;q=0.8',
75
+ 'content-length': '0',
76
+ dnt: '1',
77
+ 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
78
+ 'sec-ch-ua-mobile': '?0',
79
+ 'sec-ch-ua-platform': '"Windows"',
80
+ 'sec-fetch-dest': 'document',
81
+ 'sec-fetch-mode': 'navigate',
82
+ 'sec-fetch-site': 'none',
83
+ 'sec-fetch-user': '?1',
84
+ 'upgrade-insecure-requests': '1',
85
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
86
+ 'x-amzn-trace-id': 'Root=1-61ce5e14-5d8a4b4e22d2e69f3af9eb20',
87
+ 'x-forwarded-for': '120.148.16.26',
88
+ 'x-forwarded-port': '443',
89
+ 'x-forwarded-proto': 'https',
90
+ ...normalisedHeaders,
91
+ },
92
+ requestContext: {
93
+ accountId: '111111128371',
94
+ apiId: 'd5811h14p0',
95
+ domainName: 'localhost',
96
+ domainPrefix: 'localhost',
97
+ http: {
98
+ method: params.req.method,
99
+ path: params.req.url,
100
+ protocol: 'HTTP/1.1',
101
+ sourceIp: '120.148.16.26',
102
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
103
+ },
104
+ requestId: 'LMOjOiBiPHcEMkQ=',
105
+ routeKey: params.lambdaConfig.route,
106
+ stage: '$default',
107
+ time: '31/Dec/2021:01:34:12 +0000',
108
+ timeEpoch: new Date().getTime(),
109
+ },
110
+ isBase64Encoded: false,
111
+ body: JSON.stringify(params.req.body),
112
+ };
113
+ };
114
+ exports.convertToGatewayEvent = convertToGatewayEvent;
115
+ const createContext = (params) => {
116
+ return {
117
+ callbackWaitsForEmptyEventLoop: true,
118
+ getRemainingTimeInMillis: () => {
119
+ return 0;
120
+ },
121
+ done: () => { },
122
+ fail: () => { },
123
+ succeed: () => { },
124
+ functionVersion: '$LATEST',
125
+ functionName: params.functionName,
126
+ memoryLimitInMB: '2048',
127
+ logGroupName: `/aws/lambda/${params.functionName}`,
128
+ logStreamName: '2021/12/31/[$LATEST]11f0a4a770034f1c822a5c4c69490bb1',
129
+ invokedFunctionArn: `arn:aws:lambda:us-west-2:475629728374:function:${params.functionName}`,
130
+ awsRequestId: '8bb853aa-6c00-42cb-9877-0963bd56ae01',
131
+ };
132
+ };
133
+ exports.createContext = createContext;
134
+ const injectGatewayResultIntoResponse = (result, resp) => {
135
+ // result can have three different structures https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
136
+ var _a, _b;
137
+ // 1: string
138
+ if (typeof result === 'string') {
139
+ resp.status(200);
140
+ resp.contentType('application/json');
141
+ resp.json(JSON.parse(result));
142
+ return;
143
+ }
144
+ // 2: structured output
145
+ if (result.statusCode) {
146
+ const structuredResult = result;
147
+ resp.status(structuredResult.statusCode || 200);
148
+ if (structuredResult.headers) {
149
+ resp.set(structuredResult.headers);
150
+ }
151
+ const contentType = ((_a = structuredResult.headers) === null || _a === void 0 ? void 0 : _a['content-type']) ||
152
+ ((_b = structuredResult.headers) === null || _b === void 0 ? void 0 : _b['Content-Type']);
153
+ if (!contentType) {
154
+ resp.contentType('application/json');
155
+ }
156
+ else {
157
+ // content type would be set by headers above
158
+ }
159
+ if (structuredResult.cookies) {
160
+ structuredResult.cookies.forEach((val) => {
161
+ const obj = cookie_1.default.parse(val);
162
+ Object.entries(obj).forEach((element) => {
163
+ resp.cookie(element[0], element[1]);
164
+ });
165
+ });
166
+ }
167
+ if (structuredResult.body) {
168
+ if (!structuredResult.isBase64Encoded) {
169
+ resp.send(structuredResult.body);
170
+ }
171
+ else {
172
+ resp.send(Buffer.from(structuredResult.body, 'base64'));
173
+ }
174
+ }
175
+ else {
176
+ resp.end();
177
+ }
178
+ return;
179
+ }
180
+ // 3: json object
181
+ resp.status(200);
182
+ resp.contentType('application/json');
183
+ resp.json(result);
184
+ return;
185
+ };
186
+ exports.injectGatewayResultIntoResponse = injectGatewayResultIntoResponse;
187
187
  //# sourceMappingURL=expressRequestToHttpApiGatewayEvent.js.map
@@ -1,10 +1,10 @@
1
- import { LambdaConfig } from '@goldstack/utils-aws-lambda';
2
- import express from 'express';
3
- export interface InjectRoutesParam {
4
- lambdaConfigs: LambdaConfig[];
5
- app: express.Application;
6
- }
7
- export declare const sortRoutesBySpecificity: (configs: LambdaConfig[]) => LambdaConfig[];
8
- export declare const gatewayRouteToExpressPath: (route: string) => string;
9
- export declare const injectRoutes: (params: InjectRoutesParam) => void;
1
+ import { LambdaConfig } from '@goldstack/utils-aws-lambda';
2
+ import express from 'express';
3
+ export interface InjectRoutesParam {
4
+ lambdaConfigs: LambdaConfig[];
5
+ app: express.Application;
6
+ }
7
+ export declare const sortRoutesBySpecificity: (configs: LambdaConfig[]) => LambdaConfig[];
8
+ export declare const gatewayRouteToExpressPath: (route: string) => string;
9
+ export declare const injectRoutes: (params: InjectRoutesParam) => void;
10
10
  //# sourceMappingURL=expressRoutes.d.ts.map
@@ -1,65 +1,65 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.injectRoutes = exports.gatewayRouteToExpressPath = exports.sortRoutesBySpecificity = void 0;
4
- const utils_aws_lambda_1 = require("@goldstack/utils-aws-lambda");
5
- const expressRequestToHttpApiGatewayEvent_1 = require("./expressRequestToHttpApiGatewayEvent");
6
- /*
7
- Ensure more generic routes are handled later
8
- */
9
- const sortRoutesBySpecificity = (configs) => {
10
- const res = [...configs];
11
- res.sort((first, second) => {
12
- if (first.path === '$default') {
13
- return 1;
14
- }
15
- if (second.path === '$default') {
16
- return -1;
17
- }
18
- if (first.route.indexOf('+}') !== -1 && second.route.indexOf('+}') === -1) {
19
- return 1;
20
- }
21
- if (second.route.indexOf('+}') !== -1 && first.route.indexOf('+}') === -1) {
22
- return -1;
23
- }
24
- if (first.route.indexOf('}') !== -1 && second.route.indexOf('}') === -1) {
25
- return 1;
26
- }
27
- if (second.route.indexOf('}') !== -1 && first.route.indexOf('}') === -1) {
28
- return -1;
29
- }
30
- // ensure longer routes come first
31
- return (second.route.replace(/\{(.*?)\}/g, '').length -
32
- first.route.replace(/\{(.*?)\}/g, '').length);
33
- });
34
- return res;
35
- };
36
- exports.sortRoutesBySpecificity = sortRoutesBySpecificity;
37
- const gatewayRouteToExpressPath = (route) => {
38
- if (route === '$default') {
39
- return '*';
40
- }
41
- // see https://expressjs.com/en/guide/routing.html
42
- let path = route;
43
- // see https://stackoverflow.com/a/16829917/270662
44
- path = path.replace(/\{(.*?)\+\}/g, ':$1*');
45
- path = path.replace(/\{(.*?)\}/g, ':$1');
46
- return path;
47
- };
48
- exports.gatewayRouteToExpressPath = gatewayRouteToExpressPath;
49
- const injectRoutes = (params) => {
50
- const sortedConfigs = (0, exports.sortRoutesBySpecificity)(params.lambdaConfigs);
51
- for (const lambdaConfig of sortedConfigs) {
52
- // eslint-disable-next-line @typescript-eslint/no-var-requires
53
- const script = require(lambdaConfig.absoluteFilePath);
54
- const handler = script.handler;
55
- const expressPath = (0, exports.gatewayRouteToExpressPath)(lambdaConfig.path);
56
- params.app.all(expressPath, async (req, resp) => {
57
- const result = await handler((0, expressRequestToHttpApiGatewayEvent_1.convertToGatewayEvent)({ req: req, lambdaConfig: lambdaConfig }), (0, expressRequestToHttpApiGatewayEvent_1.createContext)({
58
- functionName: (0, utils_aws_lambda_1.generateFunctionName)('local', lambdaConfig),
59
- }));
60
- (0, expressRequestToHttpApiGatewayEvent_1.injectGatewayResultIntoResponse)(result, resp);
61
- });
62
- }
63
- };
64
- exports.injectRoutes = injectRoutes;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.injectRoutes = exports.gatewayRouteToExpressPath = exports.sortRoutesBySpecificity = void 0;
4
+ const utils_aws_lambda_1 = require("@goldstack/utils-aws-lambda");
5
+ const expressRequestToHttpApiGatewayEvent_1 = require("./expressRequestToHttpApiGatewayEvent");
6
+ /*
7
+ Ensure more generic routes are handled later
8
+ */
9
+ const sortRoutesBySpecificity = (configs) => {
10
+ const res = [...configs];
11
+ res.sort((first, second) => {
12
+ if (first.path === '$default') {
13
+ return 1;
14
+ }
15
+ if (second.path === '$default') {
16
+ return -1;
17
+ }
18
+ if (first.route.indexOf('+}') !== -1 && second.route.indexOf('+}') === -1) {
19
+ return 1;
20
+ }
21
+ if (second.route.indexOf('+}') !== -1 && first.route.indexOf('+}') === -1) {
22
+ return -1;
23
+ }
24
+ if (first.route.indexOf('}') !== -1 && second.route.indexOf('}') === -1) {
25
+ return 1;
26
+ }
27
+ if (second.route.indexOf('}') !== -1 && first.route.indexOf('}') === -1) {
28
+ return -1;
29
+ }
30
+ // ensure longer routes come first
31
+ return (second.route.replace(/\{(.*?)\}/g, '').length -
32
+ first.route.replace(/\{(.*?)\}/g, '').length);
33
+ });
34
+ return res;
35
+ };
36
+ exports.sortRoutesBySpecificity = sortRoutesBySpecificity;
37
+ const gatewayRouteToExpressPath = (route) => {
38
+ if (route === '$default') {
39
+ return '*';
40
+ }
41
+ // see https://expressjs.com/en/guide/routing.html
42
+ let path = route;
43
+ // see https://stackoverflow.com/a/16829917/270662
44
+ path = path.replace(/\{(.*?)\+\}/g, ':$1*');
45
+ path = path.replace(/\{(.*?)\}/g, ':$1');
46
+ return path;
47
+ };
48
+ exports.gatewayRouteToExpressPath = gatewayRouteToExpressPath;
49
+ const injectRoutes = (params) => {
50
+ const sortedConfigs = (0, exports.sortRoutesBySpecificity)(params.lambdaConfigs);
51
+ for (const lambdaConfig of sortedConfigs) {
52
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
53
+ const script = require(lambdaConfig.absoluteFilePath);
54
+ const handler = script.handler;
55
+ const expressPath = (0, exports.gatewayRouteToExpressPath)(lambdaConfig.path);
56
+ params.app.all(expressPath, async (req, resp) => {
57
+ const result = await handler((0, expressRequestToHttpApiGatewayEvent_1.convertToGatewayEvent)({ req: req, lambdaConfig: lambdaConfig }), (0, expressRequestToHttpApiGatewayEvent_1.createContext)({
58
+ functionName: (0, utils_aws_lambda_1.generateFunctionName)('local', lambdaConfig),
59
+ }));
60
+ (0, expressRequestToHttpApiGatewayEvent_1.injectGatewayResultIntoResponse)(result, resp);
61
+ });
62
+ }
63
+ };
64
+ exports.injectRoutes = injectRoutes;
65
65
  //# sourceMappingURL=expressRoutes.js.map
@@ -1,23 +1,23 @@
1
- /// <reference types="node" />
2
- import { Server } from 'http';
3
- import { LambdaConfig } from '@goldstack/utils-aws-lambda';
4
- declare type StaticRoutes = {
5
- [key: string]: string;
6
- };
7
- export interface LocalHttpAPIOptions {
8
- port: string;
9
- routesDir: string;
10
- cors?: string;
11
- /**
12
- * Maps routes to local directories
13
- */
14
- staticRoutes?: StaticRoutes;
15
- }
16
- export interface StartServerResult {
17
- shutdown: () => Promise<void>;
18
- server: Server;
19
- lambdaConfig: LambdaConfig[];
20
- }
21
- export declare const startServer: (options: LocalHttpAPIOptions) => Promise<StartServerResult>;
22
- export {};
1
+ /// <reference types="node" />
2
+ import { Server } from 'http';
3
+ import { LambdaConfig } from '@goldstack/utils-aws-lambda';
4
+ declare type StaticRoutes = {
5
+ [key: string]: string;
6
+ };
7
+ export interface LocalHttpAPIOptions {
8
+ port: string;
9
+ routesDir: string;
10
+ cors?: string;
11
+ /**
12
+ * Maps routes to local directories
13
+ */
14
+ staticRoutes?: StaticRoutes;
15
+ }
16
+ export interface StartServerResult {
17
+ shutdown: () => Promise<void>;
18
+ server: Server;
19
+ lambdaConfig: LambdaConfig[];
20
+ }
21
+ export declare const startServer: (options: LocalHttpAPIOptions) => Promise<StartServerResult>;
22
+ export {};
23
23
  //# sourceMappingURL=utilsAwsHttpApiLocal.d.ts.map
@@ -1,49 +1,49 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.startServer = void 0;
7
- const express_1 = __importDefault(require("express"));
8
- const cors_1 = __importDefault(require("cors"));
9
- const utils_aws_lambda_1 = require("@goldstack/utils-aws-lambda");
10
- const expressRoutes_1 = require("./expressRoutes");
11
- const startServer = async (options) => {
12
- const app = (0, express_1.default)();
13
- app.use(express_1.default.json());
14
- if (options.cors) {
15
- app.use((0, cors_1.default)({ origin: options.cors, credentials: true }));
16
- }
17
- const lambdaConfig = (0, utils_aws_lambda_1.readLambdaConfig)(options.routesDir);
18
- (0, expressRoutes_1.injectRoutes)({
19
- app: app,
20
- lambdaConfigs: lambdaConfig,
21
- });
22
- if (options.staticRoutes) {
23
- Object.entries(options.staticRoutes).forEach((e) => {
24
- app.use(e[0], express_1.default.static(e[1]));
25
- });
26
- }
27
- const result = await new Promise((resolve) => {
28
- const server = app.listen(parseInt(options.port), function () {
29
- resolve(server);
30
- });
31
- });
32
- return {
33
- server: result,
34
- lambdaConfig: lambdaConfig,
35
- shutdown: () => {
36
- return new Promise((resolve, reject) => {
37
- result.close((err) => {
38
- if (err) {
39
- reject(err);
40
- return;
41
- }
42
- resolve();
43
- });
44
- });
45
- },
46
- };
47
- };
48
- exports.startServer = startServer;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startServer = void 0;
7
+ const express_1 = __importDefault(require("express"));
8
+ const cors_1 = __importDefault(require("cors"));
9
+ const utils_aws_lambda_1 = require("@goldstack/utils-aws-lambda");
10
+ const expressRoutes_1 = require("./expressRoutes");
11
+ const startServer = async (options) => {
12
+ const app = (0, express_1.default)();
13
+ app.use(express_1.default.json());
14
+ if (options.cors) {
15
+ app.use((0, cors_1.default)({ origin: options.cors, credentials: true }));
16
+ }
17
+ const lambdaConfig = (0, utils_aws_lambda_1.readLambdaConfig)(options.routesDir);
18
+ (0, expressRoutes_1.injectRoutes)({
19
+ app: app,
20
+ lambdaConfigs: lambdaConfig,
21
+ });
22
+ if (options.staticRoutes) {
23
+ Object.entries(options.staticRoutes).forEach((e) => {
24
+ app.use(e[0], express_1.default.static(e[1]));
25
+ });
26
+ }
27
+ const result = await new Promise((resolve) => {
28
+ const server = app.listen(parseInt(options.port), function () {
29
+ resolve(server);
30
+ });
31
+ });
32
+ return {
33
+ server: result,
34
+ lambdaConfig: lambdaConfig,
35
+ shutdown: () => {
36
+ return new Promise((resolve, reject) => {
37
+ result.close((err) => {
38
+ if (err) {
39
+ reject(err);
40
+ return;
41
+ }
42
+ resolve();
43
+ });
44
+ });
45
+ },
46
+ };
47
+ };
48
+ exports.startServer = startServer;
49
49
  //# sourceMappingURL=utilsAwsHttpApiLocal.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goldstack/utils-aws-http-api-local",
3
- "version": "0.1.43",
3
+ "version": "0.3.0",
4
4
  "description": "Starts a local AWS HTTP API for testing",
5
5
  "keywords": [
6
6
  "goldstack",
@@ -45,14 +45,14 @@
45
45
  "version:apply:force": "yarn version $@ && yarn version apply"
46
46
  },
47
47
  "dependencies": {
48
- "@goldstack/utils-aws-lambda": "0.1.40",
48
+ "@goldstack/utils-aws-lambda": "0.3.0",
49
49
  "@types/aws-lambda": "^8.10.88",
50
50
  "cookie": "^0.4.1",
51
51
  "cors": "^2.8.5",
52
52
  "express": "^4.17.1"
53
53
  },
54
54
  "devDependencies": {
55
- "@goldstack/utils-git": "0.1.37",
55
+ "@goldstack/utils-git": "0.2.0",
56
56
  "@types/cookie": "^0",
57
57
  "@types/express": "^4.17.13",
58
58
  "@types/jest": "^28.1.8",