@bifravst/http-api-mock 3.0.7 → 3.0.8
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 +3 -3
- package/{npm → dist}/cdk/http-api-mock.js +1 -1
- package/dist/package.json +103 -0
- package/package.json +3 -5
- package/cdk/App.ts +0 -26
- package/cdk/Stack.ts +0 -66
- package/cdk/http-api-mock.ts +0 -109
- package/cdk/resources/HttpApiMock.ts +0 -117
- package/cdk/resources/checkMatchingQueryParams.spec.ts +0 -67
- package/cdk/resources/checkMatchingQueryParams.ts +0 -40
- package/cdk/resources/http-api-mock-lambda.ts +0 -147
- package/cdk/resources/splitMockResponse.spec.ts +0 -17
- package/cdk/resources/splitMockResponse.ts +0 -25
- package/npm/cdk/App.ts +0 -26
- package/npm/cdk/Stack.ts +0 -66
- package/npm/cdk/http-api-mock.ts +0 -109
- package/npm/cdk/resources/HttpApiMock.ts +0 -117
- package/npm/cdk/resources/checkMatchingQueryParams.spec.ts +0 -67
- package/npm/cdk/resources/checkMatchingQueryParams.ts +0 -40
- package/npm/cdk/resources/http-api-mock-lambda.ts +0 -147
- package/npm/cdk/resources/splitMockResponse.spec.ts +0 -17
- package/npm/cdk/resources/splitMockResponse.ts +0 -25
- package/npm/package.json +0 -105
- package/src/mock.spec.ts +0 -52
- package/src/mock.ts +0 -61
- package/src/parseMockRequest.spec.ts +0 -30
- package/src/parseMockRequest.ts +0 -35
- package/src/parseMockResponse.spec.ts +0 -27
- package/src/parseMockResponse.ts +0 -35
- package/src/randomString.ts +0 -7
- package/src/requests.ts +0 -28
- package/src/responses.ts +0 -50
- package/src/sortQueryString.spec.ts +0 -38
- package/src/sortQueryString.ts +0 -26
- /package/{npm → dist}/cdk/App.d.ts +0 -0
- /package/{npm → dist}/cdk/App.js +0 -0
- /package/{npm → dist}/cdk/Stack.d.ts +0 -0
- /package/{npm → dist}/cdk/Stack.js +0 -0
- /package/{npm → dist}/cdk/http-api-mock.d.ts +0 -0
- /package/{npm → dist}/cdk/resources/HttpApiMock.d.ts +0 -0
- /package/{npm → dist}/cdk/resources/HttpApiMock.js +0 -0
- /package/{npm → dist}/cdk/resources/checkMatchingQueryParams.d.ts +0 -0
- /package/{npm → dist}/cdk/resources/checkMatchingQueryParams.js +0 -0
- /package/{npm → dist}/cdk/resources/checkMatchingQueryParams.spec.d.ts +0 -0
- /package/{npm → dist}/cdk/resources/checkMatchingQueryParams.spec.js +0 -0
- /package/{npm → dist}/cdk/resources/http-api-mock-lambda.d.ts +0 -0
- /package/{npm → dist}/cdk/resources/http-api-mock-lambda.js +0 -0
- /package/{npm → dist}/cdk/resources/splitMockResponse.d.ts +0 -0
- /package/{npm → dist}/cdk/resources/splitMockResponse.js +0 -0
- /package/{npm → dist}/cdk/resources/splitMockResponse.spec.d.ts +0 -0
- /package/{npm → dist}/cdk/resources/splitMockResponse.spec.js +0 -0
- /package/{npm → dist}/e2e.spec.d.ts +0 -0
- /package/{npm → dist}/e2e.spec.js +0 -0
- /package/{npm → dist}/src/mock.d.ts +0 -0
- /package/{npm → dist}/src/mock.js +0 -0
- /package/{npm → dist}/src/mock.spec.d.ts +0 -0
- /package/{npm → dist}/src/mock.spec.js +0 -0
- /package/{npm → dist}/src/parseMockRequest.d.ts +0 -0
- /package/{npm → dist}/src/parseMockRequest.js +0 -0
- /package/{npm → dist}/src/parseMockRequest.spec.d.ts +0 -0
- /package/{npm → dist}/src/parseMockRequest.spec.js +0 -0
- /package/{npm → dist}/src/parseMockResponse.d.ts +0 -0
- /package/{npm → dist}/src/parseMockResponse.js +0 -0
- /package/{npm → dist}/src/parseMockResponse.spec.d.ts +0 -0
- /package/{npm → dist}/src/parseMockResponse.spec.js +0 -0
- /package/{npm → dist}/src/randomString.d.ts +0 -0
- /package/{npm → dist}/src/randomString.js +0 -0
- /package/{npm → dist}/src/requests.d.ts +0 -0
- /package/{npm → dist}/src/requests.js +0 -0
- /package/{npm → dist}/src/responses.d.ts +0 -0
- /package/{npm → dist}/src/responses.js +0 -0
- /package/{npm → dist}/src/sortQueryString.d.ts +0 -0
- /package/{npm → dist}/src/sortQueryString.js +0 -0
- /package/{npm → dist}/src/sortQueryString.spec.d.ts +0 -0
- /package/{npm → dist}/src/sortQueryString.spec.js +0 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Provides a mock HTTP API for testing third-party API integrations.
|
|
|
16
16
|
Create a new mock API:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
|
|
19
|
+
node node_modules/@bifravst/http-api-mock/dist/cdk/http-api-mock.js
|
|
20
20
|
|
|
21
21
|
{
|
|
22
22
|
"stackName": "http-api-mock-69c2c4b9",
|
|
@@ -29,13 +29,13 @@ npx @bifravst/http-api-mock
|
|
|
29
29
|
## Describe a mock HTTP API
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
|
|
32
|
+
node node_modules/@bifravst/http-api-mock/dist/cdk/http-api-mock.js describe <stackName>
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
## Delete a mock HTTP API
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
|
|
38
|
+
node node_modules/@bifravst/http-api-mock/dist/cdk/http-api-mock.js destroy <stackName>
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
## Node & NPM
|
|
@@ -59,7 +59,7 @@ const app = new HTTPAPIMockApp(stackName, {
|
|
|
59
59
|
lambdaSources: {
|
|
60
60
|
httpApiMock: await packLambdaFromPath({
|
|
61
61
|
id: 'httpApiMock',
|
|
62
|
-
sourceFilePath: 'cdk/resources/http-api-mock-lambda.
|
|
62
|
+
sourceFilePath: 'cdk/resources/http-api-mock-lambda.js',
|
|
63
63
|
baseDir,
|
|
64
64
|
distDir: lambdasDir,
|
|
65
65
|
}),
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bifravst/http-api-mock",
|
|
3
|
+
"version": "3.0.8",
|
|
4
|
+
"description": "Helper functions for AWS lambdas written in TypeScript.",
|
|
5
|
+
"exports": {
|
|
6
|
+
"./*": {
|
|
7
|
+
"import": {
|
|
8
|
+
"default": "./npm/src/*.js",
|
|
9
|
+
"types": "./npm/src/*.d.ts"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"scripts": {
|
|
15
|
+
"prepare": "husky && case \"$npm_command\" in install|ci) check-node-version --package ;; esac",
|
|
16
|
+
"prepublishOnly": "npx tsc --noEmit false -d",
|
|
17
|
+
"test": "node --no-warnings --experimental-transform-types --test \"!(node_modules|e2e-tests|integration-tests)/**/*.spec.ts\""
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/bifravst/http-api-mock.git"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/bifravst/http-api-mock/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/bifravst/http-api-mock",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"aws",
|
|
29
|
+
"lambda",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
32
|
+
"author": "Nordic Semiconductor ASA | nordicsemi.no",
|
|
33
|
+
"license": "BSD-3-Clause",
|
|
34
|
+
"lint-staged": {
|
|
35
|
+
"*.ts": [
|
|
36
|
+
"prettier --write",
|
|
37
|
+
"eslint"
|
|
38
|
+
],
|
|
39
|
+
"*.{md,json,yaml,yml}": [
|
|
40
|
+
"prettier --write"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=24.19.0 <25",
|
|
45
|
+
"npm": ">=12.0.2 <13"
|
|
46
|
+
},
|
|
47
|
+
"release": {
|
|
48
|
+
"branches": [
|
|
49
|
+
"saga"
|
|
50
|
+
],
|
|
51
|
+
"remoteTags": true,
|
|
52
|
+
"plugins": [
|
|
53
|
+
"@semantic-release/commit-analyzer",
|
|
54
|
+
"@semantic-release/release-notes-generator",
|
|
55
|
+
"@semantic-release/npm",
|
|
56
|
+
[
|
|
57
|
+
"@semantic-release/github",
|
|
58
|
+
{
|
|
59
|
+
"successCommentCondition": false,
|
|
60
|
+
"failTitle": false
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
},
|
|
68
|
+
"files": [
|
|
69
|
+
"dist",
|
|
70
|
+
"LICENSE",
|
|
71
|
+
"README.md"
|
|
72
|
+
],
|
|
73
|
+
"prettier": "@bifravst/prettier-config",
|
|
74
|
+
"dependencies": {
|
|
75
|
+
"@aws-sdk/client-cloudformation": "3.1111.0",
|
|
76
|
+
"@aws-sdk/client-dynamodb": "3.1111.0",
|
|
77
|
+
"@aws-sdk/client-sts": "3.1111.0",
|
|
78
|
+
"@aws-cdk/toolkit-lib": "1.38.2",
|
|
79
|
+
"@aws-sdk/util-dynamodb": "3.996.9",
|
|
80
|
+
"@bifravst/aws-cdk-lambda-helpers": "5.0.4",
|
|
81
|
+
"@bifravst/cloudformation-helpers": "10.0.1",
|
|
82
|
+
"@bifravst/from-env": "4.0.0",
|
|
83
|
+
"@bifravst/run": "2.0.1",
|
|
84
|
+
"aws-cdk-lib": "2.265.0",
|
|
85
|
+
"cdk": "2.1136.0",
|
|
86
|
+
"chalk": "6.0.0",
|
|
87
|
+
"command-line-args": "6.0.2"
|
|
88
|
+
},
|
|
89
|
+
"devDependencies": {
|
|
90
|
+
"@bifravst/eslint-config-typescript": "8.0.0",
|
|
91
|
+
"@bifravst/prettier-config": "2.0.0",
|
|
92
|
+
"@commitlint/config-conventional": "21.2.2",
|
|
93
|
+
"@types/aws-lambda": "8.10.162",
|
|
94
|
+
"@types/command-line-args": "5.2.3",
|
|
95
|
+
"@types/node": "26.2.0",
|
|
96
|
+
"@typescript/native": "npm:typescript@7.0.2",
|
|
97
|
+
"check-node-version": "4.2.1",
|
|
98
|
+
"commitlint": "21.2.2",
|
|
99
|
+
"husky": "9.1.7",
|
|
100
|
+
"lint-staged": "17.3.0",
|
|
101
|
+
"typescript": "npm:@typescript/typescript6@6.0.2"
|
|
102
|
+
}
|
|
103
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bifravst/http-api-mock",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.8",
|
|
4
4
|
"description": "Helper functions for AWS lambdas written in TypeScript.",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./*": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"type": "module",
|
|
14
14
|
"scripts": {
|
|
15
15
|
"prepare": "husky && case \"$npm_command\" in install|ci) check-node-version --package ;; esac",
|
|
16
|
-
"prepublishOnly": "npx tsc --noEmit false
|
|
16
|
+
"prepublishOnly": "npx tsc --noEmit false -d",
|
|
17
17
|
"test": "node --no-warnings --experimental-transform-types --test \"!(node_modules|e2e-tests|integration-tests)/**/*.spec.ts\""
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
@@ -66,9 +66,7 @@
|
|
|
66
66
|
"access": "public"
|
|
67
67
|
},
|
|
68
68
|
"files": [
|
|
69
|
-
"
|
|
70
|
-
"cdk",
|
|
71
|
-
"src",
|
|
69
|
+
"dist",
|
|
72
70
|
"LICENSE",
|
|
73
71
|
"README.md"
|
|
74
72
|
],
|
package/cdk/App.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { PackedLambda } from '@bifravst/aws-cdk-lambda-helpers'
|
|
2
|
-
import type { PackedLayer } from '@bifravst/aws-cdk-lambda-helpers/layer'
|
|
3
|
-
import { App } from 'aws-cdk-lib'
|
|
4
|
-
import { HTTPAPIMockStack } from './Stack.ts'
|
|
5
|
-
|
|
6
|
-
export class HTTPAPIMockApp extends App {
|
|
7
|
-
public constructor(
|
|
8
|
-
stackName: string,
|
|
9
|
-
{
|
|
10
|
-
lambdaSources,
|
|
11
|
-
layer,
|
|
12
|
-
}: {
|
|
13
|
-
lambdaSources: {
|
|
14
|
-
httpApiMock: PackedLambda
|
|
15
|
-
}
|
|
16
|
-
layer: PackedLayer
|
|
17
|
-
},
|
|
18
|
-
) {
|
|
19
|
-
super({
|
|
20
|
-
context: {
|
|
21
|
-
isTest: true,
|
|
22
|
-
},
|
|
23
|
-
})
|
|
24
|
-
new HTTPAPIMockStack(this, stackName, { lambdaSources, layer })
|
|
25
|
-
}
|
|
26
|
-
}
|
package/cdk/Stack.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import type { PackedLambda } from '@bifravst/aws-cdk-lambda-helpers'
|
|
2
|
-
import { LambdaSource } from '@bifravst/aws-cdk-lambda-helpers/cdk'
|
|
3
|
-
import type { PackedLayer } from '@bifravst/aws-cdk-lambda-helpers/layer'
|
|
4
|
-
import type { App } from 'aws-cdk-lib'
|
|
5
|
-
import { CfnOutput, aws_lambda as Lambda, Stack } from 'aws-cdk-lib'
|
|
6
|
-
import { HttpApiMock } from './resources/HttpApiMock.ts'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* This is CloudFormation stack sets up a dummy HTTP API which stores all requests in SQS for inspection
|
|
10
|
-
*/
|
|
11
|
-
export class HTTPAPIMockStack extends Stack {
|
|
12
|
-
public constructor(
|
|
13
|
-
parent: App,
|
|
14
|
-
stackName: string,
|
|
15
|
-
{
|
|
16
|
-
lambdaSources,
|
|
17
|
-
layer,
|
|
18
|
-
}: {
|
|
19
|
-
lambdaSources: {
|
|
20
|
-
httpApiMock: PackedLambda
|
|
21
|
-
}
|
|
22
|
-
layer: PackedLayer
|
|
23
|
-
},
|
|
24
|
-
) {
|
|
25
|
-
super(parent, stackName, {
|
|
26
|
-
description:
|
|
27
|
-
'Provides a mock HTTP API for testing third-party API integrations.',
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
const baseLayer = new Lambda.LayerVersion(this, 'baseLayer', {
|
|
31
|
-
layerVersionName: `${Stack.of(this).stackName}-baseLayer`,
|
|
32
|
-
code: new LambdaSource(this, {
|
|
33
|
-
id: 'baseLayer',
|
|
34
|
-
zipFilePath: layer.layerZipFilePath,
|
|
35
|
-
hash: layer.hash,
|
|
36
|
-
}).code,
|
|
37
|
-
compatibleArchitectures: [Lambda.Architecture.ARM_64],
|
|
38
|
-
compatibleRuntimes: [Lambda.Runtime.NODEJS_24_X],
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
const httpMockApi = new HttpApiMock(this, {
|
|
42
|
-
lambdaSources,
|
|
43
|
-
layers: [baseLayer],
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
// Export these so the test runner can use them
|
|
47
|
-
new CfnOutput(this, 'apiURL', {
|
|
48
|
-
value: httpMockApi.api.url,
|
|
49
|
-
exportName: `${this.stackName}:apiURL`,
|
|
50
|
-
})
|
|
51
|
-
new CfnOutput(this, 'responsesTableName', {
|
|
52
|
-
value: httpMockApi.responsesTable.tableName,
|
|
53
|
-
exportName: `${this.stackName}:responsesTableName`,
|
|
54
|
-
})
|
|
55
|
-
new CfnOutput(this, 'requestsTableName', {
|
|
56
|
-
value: httpMockApi.requestsTable.tableName,
|
|
57
|
-
exportName: `${this.stackName}:requestsTableName`,
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export type StackOutputs = {
|
|
63
|
-
apiURL: string
|
|
64
|
-
requestsTableName: string
|
|
65
|
-
responsesTableName: string
|
|
66
|
-
}
|
package/cdk/http-api-mock.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { Toolkit } from '@aws-cdk/toolkit-lib'
|
|
2
|
-
import { CloudFormationClient } from '@aws-sdk/client-cloudformation'
|
|
3
|
-
import { packLambdaFromPath } from '@bifravst/aws-cdk-lambda-helpers'
|
|
4
|
-
import { packLayer } from '@bifravst/aws-cdk-lambda-helpers/layer'
|
|
5
|
-
import { stackOutput } from '@bifravst/cloudformation-helpers'
|
|
6
|
-
import commandLineArgs from 'command-line-args'
|
|
7
|
-
import { writeFileSync } from 'node:fs'
|
|
8
|
-
import fs from 'node:fs/promises'
|
|
9
|
-
import os from 'node:os'
|
|
10
|
-
import path from 'node:path'
|
|
11
|
-
import { fileURLToPath } from 'node:url'
|
|
12
|
-
import pJSON from '../package.json' with { type: 'json' }
|
|
13
|
-
import { randomString } from '../src/randomString.ts'
|
|
14
|
-
import { HTTPAPIMockApp } from './App.ts'
|
|
15
|
-
import type { StackOutputs } from './Stack.ts'
|
|
16
|
-
|
|
17
|
-
const options = commandLineArgs([
|
|
18
|
-
{
|
|
19
|
-
name: 'config',
|
|
20
|
-
type: Boolean,
|
|
21
|
-
defaultValue: false,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
name: 'destroy',
|
|
25
|
-
type: Boolean,
|
|
26
|
-
defaultValue: false,
|
|
27
|
-
},
|
|
28
|
-
])
|
|
29
|
-
|
|
30
|
-
const loadConfig = async (): Promise<
|
|
31
|
-
Partial<StackOutputs & { stackName: string }>
|
|
32
|
-
> => {
|
|
33
|
-
try {
|
|
34
|
-
const config = JSON.parse(
|
|
35
|
-
await fs.readFile(
|
|
36
|
-
path.join(process.cwd(), 'http-api-mock.json'),
|
|
37
|
-
'utf-8',
|
|
38
|
-
),
|
|
39
|
-
)
|
|
40
|
-
return config
|
|
41
|
-
} catch {
|
|
42
|
-
return {}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const stackName =
|
|
47
|
-
process.env.HTTP_API_MOCK_STACK_NAME ??
|
|
48
|
-
(await loadConfig())?.stackName ??
|
|
49
|
-
`http-api-mock-${randomString()}`
|
|
50
|
-
|
|
51
|
-
const saveConfig = async () => {
|
|
52
|
-
writeFileSync(
|
|
53
|
-
path.join(process.cwd(), 'http-api-mock.json'),
|
|
54
|
-
JSON.stringify(
|
|
55
|
-
{
|
|
56
|
-
stackName,
|
|
57
|
-
...(await stackOutput(new CloudFormationClient({}))<StackOutputs>(
|
|
58
|
-
stackName,
|
|
59
|
-
)),
|
|
60
|
-
},
|
|
61
|
-
null,
|
|
62
|
-
2,
|
|
63
|
-
),
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (options.config === true) {
|
|
68
|
-
await saveConfig()
|
|
69
|
-
process.exit(0)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const baseDir = path.join(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
73
|
-
const distDir = await fs.mkdtemp(path.join(os.tmpdir(), 'temp-'))
|
|
74
|
-
const lambdasDir = path.join(distDir, 'lambdas')
|
|
75
|
-
await fs.mkdir(lambdasDir)
|
|
76
|
-
const layersDir = path.join(distDir, 'layers')
|
|
77
|
-
await fs.mkdir(layersDir)
|
|
78
|
-
|
|
79
|
-
const dependencies: Array<keyof (typeof pJSON)['dependencies']> = [
|
|
80
|
-
'@bifravst/from-env',
|
|
81
|
-
]
|
|
82
|
-
|
|
83
|
-
const app = new HTTPAPIMockApp(stackName, {
|
|
84
|
-
lambdaSources: {
|
|
85
|
-
httpApiMock: await packLambdaFromPath({
|
|
86
|
-
id: 'httpApiMock',
|
|
87
|
-
sourceFilePath: 'cdk/resources/http-api-mock-lambda.ts',
|
|
88
|
-
baseDir,
|
|
89
|
-
distDir: lambdasDir,
|
|
90
|
-
}),
|
|
91
|
-
},
|
|
92
|
-
layer: await packLayer({
|
|
93
|
-
id: 'testResources',
|
|
94
|
-
dependencies,
|
|
95
|
-
baseDir,
|
|
96
|
-
distDir: layersDir,
|
|
97
|
-
}),
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
const cdk = new Toolkit()
|
|
101
|
-
|
|
102
|
-
const cx = await cdk.fromAssemblyBuilder(async () => app.synth())
|
|
103
|
-
|
|
104
|
-
if (options.destroy === true) {
|
|
105
|
-
await cdk.destroy(cx)
|
|
106
|
-
} else {
|
|
107
|
-
await cdk.deploy(cx)
|
|
108
|
-
await saveConfig()
|
|
109
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import type { PackedLambda } from '@bifravst/aws-cdk-lambda-helpers'
|
|
2
|
-
import {
|
|
3
|
-
LambdaLogGroup,
|
|
4
|
-
LambdaSource,
|
|
5
|
-
} from '@bifravst/aws-cdk-lambda-helpers/cdk'
|
|
6
|
-
import {
|
|
7
|
-
aws_apigateway as ApiGateway,
|
|
8
|
-
Duration,
|
|
9
|
-
aws_dynamodb as DynamoDB,
|
|
10
|
-
aws_iam as IAM,
|
|
11
|
-
aws_lambda as Lambda,
|
|
12
|
-
aws_logs as Logs,
|
|
13
|
-
RemovalPolicy,
|
|
14
|
-
Resource,
|
|
15
|
-
} from 'aws-cdk-lib'
|
|
16
|
-
import type { Construct } from 'constructs'
|
|
17
|
-
|
|
18
|
-
export class HttpApiMock extends Resource {
|
|
19
|
-
public readonly api: ApiGateway.RestApi
|
|
20
|
-
public readonly requestsTable: DynamoDB.Table
|
|
21
|
-
public readonly responsesTable: DynamoDB.Table
|
|
22
|
-
|
|
23
|
-
public constructor(
|
|
24
|
-
parent: Construct,
|
|
25
|
-
{
|
|
26
|
-
lambdaSources,
|
|
27
|
-
layers,
|
|
28
|
-
}: {
|
|
29
|
-
lambdaSources: {
|
|
30
|
-
httpApiMock: PackedLambda
|
|
31
|
-
}
|
|
32
|
-
layers: Lambda.ILayerVersion[]
|
|
33
|
-
},
|
|
34
|
-
) {
|
|
35
|
-
super(parent, 'http-api-mock')
|
|
36
|
-
|
|
37
|
-
// This table will store all the requests made to the API Gateway
|
|
38
|
-
this.requestsTable = new DynamoDB.Table(this, 'requests', {
|
|
39
|
-
billingMode: DynamoDB.BillingMode.PAY_PER_REQUEST,
|
|
40
|
-
partitionKey: {
|
|
41
|
-
name: 'requestId',
|
|
42
|
-
type: DynamoDB.AttributeType.STRING,
|
|
43
|
-
},
|
|
44
|
-
sortKey: {
|
|
45
|
-
name: 'timestamp',
|
|
46
|
-
type: DynamoDB.AttributeType.STRING,
|
|
47
|
-
},
|
|
48
|
-
removalPolicy: RemovalPolicy.DESTROY,
|
|
49
|
-
})
|
|
50
|
-
this.requestsTable.addGlobalSecondaryIndex({
|
|
51
|
-
indexName: 'methodPathQuery',
|
|
52
|
-
partitionKey: {
|
|
53
|
-
name: 'methodPathQuery',
|
|
54
|
-
type: DynamoDB.AttributeType.STRING,
|
|
55
|
-
},
|
|
56
|
-
projectionType: DynamoDB.ProjectionType.ALL,
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
// This table will store optional responses to be sent
|
|
60
|
-
this.responsesTable = new DynamoDB.Table(this, 'responses', {
|
|
61
|
-
billingMode: DynamoDB.BillingMode.PAY_PER_REQUEST,
|
|
62
|
-
partitionKey: {
|
|
63
|
-
name: 'responseId',
|
|
64
|
-
type: DynamoDB.AttributeType.STRING,
|
|
65
|
-
},
|
|
66
|
-
sortKey: {
|
|
67
|
-
name: 'timestamp',
|
|
68
|
-
type: DynamoDB.AttributeType.STRING,
|
|
69
|
-
},
|
|
70
|
-
removalPolicy: RemovalPolicy.DESTROY,
|
|
71
|
-
timeToLiveAttribute: 'ttl',
|
|
72
|
-
})
|
|
73
|
-
this.responsesTable.addGlobalSecondaryIndex({
|
|
74
|
-
indexName: 'methodPathQuery',
|
|
75
|
-
partitionKey: {
|
|
76
|
-
name: 'methodPathQuery',
|
|
77
|
-
type: DynamoDB.AttributeType.STRING,
|
|
78
|
-
},
|
|
79
|
-
projectionType: DynamoDB.ProjectionType.ALL,
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
// This lambda will publish all requests made to the API Gateway in the queue
|
|
83
|
-
const lambda = new Lambda.Function(this, 'Lambda', {
|
|
84
|
-
description:
|
|
85
|
-
'Mocks a HTTP API and stores all requests in SQS for inspection, and optionally replies with enqued responses',
|
|
86
|
-
code: new LambdaSource(this, lambdaSources.httpApiMock).code,
|
|
87
|
-
layers,
|
|
88
|
-
handler: lambdaSources.httpApiMock.handler,
|
|
89
|
-
architecture: Lambda.Architecture.ARM_64,
|
|
90
|
-
runtime: Lambda.Runtime.NODEJS_24_X,
|
|
91
|
-
timeout: Duration.seconds(5),
|
|
92
|
-
environment: {
|
|
93
|
-
REQUESTS_TABLE_NAME: this.requestsTable.tableName,
|
|
94
|
-
RESPONSES_TABLE_NAME: this.responsesTable.tableName,
|
|
95
|
-
LOG_LEVEL: this.node.tryGetContext('logLevel'),
|
|
96
|
-
NODE_NO_WARNINGS: '1',
|
|
97
|
-
},
|
|
98
|
-
...new LambdaLogGroup(this, 'LambdaLogs', Logs.RetentionDays.ONE_DAY),
|
|
99
|
-
})
|
|
100
|
-
this.responsesTable.grantReadWriteData(lambda)
|
|
101
|
-
this.requestsTable.grantReadWriteData(lambda)
|
|
102
|
-
|
|
103
|
-
// This is the API Gateway, AWS CDK automatically creates a prod stage and deployment
|
|
104
|
-
this.api = new ApiGateway.RestApi(this, 'api', {
|
|
105
|
-
restApiName: `HTTP Mock API for testing`,
|
|
106
|
-
description: 'API Gateway to test outgoing requests',
|
|
107
|
-
binaryMediaTypes: ['application/octet-stream'],
|
|
108
|
-
})
|
|
109
|
-
const proxyResource = this.api.root.addResource('{proxy+}')
|
|
110
|
-
proxyResource.addMethod('ANY', new ApiGateway.LambdaIntegration(lambda))
|
|
111
|
-
// API Gateway needs to be able to call the lambda
|
|
112
|
-
lambda.addPermission('InvokeByApiGateway', {
|
|
113
|
-
principal: new IAM.ServicePrincipal('apigateway.amazonaws.com'),
|
|
114
|
-
sourceArn: this.api.arnForExecuteApi(),
|
|
115
|
-
})
|
|
116
|
-
}
|
|
117
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict'
|
|
2
|
-
import { describe, it } from 'node:test'
|
|
3
|
-
import { checkMatchingQueryParams } from './checkMatchingQueryParams.ts'
|
|
4
|
-
|
|
5
|
-
void describe('checkMatchingQueryParams', () => {
|
|
6
|
-
void it('should return true when expected is subset of actual parameters', () => {
|
|
7
|
-
const actual = {
|
|
8
|
-
param1: 'value1',
|
|
9
|
-
param2: 'value2',
|
|
10
|
-
}
|
|
11
|
-
const expected = {
|
|
12
|
-
param1: 'value1',
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const result = checkMatchingQueryParams(actual, expected)
|
|
16
|
-
assert.equal(result, true)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
void it('should return true when expected contains regular expression and it matches', () => {
|
|
20
|
-
const actual = {
|
|
21
|
-
param1: 'value1,value2,value3',
|
|
22
|
-
}
|
|
23
|
-
const expected = {
|
|
24
|
-
param1: '/\\bvalue2\\b/',
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const result = checkMatchingQueryParams(actual, expected)
|
|
28
|
-
assert.equal(result, true)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
void it('should return false when expected does not match actual parameters', () => {
|
|
32
|
-
const actual = {
|
|
33
|
-
param1: 'value1',
|
|
34
|
-
param2: 'value2',
|
|
35
|
-
}
|
|
36
|
-
const expected = {
|
|
37
|
-
param1: 'value2',
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const result = checkMatchingQueryParams(actual, expected)
|
|
41
|
-
assert.equal(result, false)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
void it('should return false when actual is null', () => {
|
|
45
|
-
const actual = null
|
|
46
|
-
const expected = {
|
|
47
|
-
param1: 'value1',
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const result = checkMatchingQueryParams(actual, expected)
|
|
51
|
-
assert.equal(result, false)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
void it('should return true when expected parameters having number or boolean', () => {
|
|
55
|
-
const actual = {
|
|
56
|
-
param1: 'true',
|
|
57
|
-
param2: '1',
|
|
58
|
-
}
|
|
59
|
-
const expected = {
|
|
60
|
-
param1: true,
|
|
61
|
-
param2: 1,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const result = checkMatchingQueryParams(actual, expected)
|
|
65
|
-
assert.equal(result, true)
|
|
66
|
-
})
|
|
67
|
-
})
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
type Logger = {
|
|
2
|
-
debug: (...arg: any) => void
|
|
3
|
-
}
|
|
4
|
-
const matchRegex = /^\/(?<re>.+)\/(?<option>[gi])?$/
|
|
5
|
-
|
|
6
|
-
export const checkMatchingQueryParams = (
|
|
7
|
-
actual: Record<string, unknown> | null,
|
|
8
|
-
expected: Record<string, unknown>,
|
|
9
|
-
log?: Logger,
|
|
10
|
-
): boolean => {
|
|
11
|
-
log?.debug('checkMatchingQueryParams', { actual, expected })
|
|
12
|
-
if (actual === null) return false
|
|
13
|
-
|
|
14
|
-
// Check whether expected query parameters is subset of actual query parameters
|
|
15
|
-
for (const prop in expected) {
|
|
16
|
-
const expectedValue = expected[prop]
|
|
17
|
-
const actualValue = actual?.[prop]
|
|
18
|
-
if (actualValue === undefined) return false
|
|
19
|
-
|
|
20
|
-
if (typeof expectedValue === 'string') {
|
|
21
|
-
const match = matchRegex.exec(expectedValue)
|
|
22
|
-
if (match !== null) {
|
|
23
|
-
log?.debug('Compare using regex', { expectedValue })
|
|
24
|
-
// Expect is regex
|
|
25
|
-
const check = new RegExp(
|
|
26
|
-
match?.groups?.re ?? '',
|
|
27
|
-
match?.groups?.option,
|
|
28
|
-
).test(String(actualValue))
|
|
29
|
-
if (check === false) return false
|
|
30
|
-
} else {
|
|
31
|
-
if (actualValue !== expectedValue) return false
|
|
32
|
-
}
|
|
33
|
-
} else {
|
|
34
|
-
// All query parameters are string
|
|
35
|
-
if (actualValue !== String(expectedValue)) return false
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return true
|
|
40
|
-
}
|