skuba 7.2.0 โ†’ 7.3.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 (63) hide show
  1. package/config/prettier.d.ts +1 -0
  2. package/config/prettier.js +1 -0
  3. package/lib/api/git/commitAllChanges.js +16 -2
  4. package/lib/api/git/commitAllChanges.js.map +3 -3
  5. package/lib/api/github/push.d.ts +1 -1
  6. package/lib/api/github/push.js +13 -4
  7. package/lib/api/github/push.js.map +3 -3
  8. package/lib/api/jest/index.d.ts +2 -2
  9. package/lib/api/jest/index.js +19 -1
  10. package/lib/api/jest/index.js.map +2 -2
  11. package/lib/api/net/compose.js +2 -1
  12. package/lib/api/net/compose.js.map +2 -2
  13. package/lib/cli/configure/getProjectType.d.ts +1 -1
  14. package/lib/cli/configure/getProjectType.js +5 -2
  15. package/lib/cli/configure/getProjectType.js.map +2 -2
  16. package/lib/cli/configure/index.js +0 -4
  17. package/lib/cli/configure/index.js.map +2 -2
  18. package/lib/cli/configure/patchRenovateConfig.js +13 -11
  19. package/lib/cli/configure/patchRenovateConfig.js.map +2 -2
  20. package/lib/cli/configure/processing/package.d.ts +1 -1
  21. package/lib/cli/configure/processing/package.js +8 -10
  22. package/lib/cli/configure/processing/package.js.map +2 -2
  23. package/lib/cli/init/getConfig.d.ts +3 -3
  24. package/lib/cli/init/getConfig.js +8 -8
  25. package/lib/cli/init/getConfig.js.map +2 -2
  26. package/lib/cli/init/index.js +0 -1
  27. package/lib/cli/init/index.js.map +2 -2
  28. package/lib/cli/init/types.d.ts +99 -27
  29. package/lib/cli/init/types.js +26 -35
  30. package/lib/cli/init/types.js.map +2 -2
  31. package/lib/cli/lint/autofix.js +1 -1
  32. package/lib/cli/lint/autofix.js.map +2 -2
  33. package/lib/utils/error.d.ts +30 -10
  34. package/lib/utils/error.js +10 -20
  35. package/lib/utils/error.js.map +2 -2
  36. package/lib/utils/exec.js +2 -2
  37. package/lib/utils/exec.js.map +2 -2
  38. package/lib/utils/manifest.d.ts +3 -3
  39. package/lib/utils/manifest.js +9 -9
  40. package/lib/utils/manifest.js.map +2 -2
  41. package/lib/utils/template.d.ts +43 -13
  42. package/lib/utils/template.js +15 -15
  43. package/lib/utils/template.js.map +2 -2
  44. package/package.json +24 -24
  45. package/template/express-rest-api/.buildkite/pipeline.yml +7 -4
  46. package/template/express-rest-api/Dockerfile.dev-deps +1 -1
  47. package/template/express-rest-api/README.md +6 -6
  48. package/template/greeter/.buildkite/pipeline.yml +4 -3
  49. package/template/greeter/Dockerfile +1 -1
  50. package/template/greeter/README.md +3 -3
  51. package/template/koa-rest-api/.buildkite/pipeline.yml +7 -4
  52. package/template/koa-rest-api/Dockerfile.dev-deps +1 -1
  53. package/template/koa-rest-api/README.md +6 -6
  54. package/template/koa-rest-api/package.json +3 -3
  55. package/template/koa-rest-api/src/app.test.ts +8 -4
  56. package/template/lambda-sqs-worker/.buildkite/pipeline.yml +9 -6
  57. package/template/lambda-sqs-worker/Dockerfile +1 -1
  58. package/template/lambda-sqs-worker/README.md +6 -6
  59. package/template/lambda-sqs-worker/src/framework/validation.test.ts +1 -1
  60. package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +9 -6
  61. package/template/lambda-sqs-worker-cdk/Dockerfile +1 -1
  62. package/template/oss-npm-package/README.md +1 -1
  63. package/template/private-npm-package/README.md +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/exec.ts"],
4
- "sourcesContent": ["import { cpus } from 'os';\nimport stream from 'stream';\nimport util from 'util';\n\nimport type { Color } from 'chalk';\nimport concurrently from 'concurrently';\nimport execa, { type ExecaChildProcess } from 'execa';\nimport npmRunPath from 'npm-run-path';\nimport npmWhich from 'npm-which';\n\nimport { ConcurrentlyErrors, isErrorWithCode } from './error';\nimport { log } from './logging';\n\nclass YarnSpamFilter extends stream.Transform {\n silenced = false;\n\n _transform(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: stream.TransformCallback,\n ) {\n const str = Buffer.from(chunk).toString();\n\n // Yarn spews the entire installed dependency tree after this message\n if (str.startsWith('info Direct dependencies')) {\n this.silenced = true;\n }\n\n if (\n !this.silenced &&\n // This isn't very useful given the command generates a lockfile\n !str.startsWith('info No lockfile found')\n ) {\n this.push(chunk);\n }\n\n callback();\n }\n}\n\nclass YarnWarningFilter extends stream.Transform {\n _transform(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: stream.TransformCallback,\n ) {\n const str = Buffer.from(chunk).toString();\n\n // Filter out annoying deprecation warnings that users can do little about\n if (!str.startsWith('warning skuba >')) {\n this.push(chunk);\n }\n\n callback();\n }\n}\n\nexport type Exec = (\n command: string,\n ...args: string[]\n) => ExecaChildProcess<string>;\n\ninterface ExecConcurrentlyCommand {\n command: string;\n name: string;\n prefixColor?: typeof Color;\n}\n\ninterface ExecConcurrentlyOptions {\n /**\n * The maximum number of processes that can execute concurrently.\n *\n * Defaults to the CPU core count.\n */\n maxProcesses?: number;\n\n /**\n * A set length to pad names to.\n *\n * Defaults to the length of the longest command name.\n */\n nameLength?: number;\n\n /**\n * The stream that logging output will be written to.\n *\n * Defaults to `process.stdout`.\n */\n outputStream?: stream.Writable;\n}\n\ntype ExecOptions = execa.Options & { streamStdio?: true | 'yarn' };\n\nconst envWithPath = {\n PATH: npmRunPath({ cwd: __dirname }),\n};\n\nconst runCommand = (command: string, args: string[], opts?: ExecOptions) => {\n const subprocess = execa(command, args, {\n localDir: __dirname,\n preferLocal: true,\n stdio: 'inherit',\n ...opts,\n });\n\n switch (opts?.streamStdio) {\n case 'yarn':\n const stderrFilter = new YarnWarningFilter();\n const stdoutFilter = new YarnSpamFilter();\n\n subprocess.stderr?.pipe(stderrFilter).pipe(process.stderr);\n subprocess.stdout?.pipe(stdoutFilter).pipe(process.stdout);\n\n break;\n\n case true:\n subprocess.stderr?.pipe(process.stderr);\n subprocess.stdout?.pipe(process.stdout);\n\n break;\n }\n\n return subprocess;\n};\n\nconst whichCallback = npmWhich(__dirname);\n\nconst which = util.promisify<string, string>(whichCallback);\n\nexport const createExec =\n (opts: ExecOptions): Exec =>\n (command, ...args) =>\n runCommand(command, args, opts);\n\nexport const exec: Exec = (command, ...args) => runCommand(command, args);\n\nexport const execConcurrently = async (\n commands: ExecConcurrentlyCommand[],\n { maxProcesses, nameLength, outputStream }: ExecConcurrentlyOptions = {},\n) => {\n const maxNameLength =\n nameLength ??\n commands.reduce(\n (length, command) => Math.max(length, command.name.length),\n 0,\n );\n\n try {\n await concurrently(\n commands.map(({ command, name, prefixColor }) => ({\n command,\n env: envWithPath,\n name: name.padEnd(maxNameLength),\n prefixColor,\n })),\n {\n maxProcesses: maxProcesses ?? cpus().length,\n\n outputStream,\n\n // Use a minimalist logging prefix.\n prefix: '{name} \u2502',\n },\n ).result;\n } catch (err) {\n const result = ConcurrentlyErrors.validate(err);\n\n if (!result.success) {\n throw err;\n }\n\n const failed = result.value\n .filter(({ exitCode }) => exitCode !== 0)\n .sort(({ index: indexA }, { index: indexB }) => indexA - indexB)\n .map((subprocess) => subprocess.command.name);\n\n throw Error(\n `${failed.join(', ')} subprocess${\n failed.length === 1 ? '' : 'es'\n } failed.`,\n );\n }\n};\n\nexport const ensureCommands = async (...names: string[]) => {\n let success = true;\n\n await Promise.all(\n names.map(async (name) => {\n const result = await hasCommand(name);\n\n if (!result) {\n success = false;\n\n log.err(log.bold(name), 'needs to be installed.');\n }\n }),\n );\n\n if (!success) {\n process.exit(1);\n }\n};\n\nexport const hasCommand = async (name: string) => {\n try {\n await which(name);\n\n return true;\n } catch (err) {\n if (isErrorWithCode(err, 'ENOENT')) {\n return false;\n }\n\n throw err;\n }\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { cpus } from 'os';\nimport stream from 'stream';\nimport util from 'util';\n\nimport type { Color } from 'chalk';\nimport concurrently from 'concurrently';\nimport execa, { type ExecaChildProcess } from 'execa';\nimport npmRunPath from 'npm-run-path';\nimport npmWhich from 'npm-which';\n\nimport { concurrentlyErrorsSchema, isErrorWithCode } from './error';\nimport { log } from './logging';\n\nclass YarnSpamFilter extends stream.Transform {\n silenced = false;\n\n _transform(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: stream.TransformCallback,\n ) {\n const str = Buffer.from(chunk).toString();\n\n // Yarn spews the entire installed dependency tree after this message\n if (str.startsWith('info Direct dependencies')) {\n this.silenced = true;\n }\n\n if (\n !this.silenced &&\n // This isn't very useful given the command generates a lockfile\n !str.startsWith('info No lockfile found')\n ) {\n this.push(chunk);\n }\n\n callback();\n }\n}\n\nclass YarnWarningFilter extends stream.Transform {\n _transform(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: stream.TransformCallback,\n ) {\n const str = Buffer.from(chunk).toString();\n\n // Filter out annoying deprecation warnings that users can do little about\n if (!str.startsWith('warning skuba >')) {\n this.push(chunk);\n }\n\n callback();\n }\n}\n\nexport type Exec = (\n command: string,\n ...args: string[]\n) => ExecaChildProcess<string>;\n\ninterface ExecConcurrentlyCommand {\n command: string;\n name: string;\n prefixColor?: typeof Color;\n}\n\ninterface ExecConcurrentlyOptions {\n /**\n * The maximum number of processes that can execute concurrently.\n *\n * Defaults to the CPU core count.\n */\n maxProcesses?: number;\n\n /**\n * A set length to pad names to.\n *\n * Defaults to the length of the longest command name.\n */\n nameLength?: number;\n\n /**\n * The stream that logging output will be written to.\n *\n * Defaults to `process.stdout`.\n */\n outputStream?: stream.Writable;\n}\n\ntype ExecOptions = execa.Options & { streamStdio?: true | 'yarn' };\n\nconst envWithPath = {\n PATH: npmRunPath({ cwd: __dirname }),\n};\n\nconst runCommand = (command: string, args: string[], opts?: ExecOptions) => {\n const subprocess = execa(command, args, {\n localDir: __dirname,\n preferLocal: true,\n stdio: 'inherit',\n ...opts,\n });\n\n switch (opts?.streamStdio) {\n case 'yarn':\n const stderrFilter = new YarnWarningFilter();\n const stdoutFilter = new YarnSpamFilter();\n\n subprocess.stderr?.pipe(stderrFilter).pipe(process.stderr);\n subprocess.stdout?.pipe(stdoutFilter).pipe(process.stdout);\n\n break;\n\n case true:\n subprocess.stderr?.pipe(process.stderr);\n subprocess.stdout?.pipe(process.stdout);\n\n break;\n }\n\n return subprocess;\n};\n\nconst whichCallback = npmWhich(__dirname);\n\nconst which = util.promisify<string, string>(whichCallback);\n\nexport const createExec =\n (opts: ExecOptions): Exec =>\n (command, ...args) =>\n runCommand(command, args, opts);\n\nexport const exec: Exec = (command, ...args) => runCommand(command, args);\n\nexport const execConcurrently = async (\n commands: ExecConcurrentlyCommand[],\n { maxProcesses, nameLength, outputStream }: ExecConcurrentlyOptions = {},\n) => {\n const maxNameLength =\n nameLength ??\n commands.reduce(\n (length, command) => Math.max(length, command.name.length),\n 0,\n );\n\n try {\n await concurrently(\n commands.map(({ command, name, prefixColor }) => ({\n command,\n env: envWithPath,\n name: name.padEnd(maxNameLength),\n prefixColor,\n })),\n {\n maxProcesses: maxProcesses ?? cpus().length,\n\n outputStream,\n\n // Use a minimalist logging prefix.\n prefix: '{name} \u2502',\n },\n ).result;\n } catch (err) {\n const result = concurrentlyErrorsSchema.safeParse(err);\n\n if (!result.success) {\n throw err;\n }\n\n const failed = result.data\n .filter(({ exitCode }) => exitCode !== 0)\n .sort(({ index: indexA }, { index: indexB }) => indexA - indexB)\n .map((subprocess) => subprocess.command.name);\n\n throw Error(\n `${failed.join(', ')} subprocess${\n failed.length === 1 ? '' : 'es'\n } failed.`,\n );\n }\n};\n\nexport const ensureCommands = async (...names: string[]) => {\n let success = true;\n\n await Promise.all(\n names.map(async (name) => {\n const result = await hasCommand(name);\n\n if (!result) {\n success = false;\n\n log.err(log.bold(name), 'needs to be installed.');\n }\n }),\n );\n\n if (!success) {\n process.exit(1);\n }\n};\n\nexport const hasCommand = async (name: string) => {\n try {\n await which(name);\n\n return true;\n } catch (err) {\n if (isErrorWithCode(err, 'ENOENT')) {\n return false;\n }\n\n throw err;\n }\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAqB;AACrB,oBAAmB;AACnB,kBAAiB;AAGjB,0BAAyB;AACzB,mBAA8C;AAC9C,0BAAuB;AACvB,uBAAqB;AAErB,mBAA0D;AAC1D,qBAAoB;AAEpB,MAAM,uBAAuB,cAAAA,QAAO,UAAU;AAAA,EAC5C,WAAW;AAAA,EAEX,WACE,OACA,WACA,UACA;AACA,UAAM,MAAM,OAAO,KAAK,KAAK,EAAE,SAAS;AAGxC,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC9C,WAAK,WAAW;AAAA,IAClB;AAEA,QACE,CAAC,KAAK;AAAA,IAEN,CAAC,IAAI,WAAW,wBAAwB,GACxC;AACA,WAAK,KAAK,KAAK;AAAA,IACjB;AAEA,aAAS;AAAA,EACX;AACF;AAEA,MAAM,0BAA0B,cAAAA,QAAO,UAAU;AAAA,EAC/C,WACE,OACA,WACA,UACA;AACA,UAAM,MAAM,OAAO,KAAK,KAAK,EAAE,SAAS;AAGxC,QAAI,CAAC,IAAI,WAAW,iBAAiB,GAAG;AACtC,WAAK,KAAK,KAAK;AAAA,IACjB;AAEA,aAAS;AAAA,EACX;AACF;AAsCA,MAAM,cAAc;AAAA,EAClB,UAAM,oBAAAC,SAAW,EAAE,KAAK,UAAU,CAAC;AACrC;AAEA,MAAM,aAAa,CAAC,SAAiB,MAAgB,SAAuB;AAC1E,QAAM,iBAAa,aAAAC,SAAM,SAAS,MAAM;AAAA,IACtC,UAAU;AAAA,IACV,aAAa;AAAA,IACb,OAAO;AAAA,IACP,GAAG;AAAA,EACL,CAAC;AAED,UAAQ,MAAM,aAAa;AAAA,IACzB,KAAK;AACH,YAAM,eAAe,IAAI,kBAAkB;AAC3C,YAAM,eAAe,IAAI,eAAe;AAExC,iBAAW,QAAQ,KAAK,YAAY,EAAE,KAAK,QAAQ,MAAM;AACzD,iBAAW,QAAQ,KAAK,YAAY,EAAE,KAAK,QAAQ,MAAM;AAEzD;AAAA,IAEF,KAAK;AACH,iBAAW,QAAQ,KAAK,QAAQ,MAAM;AACtC,iBAAW,QAAQ,KAAK,QAAQ,MAAM;AAEtC;AAAA,EACJ;AAEA,SAAO;AACT;AAEA,MAAM,oBAAgB,iBAAAC,SAAS,SAAS;AAExC,MAAM,QAAQ,YAAAC,QAAK,UAA0B,aAAa;AAEnD,MAAM,aACX,CAAC,SACD,CAAC,YAAY,SACX,WAAW,SAAS,MAAM,IAAI;AAE3B,MAAM,OAAa,CAAC,YAAY,SAAS,WAAW,SAAS,IAAI;AAEjE,MAAM,mBAAmB,OAC9B,UACA,EAAE,cAAc,YAAY,aAAa,IAA6B,CAAC,MACpE;AACH,QAAM,gBACJ,cACA,SAAS;AAAA,IACP,CAAC,QAAQ,YAAY,KAAK,IAAI,QAAQ,QAAQ,KAAK,MAAM;AAAA,IACzD;AAAA,EACF;AAEF,MAAI;AACF,cAAM,oBAAAC;AAAA,MACJ,SAAS,IAAI,CAAC,EAAE,SAAS,MAAM,YAAY,OAAO;AAAA,QAChD;AAAA,QACA,KAAK;AAAA,QACL,MAAM,KAAK,OAAO,aAAa;AAAA,QAC/B;AAAA,MACF,EAAE;AAAA,MACF;AAAA,QACE,cAAc,oBAAgB,gBAAK,EAAE;AAAA,QAErC;AAAA;AAAA,QAGA,QAAQ;AAAA,MACV;AAAA,IACF,EAAE;AAAA,EACJ,SAAS,KAAK;AACZ,UAAM,SAAS,sCAAyB,UAAU,GAAG;AAErD,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM;AAAA,IACR;AAEA,UAAM,SAAS,OAAO,KACnB,OAAO,CAAC,EAAE,SAAS,MAAM,aAAa,CAAC,EACvC,KAAK,CAAC,EAAE,OAAO,OAAO,GAAG,EAAE,OAAO,OAAO,MAAM,SAAS,MAAM,EAC9D,IAAI,CAAC,eAAe,WAAW,QAAQ,IAAI;AAE9C,UAAM;AAAA,MACJ,GAAG,OAAO,KAAK,IAAI,CAAC,cAClB,OAAO,WAAW,IAAI,KAAK,IAC7B;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,iBAAiB,UAAU,UAAoB;AAC1D,MAAI,UAAU;AAEd,QAAM,QAAQ;AAAA,IACZ,MAAM,IAAI,OAAO,SAAS;AACxB,YAAM,SAAS,MAAM,WAAW,IAAI;AAEpC,UAAI,CAAC,QAAQ;AACX,kBAAU;AAEV,2BAAI,IAAI,mBAAI,KAAK,IAAI,GAAG,wBAAwB;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,SAAS;AACZ,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEO,MAAM,aAAa,OAAO,SAAiB;AAChD,MAAI;AACF,UAAM,MAAM,IAAI;AAEhB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAI,8BAAgB,KAAK,QAAQ,GAAG;AAClC,aAAO;AAAA,IACT;AAEA,UAAM;AAAA,EACR;AACF;",
6
6
  "names": ["stream", "npmRunPath", "execa", "npmWhich", "util", "concurrently"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import readPkgUp, { type NormalizedPackageJson } from 'read-pkg-up';
2
- import * as t from 'runtypes';
3
- export type ProjectType = t.Static<typeof ProjectType>;
4
- export declare const ProjectType: t.Union<[t.Literal<"application">, t.Literal<"package">]>;
2
+ import { z } from 'zod';
3
+ export type ProjectType = z.infer<typeof projectTypeSchema>;
4
+ export declare const projectTypeSchema: z.ZodUnion<[z.ZodLiteral<"application">, z.ZodLiteral<"package">]>;
5
5
  export declare const PROJECT_TYPES: readonly ["application", "package"];
6
6
  export declare const getSkubaManifest: () => Promise<NormalizedPackageJson>;
7
7
  export declare const getConsumerManifest: () => Promise<readPkgUp.NormalizedReadResult | undefined>;
@@ -29,21 +29,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var manifest_exports = {};
30
30
  __export(manifest_exports, {
31
31
  PROJECT_TYPES: () => PROJECT_TYPES,
32
- ProjectType: () => ProjectType,
33
32
  getConsumerManifest: () => getConsumerManifest,
34
33
  getEntryPointFromManifest: () => getEntryPointFromManifest,
35
34
  getPropFromConsumerManifest: () => getPropFromConsumerManifest,
36
35
  getSkubaManifest: () => getSkubaManifest,
37
- getStringPropFromConsumerManifest: () => getStringPropFromConsumerManifest
36
+ getStringPropFromConsumerManifest: () => getStringPropFromConsumerManifest,
37
+ projectTypeSchema: () => projectTypeSchema
38
38
  });
39
39
  module.exports = __toCommonJS(manifest_exports);
40
40
  var import_read_pkg_up = __toESM(require("read-pkg-up"));
41
- var t = __toESM(require("runtypes"));
41
+ var import_zod = require("zod");
42
42
  var import_validation = require("./validation");
43
- const ProjectType = t.Union(
44
- t.Literal("application"),
45
- t.Literal("package")
46
- );
43
+ const projectTypeSchema = import_zod.z.union([
44
+ import_zod.z.literal("application"),
45
+ import_zod.z.literal("package")
46
+ ]);
47
47
  const PROJECT_TYPES = ["application", "package"];
48
48
  const DEFAULT_ENTRY_POINT = "src/app.ts";
49
49
  let skubaManifest;
@@ -73,11 +73,11 @@ const getEntryPointFromManifest = async () => {
73
73
  // Annotate the CommonJS export names for ESM import in node:
74
74
  0 && (module.exports = {
75
75
  PROJECT_TYPES,
76
- ProjectType,
77
76
  getConsumerManifest,
78
77
  getEntryPointFromManifest,
79
78
  getPropFromConsumerManifest,
80
79
  getSkubaManifest,
81
- getStringPropFromConsumerManifest
80
+ getStringPropFromConsumerManifest,
81
+ projectTypeSchema
82
82
  });
83
83
  //# sourceMappingURL=manifest.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/manifest.ts"],
4
- "sourcesContent": ["/* eslint-disable new-cap */\n\nimport readPkgUp, { type NormalizedPackageJson } from 'read-pkg-up';\nimport * as t from 'runtypes';\n\nimport { hasProp } from './validation';\n\nexport type ProjectType = t.Static<typeof ProjectType>;\n\nexport const ProjectType = t.Union(\n t.Literal('application'),\n t.Literal('package'),\n);\n\nexport const PROJECT_TYPES = ['application', 'package'] as const;\n\nconst DEFAULT_ENTRY_POINT = 'src/app.ts';\n\nlet skubaManifest: NormalizedPackageJson | undefined;\n\nexport const getSkubaManifest = async (): Promise<NormalizedPackageJson> => {\n if (skubaManifest !== undefined) {\n return skubaManifest;\n }\n\n const result = await readPkgUp({ cwd: __dirname });\n\n if (result === undefined) {\n throw Error('skuba could not find its own manifest');\n }\n\n return (skubaManifest = result.packageJson);\n};\n\nexport const getConsumerManifest = () => readPkgUp();\n\nexport const getPropFromConsumerManifest = async <\n T extends string,\n V = unknown,\n>(\n prop: T,\n): Promise<V | undefined> => {\n const result = await getConsumerManifest();\n\n return result !== undefined && hasProp<T, V>(result.packageJson.skuba, prop)\n ? result.packageJson.skuba[prop]\n : undefined;\n};\n\nexport const getStringPropFromConsumerManifest = async <T extends string>(\n prop: T,\n): Promise<string | undefined> => {\n const result = await getPropFromConsumerManifest(prop);\n\n return typeof result === 'string' ? result : undefined;\n};\n\nexport const getEntryPointFromManifest = async (): Promise<string> => {\n const entryPoint = await getStringPropFromConsumerManifest('entryPoint');\n\n return entryPoint ?? DEFAULT_ENTRY_POINT;\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,yBAAsD;AACtD,QAAmB;AAEnB,wBAAwB;AAIjB,MAAM,cAAc,EAAE;AAAA,EAC3B,EAAE,QAAQ,aAAa;AAAA,EACvB,EAAE,QAAQ,SAAS;AACrB;AAEO,MAAM,gBAAgB,CAAC,eAAe,SAAS;AAEtD,MAAM,sBAAsB;AAE5B,IAAI;AAEG,MAAM,mBAAmB,YAA4C;AAC1E,MAAI,kBAAkB,QAAW;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,UAAM,mBAAAA,SAAU,EAAE,KAAK,UAAU,CAAC;AAEjD,MAAI,WAAW,QAAW;AACxB,UAAM,MAAM,uCAAuC;AAAA,EACrD;AAEA,SAAQ,gBAAgB,OAAO;AACjC;AAEO,MAAM,sBAAsB,UAAM,mBAAAA,SAAU;AAE5C,MAAM,8BAA8B,OAIzC,SAC2B;AAC3B,QAAM,SAAS,MAAM,oBAAoB;AAEzC,SAAO,WAAW,cAAa,2BAAc,OAAO,YAAY,OAAO,IAAI,IACvE,OAAO,YAAY,MAAM,IAAI,IAC7B;AACN;AAEO,MAAM,oCAAoC,OAC/C,SACgC;AAChC,QAAM,SAAS,MAAM,4BAA4B,IAAI;AAErD,SAAO,OAAO,WAAW,WAAW,SAAS;AAC/C;AAEO,MAAM,4BAA4B,YAA6B;AACpE,QAAM,aAAa,MAAM,kCAAkC,YAAY;AAEvE,SAAO,cAAc;AACvB;",
4
+ "sourcesContent": ["import readPkgUp, { type NormalizedPackageJson } from 'read-pkg-up';\nimport { z } from 'zod';\n\nimport { hasProp } from './validation';\n\nexport type ProjectType = z.infer<typeof projectTypeSchema>;\n\nexport const projectTypeSchema = z.union([\n z.literal('application'),\n z.literal('package'),\n]);\n\nexport const PROJECT_TYPES = ['application', 'package'] as const;\n\nconst DEFAULT_ENTRY_POINT = 'src/app.ts';\n\nlet skubaManifest: NormalizedPackageJson | undefined;\n\nexport const getSkubaManifest = async (): Promise<NormalizedPackageJson> => {\n if (skubaManifest !== undefined) {\n return skubaManifest;\n }\n\n const result = await readPkgUp({ cwd: __dirname });\n\n if (result === undefined) {\n throw Error('skuba could not find its own manifest');\n }\n\n return (skubaManifest = result.packageJson);\n};\n\nexport const getConsumerManifest = () => readPkgUp();\n\nexport const getPropFromConsumerManifest = async <\n T extends string,\n V = unknown,\n>(\n prop: T,\n): Promise<V | undefined> => {\n const result = await getConsumerManifest();\n\n return result !== undefined && hasProp<T, V>(result.packageJson.skuba, prop)\n ? result.packageJson.skuba[prop]\n : undefined;\n};\n\nexport const getStringPropFromConsumerManifest = async <T extends string>(\n prop: T,\n): Promise<string | undefined> => {\n const result = await getPropFromConsumerManifest(prop);\n\n return typeof result === 'string' ? result : undefined;\n};\n\nexport const getEntryPointFromManifest = async (): Promise<string> => {\n const entryPoint = await getStringPropFromConsumerManifest('entryPoint');\n\n return entryPoint ?? DEFAULT_ENTRY_POINT;\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAsD;AACtD,iBAAkB;AAElB,wBAAwB;AAIjB,MAAM,oBAAoB,aAAE,MAAM;AAAA,EACvC,aAAE,QAAQ,aAAa;AAAA,EACvB,aAAE,QAAQ,SAAS;AACrB,CAAC;AAEM,MAAM,gBAAgB,CAAC,eAAe,SAAS;AAEtD,MAAM,sBAAsB;AAE5B,IAAI;AAEG,MAAM,mBAAmB,YAA4C;AAC1E,MAAI,kBAAkB,QAAW;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,UAAM,mBAAAA,SAAU,EAAE,KAAK,UAAU,CAAC;AAEjD,MAAI,WAAW,QAAW;AACxB,UAAM,MAAM,uCAAuC;AAAA,EACrD;AAEA,SAAQ,gBAAgB,OAAO;AACjC;AAEO,MAAM,sBAAsB,UAAM,mBAAAA,SAAU;AAE5C,MAAM,8BAA8B,OAIzC,SAC2B;AAC3B,QAAM,SAAS,MAAM,oBAAoB;AAEzC,SAAO,WAAW,cAAa,2BAAc,OAAO,YAAY,OAAO,IAAI,IACvE,OAAO,YAAY,MAAM,IAAI,IAC7B;AACN;AAEO,MAAM,oCAAoC,OAC/C,SACgC;AAChC,QAAM,SAAS,MAAM,4BAA4B,IAAI;AAErD,SAAO,OAAO,WAAW,WAAW,SAAS;AAC/C;AAEO,MAAM,4BAA4B,YAA6B;AACpE,QAAM,aAAa,MAAM,kCAAkC,YAAY;AAEvE,SAAO,cAAc;AACvB;",
6
6
  "names": ["readPkgUp"]
7
7
  }
@@ -1,4 +1,4 @@
1
- import * as t from 'runtypes';
1
+ import { z } from 'zod';
2
2
  export declare const TEMPLATE_NAMES: readonly ["express-rest-api", "greeter", "koa-rest-api", "lambda-sqs-worker", "lambda-sqs-worker-cdk", "oss-npm-package", "private-npm-package"];
3
3
  export type TemplateName = (typeof TEMPLATE_NAMES)[number];
4
4
  export declare const TEMPLATE_NAMES_WITH_BYO: readonly ["express-rest-api", "greeter", "koa-rest-api", "lambda-sqs-worker", "lambda-sqs-worker-cdk", "oss-npm-package", "private-npm-package", "github โ†’"];
@@ -17,18 +17,48 @@ interface TemplateDocumentationConfig {
17
17
  filename: string;
18
18
  }
19
19
  export declare const TEMPLATE_DOCUMENTATION_CONFIG: Record<TemplateName, TemplateDocumentationConfig>;
20
- export type TemplateConfig = t.Static<typeof TemplateConfig>;
21
- export declare const TemplateConfig: t.Record<{
22
- fields: t.Array<t.Record<{
23
- name: t.String;
24
- message: t.String;
25
- initial: t.String;
26
- validate: t.Optional<t.Function>;
27
- }, false>, false>;
28
- entryPoint: t.Optional<t.String>;
29
- noSkip: t.Optional<t.Boolean>;
30
- type: t.Optional<t.Union<[t.Literal<"application">, t.Literal<"package">]>>;
31
- }, false>;
20
+ export type TemplateConfig = z.infer<typeof templateConfigSchema>;
21
+ export declare const templateConfigSchema: z.ZodObject<{
22
+ fields: z.ZodArray<z.ZodObject<{
23
+ name: z.ZodString;
24
+ message: z.ZodString;
25
+ initial: z.ZodString;
26
+ validate: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodString], null>, z.ZodBoolean>>;
27
+ }, "strip", z.ZodTypeAny, {
28
+ message: string;
29
+ name: string;
30
+ initial: string;
31
+ validate?: ((args_0: string) => boolean) | undefined;
32
+ }, {
33
+ message: string;
34
+ name: string;
35
+ initial: string;
36
+ validate?: ((args_0: string) => boolean) | undefined;
37
+ }>, "many">;
38
+ entryPoint: z.ZodOptional<z.ZodString>;
39
+ noSkip: z.ZodOptional<z.ZodBoolean>;
40
+ type: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"application">, z.ZodLiteral<"package">]>>;
41
+ }, "strip", z.ZodTypeAny, {
42
+ fields: {
43
+ message: string;
44
+ name: string;
45
+ initial: string;
46
+ validate?: ((args_0: string) => boolean) | undefined;
47
+ }[];
48
+ entryPoint?: string | undefined;
49
+ noSkip?: boolean | undefined;
50
+ type?: "package" | "application" | undefined;
51
+ }, {
52
+ fields: {
53
+ message: string;
54
+ name: string;
55
+ initial: string;
56
+ validate?: ((args_0: string) => boolean) | undefined;
57
+ }[];
58
+ entryPoint?: string | undefined;
59
+ noSkip?: boolean | undefined;
60
+ type?: "package" | "application" | undefined;
61
+ }>;
32
62
  export declare const TEMPLATE_CONFIG_FILENAME = "skuba.template.js";
33
63
  export declare const TEMPLATE_DIR: string;
34
64
  export declare const BASE_TEMPLATE_DIR: string;
@@ -34,14 +34,14 @@ __export(template_exports, {
34
34
  TEMPLATE_DOCUMENTATION_CONFIG: () => TEMPLATE_DOCUMENTATION_CONFIG,
35
35
  TEMPLATE_NAMES: () => TEMPLATE_NAMES,
36
36
  TEMPLATE_NAMES_WITH_BYO: () => TEMPLATE_NAMES_WITH_BYO,
37
- TemplateConfig: () => TemplateConfig,
38
37
  ensureTemplateConfigDeletion: () => ensureTemplateConfigDeletion,
39
- readBaseTemplateFile: () => readBaseTemplateFile
38
+ readBaseTemplateFile: () => readBaseTemplateFile,
39
+ templateConfigSchema: () => templateConfigSchema
40
40
  });
41
41
  module.exports = __toCommonJS(template_exports);
42
42
  var import_path = __toESM(require("path"));
43
43
  var import_fs_extra = __toESM(require("fs-extra"));
44
- var t = __toESM(require("runtypes"));
44
+ var import_zod = require("zod");
45
45
  var import_manifest = require("./manifest");
46
46
  const TEMPLATE_NAMES = [
47
47
  "express-rest-api",
@@ -83,18 +83,18 @@ const TEMPLATE_DOCUMENTATION_CONFIG = {
83
83
  filename: "package.md"
84
84
  }
85
85
  };
86
- const TemplateConfig = t.Record({
87
- fields: t.Array(
88
- t.Record({
89
- name: t.String,
90
- message: t.String,
91
- initial: t.String,
92
- validate: t.Function.optional()
86
+ const templateConfigSchema = import_zod.z.object({
87
+ fields: import_zod.z.array(
88
+ import_zod.z.object({
89
+ name: import_zod.z.string(),
90
+ message: import_zod.z.string(),
91
+ initial: import_zod.z.string(),
92
+ validate: import_zod.z.function(import_zod.z.tuple([import_zod.z.string()]), import_zod.z.boolean()).optional()
93
93
  })
94
94
  ),
95
- entryPoint: t.String.optional(),
96
- noSkip: t.Boolean.optional(),
97
- type: import_manifest.ProjectType.optional()
95
+ entryPoint: import_zod.z.string().optional(),
96
+ noSkip: import_zod.z.boolean().optional(),
97
+ type: import_manifest.projectTypeSchema.optional()
98
98
  });
99
99
  const TEMPLATE_CONFIG_FILENAME = "skuba.template.js";
100
100
  const TEMPLATE_DIR = import_path.default.join(__dirname, "..", "..", "template");
@@ -109,8 +109,8 @@ const readBaseTemplateFile = (src) => import_fs_extra.default.promises.readFile(
109
109
  TEMPLATE_DOCUMENTATION_CONFIG,
110
110
  TEMPLATE_NAMES,
111
111
  TEMPLATE_NAMES_WITH_BYO,
112
- TemplateConfig,
113
112
  ensureTemplateConfigDeletion,
114
- readBaseTemplateFile
113
+ readBaseTemplateFile,
114
+ templateConfigSchema
115
115
  });
116
116
  //# sourceMappingURL=template.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/template.ts"],
4
- "sourcesContent": ["/* eslint-disable new-cap */\n\nimport path from 'path';\n\nimport fs from 'fs-extra';\nimport * as t from 'runtypes';\n\nimport { ProjectType } from './manifest';\n\nexport const TEMPLATE_NAMES = [\n 'express-rest-api',\n 'greeter',\n 'koa-rest-api',\n 'lambda-sqs-worker',\n 'lambda-sqs-worker-cdk',\n 'oss-npm-package',\n 'private-npm-package',\n] as const;\n\nexport type TemplateName = (typeof TEMPLATE_NAMES)[number];\n\nexport const TEMPLATE_NAMES_WITH_BYO = [...TEMPLATE_NAMES, 'github \u2192'] as const;\n\ninterface TemplateDocumentationConfig {\n /**\n * The semantic version in which the template was first added.\n *\n * This is used to filter out historical changelogs.\n */\n added: string;\n\n /**\n * The Markdown file for the template in our `/docs`.\n *\n * This is used to compile per-template changelogs for our documentation site.\n */\n filename: string;\n}\n\nexport const TEMPLATE_DOCUMENTATION_CONFIG: Record<\n TemplateName,\n TemplateDocumentationConfig\n> = {\n 'express-rest-api': {\n added: '3.8.0',\n filename: 'api.md',\n },\n greeter: {\n added: '3.4.1',\n filename: 'barebones.md',\n },\n 'koa-rest-api': {\n added: '3.4.1',\n filename: 'api.md',\n },\n 'lambda-sqs-worker': {\n added: '3.4.1',\n filename: 'worker.md',\n },\n 'lambda-sqs-worker-cdk': {\n added: '3.13.0',\n filename: 'worker.md',\n },\n 'oss-npm-package': {\n added: '3.7.0',\n filename: 'package.md',\n },\n 'private-npm-package': {\n added: '3.6.0',\n filename: 'package.md',\n },\n};\n\nexport type TemplateConfig = t.Static<typeof TemplateConfig>;\n\nexport const TemplateConfig = t.Record({\n fields: t.Array(\n t.Record({\n name: t.String,\n message: t.String,\n initial: t.String,\n validate: t.Function.optional(),\n }),\n ),\n entryPoint: t.String.optional(),\n noSkip: t.Boolean.optional(),\n type: ProjectType.optional(),\n});\n\nexport const TEMPLATE_CONFIG_FILENAME = 'skuba.template.js';\n\nexport const TEMPLATE_DIR = path.join(__dirname, '..', '..', 'template');\n\nexport const BASE_TEMPLATE_DIR = path.join(TEMPLATE_DIR, 'base');\n\nexport const ensureTemplateConfigDeletion = (dir: string): Promise<void> =>\n fs.promises.rm(path.join(dir, TEMPLATE_CONFIG_FILENAME));\n\nexport const readBaseTemplateFile = (src: string): Promise<string> =>\n fs.promises.readFile(path.join(BASE_TEMPLATE_DIR, src), 'utf8');\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,kBAAiB;AAEjB,sBAAe;AACf,QAAmB;AAEnB,sBAA4B;AAErB,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,MAAM,0BAA0B,CAAC,GAAG,gBAAgB,eAAU;AAkB9D,MAAM,gCAGT;AAAA,EACF,oBAAoB;AAAA,IAClB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,qBAAqB;AAAA,IACnB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,yBAAyB;AAAA,IACvB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,mBAAmB;AAAA,IACjB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,uBAAuB;AAAA,IACrB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AACF;AAIO,MAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,QAAQ,EAAE;AAAA,IACR,EAAE,OAAO;AAAA,MACP,MAAM,EAAE;AAAA,MACR,SAAS,EAAE;AAAA,MACX,SAAS,EAAE;AAAA,MACX,UAAU,EAAE,SAAS,SAAS;AAAA,IAChC,CAAC;AAAA,EACH;AAAA,EACA,YAAY,EAAE,OAAO,SAAS;AAAA,EAC9B,QAAQ,EAAE,QAAQ,SAAS;AAAA,EAC3B,MAAM,4BAAY,SAAS;AAC7B,CAAC;AAEM,MAAM,2BAA2B;AAEjC,MAAM,eAAe,YAAAA,QAAK,KAAK,WAAW,MAAM,MAAM,UAAU;AAEhE,MAAM,oBAAoB,YAAAA,QAAK,KAAK,cAAc,MAAM;AAExD,MAAM,+BAA+B,CAAC,QAC3C,gBAAAC,QAAG,SAAS,GAAG,YAAAD,QAAK,KAAK,KAAK,wBAAwB,CAAC;AAElD,MAAM,uBAAuB,CAAC,QACnC,gBAAAC,QAAG,SAAS,SAAS,YAAAD,QAAK,KAAK,mBAAmB,GAAG,GAAG,MAAM;",
4
+ "sourcesContent": ["import path from 'path';\n\nimport fs from 'fs-extra';\nimport { z } from 'zod';\n\nimport { projectTypeSchema } from './manifest';\n\nexport const TEMPLATE_NAMES = [\n 'express-rest-api',\n 'greeter',\n 'koa-rest-api',\n 'lambda-sqs-worker',\n 'lambda-sqs-worker-cdk',\n 'oss-npm-package',\n 'private-npm-package',\n] as const;\n\nexport type TemplateName = (typeof TEMPLATE_NAMES)[number];\n\nexport const TEMPLATE_NAMES_WITH_BYO = [...TEMPLATE_NAMES, 'github \u2192'] as const;\n\ninterface TemplateDocumentationConfig {\n /**\n * The semantic version in which the template was first added.\n *\n * This is used to filter out historical changelogs.\n */\n added: string;\n\n /**\n * The Markdown file for the template in our `/docs`.\n *\n * This is used to compile per-template changelogs for our documentation site.\n */\n filename: string;\n}\n\nexport const TEMPLATE_DOCUMENTATION_CONFIG: Record<\n TemplateName,\n TemplateDocumentationConfig\n> = {\n 'express-rest-api': {\n added: '3.8.0',\n filename: 'api.md',\n },\n greeter: {\n added: '3.4.1',\n filename: 'barebones.md',\n },\n 'koa-rest-api': {\n added: '3.4.1',\n filename: 'api.md',\n },\n 'lambda-sqs-worker': {\n added: '3.4.1',\n filename: 'worker.md',\n },\n 'lambda-sqs-worker-cdk': {\n added: '3.13.0',\n filename: 'worker.md',\n },\n 'oss-npm-package': {\n added: '3.7.0',\n filename: 'package.md',\n },\n 'private-npm-package': {\n added: '3.6.0',\n filename: 'package.md',\n },\n};\n\nexport type TemplateConfig = z.infer<typeof templateConfigSchema>;\n\nexport const templateConfigSchema = z.object({\n fields: z.array(\n z.object({\n name: z.string(),\n message: z.string(),\n initial: z.string(),\n validate: z.function(z.tuple([z.string()]), z.boolean()).optional(),\n }),\n ),\n entryPoint: z.string().optional(),\n noSkip: z.boolean().optional(),\n type: projectTypeSchema.optional(),\n});\n\nexport const TEMPLATE_CONFIG_FILENAME = 'skuba.template.js';\n\nexport const TEMPLATE_DIR = path.join(__dirname, '..', '..', 'template');\n\nexport const BASE_TEMPLATE_DIR = path.join(TEMPLATE_DIR, 'base');\n\nexport const ensureTemplateConfigDeletion = (dir: string): Promise<void> =>\n fs.promises.rm(path.join(dir, TEMPLATE_CONFIG_FILENAME));\n\nexport const readBaseTemplateFile = (src: string): Promise<string> =>\n fs.promises.readFile(path.join(BASE_TEMPLATE_DIR, src), 'utf8');\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,sBAAe;AACf,iBAAkB;AAElB,sBAAkC;AAE3B,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,MAAM,0BAA0B,CAAC,GAAG,gBAAgB,eAAU;AAkB9D,MAAM,gCAGT;AAAA,EACF,oBAAoB;AAAA,IAClB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,qBAAqB;AAAA,IACnB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,yBAAyB;AAAA,IACvB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,mBAAmB;AAAA,IACjB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA,uBAAuB;AAAA,IACrB,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AACF;AAIO,MAAM,uBAAuB,aAAE,OAAO;AAAA,EAC3C,QAAQ,aAAE;AAAA,IACR,aAAE,OAAO;AAAA,MACP,MAAM,aAAE,OAAO;AAAA,MACf,SAAS,aAAE,OAAO;AAAA,MAClB,SAAS,aAAE,OAAO;AAAA,MAClB,UAAU,aAAE,SAAS,aAAE,MAAM,CAAC,aAAE,OAAO,CAAC,CAAC,GAAG,aAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,IACpE,CAAC;AAAA,EACH;AAAA,EACA,YAAY,aAAE,OAAO,EAAE,SAAS;AAAA,EAChC,QAAQ,aAAE,QAAQ,EAAE,SAAS;AAAA,EAC7B,MAAM,kCAAkB,SAAS;AACnC,CAAC;AAEM,MAAM,2BAA2B;AAEjC,MAAM,eAAe,YAAAA,QAAK,KAAK,WAAW,MAAM,MAAM,UAAU;AAEhE,MAAM,oBAAoB,YAAAA,QAAK,KAAK,cAAc,MAAM;AAExD,MAAM,+BAA+B,CAAC,QAC3C,gBAAAC,QAAG,SAAS,GAAG,YAAAD,QAAK,KAAK,KAAK,wBAAwB,CAAC;AAElD,MAAM,uBAAuB,CAAC,QACnC,gBAAAC,QAAG,SAAS,SAAS,YAAAD,QAAK,KAAK,mBAAmB,GAAG,GAAG,MAAM;",
6
6
  "names": ["path", "fs"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skuba",
3
- "version": "7.2.0",
3
+ "version": "7.3.0",
4
4
  "private": false,
5
5
  "description": "SEEK development toolkit for backend applications and packages",
6
6
  "homepage": "https://github.com/seek-oss/skuba#readme",
@@ -36,11 +36,11 @@
36
36
  "release": "yarn build && changeset publish",
37
37
  "skuba": "yarn build && node lib/skuba",
38
38
  "stage": "changeset version && yarn format",
39
- "test": "yarn skuba test",
40
- "test:ci": "yarn skuba test --config jest.config.int.ts --runInBand",
41
- "test:int": "yarn skuba test --config jest.config.int.ts --runInBand",
39
+ "test": "yarn skuba test --selectProjects unit",
40
+ "test:ci": "yarn skuba test --runInBand",
41
+ "test:int": "yarn skuba test --selectProjects integration --runInBand",
42
42
  "test:template": "scripts/test-template.sh",
43
- "test:watch": "yarn skuba test --config jest.config.int.ts --runInBand --watch"
43
+ "test:watch": "yarn skuba test --runInBand --watch"
44
44
  },
45
45
  "remarkConfig": {
46
46
  "plugins": [
@@ -73,7 +73,7 @@
73
73
  "@octokit/graphql": "^7.0.0",
74
74
  "@octokit/graphql-schema": "^14.5.0",
75
75
  "@octokit/rest": "^20.0.0",
76
- "@octokit/types": "^11.0.0",
76
+ "@octokit/types": "^12.0.0",
77
77
  "@types/jest": "^29.0.0",
78
78
  "@types/node": ">=18.12",
79
79
  "chalk": "^4.1.0",
@@ -103,12 +103,11 @@
103
103
  "npm-which": "^3.0.1",
104
104
  "picomatch": "^2.2.2",
105
105
  "prettier": "~3.0.3",
106
+ "prettier-plugin-packagejson": "^2.4.6",
106
107
  "read-pkg-up": "^7.0.1",
107
- "runtypes": "^6.0.0",
108
108
  "semantic-release": "^21.0.0",
109
109
  "serialize-error": "^8.0.1",
110
110
  "simple-git": "^3.5.0",
111
- "sort-package-json": "^2.5.1",
112
111
  "strip-ansi": "^6.0.1",
113
112
  "ts-dedent": "^2.2.0",
114
113
  "ts-jest": "^29.1.0",
@@ -117,30 +116,31 @@
117
116
  "tsconfig-paths": "^4.0.0",
118
117
  "tsconfig-seek": "2.0.0",
119
118
  "typescript": "~5.2.0",
120
- "validate-npm-package-name": "^5.0.0"
119
+ "validate-npm-package-name": "^5.0.0",
120
+ "zod": "^3.22.4"
121
121
  },
122
122
  "devDependencies": {
123
123
  "@changesets/cli": "2.26.2",
124
124
  "@changesets/get-github-info": "0.5.2",
125
- "@jest/reporters": "29.6.4",
126
- "@types/ejs": "3.1.2",
127
- "@types/express": "4.17.17",
128
- "@types/fs-extra": "11.0.1",
129
- "@types/koa": "2.13.8",
130
- "@types/libnpmsearch": "2.0.3",
131
- "@types/lodash.mergewith": "4.6.7",
132
- "@types/module-alias": "2.0.2",
133
- "@types/npm-which": "3.0.1",
134
- "@types/picomatch": "2.3.0",
135
- "@types/supertest": "2.0.12",
136
- "@types/validate-npm-package-name": "4.0.0",
125
+ "@jest/reporters": "29.7.0",
126
+ "@types/ejs": "3.1.4",
127
+ "@types/express": "4.17.20",
128
+ "@types/fs-extra": "11.0.3",
129
+ "@types/koa": "2.13.10",
130
+ "@types/libnpmsearch": "2.0.5",
131
+ "@types/lodash.mergewith": "4.6.8",
132
+ "@types/module-alias": "2.0.3",
133
+ "@types/npm-which": "3.0.2",
134
+ "@types/picomatch": "2.3.2",
135
+ "@types/supertest": "2.0.15",
136
+ "@types/validate-npm-package-name": "4.0.1",
137
137
  "enhanced-resolve": "5.15.0",
138
138
  "express": "4.18.2",
139
- "fastify": "4.22.0",
139
+ "fastify": "4.24.3",
140
140
  "jsonfile": "6.1.0",
141
141
  "koa": "2.14.2",
142
- "memfs": "4.2.1",
143
- "remark-cli": "11.0.0",
142
+ "memfs": "4.6.0",
143
+ "remark-cli": "12.0.0",
144
144
  "remark-preset-lint-recommended": "6.1.3",
145
145
  "semver": "7.5.4",
146
146
  "supertest": "6.3.3",
@@ -9,16 +9,17 @@ configs:
9
9
  NPM_READ_TOKEN: arn:aws:secretsmanager:ap-southeast-2:987872074697:secret:npm/npm-read-token
10
10
 
11
11
  - &docker-ecr-cache
12
- seek-oss/docker-ecr-cache#v2.0.0:
12
+ seek-oss/docker-ecr-cache#v2.1.0: &docker-ecr-cache-defaults
13
13
  cache-on:
14
14
  - package.json
15
15
  - yarn.lock
16
16
  dockerfile: Dockerfile.dev-deps
17
- secrets: id=npm,src=.npmrc
17
+ secrets: id=npm,src=tmp/.npmrc
18
18
 
19
19
  - &private-npm
20
20
  seek-oss/private-npm#v1.2.0:
21
21
  env: NPM_READ_TOKEN
22
+ output-path: tmp/
22
23
 
23
24
  base-steps:
24
25
  - &deploy
@@ -36,7 +37,9 @@ steps:
36
37
  plugins:
37
38
  - *aws-sm
38
39
  - *private-npm
39
- - *docker-ecr-cache
40
+ - seek-oss/docker-ecr-cache#v2.1.0:
41
+ <<: *docker-ecr-cache-defaults
42
+ skip-pull-from-cache: true
40
43
 
41
44
  - label: ๐Ÿงช Test & Lint
42
45
  commands:
@@ -51,7 +54,7 @@ steps:
51
54
  - *aws-sm
52
55
  - *private-npm
53
56
  - *docker-ecr-cache
54
- - docker-compose#v4.14.0:
57
+ - docker-compose#v4.16.0:
55
58
  run: app
56
59
  timeout_in_minutes: 10
57
60
 
@@ -7,5 +7,5 @@ WORKDIR /workdir
7
7
  COPY package.json yarn.lock ./
8
8
 
9
9
  RUN \
10
- --mount=type=secret,id=npm,dst=/workdir/.npmrc \
10
+ --mount=type=secret,id=npm,dst=/root/.npmrc \
11
11
  yarn install --frozen-lockfile --ignore-optional --non-interactive
@@ -19,12 +19,12 @@ Next steps:
19
19
  6. [ ] Configure [GitHub repository settings].
20
20
  7. [ ] Delete this checklist ๐Ÿ˜Œ.
21
21
 
22
- [builds at seek]: https://builds-at-seek.ssod.skinfra.xyz
22
+ [builds at seek]: https://backstage.myseek.xyz/docs/default/component/builds-cicd-seek/
23
23
  [github repository settings]: https://github.com/<%-orgName%>/<%-repoName%>/settings
24
24
 
25
25
  ## Design
26
26
 
27
- <%-repoName %> is a Node.js HTTP server built in line with our [technology strategy].
27
+ <%-repoName %> is a Node.js HTTP server built in line with our [Technical Guidelines].
28
28
  It uses the [Express] middleware framework and common SEEK packages.
29
29
  Resource APIs enable synchronous interactions and serve as the backbone of SEEK's general service architecture.
30
30
 
@@ -100,7 +100,7 @@ TODO: add support links for the prod environment.
100
100
  - Splunk logs
101
101
  -->
102
102
 
103
- [codedeploy]: https://docs.aws.amazon.com/codedeploy
104
- [express]: https://expressjs.com
105
- [gantry]: https://backstage.myseek.xyz/docs/default/component/gantry/
106
- [technology strategy]: https://tech-strategy.ssod.skinfra.xyz
103
+ [CodeDeploy]: https://docs.aws.amazon.com/codedeploy
104
+ [Express]: https://expressjs.com
105
+ [Gantry]: https://backstage.myseek.xyz/docs/default/component/gantry/
106
+ [Technical Guidelines]: https://myseek.atlassian.net/wiki/spaces/AA/pages/2358346017/
@@ -9,15 +9,16 @@ configs:
9
9
  NPM_READ_TOKEN: arn:aws:secretsmanager:ap-southeast-2:987872074697:secret:npm/npm-read-token
10
10
 
11
11
  - &docker-ecr-cache
12
- seek-oss/docker-ecr-cache#v2.0.0:
12
+ seek-oss/docker-ecr-cache#v2.1.0:
13
13
  cache-on:
14
14
  - package.json
15
15
  - yarn.lock
16
- secrets: id=npm,src=.npmrc
16
+ secrets: id=npm,src=tmp/.npmrc
17
17
 
18
18
  - &private-npm
19
19
  seek-oss/private-npm#v1.2.0:
20
20
  env: NPM_READ_TOKEN
21
+ output-path: tmp/
21
22
 
22
23
  steps:
23
24
  - label: ๐Ÿงช Test & Lint
@@ -32,6 +33,6 @@ steps:
32
33
  - *aws-sm
33
34
  - *private-npm
34
35
  - *docker-ecr-cache
35
- - docker-compose#v4.14.0:
36
+ - docker-compose#v4.16.0:
36
37
  run: app
37
38
  timeout_in_minutes: 10
@@ -7,5 +7,5 @@ WORKDIR /workdir
7
7
  COPY package.json yarn.lock ./
8
8
 
9
9
  RUN \
10
- --mount=type=secret,id=npm,dst=/workdir/.npmrc \
10
+ --mount=type=secret,id=npm,dst=/root/.npmrc \
11
11
  yarn install --frozen-lockfile --ignore-optional --non-interactive
@@ -17,13 +17,13 @@ Next steps:
17
17
  5. [ ] Configure [GitHub repository settings].
18
18
  6. [ ] Delete this checklist ๐Ÿ˜Œ.
19
19
 
20
- [builds at seek]: https://builds-at-seek.ssod.skinfra.xyz
20
+ [builds at seek]: https://backstage.myseek.xyz/docs/default/component/builds-cicd-seek/
21
21
  [github repository settings]: https://github.com/<%-orgName%>/<%-repoName%>/settings
22
22
 
23
23
  ## Design
24
24
 
25
25
  The `greeter` template is the prototypical _hello world_ project.
26
- It can function as a playground for the TypeScript tooling prescribed by our [technology strategy],
26
+ It can function as a playground for the TypeScript tooling prescribed by our [Technical Guidelines],
27
27
  or serve as a starting point for a backend project if the other built-in templates are not a good fit.
28
28
 
29
29
  It's a barebones Node.js application that comprises:
@@ -93,4 +93,4 @@ TODO: add support links for the prod environment.
93
93
  - Splunk logs
94
94
  -->
95
95
 
96
- [technology strategy]: https://tech-strategy.ssod.skinfra.xyz
96
+ [Technical Guidelines]: https://myseek.atlassian.net/wiki/spaces/AA/pages/2358346017/
@@ -9,16 +9,17 @@ configs:
9
9
  NPM_READ_TOKEN: arn:aws:secretsmanager:ap-southeast-2:987872074697:secret:npm/npm-read-token
10
10
 
11
11
  - &docker-ecr-cache
12
- seek-oss/docker-ecr-cache#v2.0.0:
12
+ seek-oss/docker-ecr-cache#v2.1.0: &docker-ecr-cache-defaults
13
13
  cache-on:
14
14
  - package.json
15
15
  - yarn.lock
16
16
  dockerfile: Dockerfile.dev-deps
17
- secrets: id=npm,src=.npmrc
17
+ secrets: id=npm,src=tmp/.npmrc
18
18
 
19
19
  - &private-npm
20
20
  seek-oss/private-npm#v1.2.0:
21
21
  env: NPM_READ_TOKEN
22
+ output-path: tmp/
22
23
 
23
24
  base-steps:
24
25
  - &deploy
@@ -36,7 +37,9 @@ steps:
36
37
  plugins:
37
38
  - *aws-sm
38
39
  - *private-npm
39
- - *docker-ecr-cache
40
+ - seek-oss/docker-ecr-cache#v2.1.0:
41
+ <<: *docker-ecr-cache-defaults
42
+ skip-pull-from-cache: true
40
43
 
41
44
  - label: ๐Ÿงช Test & Lint
42
45
  commands:
@@ -51,7 +54,7 @@ steps:
51
54
  - *aws-sm
52
55
  - *private-npm
53
56
  - *docker-ecr-cache
54
- - docker-compose#v4.14.0:
57
+ - docker-compose#v4.16.0:
55
58
  run: app
56
59
  timeout_in_minutes: 10
57
60
 
@@ -7,5 +7,5 @@ WORKDIR /workdir
7
7
  COPY package.json yarn.lock ./
8
8
 
9
9
  RUN \
10
- --mount=type=secret,id=npm,dst=/workdir/.npmrc \
10
+ --mount=type=secret,id=npm,dst=/root/.npmrc \
11
11
  yarn install --frozen-lockfile --ignore-optional --non-interactive
@@ -19,12 +19,12 @@ Next steps:
19
19
  6. [ ] Configure [GitHub repository settings].
20
20
  7. [ ] Delete this checklist ๐Ÿ˜Œ.
21
21
 
22
- [builds at seek]: https://builds-at-seek.ssod.skinfra.xyz
22
+ [builds at seek]: https://backstage.myseek.xyz/docs/default/component/builds-cicd-seek/
23
23
  [github repository settings]: https://github.com/<%-orgName%>/<%-repoName%>/settings
24
24
 
25
25
  ## Design
26
26
 
27
- <%-repoName %> is a Node.js HTTP server built in line with our [technology strategy].
27
+ <%-repoName %> is a Node.js HTTP server built in line with our [Technical Guidelines].
28
28
  It uses the [Koa] middleware framework and common SEEK packages.
29
29
  Resource APIs enable synchronous interactions and serve as the backbone of SEEK's general service architecture.
30
30
 
@@ -105,7 +105,7 @@ TODO: add support links for the prod environment.
105
105
  - Splunk logs
106
106
  -->
107
107
 
108
- [codedeploy]: https://docs.aws.amazon.com/codedeploy
109
- [gantry]: https://backstage.myseek.xyz/docs/default/component/gantry/
110
- [koa]: https://koajs.com
111
- [technology strategy]: https://tech-strategy.ssod.skinfra.xyz
108
+ [CodeDeploy]: https://docs.aws.amazon.com/codedeploy
109
+ [Gantry]: https://backstage.myseek.xyz/docs/default/component/gantry/
110
+ [Koa]: https://koajs.com
111
+ [Technical Guidelines]: https://myseek.atlassian.net/wiki/spaces/AA/pages/2358346017/
@@ -14,10 +14,10 @@
14
14
  "dependencies": {
15
15
  "@koa/router": "^12.0.0",
16
16
  "@opentelemetry/api": "^1.1.0",
17
- "@opentelemetry/exporter-trace-otlp-grpc": "^0.41.0",
17
+ "@opentelemetry/exporter-trace-otlp-grpc": "^0.44.0",
18
18
  "@opentelemetry/instrumentation-aws-sdk": "^0.36.0",
19
- "@opentelemetry/instrumentation-http": "^0.41.0",
20
- "@opentelemetry/sdk-node": "^0.41.0",
19
+ "@opentelemetry/instrumentation-http": "^0.44.0",
20
+ "@opentelemetry/sdk-node": "^0.44.0",
21
21
  "@seek/logger": "^6.0.0",
22
22
  "aws-sdk": "^2.1039.0",
23
23
  "hot-shots": "^10.0.0",
@@ -10,11 +10,15 @@ describe('app', () => {
10
10
 
11
11
  it('has a happy health check', () => agent.get('/health').expect(200, ''));
12
12
 
13
- it('has a reachable smoke test', () =>
14
- agent.get('/smoke').expect(({ status }) => status !== 404));
13
+ it('has a reachable smoke test', async () => {
14
+ const response = await agent.get('/smoke');
15
+ expect(response.status).not.toBe(404);
16
+ });
15
17
 
16
- it('has a reachable nested route', () =>
17
- agent.get('/jobs').expect(({ status }) => status !== 404));
18
+ it('has a reachable nested route', async () => {
19
+ const response = await agent.get('/jobs');
20
+ expect(response.status).not.toBe(404);
21
+ });
18
22
 
19
23
  it('has OPTIONS for a nested route', () =>
20
24
  agent.options('/jobs').expect(200).expect('allow', /HEAD/));