@cumulusds/aws-apig-bypass 0.0.1

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.
Files changed (42) hide show
  1. package/.babelrc.js +15 -0
  2. package/.eslintrc.js +15 -0
  3. package/.flowconfig +14 -0
  4. package/.github/dependabot.yml +15 -0
  5. package/.github/pull_request_template.md +18 -0
  6. package/.github/workflows/ci-cd.yml +86 -0
  7. package/LICENSE +9 -0
  8. package/README.md +68 -0
  9. package/doc/CreateAccessKey.png +0 -0
  10. package/doc/development.md +244 -0
  11. package/doc/prettier-watchers-pc.xml +222 -0
  12. package/doc/prettier-watchers-unix.xml +222 -0
  13. package/doc/webstorm-file-watcher-prettier.png +0 -0
  14. package/doc/webstorm-flow.png +0 -0
  15. package/flow-typed/npm/jest_v26.x.x.js +1218 -0
  16. package/lib/create-api-gateway-event.js +50 -0
  17. package/lib/create-api-gateway-event.js.flow +57 -0
  18. package/lib/create-client.js +25 -0
  19. package/lib/create-client.js.flow +30 -0
  20. package/lib/create-lambda-client.js +33 -0
  21. package/lib/create-lambda-client.js.flow +35 -0
  22. package/lib/index.js +23 -0
  23. package/lib/index.js.flow +4 -0
  24. package/lib/json-stringify.js +23 -0
  25. package/lib/json-stringify.js.flow +16 -0
  26. package/lib/lambda-invoke.js +1 -0
  27. package/lib/lambda-invoke.js.flow +10 -0
  28. package/lib/parse-payload.js +31 -0
  29. package/lib/parse-payload.js.flow +25 -0
  30. package/lib/response.js +1 -0
  31. package/lib/response.js.flow +15 -0
  32. package/package.json +86 -0
  33. package/prettier.config.js +3 -0
  34. package/src/create-api-gateway-event.js +57 -0
  35. package/src/create-client.js +30 -0
  36. package/src/create-lambda-client.js +35 -0
  37. package/src/index.js +4 -0
  38. package/src/json-stringify.js +16 -0
  39. package/src/lambda-invoke.js +10 -0
  40. package/src/parse-payload.js +25 -0
  41. package/src/response.js +15 -0
  42. package/test/unit/index.test.js +142 -0
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = createAPIGatewayEvent;
7
+
8
+ function createAPIGatewayEvent({
9
+ pathParameters = null,
10
+ path = "",
11
+ body = null,
12
+ queryStringParameters = null
13
+ } = {}) {
14
+ return {
15
+ body,
16
+ headers: {},
17
+ multiValueHeaders: {},
18
+ httpMethod: "",
19
+ isBase64Encoded: false,
20
+ path,
21
+ pathParameters,
22
+ queryStringParameters,
23
+ multiValueQueryStringParameters: null,
24
+ stageVariables: null,
25
+ requestContext: {
26
+ accountId: "",
27
+ apiId: "",
28
+ httpMethod: "",
29
+ identity: {
30
+ accessKey: null,
31
+ accountId: null,
32
+ apiKey: null,
33
+ caller: null,
34
+ cognitoAuthenticationProvider: null,
35
+ cognitoAuthenticationType: null,
36
+ cognitoIdentityId: null,
37
+ cognitoIdentityPoolId: null,
38
+ sourceIp: "",
39
+ user: null,
40
+ userAgent: null,
41
+ userArn: null
42
+ },
43
+ stage: "",
44
+ requestId: "",
45
+ resourceId: "",
46
+ resourcePath: ""
47
+ },
48
+ resource: ""
49
+ };
50
+ }
@@ -0,0 +1,57 @@
1
+ // @flow
2
+
3
+ import type { APIGatewayEvent } from "flow-aws-lambda";
4
+
5
+ export type PathParameters = { [name: string]: string } | null;
6
+ export type QueryStringParameters = { [name: string]: string } | null;
7
+
8
+ export type CreateAPIGatewayEventOptions = {
9
+ body?: string,
10
+ path?: string,
11
+ pathParameters?: PathParameters,
12
+ queryStringParameters?: QueryStringParameters
13
+ };
14
+
15
+ export default function createAPIGatewayEvent({
16
+ pathParameters = null,
17
+ path = "",
18
+ body = null,
19
+ queryStringParameters = null
20
+ }: CreateAPIGatewayEventOptions = {}): APIGatewayEvent<string> {
21
+ return {
22
+ body,
23
+ headers: {},
24
+ multiValueHeaders: {},
25
+ httpMethod: "",
26
+ isBase64Encoded: false,
27
+ path,
28
+ pathParameters,
29
+ queryStringParameters,
30
+ multiValueQueryStringParameters: null,
31
+ stageVariables: null,
32
+ requestContext: {
33
+ accountId: "",
34
+ apiId: "",
35
+ httpMethod: "",
36
+ identity: {
37
+ accessKey: null,
38
+ accountId: null,
39
+ apiKey: null,
40
+ caller: null,
41
+ cognitoAuthenticationProvider: null,
42
+ cognitoAuthenticationType: null,
43
+ cognitoIdentityId: null,
44
+ cognitoIdentityPoolId: null,
45
+ sourceIp: "",
46
+ user: null,
47
+ userAgent: null,
48
+ userArn: null
49
+ },
50
+ stage: "",
51
+ requestId: "",
52
+ resourceId: "",
53
+ resourcePath: ""
54
+ },
55
+ resource: ""
56
+ };
57
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = createClient;
7
+
8
+ var _createLambdaClient = _interopRequireDefault(require("./create-lambda-client"));
9
+
10
+ var _jsonStringify = _interopRequireDefault(require("./json-stringify"));
11
+
12
+ var _parsePayload = _interopRequireDefault(require("./parse-payload"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ /**
17
+ * Create an APIGatewayHandlerClient. The client invokes an API Gateway handler, bypassing the gateway. It adapts the AWS SDK by packing and unpacking messages for invoking the handler.
18
+ *
19
+ * @param options
20
+ * @returns {APIGatewayHandlerClient<T>}
21
+ */
22
+ function createClient(options) {
23
+ const client = (0, _createLambdaClient.default)(options);
24
+ return async event => (0, _parsePayload.default)((await client((0, _jsonStringify.default)(event))));
25
+ }
@@ -0,0 +1,30 @@
1
+ // @flow
2
+
3
+ import type { APIGatewayEvent } from "flow-aws-lambda";
4
+ import createLambdaClient from "./create-lambda-client";
5
+ import type { Response } from "./response";
6
+ import jsonStringify from "./json-stringify";
7
+ import parsePayload from "./parse-payload";
8
+ import type { LambdaInvoke } from "./lambda-invoke";
9
+
10
+ /**
11
+ * Client that directly invokes an API Gateway handler, bypassing the gateway. The client handles packing and unpacking messages for invoking the handler.
12
+ */
13
+ export type APIGatewayHandlerClient<T> = (event: APIGatewayEvent<string>) => Promise<Response<T>>;
14
+
15
+ export type CreateClientOptions<T> = {
16
+ Lambda: LambdaInvoke,
17
+ FunctionName: string,
18
+ Validate?: T => void
19
+ };
20
+
21
+ /**
22
+ * Create an APIGatewayHandlerClient. The client invokes an API Gateway handler, bypassing the gateway. It adapts the AWS SDK by packing and unpacking messages for invoking the handler.
23
+ *
24
+ * @param options
25
+ * @returns {APIGatewayHandlerClient<T>}
26
+ */
27
+ export default function createClient<T>(options: CreateClientOptions<T>): APIGatewayHandlerClient<T> {
28
+ const client = createLambdaClient(options);
29
+ return async (event: APIGatewayEvent<string>) => parsePayload<T>(await client(jsonStringify(event)));
30
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = createLambdaClient;
7
+
8
+ /**
9
+ * AWS Lambda SDK adapter for createClient.
10
+ */
11
+ function createLambdaClient({
12
+ Lambda,
13
+ FunctionName
14
+ }) {
15
+ return async Payload => {
16
+ const invocationResponse = await Lambda.invoke({
17
+ FunctionName,
18
+ Payload
19
+ }).promise();
20
+
21
+ if (invocationResponse.StatusCode !== 200) {
22
+ var _invocationResponse$S;
23
+
24
+ throw new Error(`AWS Lambda invocation API failed with status ${(_invocationResponse$S = invocationResponse.StatusCode) !== null && _invocationResponse$S !== void 0 ? _invocationResponse$S : "(no status code)"}`);
25
+ }
26
+
27
+ if (typeof invocationResponse.Payload !== "string") {
28
+ throw new Error(`AWS Lambda invocation API returned the wrong payload type '${typeof invocationResponse.Payload}'; expected 'string'`);
29
+ }
30
+
31
+ return invocationResponse.Payload;
32
+ };
33
+ }
@@ -0,0 +1,35 @@
1
+ // @flow
2
+
3
+ import type { LambdaInvoke } from "./lambda-invoke";
4
+
5
+ interface Blob {}
6
+ type _Blob = Buffer | Uint8Array | Blob | string;
7
+ type LambdaClientType = (event: _Blob) => Promise<string>;
8
+
9
+ export type CreateLambdaClientOptions = {
10
+ Lambda: LambdaInvoke,
11
+ FunctionName: string
12
+ };
13
+
14
+ /**
15
+ * AWS Lambda SDK adapter for createClient.
16
+ */
17
+ export default function createLambdaClient({ Lambda, FunctionName }: CreateLambdaClientOptions): LambdaClientType {
18
+ return async (Payload: _Blob) => {
19
+ const invocationResponse = await Lambda.invoke({
20
+ FunctionName,
21
+ Payload
22
+ }).promise();
23
+ if (invocationResponse.StatusCode !== 200) {
24
+ throw new Error(
25
+ `AWS Lambda invocation API failed with status ${invocationResponse.StatusCode ?? "(no status code)"}`
26
+ );
27
+ }
28
+ if (typeof invocationResponse.Payload !== "string") {
29
+ throw new Error(
30
+ `AWS Lambda invocation API returned the wrong payload type '${typeof invocationResponse.Payload}'; expected 'string'`
31
+ );
32
+ }
33
+ return invocationResponse.Payload;
34
+ };
35
+ }
package/lib/index.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "createClient", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _createClient.default;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "createAPIGatewayEvent", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _createApiGatewayEvent.default;
16
+ }
17
+ });
18
+
19
+ var _createClient = _interopRequireDefault(require("./create-client"));
20
+
21
+ var _createApiGatewayEvent = _interopRequireDefault(require("./create-api-gateway-event"));
22
+
23
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -0,0 +1,4 @@
1
+ // @flow
2
+
3
+ export { default as createClient } from "./create-client";
4
+ export { default as createAPIGatewayEvent } from "./create-api-gateway-event";
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = jsonStringify;
7
+
8
+ /**
9
+ * Stringify to JSON, returning a string or else throwing an exception because of unserializable input.
10
+ *
11
+ * @param value
12
+ * @returns {string}
13
+ */
14
+ // flowlint-next-line unclear-type:off
15
+ function jsonStringify(value) {
16
+ const result = JSON.stringify(value);
17
+
18
+ if (result == null) {
19
+ throw new Error("Cannot stringify value");
20
+ }
21
+
22
+ return result;
23
+ }
@@ -0,0 +1,16 @@
1
+ // @flow
2
+
3
+ /**
4
+ * Stringify to JSON, returning a string or else throwing an exception because of unserializable input.
5
+ *
6
+ * @param value
7
+ * @returns {string}
8
+ */
9
+ // flowlint-next-line unclear-type:off
10
+ export default function jsonStringify(value: any): string {
11
+ const result = JSON.stringify(value);
12
+ if (result == null) {
13
+ throw new Error("Cannot stringify value");
14
+ }
15
+ return result;
16
+ }
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,10 @@
1
+ // @flow
2
+
3
+ import type Lambda from "@cumulusds/flow-aws-sdk/clients/lambda";
4
+
5
+ /**
6
+ * This library only needs the invoke method from aws-sdk Lambda client.
7
+ */
8
+ export type LambdaInvoke = {
9
+ +invoke: $PropertyType<Lambda, "invoke">
10
+ };
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = parsePayload;
7
+
8
+ /**
9
+ * Decode the handler response
10
+ *
11
+ * @param payload
12
+ * @param validate if given, the validate function is called on the parsed response body. The function should throw an exception if the response is invalid.
13
+ * @returns {{headers: {[p: string]: boolean|number|string}, data: *, status: number}}
14
+ */
15
+ function parsePayload(payload, validate) {
16
+ var _proxyResult$headers;
17
+
18
+ const proxyResult = JSON.parse(payload);
19
+
20
+ if (proxyResult.isBase64Encoded === true) {
21
+ throw new Error("A base64 encoded response from API Gateway handler was received, but is not supported.");
22
+ }
23
+
24
+ const data = JSON.parse(proxyResult.body);
25
+ validate === null || validate === void 0 ? void 0 : validate(data);
26
+ return {
27
+ data,
28
+ status: proxyResult.statusCode,
29
+ headers: (_proxyResult$headers = proxyResult.headers) !== null && _proxyResult$headers !== void 0 ? _proxyResult$headers : {}
30
+ };
31
+ }
@@ -0,0 +1,25 @@
1
+ // @flow
2
+
3
+ import type { ProxyResult } from "flow-aws-lambda";
4
+ import type { Response } from "./response";
5
+
6
+ /**
7
+ * Decode the handler response
8
+ *
9
+ * @param payload
10
+ * @param validate if given, the validate function is called on the parsed response body. The function should throw an exception if the response is invalid.
11
+ * @returns {{headers: {[p: string]: boolean|number|string}, data: *, status: number}}
12
+ */
13
+ export default function parsePayload<T>(payload: string, validate?: T => void): Response<T> {
14
+ const proxyResult: ProxyResult = JSON.parse(payload);
15
+ if (proxyResult.isBase64Encoded === true) {
16
+ throw new Error("A base64 encoded response from API Gateway handler was received, but is not supported.");
17
+ }
18
+ const data: T = JSON.parse(proxyResult.body);
19
+ validate?.(data);
20
+ return {
21
+ data,
22
+ status: proxyResult.statusCode,
23
+ headers: proxyResult.headers ?? {}
24
+ };
25
+ }
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,15 @@
1
+ // @flow
2
+
3
+ /**
4
+ * Decoded handler response
5
+ */
6
+ export type Response<T> = {|
7
+ // the response provided by the handler
8
+ data: T,
9
+
10
+ // the HTTP status code
11
+ status: number,
12
+
13
+ // response headers
14
+ headers: { [header: string]: boolean | number | string }
15
+ |};
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@cumulusds/aws-apig-bypass",
3
+ "version": "0.0.1",
4
+ "description": "Client for API Gateway handlers, bypassing API Gateway by directly invoking the Lambda",
5
+ "repository": "https://github.com/CumulusDS/aws-apig-bypass",
6
+ "author": "Cumulus Digital Systems",
7
+ "license": "MIT",
8
+ "private": false,
9
+ "engines": {
10
+ "node": ">=10"
11
+ },
12
+ "main": "lib/index.js",
13
+ "src": [
14
+ "bin, lib",
15
+ "package.json"
16
+ ],
17
+ "scripts": {
18
+ "build": "run-p build:babel build:flow-copy-source build:license-checker",
19
+ "build:babel": "babel src --out-dir lib --ignore test.js",
20
+ "build:flow-copy-source": "flow-copy-source --ignore test.js src lib",
21
+ "build:license-checker": "license-checker --csv --out var/licenses.csv",
22
+ "clean": "shx rm -rf lib",
23
+ "git:push": "git push --follow-tags",
24
+ "publish:patch": "run-s version:patch git:push",
25
+ "publish:minor": "run-s version:minor git:push",
26
+ "publish:major": "run-s version:major git:push",
27
+ "sites": "node bin/sites.js",
28
+ "test": "run-p --aggregate-output test:**",
29
+ "test:flow:coverage-report": "flow-coverage-report -i '{src,test}/**/*.js' -t html -t text --threshold 99 --output-dir var/coverage/flow",
30
+ "test:flow:status": "flow status",
31
+ "test:jest": "jest --color",
32
+ "test:lint": "eslint *.js src test",
33
+ "test:prettier": "prettier --list-different \"{src,test}/**/*.{js,jsx,yml}\" \"*.{js,yml}\"",
34
+ "version:patch": "yarn version --new-version patch",
35
+ "version:minor": "yarn version --new-version minor",
36
+ "version:major": "yarn version --new-version major"
37
+ },
38
+ "jest": {
39
+ "verbose": true,
40
+ "collectCoverage": true,
41
+ "collectCoverageFrom": [
42
+ "src/**/*.js"
43
+ ],
44
+ "testEnvironment": "node",
45
+ "coverageDirectory": "var/coverage/test",
46
+ "coverageThreshold": {
47
+ "global": {
48
+ "branches": 100,
49
+ "functions": 100,
50
+ "lines": 100,
51
+ "statements": 100
52
+ }
53
+ }
54
+ },
55
+ "dependencies": {
56
+ "@cumulusds/flow-aws-sdk": "^2.818.0",
57
+ "flow-aws-lambda": "CumulusDS/flow-aws-lambda#ef1bd9a0342e55a0e9e1b225bdbc2a3c2a4d5632"
58
+ },
59
+ "devDependencies": {
60
+ "@babel/cli": "^7.0.0",
61
+ "@babel/core": "^7.7.4",
62
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.7.4",
63
+ "@babel/plugin-proposal-optional-chaining": "^7.12.7",
64
+ "@babel/preset-env": "^7.0.0",
65
+ "@babel/preset-flow": "^7.0.0",
66
+ "babel-eslint": "10.0.3",
67
+ "babel-jest": "^24.9.0",
68
+ "eslint": "^7.5.0",
69
+ "eslint-config-airbnb-base": "14.0.0",
70
+ "eslint-config-prettier": "^2.9.0",
71
+ "eslint-plugin-flowtype": "^2.49.3",
72
+ "eslint-plugin-import": "2.18.2",
73
+ "eslint-plugin-jest": "^21.15.1",
74
+ "eslint-plugin-prettier": "^2.6.0",
75
+ "flow-bin": "^0.141.0",
76
+ "flow-copy-source": "^2.0.9",
77
+ "flow-coverage-report": "^0.8.0",
78
+ "flow-typed": "^3.2.1",
79
+ "git-describe": "^4.0.4",
80
+ "jest": "^26.0.0",
81
+ "license-checker": "^25.0.1",
82
+ "npm-run-all": "^4.1.3",
83
+ "prettier": "^1.14.0",
84
+ "shx": "^0.3.2"
85
+ }
86
+ }
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ printWidth: 120
3
+ };
@@ -0,0 +1,57 @@
1
+ // @flow
2
+
3
+ import type { APIGatewayEvent } from "flow-aws-lambda";
4
+
5
+ export type PathParameters = { [name: string]: string } | null;
6
+ export type QueryStringParameters = { [name: string]: string } | null;
7
+
8
+ export type CreateAPIGatewayEventOptions = {
9
+ body?: string,
10
+ path?: string,
11
+ pathParameters?: PathParameters,
12
+ queryStringParameters?: QueryStringParameters
13
+ };
14
+
15
+ export default function createAPIGatewayEvent({
16
+ pathParameters = null,
17
+ path = "",
18
+ body = null,
19
+ queryStringParameters = null
20
+ }: CreateAPIGatewayEventOptions = {}): APIGatewayEvent<string> {
21
+ return {
22
+ body,
23
+ headers: {},
24
+ multiValueHeaders: {},
25
+ httpMethod: "",
26
+ isBase64Encoded: false,
27
+ path,
28
+ pathParameters,
29
+ queryStringParameters,
30
+ multiValueQueryStringParameters: null,
31
+ stageVariables: null,
32
+ requestContext: {
33
+ accountId: "",
34
+ apiId: "",
35
+ httpMethod: "",
36
+ identity: {
37
+ accessKey: null,
38
+ accountId: null,
39
+ apiKey: null,
40
+ caller: null,
41
+ cognitoAuthenticationProvider: null,
42
+ cognitoAuthenticationType: null,
43
+ cognitoIdentityId: null,
44
+ cognitoIdentityPoolId: null,
45
+ sourceIp: "",
46
+ user: null,
47
+ userAgent: null,
48
+ userArn: null
49
+ },
50
+ stage: "",
51
+ requestId: "",
52
+ resourceId: "",
53
+ resourcePath: ""
54
+ },
55
+ resource: ""
56
+ };
57
+ }
@@ -0,0 +1,30 @@
1
+ // @flow
2
+
3
+ import type { APIGatewayEvent } from "flow-aws-lambda";
4
+ import createLambdaClient from "./create-lambda-client";
5
+ import type { Response } from "./response";
6
+ import jsonStringify from "./json-stringify";
7
+ import parsePayload from "./parse-payload";
8
+ import type { LambdaInvoke } from "./lambda-invoke";
9
+
10
+ /**
11
+ * Client that directly invokes an API Gateway handler, bypassing the gateway. The client handles packing and unpacking messages for invoking the handler.
12
+ */
13
+ export type APIGatewayHandlerClient<T> = (event: APIGatewayEvent<string>) => Promise<Response<T>>;
14
+
15
+ export type CreateClientOptions<T> = {
16
+ Lambda: LambdaInvoke,
17
+ FunctionName: string,
18
+ Validate?: T => void
19
+ };
20
+
21
+ /**
22
+ * Create an APIGatewayHandlerClient. The client invokes an API Gateway handler, bypassing the gateway. It adapts the AWS SDK by packing and unpacking messages for invoking the handler.
23
+ *
24
+ * @param options
25
+ * @returns {APIGatewayHandlerClient<T>}
26
+ */
27
+ export default function createClient<T>(options: CreateClientOptions<T>): APIGatewayHandlerClient<T> {
28
+ const client = createLambdaClient(options);
29
+ return async (event: APIGatewayEvent<string>) => parsePayload<T>(await client(jsonStringify(event)));
30
+ }
@@ -0,0 +1,35 @@
1
+ // @flow
2
+
3
+ import type { LambdaInvoke } from "./lambda-invoke";
4
+
5
+ interface Blob {}
6
+ type _Blob = Buffer | Uint8Array | Blob | string;
7
+ type LambdaClientType = (event: _Blob) => Promise<string>;
8
+
9
+ export type CreateLambdaClientOptions = {
10
+ Lambda: LambdaInvoke,
11
+ FunctionName: string
12
+ };
13
+
14
+ /**
15
+ * AWS Lambda SDK adapter for createClient.
16
+ */
17
+ export default function createLambdaClient({ Lambda, FunctionName }: CreateLambdaClientOptions): LambdaClientType {
18
+ return async (Payload: _Blob) => {
19
+ const invocationResponse = await Lambda.invoke({
20
+ FunctionName,
21
+ Payload
22
+ }).promise();
23
+ if (invocationResponse.StatusCode !== 200) {
24
+ throw new Error(
25
+ `AWS Lambda invocation API failed with status ${invocationResponse.StatusCode ?? "(no status code)"}`
26
+ );
27
+ }
28
+ if (typeof invocationResponse.Payload !== "string") {
29
+ throw new Error(
30
+ `AWS Lambda invocation API returned the wrong payload type '${typeof invocationResponse.Payload}'; expected 'string'`
31
+ );
32
+ }
33
+ return invocationResponse.Payload;
34
+ };
35
+ }
package/src/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // @flow
2
+
3
+ export { default as createClient } from "./create-client";
4
+ export { default as createAPIGatewayEvent } from "./create-api-gateway-event";
@@ -0,0 +1,16 @@
1
+ // @flow
2
+
3
+ /**
4
+ * Stringify to JSON, returning a string or else throwing an exception because of unserializable input.
5
+ *
6
+ * @param value
7
+ * @returns {string}
8
+ */
9
+ // flowlint-next-line unclear-type:off
10
+ export default function jsonStringify(value: any): string {
11
+ const result = JSON.stringify(value);
12
+ if (result == null) {
13
+ throw new Error("Cannot stringify value");
14
+ }
15
+ return result;
16
+ }
@@ -0,0 +1,10 @@
1
+ // @flow
2
+
3
+ import type Lambda from "@cumulusds/flow-aws-sdk/clients/lambda";
4
+
5
+ /**
6
+ * This library only needs the invoke method from aws-sdk Lambda client.
7
+ */
8
+ export type LambdaInvoke = {
9
+ +invoke: $PropertyType<Lambda, "invoke">
10
+ };
@@ -0,0 +1,25 @@
1
+ // @flow
2
+
3
+ import type { ProxyResult } from "flow-aws-lambda";
4
+ import type { Response } from "./response";
5
+
6
+ /**
7
+ * Decode the handler response
8
+ *
9
+ * @param payload
10
+ * @param validate if given, the validate function is called on the parsed response body. The function should throw an exception if the response is invalid.
11
+ * @returns {{headers: {[p: string]: boolean|number|string}, data: *, status: number}}
12
+ */
13
+ export default function parsePayload<T>(payload: string, validate?: T => void): Response<T> {
14
+ const proxyResult: ProxyResult = JSON.parse(payload);
15
+ if (proxyResult.isBase64Encoded === true) {
16
+ throw new Error("A base64 encoded response from API Gateway handler was received, but is not supported.");
17
+ }
18
+ const data: T = JSON.parse(proxyResult.body);
19
+ validate?.(data);
20
+ return {
21
+ data,
22
+ status: proxyResult.statusCode,
23
+ headers: proxyResult.headers ?? {}
24
+ };
25
+ }