skuba 4.4.1 → 5.0.0-beta.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.
- package/config/tsconfig.json +1 -0
- package/jest/moduleNameMapper.js +50 -78
- package/jest/moduleNameMapper.test.ts +4 -14
- package/jest/transform.js +10 -1
- package/jest/tsConfig.js +26 -0
- package/lib/api/buildkite/annotate.js +46 -33
- package/lib/api/buildkite/annotate.js.map +7 -1
- package/lib/api/buildkite/index.js +31 -7
- package/lib/api/buildkite/index.js.map +7 -1
- package/lib/api/buildkite/md.js +31 -8
- package/lib/api/buildkite/md.js.map +7 -1
- package/lib/api/git/commit.js +45 -17
- package/lib/api/git/commit.js.map +7 -1
- package/lib/api/git/commitAllChanges.js +57 -27
- package/lib/api/git/commitAllChanges.js.map +7 -1
- package/lib/api/git/currentBranch.js +50 -28
- package/lib/api/git/currentBranch.js.map +7 -1
- package/lib/api/git/getChangedFiles.js +49 -27
- package/lib/api/git/getChangedFiles.js.map +7 -1
- package/lib/api/git/index.js +54 -22
- package/lib/api/git/index.js.map +7 -1
- package/lib/api/git/log.js +63 -42
- package/lib/api/git/log.js.map +7 -1
- package/lib/api/git/pull.js +62 -31
- package/lib/api/git/pull.js.map +7 -1
- package/lib/api/git/push.js +63 -31
- package/lib/api/git/push.js.map +7 -1
- package/lib/api/git/remote.js +59 -56
- package/lib/api/git/remote.js.map +7 -1
- package/lib/api/git/reset.js +55 -27
- package/lib/api/git/reset.js.map +7 -1
- package/lib/api/git/statusMatrix.js +46 -13
- package/lib/api/git/statusMatrix.js.map +7 -1
- package/lib/api/github/checkRun.js +70 -79
- package/lib/api/github/checkRun.js.map +7 -1
- package/lib/api/github/environment.js +40 -33
- package/lib/api/github/environment.js.map +7 -1
- package/lib/api/github/index.js +47 -17
- package/lib/api/github/index.js.map +7 -1
- package/lib/api/github/issueComment.js +73 -81
- package/lib/api/github/issueComment.js.map +7 -1
- package/lib/api/github/pullRequest.js +60 -61
- package/lib/api/github/pullRequest.js.map +7 -1
- package/lib/api/github/push.js +138 -133
- package/lib/api/github/push.js.map +7 -1
- package/lib/api/jest/index.d.ts +2 -1
- package/lib/api/jest/index.js +35 -14
- package/lib/api/jest/index.js.map +7 -1
- package/lib/api/net/compose.js +45 -17
- package/lib/api/net/compose.js.map +7 -1
- package/lib/api/net/index.js +28 -5
- package/lib/api/net/index.js.map +7 -1
- package/lib/api/net/socket.js +58 -36
- package/lib/api/net/socket.js.map +7 -1
- package/lib/api/net/waitFor.js +38 -18
- package/lib/api/net/waitFor.js.map +7 -1
- package/lib/cli/adapter/eslint.js +95 -72
- package/lib/cli/adapter/eslint.js.map +7 -1
- package/lib/cli/adapter/prettier.js +126 -124
- package/lib/cli/adapter/prettier.js.map +7 -1
- package/lib/cli/build/args.d.ts +7 -0
- package/lib/cli/build/args.js +69 -0
- package/lib/cli/build/args.js.map +7 -0
- package/lib/cli/build/esbuild.d.ts +5 -0
- package/lib/cli/build/esbuild.js +128 -0
- package/lib/cli/build/esbuild.js.map +7 -0
- package/lib/cli/build/index.d.ts +1 -1
- package/lib/cli/build/index.js +68 -5
- package/lib/cli/build/index.js.map +7 -1
- package/lib/cli/build/tsc.d.ts +1 -1
- package/lib/cli/build/tsc.js +34 -23
- package/lib/cli/build/tsc.js.map +7 -1
- package/lib/cli/buildPackage.js +53 -23
- package/lib/cli/buildPackage.js.map +7 -1
- package/lib/cli/configure/addEmptyExports.d.ts +5 -0
- package/lib/cli/configure/addEmptyExports.js +67 -0
- package/lib/cli/configure/addEmptyExports.js.map +7 -0
- package/lib/cli/configure/analyseConfiguration.js +61 -31
- package/lib/cli/configure/analyseConfiguration.js.map +7 -1
- package/lib/cli/configure/analyseDependencies.js +122 -113
- package/lib/cli/configure/analyseDependencies.js.map +7 -1
- package/lib/cli/configure/analysis/diff.js +37 -11
- package/lib/cli/configure/analysis/diff.js.map +7 -1
- package/lib/cli/configure/analysis/files.js +49 -22
- package/lib/cli/configure/analysis/files.js.map +7 -1
- package/lib/cli/configure/analysis/git.js +46 -16
- package/lib/cli/configure/analysis/git.js.map +7 -1
- package/lib/cli/configure/analysis/package.js +99 -52
- package/lib/cli/configure/analysis/package.js.map +7 -1
- package/lib/cli/configure/analysis/project.js +90 -54
- package/lib/cli/configure/analysis/project.js.map +7 -1
- package/lib/cli/configure/dependencies/index.js +40 -13
- package/lib/cli/configure/dependencies/index.js.map +7 -1
- package/lib/cli/configure/dependencies/seekDatadogCustomMetrics.js +57 -32
- package/lib/cli/configure/dependencies/seekDatadogCustomMetrics.js.map +7 -1
- package/lib/cli/configure/dependencies/seekKoala.js +53 -31
- package/lib/cli/configure/dependencies/seekKoala.js.map +7 -1
- package/lib/cli/configure/dependencies/skuba.js +49 -27
- package/lib/cli/configure/dependencies/skuba.js.map +7 -1
- package/lib/cli/configure/dependencies/skubaDeps.js +49 -28
- package/lib/cli/configure/dependencies/skubaDeps.js.map +7 -1
- package/lib/cli/configure/dependencies/skubaDive.js +65 -38
- package/lib/cli/configure/dependencies/skubaDive.js.map +7 -1
- package/lib/cli/configure/ensureTemplateCompletion.js +69 -41
- package/lib/cli/configure/ensureTemplateCompletion.js.map +7 -1
- package/lib/cli/configure/getEntryPoint.js +62 -32
- package/lib/cli/configure/getEntryPoint.js.map +7 -1
- package/lib/cli/configure/getProjectType.js +50 -28
- package/lib/cli/configure/getProjectType.js.map +7 -1
- package/lib/cli/configure/index.js +134 -109
- package/lib/cli/configure/index.js.map +7 -1
- package/lib/cli/configure/modules/eslint.js +57 -26
- package/lib/cli/configure/modules/eslint.js.map +7 -1
- package/lib/cli/configure/modules/ignore.js +37 -14
- package/lib/cli/configure/modules/ignore.js.map +7 -1
- package/lib/cli/configure/modules/index.js +53 -28
- package/lib/cli/configure/modules/index.js.map +7 -1
- package/lib/cli/configure/modules/jest.js +84 -47
- package/lib/cli/configure/modules/jest.js.map +7 -1
- package/lib/cli/configure/modules/nodemon.js +29 -6
- package/lib/cli/configure/modules/nodemon.js.map +7 -1
- package/lib/cli/configure/modules/package.js +113 -92
- package/lib/cli/configure/modules/package.js.map +7 -1
- package/lib/cli/configure/modules/prettier.js +48 -19
- package/lib/cli/configure/modules/prettier.js.map +7 -1
- package/lib/cli/configure/modules/renovate.js +52 -39
- package/lib/cli/configure/modules/renovate.js.map +7 -1
- package/lib/cli/configure/modules/serverless.js +33 -15
- package/lib/cli/configure/modules/serverless.js.map +7 -1
- package/lib/cli/configure/modules/skubaDive.js +63 -37
- package/lib/cli/configure/modules/skubaDive.js.map +7 -1
- package/lib/cli/configure/modules/tsconfig.js +79 -63
- package/lib/cli/configure/modules/tsconfig.js.map +7 -1
- package/lib/cli/configure/modules/tslint.js +29 -6
- package/lib/cli/configure/modules/tslint.js.map +7 -1
- package/lib/cli/configure/processing/deleteFiles.js +30 -8
- package/lib/cli/configure/processing/deleteFiles.js.map +7 -1
- package/lib/cli/configure/processing/ignoreFile.js +65 -59
- package/lib/cli/configure/processing/ignoreFile.js.map +7 -1
- package/lib/cli/configure/processing/javascript.js +35 -15
- package/lib/cli/configure/processing/javascript.js.map +7 -1
- package/lib/cli/configure/processing/json.js +51 -20
- package/lib/cli/configure/processing/json.js.map +7 -1
- package/lib/cli/configure/processing/loadFiles.js +30 -8
- package/lib/cli/configure/processing/loadFiles.js.map +7 -1
- package/lib/cli/configure/processing/module.js +37 -14
- package/lib/cli/configure/processing/module.js.map +7 -1
- package/lib/cli/configure/processing/package.js +73 -43
- package/lib/cli/configure/processing/package.js.map +7 -1
- package/lib/cli/configure/processing/prettier.js +37 -11
- package/lib/cli/configure/processing/prettier.js.map +7 -1
- package/lib/cli/configure/processing/record.js +54 -31
- package/lib/cli/configure/processing/record.js.map +7 -1
- package/lib/cli/configure/processing/typescript.js +176 -158
- package/lib/cli/configure/processing/typescript.js.map +7 -1
- package/lib/cli/configure/refreshIgnoreFiles.js +64 -40
- package/lib/cli/configure/refreshIgnoreFiles.js.map +7 -1
- package/lib/cli/configure/types.js +16 -2
- package/lib/cli/configure/types.js.map +7 -1
- package/lib/cli/format.js +58 -31
- package/lib/cli/format.js.map +7 -1
- package/lib/cli/help.js +31 -8
- package/lib/cli/help.js.map +7 -1
- package/lib/cli/init/getConfig.js +238 -207
- package/lib/cli/init/getConfig.js.map +7 -1
- package/lib/cli/init/git.js +70 -63
- package/lib/cli/init/git.js.map +7 -1
- package/lib/cli/init/index.js +133 -100
- package/lib/cli/init/index.js.map +7 -1
- package/lib/cli/init/prompts.js +84 -54
- package/lib/cli/init/prompts.js.map +7 -1
- package/lib/cli/init/types.js +52 -52
- package/lib/cli/init/types.js.map +7 -1
- package/lib/cli/init/validation.js +34 -12
- package/lib/cli/init/validation.js.map +7 -1
- package/lib/cli/init/writePackageJson.js +51 -22
- package/lib/cli/init/writePackageJson.js.map +7 -1
- package/lib/cli/lint/annotate/buildkite/eslint.js +34 -28
- package/lib/cli/lint/annotate/buildkite/eslint.js.map +7 -1
- package/lib/cli/lint/annotate/buildkite/index.js +50 -44
- package/lib/cli/lint/annotate/buildkite/index.js.map +7 -1
- package/lib/cli/lint/annotate/buildkite/prettier.js +41 -35
- package/lib/cli/lint/annotate/buildkite/prettier.js.map +7 -1
- package/lib/cli/lint/annotate/buildkite/tsc.js +39 -39
- package/lib/cli/lint/annotate/buildkite/tsc.js.map +7 -1
- package/lib/cli/lint/annotate/github/eslint.js +40 -16
- package/lib/cli/lint/annotate/github/eslint.js.map +7 -1
- package/lib/cli/lint/annotate/github/index.js +55 -51
- package/lib/cli/lint/annotate/github/index.js.map +7 -1
- package/lib/cli/lint/annotate/github/prettier.js +36 -13
- package/lib/cli/lint/annotate/github/prettier.js.map +7 -1
- package/lib/cli/lint/annotate/github/tsc.js +52 -52
- package/lib/cli/lint/annotate/github/tsc.js.map +7 -1
- package/lib/cli/lint/annotate/index.js +33 -10
- package/lib/cli/lint/annotate/index.js.map +7 -1
- package/lib/cli/lint/autofix.js +122 -117
- package/lib/cli/lint/autofix.js.map +7 -1
- package/lib/cli/lint/eslint.js +48 -18
- package/lib/cli/lint/eslint.js.map +7 -1
- package/lib/cli/lint/external.js +102 -81
- package/lib/cli/lint/external.js.map +7 -1
- package/lib/cli/lint/index.js +42 -18
- package/lib/cli/lint/index.js.map +7 -1
- package/lib/cli/lint/internal.js +54 -21
- package/lib/cli/lint/internal.js.map +7 -1
- package/lib/cli/lint/prettier.js +48 -18
- package/lib/cli/lint/prettier.js.map +7 -1
- package/lib/cli/lint/tsc.js +56 -32
- package/lib/cli/lint/tsc.js.map +7 -1
- package/lib/cli/lint/types.js +16 -2
- package/lib/cli/lint/types.js.map +7 -1
- package/lib/cli/node.js +65 -58
- package/lib/cli/node.js.map +7 -1
- package/lib/cli/release.js +29 -6
- package/lib/cli/release.js.map +7 -1
- package/lib/cli/start.js +61 -24
- package/lib/cli/start.js.map +7 -1
- package/lib/cli/test/index.js +35 -11
- package/lib/cli/test/index.js.map +7 -1
- package/lib/cli/test/reporters/github/annotations.js +89 -92
- package/lib/cli/test/reporters/github/annotations.js.map +7 -1
- package/lib/cli/test/reporters/github/index.js +68 -68
- package/lib/cli/test/reporters/github/index.js.map +7 -1
- package/lib/cli/version.js +31 -8
- package/lib/cli/version.js.map +7 -1
- package/lib/enquirer.d.js +2 -0
- package/lib/enquirer.d.js.map +7 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +45 -41
- package/lib/index.js.map +7 -1
- package/lib/skuba.js +45 -38
- package/lib/skuba.js.map +7 -1
- package/lib/utils/args.js +97 -96
- package/lib/utils/args.js.map +7 -1
- package/lib/utils/command.js +64 -33
- package/lib/utils/command.js.map +7 -1
- package/lib/utils/copy.js +88 -51
- package/lib/utils/copy.js.map +7 -1
- package/lib/utils/dir.js +79 -67
- package/lib/utils/dir.js.map +7 -1
- package/lib/utils/env.js +27 -7
- package/lib/utils/env.js.map +7 -1
- package/lib/utils/error.js +58 -56
- package/lib/utils/error.js.map +7 -1
- package/lib/utils/exec.js +139 -110
- package/lib/utils/exec.js.map +7 -1
- package/lib/utils/help.js +31 -8
- package/lib/utils/help.js.map +7 -1
- package/lib/utils/logging.js +52 -24
- package/lib/utils/logging.js.map +7 -1
- package/lib/utils/logo.js +65 -27
- package/lib/utils/logo.js.map +7 -1
- package/lib/utils/manifest.d.ts +1 -0
- package/lib/utils/manifest.js +65 -51
- package/lib/utils/manifest.js.map +7 -1
- package/lib/utils/port.js +38 -17
- package/lib/utils/port.js.map +7 -1
- package/lib/utils/template.js +106 -87
- package/lib/utils/template.js.map +7 -1
- package/lib/utils/validation.js +43 -18
- package/lib/utils/validation.js.map +7 -1
- package/lib/utils/version.js +72 -82
- package/lib/utils/version.js.map +7 -1
- package/lib/utils/wait.js +52 -25
- package/lib/utils/wait.js.map +7 -1
- package/lib/utils/worker.js +59 -44
- package/lib/utils/worker.js.map +7 -1
- package/lib/wrapper/function-arguments.d.js +2 -0
- package/lib/wrapper/function-arguments.d.js.map +7 -0
- package/lib/wrapper/functionHandler.js +56 -29
- package/lib/wrapper/functionHandler.js.map +7 -1
- package/lib/wrapper/http.js +66 -56
- package/lib/wrapper/http.js.map +7 -1
- package/lib/wrapper/index.js +9 -21
- package/lib/wrapper/index.js.map +7 -1
- package/lib/wrapper/main.js +39 -20
- package/lib/wrapper/main.js.map +7 -1
- package/lib/wrapper/requestListener.js +50 -35
- package/lib/wrapper/requestListener.js.map +7 -1
- package/package.json +19 -13
- package/template/base/jest.config.ts +0 -6
- package/template/base/jest.setup.ts +2 -0
- package/template/express-rest-api/.buildkite/pipeline.yml +1 -1
- package/template/express-rest-api/package.json +1 -1
- package/template/greeter/.buildkite/pipeline.yml +1 -1
- package/template/greeter/package.json +1 -1
- package/template/greeter/src/app.test.ts +3 -1
- package/template/koa-rest-api/.buildkite/pipeline.yml +1 -1
- package/template/koa-rest-api/package.json +6 -7
- package/template/koa-rest-api/src/api/jobs/postJob.test.ts +3 -7
- package/template/koa-rest-api/src/api/jobs/postJob.ts +2 -2
- package/template/koa-rest-api/src/framework/validation.test.ts +17 -15
- package/template/koa-rest-api/src/framework/validation.ts +50 -9
- package/template/koa-rest-api/src/testing/types.ts +5 -10
- package/template/koa-rest-api/src/types/jobs.ts +5 -10
- package/template/lambda-sqs-worker/.buildkite/pipeline.yml +3 -3
- package/template/lambda-sqs-worker/package.json +2 -6
- package/template/lambda-sqs-worker/src/app.ts +2 -2
- package/template/lambda-sqs-worker/src/framework/validation.test.ts +37 -17
- package/template/lambda-sqs-worker/src/framework/validation.ts +4 -2
- package/template/lambda-sqs-worker/src/services/jobScorer.ts +2 -2
- package/template/lambda-sqs-worker/src/testing/types.ts +5 -10
- package/template/lambda-sqs-worker/src/types/jobScorer.ts +9 -16
- package/template/lambda-sqs-worker/src/types/pipelineEvents.ts +13 -20
- package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +3 -3
- package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +6 -0
- package/template/lambda-sqs-worker-cdk/infra/appStack.ts +3 -3
- package/template/lambda-sqs-worker-cdk/infra/index.ts +2 -2
- package/template/lambda-sqs-worker-cdk/package.json +2 -2
- package/template/lambda-sqs-worker-cdk/shared/context-types.ts +16 -25
- package/template/oss-npm-package/_package.json +1 -1
- package/template/private-npm-package/_package.json +1 -1
- package/jest/resolver.js +0 -24
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { agentFromMiddleware } from 'src/testing/server';
|
|
2
2
|
import {
|
|
3
|
+
IdDescriptionSchema,
|
|
3
4
|
chance,
|
|
4
|
-
filterIdDescription,
|
|
5
5
|
mockIdDescription,
|
|
6
6
|
} from 'src/testing/types';
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@ const agent = agentFromMiddleware(jsonBodyParser, (ctx) => {
|
|
|
12
12
|
const result = validate({
|
|
13
13
|
ctx,
|
|
14
14
|
input: ctx.request.body,
|
|
15
|
-
|
|
15
|
+
schema: IdDescriptionSchema,
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
ctx.body = result;
|
|
@@ -41,13 +41,14 @@ describe('validate', () => {
|
|
|
41
41
|
.post('/')
|
|
42
42
|
.send({ ...idDescription, id: null })
|
|
43
43
|
.expect(422)
|
|
44
|
-
.expect(({
|
|
45
|
-
expect(
|
|
46
|
-
"Validation failed:
|
|
44
|
+
.expect(({ body }) =>
|
|
45
|
+
expect(body).toMatchInlineSnapshot(`
|
|
47
46
|
{
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
"invalidFields": {
|
|
48
|
+
"/id": "Expected string, received null",
|
|
49
|
+
},
|
|
50
|
+
"message": "Input validation failed",
|
|
51
|
+
}
|
|
51
52
|
`),
|
|
52
53
|
);
|
|
53
54
|
});
|
|
@@ -57,14 +58,15 @@ describe('validate', () => {
|
|
|
57
58
|
.post('/')
|
|
58
59
|
.send({})
|
|
59
60
|
.expect(422)
|
|
60
|
-
.expect(({
|
|
61
|
-
expect(
|
|
62
|
-
"Validation failed:
|
|
61
|
+
.expect(({ body }) =>
|
|
62
|
+
expect(body).toMatchInlineSnapshot(`
|
|
63
63
|
{
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
"invalidFields": {
|
|
65
|
+
"/description": "Required",
|
|
66
|
+
"/id": "Required",
|
|
67
|
+
},
|
|
68
|
+
"message": "Input validation failed",
|
|
69
|
+
}
|
|
68
70
|
`),
|
|
69
71
|
));
|
|
70
72
|
});
|
|
@@ -1,23 +1,64 @@
|
|
|
1
|
+
import { ErrorMiddleware } from 'seek-koala';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
1
4
|
import { Context } from 'src/types/koa';
|
|
2
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Converts a `ZodError` into an `invalidFields` object
|
|
8
|
+
*
|
|
9
|
+
* For example, the `ZodError`:
|
|
10
|
+
*
|
|
11
|
+
* ```json
|
|
12
|
+
* {
|
|
13
|
+
* "issues": [
|
|
14
|
+
* {
|
|
15
|
+
* "code": "invalid_type",
|
|
16
|
+
* "expected": "string",
|
|
17
|
+
* "received": "undefined",
|
|
18
|
+
* "path": ["advertiserId"],
|
|
19
|
+
* "message": "advertiserId is required in the URL"
|
|
20
|
+
* }
|
|
21
|
+
* ],
|
|
22
|
+
* "name": "ZodError"
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Returns:
|
|
27
|
+
*
|
|
28
|
+
* ```json
|
|
29
|
+
* { "/advertiserId": "advertiserId is required in the URL" }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
const parseInvalidFieldsFromError = ({
|
|
33
|
+
errors,
|
|
34
|
+
}: z.ZodError): Record<string, string> =>
|
|
35
|
+
Object.fromEntries(
|
|
36
|
+
errors.map((err) => [`/${err.path.join('/')}`, err.message]),
|
|
37
|
+
);
|
|
38
|
+
|
|
3
39
|
export const validate = <T>({
|
|
4
40
|
ctx,
|
|
5
41
|
input,
|
|
6
|
-
|
|
42
|
+
schema,
|
|
7
43
|
}: {
|
|
8
44
|
ctx: Context;
|
|
9
45
|
input: unknown;
|
|
10
|
-
|
|
46
|
+
schema: z.ZodSchema<T>;
|
|
11
47
|
}) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
48
|
+
const parseResult = schema.safeParse(input);
|
|
49
|
+
if (parseResult.success === false) {
|
|
50
|
+
return ctx.throw(
|
|
51
|
+
422,
|
|
52
|
+
new ErrorMiddleware.JsonResponse('Input validation failed', {
|
|
53
|
+
message: 'Input validation failed',
|
|
54
|
+
invalidFields: parseInvalidFieldsFromError(parseResult.error),
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
17
57
|
}
|
|
58
|
+
return parseResult.data;
|
|
18
59
|
};
|
|
19
60
|
|
|
20
61
|
export const validateRequestBody = <T>(
|
|
21
62
|
ctx: Context,
|
|
22
|
-
|
|
23
|
-
): T => validate({ ctx, input: ctx.request.body as unknown,
|
|
63
|
+
schema: z.ZodSchema<T>,
|
|
64
|
+
): T => validate<T>({ ctx, input: ctx.request.body as unknown, schema });
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
/* eslint-disable new-cap */
|
|
2
|
-
|
|
3
1
|
import { Chance } from 'chance';
|
|
4
|
-
import
|
|
5
|
-
import checkFilter from 'runtypes-filter';
|
|
2
|
+
import { z } from 'zod';
|
|
6
3
|
|
|
7
4
|
import { JobInput } from 'src/types/jobs';
|
|
8
5
|
|
|
9
|
-
export type IdDescription =
|
|
6
|
+
export type IdDescription = z.infer<typeof IdDescriptionSchema>;
|
|
10
7
|
|
|
11
|
-
const
|
|
12
|
-
id:
|
|
13
|
-
description:
|
|
8
|
+
export const IdDescriptionSchema = z.object({
|
|
9
|
+
id: z.string(),
|
|
10
|
+
description: z.string(),
|
|
14
11
|
});
|
|
15
12
|
|
|
16
|
-
export const filterIdDescription = checkFilter(IdDescription);
|
|
17
|
-
|
|
18
13
|
export const chance = new Chance();
|
|
19
14
|
|
|
20
15
|
export const mockIdDescription = (): IdDescription => ({
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import * as t from 'runtypes';
|
|
4
|
-
import checkFilter from 'runtypes-filter';
|
|
1
|
+
import { z } from 'zod';
|
|
5
2
|
|
|
6
3
|
export interface Job {
|
|
7
4
|
id: string;
|
|
@@ -11,12 +8,10 @@ export interface Job {
|
|
|
11
8
|
};
|
|
12
9
|
}
|
|
13
10
|
|
|
14
|
-
export type JobInput =
|
|
11
|
+
export type JobInput = z.infer<typeof JobInputSchema>;
|
|
15
12
|
|
|
16
|
-
const
|
|
17
|
-
hirer:
|
|
18
|
-
id:
|
|
13
|
+
export const JobInputSchema = z.object({
|
|
14
|
+
hirer: z.object({
|
|
15
|
+
id: z.string(),
|
|
19
16
|
}),
|
|
20
17
|
});
|
|
21
|
-
|
|
22
|
-
export const filterJobInput = checkFilter(JobInput);
|
|
@@ -26,13 +26,13 @@ configs:
|
|
|
26
26
|
- yarn deploy
|
|
27
27
|
concurrency: 1
|
|
28
28
|
plugins:
|
|
29
|
-
- artifacts#v1.
|
|
29
|
+
- artifacts#v1.7.0:
|
|
30
30
|
build: ${BUILDKITE_BUILD_ID}
|
|
31
31
|
download: lib/*
|
|
32
32
|
- *aws-sm
|
|
33
33
|
- *private-npm
|
|
34
34
|
- *docker-ecr-cache
|
|
35
|
-
- docker-compose#
|
|
35
|
+
- docker-compose#v4.5.0:
|
|
36
36
|
dependencies: false
|
|
37
37
|
run: app
|
|
38
38
|
retry:
|
|
@@ -60,7 +60,7 @@ steps:
|
|
|
60
60
|
- *aws-sm
|
|
61
61
|
- *private-npm
|
|
62
62
|
- *docker-ecr-cache
|
|
63
|
-
- docker-compose#
|
|
63
|
+
- docker-compose#v4.5.0:
|
|
64
64
|
run: app
|
|
65
65
|
timeout_in_minutes: 10
|
|
66
66
|
|
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
"aws-sdk": "^2.1011.0",
|
|
5
5
|
"datadog-lambda-js": "^6.83.0",
|
|
6
6
|
"skuba-dive": "^2.0.0",
|
|
7
|
-
"
|
|
8
|
-
"runtypes-filter": "^0.6.0"
|
|
7
|
+
"zod": "^3.19.1"
|
|
9
8
|
},
|
|
10
9
|
"devDependencies": {
|
|
11
10
|
"@types/aws-lambda": "^8.10.84",
|
|
12
11
|
"@types/chance": "^1.1.3",
|
|
13
|
-
"@types/node": "
|
|
12
|
+
"@types/node": "16.11.64",
|
|
14
13
|
"chance": "^1.1.8",
|
|
15
14
|
"pino-pretty": "^9.0.0",
|
|
16
15
|
"serverless": "^3.17.0",
|
|
@@ -24,9 +23,6 @@
|
|
|
24
23
|
},
|
|
25
24
|
"license": "UNLICENSED",
|
|
26
25
|
"private": true,
|
|
27
|
-
"resolutions": {
|
|
28
|
-
"@types/responselike": "1.0.0"
|
|
29
|
-
},
|
|
30
26
|
"scripts": {
|
|
31
27
|
"build": "skuba build",
|
|
32
28
|
"deploy": "serverless deploy --force --verbose",
|
|
@@ -8,7 +8,7 @@ import { metricsClient } from 'src/framework/metrics';
|
|
|
8
8
|
import { validateJson } from 'src/framework/validation';
|
|
9
9
|
import { scoreJobPublishedEvent, scoringService } from 'src/services/jobScorer';
|
|
10
10
|
import { sendPipelineEvent } from 'src/services/pipelineEventSender';
|
|
11
|
-
import {
|
|
11
|
+
import { JobPublishedEventSchema } from 'src/types/pipelineEvents';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Tests connectivity to ensure appropriate access and network configuration.
|
|
@@ -40,7 +40,7 @@ export const handler = createHandler<SQSEvent>(async (event) => {
|
|
|
40
40
|
// the event and eventually send it to your dead-letter queue. If you don't
|
|
41
41
|
// trust your source to provide consistently well-formed input, consider
|
|
42
42
|
// catching and handling this error in code.
|
|
43
|
-
const publishedJob = validateJson(record.body,
|
|
43
|
+
const publishedJob = validateJson(record.body, JobPublishedEventSchema);
|
|
44
44
|
|
|
45
45
|
const scoredJob = await scoreJobPublishedEvent(publishedJob);
|
|
46
46
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
IdDescriptionSchema,
|
|
2
3
|
chance,
|
|
3
|
-
filterIdDescription,
|
|
4
4
|
mockIdDescription,
|
|
5
5
|
} from 'src/testing/types';
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ describe('validateJson', () => {
|
|
|
12
12
|
it('permits valid input', () => {
|
|
13
13
|
const input = JSON.stringify(idDescription);
|
|
14
14
|
|
|
15
|
-
expect(validateJson(input,
|
|
15
|
+
expect(validateJson(input, IdDescriptionSchema)).toStrictEqual(
|
|
16
16
|
idDescription,
|
|
17
17
|
);
|
|
18
18
|
});
|
|
@@ -20,7 +20,7 @@ describe('validateJson', () => {
|
|
|
20
20
|
it('filters additional properties', () => {
|
|
21
21
|
const input = JSON.stringify({ ...idDescription, hacker: chance.name() });
|
|
22
22
|
|
|
23
|
-
expect(validateJson(input,
|
|
23
|
+
expect(validateJson(input, IdDescriptionSchema)).toStrictEqual(
|
|
24
24
|
idDescription,
|
|
25
25
|
);
|
|
26
26
|
});
|
|
@@ -28,27 +28,47 @@ describe('validateJson', () => {
|
|
|
28
28
|
it('blocks mistyped prop', () => {
|
|
29
29
|
const input = JSON.stringify({ ...idDescription, id: null });
|
|
30
30
|
|
|
31
|
-
expect(() => validateJson(input,
|
|
31
|
+
expect(() => validateJson(input, IdDescriptionSchema))
|
|
32
32
|
.toThrowErrorMatchingInlineSnapshot(`
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
"[
|
|
34
|
+
{
|
|
35
|
+
"code": "invalid_type",
|
|
36
|
+
"expected": "string",
|
|
37
|
+
"received": "null",
|
|
38
|
+
"path": [
|
|
39
|
+
"id"
|
|
40
|
+
],
|
|
41
|
+
"message": "Expected string, received null"
|
|
42
|
+
}
|
|
43
|
+
]"
|
|
38
44
|
`);
|
|
39
45
|
});
|
|
40
46
|
|
|
41
47
|
it('blocks missing prop', () => {
|
|
42
48
|
const input = '{}';
|
|
43
49
|
|
|
44
|
-
expect(() => validateJson(input,
|
|
50
|
+
expect(() => validateJson(input, IdDescriptionSchema))
|
|
45
51
|
.toThrowErrorMatchingInlineSnapshot(`
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
"[
|
|
53
|
+
{
|
|
54
|
+
"code": "invalid_type",
|
|
55
|
+
"expected": "string",
|
|
56
|
+
"received": "undefined",
|
|
57
|
+
"path": [
|
|
58
|
+
"id"
|
|
59
|
+
],
|
|
60
|
+
"message": "Required"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"code": "invalid_type",
|
|
64
|
+
"expected": "string",
|
|
65
|
+
"received": "undefined",
|
|
66
|
+
"path": [
|
|
67
|
+
"description"
|
|
68
|
+
],
|
|
69
|
+
"message": "Required"
|
|
70
|
+
}
|
|
71
|
+
]"
|
|
52
72
|
`);
|
|
53
73
|
});
|
|
54
74
|
|
|
@@ -56,7 +76,7 @@ describe('validateJson', () => {
|
|
|
56
76
|
const input = '}';
|
|
57
77
|
|
|
58
78
|
expect(() =>
|
|
59
|
-
validateJson(input,
|
|
79
|
+
validateJson(input, IdDescriptionSchema),
|
|
60
80
|
).toThrowErrorMatchingInlineSnapshot(
|
|
61
81
|
`"Unexpected token } in JSON at position 0"`,
|
|
62
82
|
);
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
JobScorerInput,
|
|
7
7
|
JobScorerOutput,
|
|
8
|
-
|
|
8
|
+
JobScorerOutputSchema,
|
|
9
9
|
} from 'src/types/jobScorer';
|
|
10
10
|
import { JobPublishedEvent, JobScoredEvent } from 'src/types/pipelineEvents';
|
|
11
11
|
|
|
@@ -39,7 +39,7 @@ const scoreJob = async ({
|
|
|
39
39
|
}: JobScorerInput): Promise<JobScorerOutput> => {
|
|
40
40
|
const score = await scoringService.request(details);
|
|
41
41
|
|
|
42
|
-
return
|
|
42
|
+
return JobScorerOutputSchema.parse({
|
|
43
43
|
id,
|
|
44
44
|
score,
|
|
45
45
|
});
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
/* eslint-disable new-cap */
|
|
2
|
-
|
|
3
1
|
import { Chance } from 'chance';
|
|
4
|
-
import
|
|
5
|
-
import checkFilter from 'runtypes-filter';
|
|
2
|
+
import { z } from 'zod';
|
|
6
3
|
|
|
7
4
|
import { JobPublishedEvent } from 'src/types/pipelineEvents';
|
|
8
5
|
|
|
9
|
-
export type IdDescription =
|
|
6
|
+
export type IdDescription = z.infer<typeof IdDescriptionSchema>;
|
|
10
7
|
|
|
11
|
-
const
|
|
12
|
-
id:
|
|
13
|
-
description:
|
|
8
|
+
export const IdDescriptionSchema = z.object({
|
|
9
|
+
id: z.string(),
|
|
10
|
+
description: z.string(),
|
|
14
11
|
});
|
|
15
12
|
|
|
16
|
-
export const filterIdDescription = checkFilter(IdDescription);
|
|
17
|
-
|
|
18
13
|
export const chance = new Chance();
|
|
19
14
|
|
|
20
15
|
export const mockIdDescription = (): IdDescription => ({
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import checkFilter from 'runtypes-filter';
|
|
3
|
+
export type JobScorerInput = z.infer<typeof JobScorerInputSchema>;
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
id: t.String,
|
|
10
|
-
details: t.String,
|
|
5
|
+
const JobScorerInputSchema = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
details: z.string(),
|
|
11
8
|
});
|
|
12
9
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
export type JobScorerOutput = t.Static<typeof JobScorerOutput>;
|
|
10
|
+
export type JobScorerOutput = z.infer<typeof JobScorerOutputSchema>;
|
|
16
11
|
|
|
17
|
-
const
|
|
18
|
-
id:
|
|
19
|
-
score:
|
|
12
|
+
export const JobScorerOutputSchema = z.object({
|
|
13
|
+
id: z.string(),
|
|
14
|
+
score: z.number(),
|
|
20
15
|
});
|
|
21
|
-
|
|
22
|
-
export const filterJobScorerOutput = checkFilter(JobScorerOutput);
|
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import checkFilter from 'runtypes-filter';
|
|
3
|
+
export type JobPublishedEvent = z.infer<typeof JobPublishedEventSchema>;
|
|
5
4
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
data: t.Record({
|
|
10
|
-
details: t.String,
|
|
5
|
+
export const JobPublishedEventSchema = z.object({
|
|
6
|
+
data: z.object({
|
|
7
|
+
details: z.string(),
|
|
11
8
|
}),
|
|
12
|
-
entityId:
|
|
13
|
-
eventType:
|
|
9
|
+
entityId: z.string(),
|
|
10
|
+
eventType: z.literal('JobPublished'),
|
|
14
11
|
});
|
|
15
12
|
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
export type JobScoredEvent = t.Static<typeof JobScoredEvent>;
|
|
13
|
+
export type JobScoredEvent = z.infer<typeof JobScoredEventSchema>;
|
|
19
14
|
|
|
20
|
-
const
|
|
21
|
-
data:
|
|
22
|
-
score:
|
|
15
|
+
export const JobScoredEventSchema = z.object({
|
|
16
|
+
data: z.object({
|
|
17
|
+
score: z.number(),
|
|
23
18
|
}),
|
|
24
|
-
entityId:
|
|
25
|
-
eventType:
|
|
19
|
+
entityId: z.string(),
|
|
20
|
+
eventType: z.literal('JobScored'),
|
|
26
21
|
});
|
|
27
|
-
|
|
28
|
-
export const filterJobScoredEvent = checkFilter(JobScoredEvent);
|
|
@@ -26,13 +26,13 @@ configs:
|
|
|
26
26
|
- yarn deploy
|
|
27
27
|
concurrency: 1
|
|
28
28
|
plugins:
|
|
29
|
-
- artifacts#v1.
|
|
29
|
+
- artifacts#v1.7.0:
|
|
30
30
|
build: ${BUILDKITE_BUILD_ID}
|
|
31
31
|
download: lib/*
|
|
32
32
|
- *aws-sm
|
|
33
33
|
- *private-npm
|
|
34
34
|
- *docker-ecr-cache
|
|
35
|
-
- docker-compose#
|
|
35
|
+
- docker-compose#v4.5.0:
|
|
36
36
|
dependencies: false
|
|
37
37
|
run: app
|
|
38
38
|
retry:
|
|
@@ -57,7 +57,7 @@ steps:
|
|
|
57
57
|
- *aws-sm
|
|
58
58
|
- *private-npm
|
|
59
59
|
- *docker-ecr-cache
|
|
60
|
-
- docker-compose#
|
|
60
|
+
- docker-compose#v4.5.0:
|
|
61
61
|
run: app
|
|
62
62
|
timeout_in_minutes: 10
|
|
63
63
|
|
|
@@ -327,6 +327,9 @@ exports[`returns expected CloudFormation stack for dev 1`] = `
|
|
|
327
327
|
"Type": "AWS::SQS::QueuePolicy",
|
|
328
328
|
},
|
|
329
329
|
"workerqueueappStacktopic0CA45134AFB31FF4": {
|
|
330
|
+
"DependsOn": [
|
|
331
|
+
"workerqueuePolicy97054CB4",
|
|
332
|
+
],
|
|
330
333
|
"Properties": {
|
|
331
334
|
"Endpoint": {
|
|
332
335
|
"Fn::GetAtt": [
|
|
@@ -686,6 +689,9 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
|
|
|
686
689
|
"Type": "AWS::SQS::QueuePolicy",
|
|
687
690
|
},
|
|
688
691
|
"workerqueueappStacktopic0CA45134AFB31FF4": {
|
|
692
|
+
"DependsOn": [
|
|
693
|
+
"workerqueuePolicy97054CB4",
|
|
694
|
+
],
|
|
689
695
|
"Properties": {
|
|
690
696
|
"Endpoint": {
|
|
691
697
|
"Fn::GetAtt": [
|
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
} from 'aws-cdk-lib';
|
|
12
12
|
import type { Construct } from 'constructs';
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { EnvContextSchema, StageContextSchema } from '../shared/context-types';
|
|
15
15
|
|
|
16
16
|
export class AppStack extends Stack {
|
|
17
17
|
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
18
18
|
super(scope, id, props);
|
|
19
19
|
|
|
20
|
-
const stage =
|
|
21
|
-
const context =
|
|
20
|
+
const stage = StageContextSchema.parse(this.node.tryGetContext('stage'));
|
|
21
|
+
const context = EnvContextSchema.parse(this.node.tryGetContext(stage));
|
|
22
22
|
|
|
23
23
|
const accountPrincipal = new aws_iam.AccountPrincipal(this.account);
|
|
24
24
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { App } from 'aws-cdk-lib';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { GlobalContextSchema } from '../shared/context-types';
|
|
4
4
|
|
|
5
5
|
import { AppStack } from './appStack';
|
|
6
6
|
|
|
7
7
|
const app = new App();
|
|
8
8
|
|
|
9
|
-
const context =
|
|
9
|
+
const context = GlobalContextSchema.parse(app.node.tryGetContext('global'));
|
|
10
10
|
|
|
11
11
|
// eslint-disable-next-line no-new
|
|
12
12
|
new AppStack(app, 'appStack', {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@seek/logger": "^5.0.1",
|
|
4
|
-
"
|
|
4
|
+
"zod": "^3.19.1"
|
|
5
5
|
},
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"@aws-cdk/assert": "^2.24.0",
|
|
8
8
|
"@types/aws-lambda": "^8.10.82",
|
|
9
|
-
"@types/node": "
|
|
9
|
+
"@types/node": "16.11.64",
|
|
10
10
|
"aws-cdk": "^2.24.0",
|
|
11
11
|
"aws-cdk-lib": "^2.24.0",
|
|
12
12
|
"constructs": "^10.0.17",
|
|
@@ -1,30 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
import * as t from 'runtypes';
|
|
1
|
+
import { z } from 'zod';
|
|
3
2
|
|
|
4
|
-
export const
|
|
5
|
-
export type StageContext =
|
|
3
|
+
export const StageContextSchema = z.enum(['dev', 'prod']);
|
|
4
|
+
export type StageContext = z.infer<typeof StageContextSchema>;
|
|
6
5
|
|
|
7
|
-
export const
|
|
8
|
-
.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
})
|
|
16
|
-
.asReadonly(),
|
|
17
|
-
})
|
|
18
|
-
.asReadonly(),
|
|
19
|
-
})
|
|
20
|
-
.asReadonly();
|
|
6
|
+
export const EnvContextSchema = z.object({
|
|
7
|
+
workerLambda: z.object({
|
|
8
|
+
reservedConcurrency: z.number(),
|
|
9
|
+
environment: z.object({
|
|
10
|
+
SOMETHING: z.string(),
|
|
11
|
+
}),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
21
14
|
|
|
22
|
-
export type EnvContext =
|
|
15
|
+
export type EnvContext = z.infer<typeof EnvContextSchema>;
|
|
23
16
|
|
|
24
|
-
export const
|
|
25
|
-
.
|
|
26
|
-
|
|
27
|
-
})
|
|
28
|
-
.asReadonly();
|
|
17
|
+
export const GlobalContextSchema = z.object({
|
|
18
|
+
appName: z.string(),
|
|
19
|
+
});
|
|
29
20
|
|
|
30
|
-
export type GlobalContext =
|
|
21
|
+
export type GlobalContext = z.infer<typeof GlobalContextSchema>;
|