skuba 4.4.0 → 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 +73 -40
- 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 +21 -14
- 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 -9
- 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/storage/jobs.ts +2 -2
- 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/README.md +1 -1
- package/template/lambda-sqs-worker/package.json +4 -4
- package/template/lambda-sqs-worker/serverless.yml +17 -2
- package/template/lambda-sqs-worker/src/app.test.ts +19 -17
- package/template/lambda-sqs-worker/src/app.ts +8 -8
- package/template/lambda-sqs-worker/src/config.ts +3 -0
- package/template/lambda-sqs-worker/src/framework/handler.test.ts +7 -7
- package/template/lambda-sqs-worker/src/framework/handler.ts +31 -8
- package/template/lambda-sqs-worker/src/framework/metrics.ts +10 -6
- 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,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,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
2
|
|
|
3
3
|
import { Job, JobInput } from 'src/types/jobs';
|
|
4
4
|
|
|
5
5
|
const jobStore: Record<string, Job> = {};
|
|
6
6
|
|
|
7
7
|
export const createJob = (jobInput: JobInput): Promise<Job> => {
|
|
8
|
-
const id =
|
|
8
|
+
const id = randomUUID();
|
|
9
9
|
|
|
10
10
|
const job = { ...jobInput, id };
|
|
11
11
|
|
|
@@ -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
|
|
|
@@ -15,7 +15,7 @@ Next steps:
|
|
|
15
15
|
3. [ ] Create a new repository in the appropriate GitHub organisation.
|
|
16
16
|
4. [ ] Add the repository to BuildAgency;
|
|
17
17
|
see [Builds at SEEK] for more information.
|
|
18
|
-
5. [ ] Add deployment bucket configuration and data classification tags to [serverless.yml](serverless.yml).
|
|
18
|
+
5. [ ] Add Datadog extension, deployment bucket configuration and data classification tags to [serverless.yml](serverless.yml).
|
|
19
19
|
6. [ ] Push local commits to the upstream GitHub branch.
|
|
20
20
|
7. [ ] Configure [GitHub repository settings].
|
|
21
21
|
8. [ ] Delete this checklist 😌.
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@seek/logger": "^5.0.1",
|
|
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",
|
|
17
16
|
"serverless-plugin-canary-deployments": "^0.8.0",
|
|
17
|
+
"serverless-plugin-datadog": "^5.7.0",
|
|
18
18
|
"serverless-prune-plugin": "^2.0.0",
|
|
19
19
|
"skuba": "*"
|
|
20
20
|
},
|
|
@@ -4,21 +4,33 @@ configValidationMode: error
|
|
|
4
4
|
|
|
5
5
|
params:
|
|
6
6
|
default:
|
|
7
|
+
datadogApiKeySecretArn: 'TODO: arn:aws:secretsmanager:${aws:region}:${aws:accountId}:secret:SECRET-NAME'
|
|
7
8
|
description: <%- description %>
|
|
8
9
|
dev:
|
|
9
|
-
deploymentBucket: 'TODO:
|
|
10
|
+
deploymentBucket: 'TODO: deployment-bucket-name'
|
|
10
11
|
isProduction: false
|
|
11
12
|
prod:
|
|
12
|
-
deploymentBucket: 'TODO:
|
|
13
|
+
deploymentBucket: 'TODO: deployment-bucket-name'
|
|
13
14
|
isProduction: true
|
|
14
15
|
|
|
15
16
|
custom:
|
|
17
|
+
datadog:
|
|
18
|
+
addLayers: false
|
|
19
|
+
apiKeySecretArn: ${param:datadogApiKeySecretArn}
|
|
20
|
+
enableDDLogs: false
|
|
21
|
+
# TODO: enable Datadog extension
|
|
22
|
+
enabled: false
|
|
23
|
+
exclude:
|
|
24
|
+
- WorkerPreHook
|
|
25
|
+
injectLogContext: false
|
|
26
|
+
version: ${env:VERSION}
|
|
16
27
|
prune:
|
|
17
28
|
automatic: true
|
|
18
29
|
number: 3
|
|
19
30
|
|
|
20
31
|
plugins:
|
|
21
32
|
- serverless-plugin-canary-deployments
|
|
33
|
+
- serverless-plugin-datadog
|
|
22
34
|
- serverless-prune-plugin
|
|
23
35
|
|
|
24
36
|
provider:
|
|
@@ -51,6 +63,9 @@ provider:
|
|
|
51
63
|
- Action: lambda:InvokeFunction
|
|
52
64
|
Effect: Allow
|
|
53
65
|
Resource: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${self:functions.Worker.name}
|
|
66
|
+
- Action: secretsmanager:GetSecretValue
|
|
67
|
+
Effect: Allow
|
|
68
|
+
Resource: ${param:datadogApiKeySecretArn}-??????
|
|
54
69
|
- Action: sns:Publish
|
|
55
70
|
Effect: Allow
|
|
56
71
|
Resource: !Ref DestinationTopic
|
|
@@ -17,7 +17,9 @@ describe('handler', () => {
|
|
|
17
17
|
|
|
18
18
|
const score = chance.floating({ max: 1, min: 0 });
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const distribution = jest
|
|
21
|
+
.spyOn(metricsClient, 'distribution')
|
|
22
|
+
.mockReturnValue();
|
|
21
23
|
|
|
22
24
|
beforeAll(logger.spy);
|
|
23
25
|
beforeAll(scoringService.spy);
|
|
@@ -32,7 +34,7 @@ describe('handler', () => {
|
|
|
32
34
|
|
|
33
35
|
afterEach(() => {
|
|
34
36
|
logger.clear();
|
|
35
|
-
|
|
37
|
+
distribution.mockClear();
|
|
36
38
|
scoringService.clear();
|
|
37
39
|
sns.clear();
|
|
38
40
|
});
|
|
@@ -47,12 +49,12 @@ describe('handler', () => {
|
|
|
47
49
|
expect(logger.error).not.toHaveBeenCalled();
|
|
48
50
|
|
|
49
51
|
expect(logger.info.mock.calls).toEqual([
|
|
50
|
-
[{ count: 1 }, '
|
|
51
|
-
[{ snsMessageId: expect.any(String) }, '
|
|
52
|
-
['
|
|
52
|
+
[{ count: 1 }, 'Received jobs'],
|
|
53
|
+
[{ snsMessageId: expect.any(String) }, 'Scored job'],
|
|
54
|
+
['Function succeeded'],
|
|
53
55
|
]);
|
|
54
56
|
|
|
55
|
-
expect(
|
|
57
|
+
expect(distribution.mock.calls).toEqual([
|
|
56
58
|
['job.received', 1],
|
|
57
59
|
['job.scored', 1],
|
|
58
60
|
]);
|
|
@@ -63,7 +65,7 @@ describe('handler', () => {
|
|
|
63
65
|
it('throws on invalid input', () => {
|
|
64
66
|
const event = createSqsEvent(['}']);
|
|
65
67
|
|
|
66
|
-
return expect(app.handler(event, ctx)).rejects.toThrow('
|
|
68
|
+
return expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
|
|
67
69
|
});
|
|
68
70
|
|
|
69
71
|
it('bubbles up scoring service error', async () => {
|
|
@@ -73,9 +75,9 @@ describe('handler', () => {
|
|
|
73
75
|
|
|
74
76
|
const event = createSqsEvent([JSON.stringify(jobPublished)]);
|
|
75
77
|
|
|
76
|
-
await expect(app.handler(event, ctx)).rejects.toThrow('
|
|
78
|
+
await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
|
|
77
79
|
|
|
78
|
-
expect(logger.error).toHaveBeenCalledWith({ err }, '
|
|
80
|
+
expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
|
|
79
81
|
});
|
|
80
82
|
|
|
81
83
|
it('bubbles up SNS error', async () => {
|
|
@@ -85,31 +87,31 @@ describe('handler', () => {
|
|
|
85
87
|
|
|
86
88
|
const event = createSqsEvent([JSON.stringify(jobPublished)]);
|
|
87
89
|
|
|
88
|
-
await expect(app.handler(event, ctx)).rejects.toThrow('
|
|
90
|
+
await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
|
|
89
91
|
|
|
90
|
-
expect(logger.error).toHaveBeenCalledWith({ err }, '
|
|
92
|
+
expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
|
|
91
93
|
});
|
|
92
94
|
|
|
93
95
|
it('throws on zero records', async () => {
|
|
94
|
-
const err = new Error('
|
|
96
|
+
const err = new Error('Received 0 records');
|
|
95
97
|
|
|
96
98
|
const event = createSqsEvent([]);
|
|
97
99
|
|
|
98
|
-
await expect(app.handler(event, ctx)).rejects.toThrow('
|
|
100
|
+
await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
|
|
99
101
|
|
|
100
|
-
expect(logger.error).toHaveBeenCalledWith({ err }, '
|
|
102
|
+
expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
|
|
101
103
|
});
|
|
102
104
|
|
|
103
105
|
it('throws on multiple records', async () => {
|
|
104
|
-
const err = new Error('
|
|
106
|
+
const err = new Error('Received 2 records');
|
|
105
107
|
|
|
106
108
|
const event = createSqsEvent([
|
|
107
109
|
JSON.stringify(jobPublished),
|
|
108
110
|
JSON.stringify(jobPublished),
|
|
109
111
|
]);
|
|
110
112
|
|
|
111
|
-
await expect(app.handler(event, ctx)).rejects.toThrow('
|
|
113
|
+
await expect(app.handler(event, ctx)).rejects.toThrow('Function failed');
|
|
112
114
|
|
|
113
|
-
expect(logger.error).toHaveBeenCalledWith({ err }, '
|
|
115
|
+
expect(logger.error).toHaveBeenCalledWith({ err }, 'Function failed');
|
|
114
116
|
});
|
|
115
117
|
});
|
|
@@ -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.
|
|
@@ -20,19 +20,19 @@ const smokeTest = async () => {
|
|
|
20
20
|
export const handler = createHandler<SQSEvent>(async (event) => {
|
|
21
21
|
// Treat an empty object as our smoke test event.
|
|
22
22
|
if (!Object.keys(event).length) {
|
|
23
|
-
logger.info('
|
|
23
|
+
logger.info('Received smoke test request');
|
|
24
24
|
return smokeTest();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const count = event.Records.length;
|
|
28
28
|
|
|
29
29
|
if (count !== 1) {
|
|
30
|
-
throw Error(`
|
|
30
|
+
throw Error(`Received ${count} records`);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
logger.info({ count }, '
|
|
33
|
+
logger.info({ count }, 'Received jobs');
|
|
34
34
|
|
|
35
|
-
metricsClient.
|
|
35
|
+
metricsClient.distribution('job.received', event.Records.length);
|
|
36
36
|
|
|
37
37
|
const record = event.Records[0];
|
|
38
38
|
|
|
@@ -40,13 +40,13 @@ 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
|
|
|
47
47
|
const snsMessageId = await sendPipelineEvent(scoredJob);
|
|
48
48
|
|
|
49
|
-
logger.info({ snsMessageId }, '
|
|
49
|
+
logger.info({ snsMessageId }, 'Scored job');
|
|
50
50
|
|
|
51
|
-
metricsClient.
|
|
51
|
+
metricsClient.distribution('job.scored', 1);
|
|
52
52
|
});
|
|
@@ -4,6 +4,7 @@ interface Config {
|
|
|
4
4
|
environment: Environment;
|
|
5
5
|
|
|
6
6
|
logLevel: string;
|
|
7
|
+
metrics: boolean;
|
|
7
8
|
name: string;
|
|
8
9
|
version: string;
|
|
9
10
|
|
|
@@ -20,6 +21,7 @@ const environment = Env.oneOf(environments)('ENVIRONMENT');
|
|
|
20
21
|
const configs: Record<Environment, () => Omit<Config, 'environment'>> = {
|
|
21
22
|
local: () => ({
|
|
22
23
|
logLevel: 'debug',
|
|
24
|
+
metrics: false,
|
|
23
25
|
name: '<%- serviceName %>',
|
|
24
26
|
version: 'local',
|
|
25
27
|
|
|
@@ -41,6 +43,7 @@ const configs: Record<Environment, () => Omit<Config, 'environment'>> = {
|
|
|
41
43
|
|
|
42
44
|
prod: () => ({
|
|
43
45
|
logLevel: 'info',
|
|
46
|
+
metrics: true,
|
|
44
47
|
name: Env.string('SERVICE'),
|
|
45
48
|
version: Env.string('VERSION'),
|
|
46
49
|
|
|
@@ -18,7 +18,7 @@ describe('createHandler', () => {
|
|
|
18
18
|
const handler = createHandler((event) => {
|
|
19
19
|
expect(event).toBe(input);
|
|
20
20
|
|
|
21
|
-
logger.info('
|
|
21
|
+
logger.info('Handler invoked');
|
|
22
22
|
|
|
23
23
|
return Promise.resolve(output);
|
|
24
24
|
});
|
|
@@ -28,8 +28,8 @@ describe('createHandler', () => {
|
|
|
28
28
|
expect(logger.error).not.toHaveBeenCalled();
|
|
29
29
|
|
|
30
30
|
expect(logger.info.mock.calls).toEqual([
|
|
31
|
-
['
|
|
32
|
-
['
|
|
31
|
+
['Handler invoked'],
|
|
32
|
+
['Function succeeded'],
|
|
33
33
|
]);
|
|
34
34
|
});
|
|
35
35
|
|
|
@@ -38,9 +38,9 @@ describe('createHandler', () => {
|
|
|
38
38
|
|
|
39
39
|
const handler = createHandler(() => Promise.reject(err));
|
|
40
40
|
|
|
41
|
-
await expect(handler(input, ctx)).rejects.toThrow('
|
|
41
|
+
await expect(handler(input, ctx)).rejects.toThrow('Function failed');
|
|
42
42
|
|
|
43
|
-
expect(logger.error.mock.calls).toEqual([[{ err }, '
|
|
43
|
+
expect(logger.error.mock.calls).toEqual([[{ err }, 'Function failed']]);
|
|
44
44
|
|
|
45
45
|
expect(logger.info).not.toHaveBeenCalled();
|
|
46
46
|
});
|
|
@@ -52,9 +52,9 @@ describe('createHandler', () => {
|
|
|
52
52
|
throw err;
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
await expect(handler(input, ctx)).rejects.toThrow('
|
|
55
|
+
await expect(handler(input, ctx)).rejects.toThrow('Function failed');
|
|
56
56
|
|
|
57
|
-
expect(logger.error.mock.calls).toEqual([[{ err }, '
|
|
57
|
+
expect(logger.error.mock.calls).toEqual([[{ err }, 'Function failed']]);
|
|
58
58
|
|
|
59
59
|
expect(logger.info).not.toHaveBeenCalled();
|
|
60
60
|
});
|
|
@@ -1,20 +1,43 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { datadog } from 'datadog-lambda-js';
|
|
2
2
|
|
|
3
|
+
import { config } from 'src/config';
|
|
3
4
|
import { logger, loggerContext } from 'src/framework/logging';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
interface LambdaContext {
|
|
7
|
+
awsRequestId: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type Handler<Event, Output> = (
|
|
11
|
+
event: Event,
|
|
12
|
+
ctx: LambdaContext,
|
|
13
|
+
) => Promise<Output>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Conditionally applies the Datadog wrapper to a Lambda handler.
|
|
17
|
+
*
|
|
18
|
+
* This also "fixes" its broken type definitions.
|
|
19
|
+
*/
|
|
20
|
+
const withDatadog = <Event, Output = unknown>(
|
|
21
|
+
fn: Handler<Event, Output>,
|
|
22
|
+
): Handler<Event, Output> =>
|
|
23
|
+
// istanbul ignore next
|
|
24
|
+
config.metrics ? (datadog(fn) as Handler<Event, Output>) : fn;
|
|
25
|
+
|
|
26
|
+
export const createHandler = <Event, Output = unknown>(
|
|
27
|
+
fn: (event: Event) => Promise<Output>,
|
|
28
|
+
) =>
|
|
29
|
+
withDatadog<Event>((event, { awsRequestId }) =>
|
|
8
30
|
loggerContext.run({ awsRequestId }, async () => {
|
|
9
31
|
try {
|
|
10
32
|
const output = await fn(event);
|
|
11
33
|
|
|
12
|
-
logger.info('
|
|
34
|
+
logger.info('Function succeeded');
|
|
13
35
|
|
|
14
36
|
return output;
|
|
15
37
|
} catch (err) {
|
|
16
|
-
logger.error({ err }, '
|
|
38
|
+
logger.error({ err }, 'Function failed');
|
|
17
39
|
|
|
18
|
-
throw new Error('
|
|
40
|
+
throw new Error('Function failed');
|
|
19
41
|
}
|
|
20
|
-
})
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createCloudWatchClient,
|
|
3
|
-
createTimedSpan,
|
|
4
|
-
} from 'seek-datadog-custom-metrics';
|
|
1
|
+
import { sendDistributionMetric } from 'datadog-lambda-js';
|
|
5
2
|
|
|
6
3
|
import { config } from 'src/config';
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
const prefix = `${config.name}.`;
|
|
9
6
|
|
|
10
|
-
export const
|
|
7
|
+
export const metricsClient = {
|
|
8
|
+
distribution: (
|
|
9
|
+
...[name, ...rest]: Parameters<typeof sendDistributionMetric>
|
|
10
|
+
) =>
|
|
11
|
+
config.metrics
|
|
12
|
+
? sendDistributionMetric(`${prefix}${name}`, ...rest)
|
|
13
|
+
: undefined,
|
|
14
|
+
};
|
|
@@ -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
|
});
|