skuba 12.0.0-enforce-file-extensions-20250618112549 → 12.0.0-subpath-imports-20250710010820
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 +4 -3
- package/jest/transform.js +1 -15
- package/jest-preset.js +4 -7
- package/lib/cli/buildPackage/index.js +2 -2
- package/lib/cli/buildPackage/index.js.map +1 -1
- package/lib/cli/configure/ensureTemplateCompletion.js +1 -1
- package/lib/cli/configure/ensureTemplateCompletion.js.map +2 -2
- package/lib/cli/configure/processing/prettier.d.ts +1 -1
- package/lib/cli/configure/processing/prettier.js +8 -6
- package/lib/cli/configure/processing/prettier.js.map +3 -3
- package/lib/cli/init/getConfig.d.ts +1 -1
- package/lib/cli/init/getConfig.js +7 -5
- package/lib/cli/init/getConfig.js.map +3 -3
- package/lib/cli/init/prompts.d.ts +5 -5
- package/lib/cli/init/prompts.js +5 -4
- package/lib/cli/init/prompts.js.map +3 -3
- package/lib/cli/lint/internalLints/upgrade/patches/11.1.0/index.d.ts +2 -0
- package/lib/cli/lint/internalLints/upgrade/patches/11.1.0/index.js +35 -0
- package/lib/cli/lint/internalLints/upgrade/patches/11.1.0/index.js.map +7 -0
- package/lib/cli/lint/internalLints/upgrade/patches/11.1.0/rewriteSrcImports.d.ts +6 -0
- package/lib/cli/lint/internalLints/upgrade/patches/11.1.0/rewriteSrcImports.js +104 -0
- package/lib/cli/lint/internalLints/upgrade/patches/11.1.0/rewriteSrcImports.js.map +7 -0
- package/lib/cli/migrate/nodeVersion/index.js +18 -18
- package/lib/cli/migrate/nodeVersion/index.js.map +2 -2
- package/package.json +33 -26
- package/template/base/_.prettierrc.js +1 -1
- package/template/base/_eslint.config.js +1 -1
- package/template/base/_pnpm-workspace.yaml +2 -0
- package/template/base/jest.config.ts +17 -3
- package/template/base/jest.setup.ts +0 -2
- package/template/base/tsconfig.json +3 -3
- package/template/express-rest-api/.buildkite/pipeline.yml +1 -1
- package/template/express-rest-api/Dockerfile.dev-deps +1 -1
- package/template/express-rest-api/package.json +8 -1
- package/template/express-rest-api/src/app.ts +0 -2
- package/template/express-rest-api/src/framework/logging.ts +1 -1
- package/template/express-rest-api/src/framework/metrics.ts +2 -2
- package/template/express-rest-api/src/listen.ts +0 -2
- package/template/greeter/.buildkite/pipeline.yml +1 -1
- package/template/greeter/Dockerfile +1 -1
- package/template/greeter/package.json +10 -3
- package/template/greeter/src/app.ts +2 -2
- package/template/koa-rest-api/.buildkite/pipeline.yml +1 -1
- package/template/koa-rest-api/Dockerfile.dev-deps +1 -1
- package/template/koa-rest-api/package.json +14 -7
- package/template/koa-rest-api/src/api/healthCheck.ts +1 -1
- package/template/koa-rest-api/src/api/jobs/getJobs.test.ts +2 -2
- package/template/koa-rest-api/src/api/jobs/getJobs.ts +4 -4
- package/template/koa-rest-api/src/api/jobs/index.ts +2 -2
- package/template/koa-rest-api/src/api/jobs/postJob.test.ts +4 -4
- package/template/koa-rest-api/src/api/jobs/postJob.ts +6 -6
- package/template/koa-rest-api/src/api/smokeTest.ts +2 -2
- package/template/koa-rest-api/src/app.test.ts +2 -2
- package/template/koa-rest-api/src/app.ts +0 -2
- package/template/koa-rest-api/src/config.ts +1 -1
- package/template/koa-rest-api/src/framework/logging.ts +22 -13
- package/template/koa-rest-api/src/framework/metrics.ts +2 -2
- package/template/koa-rest-api/src/framework/server.test.ts +95 -64
- package/template/koa-rest-api/src/framework/server.ts +3 -3
- package/template/koa-rest-api/src/framework/validation.test.ts +36 -36
- package/template/koa-rest-api/src/framework/validation.ts +15 -22
- package/template/koa-rest-api/src/listen.ts +0 -2
- package/template/koa-rest-api/src/register.ts +0 -1
- package/template/koa-rest-api/src/storage/jobs.ts +1 -1
- package/template/koa-rest-api/src/testing/metrics.ts +1 -1
- package/template/koa-rest-api/src/testing/server.ts +1 -1
- package/template/koa-rest-api/src/testing/types.ts +2 -2
- package/template/koa-rest-api/src/types/jobs.ts +1 -1
- package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +2 -2
- package/template/lambda-sqs-worker-cdk/Dockerfile +1 -1
- package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +6 -0
- package/template/lambda-sqs-worker-cdk/infra/appStack.test.ts +1 -1
- package/template/lambda-sqs-worker-cdk/package.json +13 -6
- package/template/lambda-sqs-worker-cdk/src/app.test.ts +81 -22
- package/template/lambda-sqs-worker-cdk/src/app.ts +7 -9
- package/template/lambda-sqs-worker-cdk/src/config.ts +1 -1
- package/template/lambda-sqs-worker-cdk/src/framework/handler.test.ts +38 -18
- package/template/lambda-sqs-worker-cdk/src/framework/handler.ts +2 -2
- package/template/lambda-sqs-worker-cdk/src/framework/logging.ts +23 -12
- package/template/lambda-sqs-worker-cdk/src/framework/metrics.ts +1 -1
- package/template/lambda-sqs-worker-cdk/src/framework/validation.test.ts +9 -12
- package/template/lambda-sqs-worker-cdk/src/framework/validation.ts +3 -7
- package/template/lambda-sqs-worker-cdk/src/services/jobScorer.test.ts +3 -3
- package/template/lambda-sqs-worker-cdk/src/services/jobScorer.ts +7 -6
- package/template/lambda-sqs-worker-cdk/src/services/pipelineEventSender.test.ts +3 -3
- package/template/lambda-sqs-worker-cdk/src/services/pipelineEventSender.ts +2 -2
- package/template/lambda-sqs-worker-cdk/src/testing/services.ts +2 -2
- package/template/lambda-sqs-worker-cdk/src/testing/types.ts +1 -1
- package/template/lambda-sqs-worker-cdk/src/types/jobScorer.ts +1 -1
- package/template/lambda-sqs-worker-cdk/src/types/pipelineEvents.ts +1 -1
- package/template/lambda-sqs-worker-cdk/tsconfig.json +3 -3
- package/template/oss-npm-package/_package.json +8 -0
- package/template/oss-npm-package/skuba.template.js +1 -1
- package/template/oss-npm-package/tsconfig.json +3 -0
- package/template/private-npm-package/_package.json +7 -0
- package/lib/cli/test/reporters/prettier/index.d.ts +0 -4
- package/lib/cli/test/reporters/prettier/index.js +0 -67
- package/lib/cli/test/reporters/prettier/index.js.map +0 -7
- package/template/express-rest-api/src/register.ts +0 -1
- package/template/koa-rest-api/src/testing/logging.ts +0 -16
- package/template/koa-rest-api/tsconfig.json +0 -18
- package/template/lambda-sqs-worker-cdk/src/testing/logging.ts +0 -19
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { agentFromRouter } from 'src/testing/server.js';
|
|
2
|
-
import { mockJobInput } from 'src/testing/types.js';
|
|
3
|
-
|
|
4
1
|
import { jobRouter } from './index.js';
|
|
5
2
|
|
|
3
|
+
import { agentFromRouter } from '#src/testing/server.js';
|
|
4
|
+
import { mockJobInput } from '#src/testing/types.js';
|
|
5
|
+
|
|
6
6
|
const agent = agentFromRouter(jobRouter);
|
|
7
7
|
|
|
8
8
|
describe('postJobHandler', () => {
|
|
@@ -27,7 +27,7 @@ describe('postJobHandler', () => {
|
|
|
27
27
|
.expect(422)
|
|
28
28
|
.expect(({ text }) =>
|
|
29
29
|
expect(text).toMatchInlineSnapshot(
|
|
30
|
-
`"{"message":"Input validation failed","invalidFields":{"/hirer":"
|
|
30
|
+
`"{"message":"Input validation failed","invalidFields":{"/hirer":"Invalid input: expected object, received undefined"}}"`,
|
|
31
31
|
),
|
|
32
32
|
);
|
|
33
33
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { logger } from 'src/framework/logging.js';
|
|
2
|
-
import { metricsClient } from 'src/framework/metrics.js';
|
|
3
|
-
import { validateRequestBody } from 'src/framework/validation.js';
|
|
4
|
-
import * as storage from 'src/storage/jobs.js';
|
|
5
|
-
import { JobInputSchema } from 'src/types/jobs.js';
|
|
6
|
-
import type { Middleware } from 'src/types/koa.js';
|
|
1
|
+
import { logger } from '#src/framework/logging.js';
|
|
2
|
+
import { metricsClient } from '#src/framework/metrics.js';
|
|
3
|
+
import { validateRequestBody } from '#src/framework/validation.js';
|
|
4
|
+
import * as storage from '#src/storage/jobs.js';
|
|
5
|
+
import { JobInputSchema } from '#src/types/jobs.js';
|
|
6
|
+
import type { Middleware } from '#src/types/koa.js';
|
|
7
7
|
|
|
8
8
|
export const postJobHandler: Middleware = async (ctx) => {
|
|
9
9
|
const jobInput = validateRequestBody(ctx, JobInputSchema);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { smokeTestJobStorage } from 'src/storage/jobs.js';
|
|
2
|
-
import type { Middleware } from 'src/types/koa.js';
|
|
1
|
+
import { smokeTestJobStorage } from '#src/storage/jobs.js';
|
|
2
|
+
import type { Middleware } from '#src/types/koa.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Tests connectivity to ensure appropriate access and network configuration.
|
|
@@ -1,25 +1,34 @@
|
|
|
1
|
-
import createLogger from '@seek/logger';
|
|
1
|
+
import createLogger, { createDestination } from '@seek/logger';
|
|
2
2
|
import { RequestLogging } from 'seek-koala';
|
|
3
3
|
|
|
4
|
-
import { config } from 'src/config.js';
|
|
4
|
+
import { config } from '#src/config.js';
|
|
5
5
|
|
|
6
6
|
const { createContextMiddleware, mixin } =
|
|
7
7
|
RequestLogging.createContextStorage();
|
|
8
8
|
|
|
9
9
|
export const contextMiddleware = createContextMiddleware();
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
version: config.version,
|
|
15
|
-
},
|
|
11
|
+
const { destination, stdoutMock } = createDestination({
|
|
12
|
+
mock: config.environment === 'test',
|
|
13
|
+
});
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
export { stdoutMock };
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
export const logger = createLogger(
|
|
18
|
+
{
|
|
19
|
+
base: {
|
|
20
|
+
environment: config.environment,
|
|
21
|
+
version: config.version,
|
|
22
|
+
},
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
mixin,
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
level: config.logLevel,
|
|
27
|
+
|
|
28
|
+
name: config.name,
|
|
29
|
+
|
|
30
|
+
transport:
|
|
31
|
+
config.environment === 'local' ? { target: 'pino-pretty' } : undefined,
|
|
32
|
+
},
|
|
33
|
+
destination,
|
|
34
|
+
);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { StatsD } from 'hot-shots';
|
|
2
2
|
import { createStatsDClient } from 'seek-datadog-custom-metrics';
|
|
3
3
|
|
|
4
|
-
import { config } from 'src/config.js';
|
|
5
|
-
|
|
6
4
|
import { logger } from './logging.js';
|
|
7
5
|
|
|
6
|
+
import { config } from '#src/config.js';
|
|
7
|
+
|
|
8
8
|
/* istanbul ignore next: StatsD client is not our responsibility */
|
|
9
9
|
export const metricsClient = createStatsDClient(StatsD, config, (err) =>
|
|
10
10
|
logger.error({ err }, 'StatsD error'),
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Router from '@koa/router';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
3
|
+
import { stdoutMock } from './logging.js';
|
|
4
|
+
|
|
5
|
+
import { metricsClient } from '#src/testing/metrics.js';
|
|
6
|
+
import { agentFromRouter } from '#src/testing/server.js';
|
|
7
|
+
import { chance } from '#src/testing/types.js';
|
|
8
|
+
import type { Middleware } from '#src/types/koa.js';
|
|
8
9
|
|
|
9
10
|
const middleware = jest.fn<void, Parameters<Middleware>>();
|
|
10
11
|
|
|
@@ -15,10 +16,10 @@ const router = new Router()
|
|
|
15
16
|
const agent = agentFromRouter(router);
|
|
16
17
|
|
|
17
18
|
describe('createApp', () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
metricsClient.clear();
|
|
21
|
+
stdoutMock.clear();
|
|
22
|
+
});
|
|
22
23
|
|
|
23
24
|
it('handles root route', async () => {
|
|
24
25
|
middleware.mockImplementation((ctx) => (ctx.body = ''));
|
|
@@ -29,9 +30,7 @@ describe('createApp', () => {
|
|
|
29
30
|
.expect('server', /.+/)
|
|
30
31
|
.expect('x-api-version', /.+/);
|
|
31
32
|
|
|
32
|
-
expect(
|
|
33
|
-
|
|
34
|
-
expect(logger.info).not.toHaveBeenCalled();
|
|
33
|
+
expect(stdoutMock.calls).toHaveLength(0);
|
|
35
34
|
|
|
36
35
|
metricsClient.expectTagSubset(['env:test', 'version:test']);
|
|
37
36
|
metricsClient.expectTagSubset([
|
|
@@ -51,9 +50,7 @@ describe('createApp', () => {
|
|
|
51
50
|
.expect('server', /.+/)
|
|
52
51
|
.expect('x-api-version', /.+/);
|
|
53
52
|
|
|
54
|
-
expect(
|
|
55
|
-
|
|
56
|
-
expect(logger.info).not.toHaveBeenCalled();
|
|
53
|
+
expect(stdoutMock.calls).toHaveLength(0);
|
|
57
54
|
|
|
58
55
|
metricsClient.expectTagSubset([
|
|
59
56
|
'http_method:put',
|
|
@@ -72,13 +69,15 @@ describe('createApp', () => {
|
|
|
72
69
|
.expect('server', /.+/)
|
|
73
70
|
.expect('x-api-version', /.+/);
|
|
74
71
|
|
|
75
|
-
expect(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
expect(stdoutMock.calls).toMatchObject([
|
|
73
|
+
{
|
|
74
|
+
level: 30,
|
|
75
|
+
method: 'GET',
|
|
76
|
+
msg: 'Client error',
|
|
77
|
+
status: 404,
|
|
78
|
+
url: '/unknown',
|
|
79
|
+
},
|
|
80
|
+
]);
|
|
82
81
|
|
|
83
82
|
metricsClient.expectTagSubset([
|
|
84
83
|
'http_method:get',
|
|
@@ -102,13 +101,16 @@ describe('createApp', () => {
|
|
|
102
101
|
.expect('server', /.+/)
|
|
103
102
|
.expect('x-api-version', /.+/);
|
|
104
103
|
|
|
105
|
-
expect(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
expect(stdoutMock.calls).toMatchObject([
|
|
105
|
+
{
|
|
106
|
+
level: 30,
|
|
107
|
+
method: 'GET',
|
|
108
|
+
msg: 'Client error',
|
|
109
|
+
route: '/',
|
|
110
|
+
status: 400,
|
|
111
|
+
url: '/',
|
|
112
|
+
},
|
|
113
|
+
]);
|
|
112
114
|
|
|
113
115
|
metricsClient.expectTagSubset([
|
|
114
116
|
'http_method:get',
|
|
@@ -129,13 +131,20 @@ describe('createApp', () => {
|
|
|
129
131
|
.expect('server', /.+/)
|
|
130
132
|
.expect('x-api-version', /.+/);
|
|
131
133
|
|
|
132
|
-
expect(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
expect(stdoutMock.calls).toMatchObject([
|
|
135
|
+
{
|
|
136
|
+
err: {
|
|
137
|
+
statusCode: 400,
|
|
138
|
+
type: 'BadRequestError',
|
|
139
|
+
},
|
|
140
|
+
level: 30,
|
|
141
|
+
method: 'GET',
|
|
142
|
+
msg: 'Client error',
|
|
143
|
+
route: '/',
|
|
144
|
+
status: 400,
|
|
145
|
+
url: '/',
|
|
146
|
+
},
|
|
147
|
+
]);
|
|
139
148
|
|
|
140
149
|
metricsClient.expectTagSubset([
|
|
141
150
|
'http_method:get',
|
|
@@ -156,13 +165,20 @@ describe('createApp', () => {
|
|
|
156
165
|
.expect('server', /.+/)
|
|
157
166
|
.expect('x-api-version', /.+/);
|
|
158
167
|
|
|
159
|
-
expect(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
expect(stdoutMock.calls).toMatchObject([
|
|
169
|
+
{
|
|
170
|
+
err: {
|
|
171
|
+
statusCode: 500,
|
|
172
|
+
type: 'InternalServerError',
|
|
173
|
+
},
|
|
174
|
+
level: 50,
|
|
175
|
+
method: 'GET',
|
|
176
|
+
msg: 'Server error',
|
|
177
|
+
route: '/',
|
|
178
|
+
status: 500,
|
|
179
|
+
url: '/',
|
|
180
|
+
},
|
|
181
|
+
]);
|
|
166
182
|
|
|
167
183
|
metricsClient.expectTagSubset([
|
|
168
184
|
'http_method:get',
|
|
@@ -185,13 +201,20 @@ describe('createApp', () => {
|
|
|
185
201
|
.expect('server', /.+/)
|
|
186
202
|
.expect('x-api-version', /.+/);
|
|
187
203
|
|
|
188
|
-
expect(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
204
|
+
expect(stdoutMock.calls).toMatchObject([
|
|
205
|
+
{
|
|
206
|
+
err: {
|
|
207
|
+
message: err.message,
|
|
208
|
+
type: 'Error',
|
|
209
|
+
},
|
|
210
|
+
level: 50,
|
|
211
|
+
method: 'GET',
|
|
212
|
+
msg: 'Server error',
|
|
213
|
+
route: '/',
|
|
214
|
+
status: 500,
|
|
215
|
+
url: '/',
|
|
216
|
+
},
|
|
217
|
+
]);
|
|
195
218
|
|
|
196
219
|
metricsClient.expectTagSubset([
|
|
197
220
|
'http_method:get',
|
|
@@ -212,13 +235,17 @@ describe('createApp', () => {
|
|
|
212
235
|
.expect('server', /.+/)
|
|
213
236
|
.expect('x-api-version', /.+/);
|
|
214
237
|
|
|
215
|
-
expect(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
238
|
+
expect(stdoutMock.calls).toMatchObject([
|
|
239
|
+
{
|
|
240
|
+
err: null,
|
|
241
|
+
level: 50,
|
|
242
|
+
method: 'GET',
|
|
243
|
+
msg: 'Server error',
|
|
244
|
+
route: '/',
|
|
245
|
+
status: 500,
|
|
246
|
+
url: '/',
|
|
247
|
+
},
|
|
248
|
+
]);
|
|
222
249
|
|
|
223
250
|
metricsClient.expectTagSubset([
|
|
224
251
|
'http_method:get',
|
|
@@ -241,13 +268,17 @@ describe('createApp', () => {
|
|
|
241
268
|
.expect('server', /.+/)
|
|
242
269
|
.expect('x-api-version', /.+/);
|
|
243
270
|
|
|
244
|
-
expect(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
271
|
+
expect(stdoutMock.calls).toMatchObject([
|
|
272
|
+
{
|
|
273
|
+
err,
|
|
274
|
+
level: 50,
|
|
275
|
+
method: 'GET',
|
|
276
|
+
msg: 'Server error',
|
|
277
|
+
route: '/',
|
|
278
|
+
status: 500,
|
|
279
|
+
url: '/',
|
|
280
|
+
},
|
|
281
|
+
]);
|
|
251
282
|
|
|
252
283
|
metricsClient.expectTagSubset([
|
|
253
284
|
'http_method:get',
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
VersionMiddleware,
|
|
9
9
|
} from 'seek-koala';
|
|
10
10
|
|
|
11
|
-
import { config } from 'src/config.js';
|
|
12
|
-
import { contextMiddleware, logger } from 'src/framework/logging.js';
|
|
13
|
-
import { metricsClient } from 'src/framework/metrics.js';
|
|
11
|
+
import { config } from '#src/config.js';
|
|
12
|
+
import { contextMiddleware, logger } from '#src/framework/logging.js';
|
|
13
|
+
import { metricsClient } from '#src/framework/metrics.js';
|
|
14
14
|
|
|
15
15
|
const metrics = MetricsMiddleware.create(
|
|
16
16
|
metricsClient,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsonBodyParser } from './bodyParser.js';
|
|
2
|
+
import { validate } from './validation.js';
|
|
3
|
+
|
|
4
|
+
import { agentFromMiddleware } from '#src/testing/server.js';
|
|
2
5
|
import {
|
|
3
6
|
IdDescriptionSchema,
|
|
4
7
|
chance,
|
|
5
8
|
mockIdDescription,
|
|
6
|
-
} from 'src/testing/types.js';
|
|
7
|
-
|
|
8
|
-
import { jsonBodyParser } from './bodyParser.js';
|
|
9
|
-
import { validate } from './validation.js';
|
|
9
|
+
} from '#src/testing/types.js';
|
|
10
10
|
|
|
11
11
|
const agent = agentFromMiddleware(jsonBodyParser, (ctx) => {
|
|
12
12
|
const result = validate({
|
|
@@ -43,15 +43,15 @@ describe('validate', () => {
|
|
|
43
43
|
.expect(422)
|
|
44
44
|
.expect(({ body }) =>
|
|
45
45
|
expect(body).toMatchInlineSnapshot(`
|
|
46
|
-
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
`),
|
|
46
|
+
{
|
|
47
|
+
"invalidFields": {
|
|
48
|
+
"~union0/id": "Invalid input: expected string, received null",
|
|
49
|
+
"~union1/id": "Invalid input: expected number, received null",
|
|
50
|
+
"~union1/summary": "Invalid input: expected string, received undefined",
|
|
51
|
+
},
|
|
52
|
+
"message": "Input validation failed",
|
|
53
|
+
}
|
|
54
|
+
`),
|
|
55
55
|
);
|
|
56
56
|
});
|
|
57
57
|
|
|
@@ -62,17 +62,17 @@ describe('validate', () => {
|
|
|
62
62
|
.expect(422)
|
|
63
63
|
.expect(({ body }) =>
|
|
64
64
|
expect(body).toMatchInlineSnapshot(`
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
`),
|
|
65
|
+
{
|
|
66
|
+
"invalidFields": {
|
|
67
|
+
"~union0/description~union0": "Invalid input: expected string, received undefined",
|
|
68
|
+
"~union0/description~union1": "Invalid input: expected object, received undefined",
|
|
69
|
+
"~union0/id": "Invalid input: expected string, received undefined",
|
|
70
|
+
"~union1/id": "Invalid input: expected number, received undefined",
|
|
71
|
+
"~union1/summary": "Invalid input: expected string, received undefined",
|
|
72
|
+
},
|
|
73
|
+
"message": "Input validation failed",
|
|
74
|
+
}
|
|
75
|
+
`),
|
|
76
76
|
));
|
|
77
77
|
|
|
78
78
|
it('blocks invalid nested union prop', () => {
|
|
@@ -89,17 +89,17 @@ describe('validate', () => {
|
|
|
89
89
|
.expect(422)
|
|
90
90
|
.expect(({ body }) =>
|
|
91
91
|
expect(body).toMatchInlineSnapshot(`
|
|
92
|
-
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
`),
|
|
92
|
+
{
|
|
93
|
+
"invalidFields": {
|
|
94
|
+
"~union0/description~union0": "Invalid input: expected string, received object",
|
|
95
|
+
"~union0/description~union1/content": "Invalid input: expected string, received undefined",
|
|
96
|
+
"~union0/id": "Invalid input: expected string, received null",
|
|
97
|
+
"~union1/id": "Invalid input: expected number, received null",
|
|
98
|
+
"~union1/summary": "Invalid input: expected string, received undefined",
|
|
99
|
+
},
|
|
100
|
+
"message": "Input validation failed",
|
|
101
|
+
}
|
|
102
|
+
`),
|
|
103
103
|
);
|
|
104
104
|
});
|
|
105
105
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ErrorMiddleware } from 'seek-koala';
|
|
2
|
-
import {
|
|
2
|
+
import type { core, z } from 'zod/v4';
|
|
3
3
|
|
|
4
|
-
import type { Context } from 'src/types/koa.js';
|
|
4
|
+
import type { Context } from '#src/types/koa.js';
|
|
5
5
|
|
|
6
6
|
type InvalidFields = Record<string, string>;
|
|
7
7
|
|
|
@@ -35,41 +35,38 @@ type InvalidFields = Record<string, string>;
|
|
|
35
35
|
* @see [union error example](./validation.test.ts)
|
|
36
36
|
*/
|
|
37
37
|
const parseInvalidFieldsFromError = (err: z.ZodError): InvalidFields =>
|
|
38
|
-
Object.fromEntries(parseTuples(err
|
|
38
|
+
Object.fromEntries(parseTuples(err.issues));
|
|
39
39
|
|
|
40
40
|
const parseTuples = (
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
errors: core.$ZodIssue[],
|
|
42
|
+
basePath: Array<string | number | symbol> = [],
|
|
43
|
+
unions: Record<number, number[]> = {},
|
|
43
44
|
): Array<readonly [string, string]> =>
|
|
44
45
|
errors.flatMap((issue) => {
|
|
45
|
-
if (issue.code ===
|
|
46
|
-
return issue.
|
|
47
|
-
parseTuples(err, {
|
|
46
|
+
if (issue.code === 'invalid_union') {
|
|
47
|
+
return issue.errors.flatMap((err, idx) =>
|
|
48
|
+
parseTuples(err, issue.path, {
|
|
48
49
|
...unions,
|
|
49
50
|
[issue.path.length]: [...(unions[issue.path.length] ?? []), idx],
|
|
50
51
|
}),
|
|
51
52
|
);
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
const path = ['', ...issue.path]
|
|
55
|
+
const path = ['', ...basePath, ...issue.path]
|
|
55
56
|
.map((prop, idx) => [prop, ...(unions[idx] ?? [])].join('~union'))
|
|
56
57
|
.join('/');
|
|
57
58
|
|
|
58
59
|
return [[path, issue.message]] as const;
|
|
59
60
|
});
|
|
60
61
|
|
|
61
|
-
export const validate = <
|
|
62
|
-
Output,
|
|
63
|
-
Def extends z.ZodTypeDef = z.ZodTypeDef,
|
|
64
|
-
Input = Output,
|
|
65
|
-
>({
|
|
62
|
+
export const validate = <Output, Input = Output>({
|
|
66
63
|
ctx,
|
|
67
64
|
input,
|
|
68
65
|
schema,
|
|
69
66
|
}: {
|
|
70
67
|
ctx: Context;
|
|
71
68
|
input: unknown;
|
|
72
|
-
schema: z.ZodSchema<Output,
|
|
69
|
+
schema: z.ZodSchema<Output, Input>;
|
|
73
70
|
}): Output => {
|
|
74
71
|
const parseResult = schema.safeParse(input);
|
|
75
72
|
if (parseResult.success === false) {
|
|
@@ -85,15 +82,11 @@ export const validate = <
|
|
|
85
82
|
return parseResult.data;
|
|
86
83
|
};
|
|
87
84
|
|
|
88
|
-
export const validateRequestBody = <
|
|
89
|
-
Output,
|
|
90
|
-
Def extends z.ZodTypeDef = z.ZodTypeDef,
|
|
91
|
-
Input = Output,
|
|
92
|
-
>(
|
|
85
|
+
export const validateRequestBody = <Output, Input = Output>(
|
|
93
86
|
ctx: Context,
|
|
94
|
-
schema: z.ZodSchema<Output,
|
|
87
|
+
schema: z.ZodSchema<Output, Input>,
|
|
95
88
|
): Output =>
|
|
96
|
-
validate<Output,
|
|
89
|
+
validate<Output, Input>({
|
|
97
90
|
ctx,
|
|
98
91
|
input: ctx.request.body as unknown,
|
|
99
92
|
schema,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import 'skuba-dive/register';
|
|
@@ -2,7 +2,7 @@ import type Router from '@koa/router';
|
|
|
2
2
|
import type Koa from 'koa';
|
|
3
3
|
import request from 'supertest';
|
|
4
4
|
|
|
5
|
-
import { createApp } from 'src/framework/server.js';
|
|
5
|
+
import { createApp } from '#src/framework/server.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Create a new SuperTest agent from a Koa application.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Chance } from 'chance';
|
|
2
|
-
import { z } from 'zod';
|
|
2
|
+
import { z } from 'zod/v4';
|
|
3
3
|
|
|
4
|
-
import type { JobInput } from 'src/types/jobs.js';
|
|
4
|
+
import type { JobInput } from '#src/types/jobs.js';
|
|
5
5
|
|
|
6
6
|
export type IdDescription = z.infer<typeof IdDescriptionSchema>;
|
|
7
7
|
|
|
@@ -23,7 +23,7 @@ configs:
|
|
|
23
23
|
concurrency: 1
|
|
24
24
|
plugins:
|
|
25
25
|
- *docker-ecr-cache
|
|
26
|
-
- docker-compose#v5.
|
|
26
|
+
- docker-compose#v5.10.0:
|
|
27
27
|
dependencies: false
|
|
28
28
|
run: app
|
|
29
29
|
environment:
|
|
@@ -52,7 +52,7 @@ steps:
|
|
|
52
52
|
GET_NPM_TOKEN: please
|
|
53
53
|
plugins:
|
|
54
54
|
- *docker-ecr-cache
|
|
55
|
-
- docker-compose#v5.
|
|
55
|
+
- docker-compose#v5.10.0:
|
|
56
56
|
run: app
|
|
57
57
|
environment:
|
|
58
58
|
- GITHUB_API_TOKEN
|