skuba 4.4.1 → 5.0.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.
Files changed (330) hide show
  1. package/config/tsconfig.json +1 -0
  2. package/jest/moduleNameMapper.js +50 -78
  3. package/jest/moduleNameMapper.test.ts +4 -14
  4. package/jest/transform.js +10 -1
  5. package/jest/tsConfig.js +26 -0
  6. package/lib/api/buildkite/annotate.js +46 -33
  7. package/lib/api/buildkite/annotate.js.map +7 -1
  8. package/lib/api/buildkite/index.js +31 -7
  9. package/lib/api/buildkite/index.js.map +7 -1
  10. package/lib/api/buildkite/md.js +31 -8
  11. package/lib/api/buildkite/md.js.map +7 -1
  12. package/lib/api/git/commit.js +45 -17
  13. package/lib/api/git/commit.js.map +7 -1
  14. package/lib/api/git/commitAllChanges.js +57 -27
  15. package/lib/api/git/commitAllChanges.js.map +7 -1
  16. package/lib/api/git/currentBranch.js +50 -28
  17. package/lib/api/git/currentBranch.js.map +7 -1
  18. package/lib/api/git/getChangedFiles.js +49 -27
  19. package/lib/api/git/getChangedFiles.js.map +7 -1
  20. package/lib/api/git/index.js +54 -22
  21. package/lib/api/git/index.js.map +7 -1
  22. package/lib/api/git/log.js +63 -42
  23. package/lib/api/git/log.js.map +7 -1
  24. package/lib/api/git/pull.js +62 -31
  25. package/lib/api/git/pull.js.map +7 -1
  26. package/lib/api/git/push.js +63 -31
  27. package/lib/api/git/push.js.map +7 -1
  28. package/lib/api/git/remote.js +59 -56
  29. package/lib/api/git/remote.js.map +7 -1
  30. package/lib/api/git/reset.js +55 -27
  31. package/lib/api/git/reset.js.map +7 -1
  32. package/lib/api/git/statusMatrix.js +46 -13
  33. package/lib/api/git/statusMatrix.js.map +7 -1
  34. package/lib/api/github/checkRun.js +70 -79
  35. package/lib/api/github/checkRun.js.map +7 -1
  36. package/lib/api/github/environment.js +40 -33
  37. package/lib/api/github/environment.js.map +7 -1
  38. package/lib/api/github/index.js +47 -17
  39. package/lib/api/github/index.js.map +7 -1
  40. package/lib/api/github/issueComment.js +73 -81
  41. package/lib/api/github/issueComment.js.map +7 -1
  42. package/lib/api/github/pullRequest.js +60 -61
  43. package/lib/api/github/pullRequest.js.map +7 -1
  44. package/lib/api/github/push.js +138 -133
  45. package/lib/api/github/push.js.map +7 -1
  46. package/lib/api/jest/index.d.ts +2 -1
  47. package/lib/api/jest/index.js +35 -14
  48. package/lib/api/jest/index.js.map +7 -1
  49. package/lib/api/net/compose.js +45 -17
  50. package/lib/api/net/compose.js.map +7 -1
  51. package/lib/api/net/index.js +28 -5
  52. package/lib/api/net/index.js.map +7 -1
  53. package/lib/api/net/socket.js +58 -36
  54. package/lib/api/net/socket.js.map +7 -1
  55. package/lib/api/net/waitFor.js +38 -18
  56. package/lib/api/net/waitFor.js.map +7 -1
  57. package/lib/cli/adapter/eslint.js +95 -72
  58. package/lib/cli/adapter/eslint.js.map +7 -1
  59. package/lib/cli/adapter/prettier.js +135 -123
  60. package/lib/cli/adapter/prettier.js.map +7 -1
  61. package/lib/cli/build/args.d.ts +7 -0
  62. package/lib/cli/build/args.js +69 -0
  63. package/lib/cli/build/args.js.map +7 -0
  64. package/lib/cli/build/esbuild.d.ts +5 -0
  65. package/lib/cli/build/esbuild.js +128 -0
  66. package/lib/cli/build/esbuild.js.map +7 -0
  67. package/lib/cli/build/index.d.ts +1 -1
  68. package/lib/cli/build/index.js +68 -5
  69. package/lib/cli/build/index.js.map +7 -1
  70. package/lib/cli/build/tsc.d.ts +1 -1
  71. package/lib/cli/build/tsc.js +34 -23
  72. package/lib/cli/build/tsc.js.map +7 -1
  73. package/lib/cli/buildPackage.js +53 -23
  74. package/lib/cli/buildPackage.js.map +7 -1
  75. package/lib/cli/configure/addEmptyExports.d.ts +5 -0
  76. package/lib/cli/configure/addEmptyExports.js +67 -0
  77. package/lib/cli/configure/addEmptyExports.js.map +7 -0
  78. package/lib/cli/configure/analyseConfiguration.js +61 -31
  79. package/lib/cli/configure/analyseConfiguration.js.map +7 -1
  80. package/lib/cli/configure/analyseDependencies.js +122 -113
  81. package/lib/cli/configure/analyseDependencies.js.map +7 -1
  82. package/lib/cli/configure/analysis/diff.js +37 -11
  83. package/lib/cli/configure/analysis/diff.js.map +7 -1
  84. package/lib/cli/configure/analysis/files.js +49 -22
  85. package/lib/cli/configure/analysis/files.js.map +7 -1
  86. package/lib/cli/configure/analysis/git.js +46 -16
  87. package/lib/cli/configure/analysis/git.js.map +7 -1
  88. package/lib/cli/configure/analysis/package.js +99 -52
  89. package/lib/cli/configure/analysis/package.js.map +7 -1
  90. package/lib/cli/configure/analysis/project.js +90 -54
  91. package/lib/cli/configure/analysis/project.js.map +7 -1
  92. package/lib/cli/configure/dependencies/index.js +40 -13
  93. package/lib/cli/configure/dependencies/index.js.map +7 -1
  94. package/lib/cli/configure/dependencies/seekDatadogCustomMetrics.js +57 -32
  95. package/lib/cli/configure/dependencies/seekDatadogCustomMetrics.js.map +7 -1
  96. package/lib/cli/configure/dependencies/seekKoala.js +53 -31
  97. package/lib/cli/configure/dependencies/seekKoala.js.map +7 -1
  98. package/lib/cli/configure/dependencies/skuba.js +49 -27
  99. package/lib/cli/configure/dependencies/skuba.js.map +7 -1
  100. package/lib/cli/configure/dependencies/skubaDeps.js +49 -28
  101. package/lib/cli/configure/dependencies/skubaDeps.js.map +7 -1
  102. package/lib/cli/configure/dependencies/skubaDive.js +65 -38
  103. package/lib/cli/configure/dependencies/skubaDive.js.map +7 -1
  104. package/lib/cli/configure/ensureTemplateCompletion.js +69 -41
  105. package/lib/cli/configure/ensureTemplateCompletion.js.map +7 -1
  106. package/lib/cli/configure/getEntryPoint.js +62 -32
  107. package/lib/cli/configure/getEntryPoint.js.map +7 -1
  108. package/lib/cli/configure/getProjectType.js +50 -28
  109. package/lib/cli/configure/getProjectType.js.map +7 -1
  110. package/lib/cli/configure/index.js +134 -109
  111. package/lib/cli/configure/index.js.map +7 -1
  112. package/lib/cli/configure/modules/eslint.js +57 -26
  113. package/lib/cli/configure/modules/eslint.js.map +7 -1
  114. package/lib/cli/configure/modules/ignore.js +37 -14
  115. package/lib/cli/configure/modules/ignore.js.map +7 -1
  116. package/lib/cli/configure/modules/index.js +53 -28
  117. package/lib/cli/configure/modules/index.js.map +7 -1
  118. package/lib/cli/configure/modules/jest.js +82 -47
  119. package/lib/cli/configure/modules/jest.js.map +7 -1
  120. package/lib/cli/configure/modules/nodemon.js +29 -6
  121. package/lib/cli/configure/modules/nodemon.js.map +7 -1
  122. package/lib/cli/configure/modules/package.js +113 -92
  123. package/lib/cli/configure/modules/package.js.map +7 -1
  124. package/lib/cli/configure/modules/prettier.js +48 -19
  125. package/lib/cli/configure/modules/prettier.js.map +7 -1
  126. package/lib/cli/configure/modules/renovate.js +52 -39
  127. package/lib/cli/configure/modules/renovate.js.map +7 -1
  128. package/lib/cli/configure/modules/serverless.js +33 -15
  129. package/lib/cli/configure/modules/serverless.js.map +7 -1
  130. package/lib/cli/configure/modules/skubaDive.js +63 -37
  131. package/lib/cli/configure/modules/skubaDive.js.map +7 -1
  132. package/lib/cli/configure/modules/tsconfig.js +84 -63
  133. package/lib/cli/configure/modules/tsconfig.js.map +7 -1
  134. package/lib/cli/configure/modules/tslint.js +29 -6
  135. package/lib/cli/configure/modules/tslint.js.map +7 -1
  136. package/lib/cli/configure/processing/deleteFiles.js +30 -8
  137. package/lib/cli/configure/processing/deleteFiles.js.map +7 -1
  138. package/lib/cli/configure/processing/ignoreFile.js +65 -59
  139. package/lib/cli/configure/processing/ignoreFile.js.map +7 -1
  140. package/lib/cli/configure/processing/javascript.js +35 -15
  141. package/lib/cli/configure/processing/javascript.js.map +7 -1
  142. package/lib/cli/configure/processing/json.js +51 -20
  143. package/lib/cli/configure/processing/json.js.map +7 -1
  144. package/lib/cli/configure/processing/loadFiles.js +30 -8
  145. package/lib/cli/configure/processing/loadFiles.js.map +7 -1
  146. package/lib/cli/configure/processing/module.js +37 -14
  147. package/lib/cli/configure/processing/module.js.map +7 -1
  148. package/lib/cli/configure/processing/package.js +73 -43
  149. package/lib/cli/configure/processing/package.js.map +7 -1
  150. package/lib/cli/configure/processing/prettier.js +37 -11
  151. package/lib/cli/configure/processing/prettier.js.map +7 -1
  152. package/lib/cli/configure/processing/record.js +54 -31
  153. package/lib/cli/configure/processing/record.js.map +7 -1
  154. package/lib/cli/configure/processing/typescript.js +176 -158
  155. package/lib/cli/configure/processing/typescript.js.map +7 -1
  156. package/lib/cli/configure/refreshIgnoreFiles.js +64 -40
  157. package/lib/cli/configure/refreshIgnoreFiles.js.map +7 -1
  158. package/lib/cli/configure/types.js +16 -2
  159. package/lib/cli/configure/types.js.map +7 -1
  160. package/lib/cli/format.js +58 -31
  161. package/lib/cli/format.js.map +7 -1
  162. package/lib/cli/help.js +31 -8
  163. package/lib/cli/help.js.map +7 -1
  164. package/lib/cli/init/getConfig.d.ts +1 -1
  165. package/lib/cli/init/getConfig.js +238 -207
  166. package/lib/cli/init/getConfig.js.map +7 -1
  167. package/lib/cli/init/git.js +70 -63
  168. package/lib/cli/init/git.js.map +7 -1
  169. package/lib/cli/init/index.js +133 -100
  170. package/lib/cli/init/index.js.map +7 -1
  171. package/lib/cli/init/prompts.js +84 -54
  172. package/lib/cli/init/prompts.js.map +7 -1
  173. package/lib/cli/init/types.js +52 -52
  174. package/lib/cli/init/types.js.map +7 -1
  175. package/lib/cli/init/validation.js +34 -12
  176. package/lib/cli/init/validation.js.map +7 -1
  177. package/lib/cli/init/writePackageJson.js +51 -22
  178. package/lib/cli/init/writePackageJson.js.map +7 -1
  179. package/lib/cli/lint/annotate/buildkite/eslint.js +34 -28
  180. package/lib/cli/lint/annotate/buildkite/eslint.js.map +7 -1
  181. package/lib/cli/lint/annotate/buildkite/index.js +50 -44
  182. package/lib/cli/lint/annotate/buildkite/index.js.map +7 -1
  183. package/lib/cli/lint/annotate/buildkite/prettier.js +41 -35
  184. package/lib/cli/lint/annotate/buildkite/prettier.js.map +7 -1
  185. package/lib/cli/lint/annotate/buildkite/tsc.js +39 -39
  186. package/lib/cli/lint/annotate/buildkite/tsc.js.map +7 -1
  187. package/lib/cli/lint/annotate/github/eslint.js +40 -16
  188. package/lib/cli/lint/annotate/github/eslint.js.map +7 -1
  189. package/lib/cli/lint/annotate/github/index.js +55 -51
  190. package/lib/cli/lint/annotate/github/index.js.map +7 -1
  191. package/lib/cli/lint/annotate/github/prettier.js +36 -13
  192. package/lib/cli/lint/annotate/github/prettier.js.map +7 -1
  193. package/lib/cli/lint/annotate/github/tsc.js +52 -52
  194. package/lib/cli/lint/annotate/github/tsc.js.map +7 -1
  195. package/lib/cli/lint/annotate/index.d.ts +1 -1
  196. package/lib/cli/lint/annotate/index.js +33 -10
  197. package/lib/cli/lint/annotate/index.js.map +7 -1
  198. package/lib/cli/lint/autofix.js +122 -117
  199. package/lib/cli/lint/autofix.js.map +7 -1
  200. package/lib/cli/lint/eslint.js +48 -18
  201. package/lib/cli/lint/eslint.js.map +7 -1
  202. package/lib/cli/lint/external.js +102 -81
  203. package/lib/cli/lint/external.js.map +7 -1
  204. package/lib/cli/lint/index.js +42 -18
  205. package/lib/cli/lint/index.js.map +7 -1
  206. package/lib/cli/lint/internal.js +54 -21
  207. package/lib/cli/lint/internal.js.map +7 -1
  208. package/lib/cli/lint/prettier.js +48 -18
  209. package/lib/cli/lint/prettier.js.map +7 -1
  210. package/lib/cli/lint/tsc.js +56 -32
  211. package/lib/cli/lint/tsc.js.map +7 -1
  212. package/lib/cli/lint/types.js +16 -2
  213. package/lib/cli/lint/types.js.map +7 -1
  214. package/lib/cli/node.js +65 -58
  215. package/lib/cli/node.js.map +7 -1
  216. package/lib/cli/release.js +29 -6
  217. package/lib/cli/release.js.map +7 -1
  218. package/lib/cli/start.js +61 -24
  219. package/lib/cli/start.js.map +7 -1
  220. package/lib/cli/test/index.js +35 -11
  221. package/lib/cli/test/index.js.map +7 -1
  222. package/lib/cli/test/reporters/github/annotations.js +89 -92
  223. package/lib/cli/test/reporters/github/annotations.js.map +7 -1
  224. package/lib/cli/test/reporters/github/index.js +68 -68
  225. package/lib/cli/test/reporters/github/index.js.map +7 -1
  226. package/lib/cli/version.js +31 -8
  227. package/lib/cli/version.js.map +7 -1
  228. package/lib/enquirer.d.js +2 -0
  229. package/lib/enquirer.d.js.map +7 -0
  230. package/lib/index.d.ts +6 -0
  231. package/lib/index.js +45 -41
  232. package/lib/index.js.map +7 -1
  233. package/lib/skuba.js +45 -38
  234. package/lib/skuba.js.map +7 -1
  235. package/lib/utils/args.js +97 -96
  236. package/lib/utils/args.js.map +7 -1
  237. package/lib/utils/command.js +64 -33
  238. package/lib/utils/command.js.map +7 -1
  239. package/lib/utils/copy.js +88 -51
  240. package/lib/utils/copy.js.map +7 -1
  241. package/lib/utils/dir.js +79 -67
  242. package/lib/utils/dir.js.map +7 -1
  243. package/lib/utils/env.js +27 -7
  244. package/lib/utils/env.js.map +7 -1
  245. package/lib/utils/error.js +58 -56
  246. package/lib/utils/error.js.map +7 -1
  247. package/lib/utils/exec.js +139 -110
  248. package/lib/utils/exec.js.map +7 -1
  249. package/lib/utils/help.js +31 -8
  250. package/lib/utils/help.js.map +7 -1
  251. package/lib/utils/logging.js +52 -24
  252. package/lib/utils/logging.js.map +7 -1
  253. package/lib/utils/logo.js +65 -27
  254. package/lib/utils/logo.js.map +7 -1
  255. package/lib/utils/manifest.d.ts +1 -0
  256. package/lib/utils/manifest.js +65 -51
  257. package/lib/utils/manifest.js.map +7 -1
  258. package/lib/utils/port.js +38 -17
  259. package/lib/utils/port.js.map +7 -1
  260. package/lib/utils/template.js +106 -87
  261. package/lib/utils/template.js.map +7 -1
  262. package/lib/utils/validation.js +43 -18
  263. package/lib/utils/validation.js.map +7 -1
  264. package/lib/utils/version.js +72 -82
  265. package/lib/utils/version.js.map +7 -1
  266. package/lib/utils/wait.js +52 -25
  267. package/lib/utils/wait.js.map +7 -1
  268. package/lib/utils/worker.js +59 -44
  269. package/lib/utils/worker.js.map +7 -1
  270. package/lib/wrapper/function-arguments.d.js +2 -0
  271. package/lib/wrapper/function-arguments.d.js.map +7 -0
  272. package/lib/wrapper/functionHandler.js +56 -29
  273. package/lib/wrapper/functionHandler.js.map +7 -1
  274. package/lib/wrapper/http.js +66 -56
  275. package/lib/wrapper/http.js.map +7 -1
  276. package/lib/wrapper/index.js +9 -21
  277. package/lib/wrapper/index.js.map +7 -1
  278. package/lib/wrapper/main.js +39 -20
  279. package/lib/wrapper/main.js.map +7 -1
  280. package/lib/wrapper/requestListener.js +50 -35
  281. package/lib/wrapper/requestListener.js.map +7 -1
  282. package/package.json +85 -79
  283. package/template/base/jest.config.ts +0 -6
  284. package/template/base/jest.setup.ts +2 -0
  285. package/template/base/tsconfig.json +2 -2
  286. package/template/express-rest-api/.buildkite/pipeline.yml +1 -1
  287. package/template/express-rest-api/.nvmrc +1 -1
  288. package/template/express-rest-api/Dockerfile +1 -1
  289. package/template/express-rest-api/Dockerfile.dev-deps +1 -1
  290. package/template/express-rest-api/package.json +14 -14
  291. package/template/greeter/.buildkite/pipeline.yml +1 -1
  292. package/template/greeter/.nvmrc +1 -1
  293. package/template/greeter/Dockerfile +1 -1
  294. package/template/greeter/package.json +11 -11
  295. package/template/greeter/src/app.test.ts +3 -1
  296. package/template/koa-rest-api/.buildkite/pipeline.yml +1 -1
  297. package/template/koa-rest-api/.nvmrc +1 -1
  298. package/template/koa-rest-api/Dockerfile +1 -1
  299. package/template/koa-rest-api/Dockerfile.dev-deps +1 -1
  300. package/template/koa-rest-api/package.json +20 -21
  301. package/template/koa-rest-api/src/api/jobs/postJob.test.ts +3 -7
  302. package/template/koa-rest-api/src/api/jobs/postJob.ts +2 -2
  303. package/template/koa-rest-api/src/framework/validation.test.ts +17 -15
  304. package/template/koa-rest-api/src/framework/validation.ts +66 -12
  305. package/template/koa-rest-api/src/testing/types.ts +5 -10
  306. package/template/koa-rest-api/src/types/jobs.ts +5 -10
  307. package/template/lambda-sqs-worker/.buildkite/pipeline.yml +4 -4
  308. package/template/lambda-sqs-worker/Dockerfile +1 -1
  309. package/template/lambda-sqs-worker/package.json +16 -20
  310. package/template/lambda-sqs-worker/src/app.ts +2 -2
  311. package/template/lambda-sqs-worker/src/framework/validation.test.ts +37 -17
  312. package/template/lambda-sqs-worker/src/framework/validation.ts +10 -2
  313. package/template/lambda-sqs-worker/src/services/jobScorer.ts +2 -2
  314. package/template/lambda-sqs-worker/src/testing/types.ts +5 -10
  315. package/template/lambda-sqs-worker/src/types/jobScorer.ts +9 -16
  316. package/template/lambda-sqs-worker/src/types/pipelineEvents.ts +13 -20
  317. package/template/lambda-sqs-worker/tsconfig.json +13 -0
  318. package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +4 -4
  319. package/template/lambda-sqs-worker-cdk/Dockerfile +1 -1
  320. package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +6 -0
  321. package/template/lambda-sqs-worker-cdk/infra/appStack.ts +3 -3
  322. package/template/lambda-sqs-worker-cdk/infra/index.ts +2 -2
  323. package/template/lambda-sqs-worker-cdk/package.json +14 -14
  324. package/template/lambda-sqs-worker-cdk/shared/context-types.ts +16 -25
  325. package/template/lambda-sqs-worker-cdk/tsconfig.json +13 -0
  326. package/template/oss-npm-package/.nvmrc +1 -1
  327. package/template/oss-npm-package/_package.json +1 -1
  328. package/template/private-npm-package/.nvmrc +1 -1
  329. package/template/private-npm-package/_package.json +1 -1
  330. package/jest/resolver.js +0 -24
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "baseUrl": ".",
4
- "lib": ["ES2020"],
4
+ "lib": ["ES2022"],
5
5
  "outDir": "lib",
6
6
  "paths": {
7
7
  "src": ["src"]
8
8
  },
9
- "target": "ES2020"
9
+ "target": "ES2022"
10
10
  },
11
11
  "exclude": ["lib*/**/*"],
12
12
  "extends": "skuba/config/tsconfig.json"
@@ -51,7 +51,7 @@ steps:
51
51
  - *aws-sm
52
52
  - *private-npm
53
53
  - *docker-ecr-cache
54
- - docker-compose#v3.10.0:
54
+ - docker-compose#v4.5.0:
55
55
  run: app
56
56
  timeout_in_minutes: 10
57
57
 
@@ -1 +1 @@
1
- 16
1
+ 18
@@ -17,7 +17,7 @@ RUN yarn build
17
17
 
18
18
  ###
19
19
 
20
- FROM --platform=arm64 gcr.io/distroless/nodejs:16 AS runtime
20
+ FROM --platform=${BUILDPLATFORM:-arm64} gcr.io/distroless/nodejs:18 AS runtime
21
21
 
22
22
  WORKDIR /workdir
23
23
 
@@ -1,6 +1,6 @@
1
1
  # syntax=docker/dockerfile:1.2
2
2
 
3
- FROM --platform=arm64 node:16-alpine AS dev-deps
3
+ FROM --platform=${BUILDPLATFORM:-arm64} node:18-alpine AS dev-deps
4
4
 
5
5
  WORKDIR /workdir
6
6
 
@@ -1,4 +1,16 @@
1
1
  {
2
+ "private": true,
3
+ "license": "UNLICENSED",
4
+ "scripts": {
5
+ "build": "skuba build",
6
+ "format": "skuba format",
7
+ "lint": "skuba lint",
8
+ "start": "skuba start --port <%- port %>",
9
+ "start:debug": "yarn start --inspect-brk",
10
+ "test": "skuba test",
11
+ "test:ci": "skuba test --coverage",
12
+ "test:watch": "skuba test --watch"
13
+ },
2
14
  "dependencies": {
3
15
  "@seek/logger": "^5.0.1",
4
16
  "express": "^4.17.1",
@@ -6,25 +18,13 @@
6
18
  },
7
19
  "devDependencies": {
8
20
  "@types/express": "^4.17.13",
9
- "@types/node": "^16.0.0",
21
+ "@types/node": "^18.11.5",
10
22
  "@types/supertest": "^2.0.11",
11
23
  "pino-pretty": "^9.0.0",
12
24
  "skuba": "*",
13
25
  "supertest": "^6.1.6"
14
26
  },
15
27
  "engines": {
16
- "node": ">=16"
17
- },
18
- "license": "UNLICENSED",
19
- "private": true,
20
- "scripts": {
21
- "build": "skuba build",
22
- "format": "skuba format",
23
- "lint": "skuba lint",
24
- "start": "skuba start --port <%- port %>",
25
- "start:debug": "yarn start --inspect-brk",
26
- "test": "skuba test",
27
- "test:ci": "skuba test --coverage",
28
- "test:watch": "skuba test --watch"
28
+ "node": ">=18"
29
29
  }
30
30
  }
@@ -32,6 +32,6 @@ steps:
32
32
  - *aws-sm
33
33
  - *private-npm
34
34
  - *docker-ecr-cache
35
- - docker-compose#v3.10.0:
35
+ - docker-compose#v4.5.0:
36
36
  run: app
37
37
  timeout_in_minutes: 10
@@ -1 +1 @@
1
- 16
1
+ 18
@@ -1,6 +1,6 @@
1
1
  # syntax=docker/dockerfile:1.2
2
2
 
3
- FROM --platform=arm64 node:16-alpine AS dev-deps
3
+ FROM --platform=${BUILDPLATFORM:-arm64} node:18-alpine AS dev-deps
4
4
 
5
5
  WORKDIR /workdir
6
6
 
@@ -1,16 +1,6 @@
1
1
  {
2
- "dependencies": {
3
- "skuba-dive": "^2.0.0"
4
- },
5
- "devDependencies": {
6
- "@types/node": "^16.0.0",
7
- "skuba": "*"
8
- },
9
- "engines": {
10
- "node": ">=16"
11
- },
12
- "license": "UNLICENSED",
13
2
  "private": true,
3
+ "license": "UNLICENSED",
14
4
  "scripts": {
15
5
  "build": "skuba build",
16
6
  "format": "skuba format",
@@ -20,5 +10,15 @@
20
10
  "test": "skuba test",
21
11
  "test:ci": "skuba test --coverage",
22
12
  "test:watch": "skuba test --watch"
13
+ },
14
+ "dependencies": {
15
+ "skuba-dive": "^2.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^18.11.5",
19
+ "skuba": "*"
20
+ },
21
+ "engines": {
22
+ "node": ">=18"
23
23
  }
24
24
  }
@@ -1,3 +1,5 @@
1
+ import * as app from './app';
2
+
1
3
  describe('app', () => {
2
- it('is importable', () => expect(import('./app')).resolves.toEqual({}));
4
+ it('is importable', () => expect(app).toEqual({}));
3
5
  });
@@ -51,7 +51,7 @@ steps:
51
51
  - *aws-sm
52
52
  - *private-npm
53
53
  - *docker-ecr-cache
54
- - docker-compose#v3.10.0:
54
+ - docker-compose#v4.5.0:
55
55
  run: app
56
56
  timeout_in_minutes: 10
57
57
 
@@ -1 +1 @@
1
- 16
1
+ 18
@@ -17,7 +17,7 @@ RUN yarn build
17
17
 
18
18
  ###
19
19
 
20
- FROM --platform=arm64 gcr.io/distroless/nodejs:16 AS runtime
20
+ FROM --platform=${BUILDPLATFORM:-arm64} gcr.io/distroless/nodejs:18 AS runtime
21
21
 
22
22
  WORKDIR /workdir
23
23
 
@@ -1,6 +1,6 @@
1
1
  # syntax=docker/dockerfile:1.2
2
2
 
3
- FROM --platform=arm64 node:16-alpine AS dev-deps
3
+ FROM --platform=${BUILDPLATFORM:-arm64} node:18-alpine AS dev-deps
4
4
 
5
5
  WORKDIR /workdir
6
6
 
@@ -1,29 +1,40 @@
1
1
  {
2
+ "private": true,
3
+ "license": "UNLICENSED",
4
+ "scripts": {
5
+ "build": "skuba build",
6
+ "format": "skuba format",
7
+ "lint": "skuba lint",
8
+ "start": "skuba start --port <%- port %>",
9
+ "start:debug": "yarn start --inspect-brk",
10
+ "test": "skuba test",
11
+ "test:ci": "skuba test --coverage",
12
+ "test:watch": "skuba test --watch"
13
+ },
2
14
  "dependencies": {
3
15
  "@koa/router": "^12.0.0",
4
16
  "@opentelemetry/api": "^1.1.0",
5
17
  "@opentelemetry/exporter-collector-grpc": "^0.25.0",
6
- "@opentelemetry/instrumentation-aws-sdk": "^0.9.0",
7
- "@opentelemetry/instrumentation-http": "^0.32.0",
8
- "@opentelemetry/sdk-node": "^0.32.0",
18
+ "@opentelemetry/instrumentation-aws-sdk": "^0.32.0",
19
+ "@opentelemetry/instrumentation-http": "^0.33.0",
20
+ "@opentelemetry/sdk-node": "^0.33.0",
9
21
  "@seek/logger": "^5.0.1",
10
22
  "aws-sdk": "^2.1039.0",
11
23
  "hot-shots": "^9.0.0",
12
24
  "koa": "^2.13.4",
13
25
  "koa-bodyparser": "^4.3.0",
14
26
  "koa-compose": "^4.2.0",
15
- "runtypes": "^6.4.1",
16
- "runtypes-filter": "^0.6.0",
17
27
  "seek-datadog-custom-metrics": "^4.0.0",
18
28
  "seek-koala": "^6.0.0",
19
- "skuba-dive": "^2.0.0"
29
+ "skuba-dive": "^2.0.0",
30
+ "zod": "^3.19.1"
20
31
  },
21
32
  "devDependencies": {
22
33
  "@types/chance": "^1.1.3",
23
34
  "@types/koa": "^2.13.4",
24
35
  "@types/koa-bodyparser": "^5.0.2",
25
- "@types/koa__router": "^8.0.8",
26
- "@types/node": "^16.0.0",
36
+ "@types/koa__router": "^12.0.0",
37
+ "@types/node": "^18.11.5",
27
38
  "@types/supertest": "^2.0.11",
28
39
  "chance": "^1.1.8",
29
40
  "pino-pretty": "^9.0.0",
@@ -31,18 +42,6 @@
31
42
  "supertest": "^6.1.6"
32
43
  },
33
44
  "engines": {
34
- "node": ">=16"
35
- },
36
- "license": "UNLICENSED",
37
- "private": true,
38
- "scripts": {
39
- "build": "skuba build",
40
- "format": "skuba format",
41
- "lint": "skuba lint",
42
- "start": "skuba start --port <%- port %>",
43
- "start:debug": "yarn start --inspect-brk",
44
- "test": "skuba test",
45
- "test:ci": "skuba test --coverage",
46
- "test:watch": "skuba test --watch"
45
+ "node": ">=18"
47
46
  }
48
47
  }
@@ -26,13 +26,9 @@ describe('postJobHandler', () => {
26
26
  .send(jobInput)
27
27
  .expect(422)
28
28
  .expect(({ text }) =>
29
- expect(text).toMatchInlineSnapshot(`
30
- "Validation failed:
31
- {
32
- "hirer": "Expected { id: string; }, but was missing"
33
- }.
34
- Object should match { hirer: { id: string; }; }"
35
- `),
29
+ expect(text).toMatchInlineSnapshot(
30
+ `"{"message":"Input validation failed","invalidFields":{"/hirer":"Required"}}"`,
31
+ ),
36
32
  );
37
33
  });
38
34
  });
@@ -2,11 +2,11 @@ import { logger } from 'src/framework/logging';
2
2
  import { metricsClient } from 'src/framework/metrics';
3
3
  import { validateRequestBody } from 'src/framework/validation';
4
4
  import * as storage from 'src/storage/jobs';
5
- import { filterJobInput } from 'src/types/jobs';
5
+ import { JobInputSchema } from 'src/types/jobs';
6
6
  import { Middleware } from 'src/types/koa';
7
7
 
8
8
  export const postJobHandler: Middleware = async (ctx) => {
9
- const jobInput = validateRequestBody(ctx, filterJobInput);
9
+ const jobInput = validateRequestBody(ctx, JobInputSchema);
10
10
 
11
11
  const job = await storage.createJob(jobInput);
12
12
 
@@ -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
- filter: filterIdDescription,
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(({ text }) =>
45
- expect(text).toMatchInlineSnapshot(`
46
- "Validation failed:
44
+ .expect(({ body }) =>
45
+ expect(body).toMatchInlineSnapshot(`
47
46
  {
48
- "id": "Expected string, but was null"
49
- }.
50
- Object should match { id: string; description: string; }"
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(({ text }) =>
61
- expect(text).toMatchInlineSnapshot(`
62
- "Validation failed:
61
+ .expect(({ body }) =>
62
+ expect(body).toMatchInlineSnapshot(`
63
63
  {
64
- "id": "Expected string, but was missing",
65
- "description": "Expected string, but was missing"
66
- }.
67
- Object should match { id: string; description: string; }"
64
+ "invalidFields": {
65
+ "/description": "Required",
66
+ "/id": "Required",
67
+ },
68
+ "message": "Input validation failed",
69
+ }
68
70
  `),
69
71
  ));
70
72
  });
@@ -1,23 +1,77 @@
1
+ import { ErrorMiddleware } from 'seek-koala';
2
+ import { z } from 'zod';
3
+
1
4
  import { Context } from 'src/types/koa';
2
5
 
3
- export const validate = <T>({
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
+
39
+ export const validate = <
40
+ Output,
41
+ Def extends z.ZodTypeDef = z.ZodTypeDef,
42
+ Input = Output,
43
+ >({
4
44
  ctx,
5
45
  input,
6
- filter,
46
+ schema,
7
47
  }: {
8
48
  ctx: Context;
9
49
  input: unknown;
10
- filter: (data: unknown) => T;
11
- }) => {
12
- try {
13
- return filter(input);
14
- } catch (err) {
15
- // TODO: consider providing structured error messages for your consumers.
16
- return ctx.throw(422, err instanceof Error ? err.message : String(err));
50
+ schema: z.ZodSchema<Output, Def, Input>;
51
+ }): Output => {
52
+ const parseResult = schema.safeParse(input);
53
+ if (parseResult.success === false) {
54
+ return ctx.throw(
55
+ 422,
56
+ new ErrorMiddleware.JsonResponse('Input validation failed', {
57
+ message: 'Input validation failed',
58
+ invalidFields: parseInvalidFieldsFromError(parseResult.error),
59
+ }),
60
+ );
17
61
  }
62
+ return parseResult.data;
18
63
  };
19
64
 
20
- export const validateRequestBody = <T>(
65
+ export const validateRequestBody = <
66
+ Output,
67
+ Def extends z.ZodTypeDef = z.ZodTypeDef,
68
+ Input = Output,
69
+ >(
21
70
  ctx: Context,
22
- filter: (input: unknown) => T,
23
- ): T => validate({ ctx, input: ctx.request.body as unknown, filter });
71
+ schema: z.ZodSchema<Output, Def, Input>,
72
+ ): Output =>
73
+ validate<Output, Def, Input>({
74
+ ctx,
75
+ input: ctx.request.body as unknown,
76
+ schema,
77
+ });
@@ -1,20 +1,15 @@
1
- /* eslint-disable new-cap */
2
-
3
1
  import { Chance } from 'chance';
4
- import * as t from 'runtypes';
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 = t.Static<typeof IdDescription>;
6
+ export type IdDescription = z.infer<typeof IdDescriptionSchema>;
10
7
 
11
- const IdDescription = t.Record({
12
- id: t.String,
13
- description: t.String,
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
- /* eslint-disable new-cap */
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 = t.Static<typeof JobInput>;
11
+ export type JobInput = z.infer<typeof JobInputSchema>;
15
12
 
16
- const JobInput = t.Record({
17
- hirer: t.Record({
18
- id: t.String,
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.5.0:
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#v3.10.0:
35
+ - docker-compose#v4.5.0:
36
36
  dependencies: false
37
37
  run: app
38
38
  retry:
@@ -60,13 +60,13 @@ steps:
60
60
  - *aws-sm
61
61
  - *private-npm
62
62
  - *docker-ecr-cache
63
- - docker-compose#v3.10.0:
63
+ - docker-compose#v4.5.0:
64
64
  run: app
65
65
  timeout_in_minutes: 10
66
66
 
67
67
  - agents:
68
68
  queue: <%- devBuildkiteQueueName %>
69
- branches: '!renovate/*'
69
+ branches: '!renovate--*'
70
70
  label: 🧖‍♀️ Warm Dev
71
71
  command: ':'
72
72
  plugins:
@@ -1,6 +1,6 @@
1
1
  # syntax=docker/dockerfile:1.2
2
2
 
3
- FROM --platform=arm64 node:16-alpine AS dev-deps
3
+ FROM --platform=${BUILDPLATFORM:-arm64} node:16-alpine AS dev-deps
4
4
 
5
5
  WORKDIR /workdir
6
6
 
@@ -1,16 +1,29 @@
1
1
  {
2
+ "private": true,
3
+ "license": "UNLICENSED",
4
+ "scripts": {
5
+ "build": "skuba build",
6
+ "deploy": "serverless deploy --force --verbose",
7
+ "format": "skuba format",
8
+ "lint": "skuba lint",
9
+ "smoke": "serverless invoke --data '{}' --function Worker",
10
+ "start": "skuba start --port <%- port %>",
11
+ "start:debug": "yarn start --inspect-brk",
12
+ "test": "skuba test",
13
+ "test:ci": "skuba test --coverage",
14
+ "test:watch": "skuba test --watch"
15
+ },
2
16
  "dependencies": {
3
17
  "@seek/logger": "^5.0.1",
4
18
  "aws-sdk": "^2.1011.0",
5
19
  "datadog-lambda-js": "^6.83.0",
6
20
  "skuba-dive": "^2.0.0",
7
- "runtypes": "^6.4.1",
8
- "runtypes-filter": "^0.6.0"
21
+ "zod": "^3.19.1"
9
22
  },
10
23
  "devDependencies": {
11
24
  "@types/aws-lambda": "^8.10.84",
12
25
  "@types/chance": "^1.1.3",
13
- "@types/node": "^16.0.0",
26
+ "@types/node": "16.11.64",
14
27
  "chance": "^1.1.8",
15
28
  "pino-pretty": "^9.0.0",
16
29
  "serverless": "^3.17.0",
@@ -21,22 +34,5 @@
21
34
  },
22
35
  "engines": {
23
36
  "node": ">=16"
24
- },
25
- "license": "UNLICENSED",
26
- "private": true,
27
- "resolutions": {
28
- "@types/responselike": "1.0.0"
29
- },
30
- "scripts": {
31
- "build": "skuba build",
32
- "deploy": "serverless deploy --force --verbose",
33
- "format": "skuba format",
34
- "lint": "skuba lint",
35
- "smoke": "serverless invoke --data '{}' --function Worker",
36
- "start": "skuba start --port <%- port %>",
37
- "start:debug": "yarn start --inspect-brk",
38
- "test": "skuba test",
39
- "test:ci": "skuba test --coverage",
40
- "test:watch": "skuba test --watch"
41
37
  }
42
38
  }
@@ -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 { filterJobPublishedEvent } from 'src/types/pipelineEvents';
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, filterJobPublishedEvent);
43
+ const publishedJob = validateJson(record.body, JobPublishedEventSchema);
44
44
 
45
45
  const scoredJob = await scoreJobPublishedEvent(publishedJob);
46
46