skuba 5.0.0-beta.0 → 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 (44) hide show
  1. package/lib/cli/adapter/prettier.js +10 -0
  2. package/lib/cli/adapter/prettier.js.map +2 -2
  3. package/lib/cli/configure/getEntryPoint.js +1 -1
  4. package/lib/cli/configure/getEntryPoint.js.map +2 -2
  5. package/lib/cli/configure/getProjectType.js +1 -1
  6. package/lib/cli/configure/getProjectType.js.map +2 -2
  7. package/lib/cli/configure/index.js +1 -1
  8. package/lib/cli/configure/index.js.map +2 -2
  9. package/lib/cli/configure/modules/jest.js +2 -4
  10. package/lib/cli/configure/modules/jest.js.map +2 -2
  11. package/lib/cli/configure/modules/tsconfig.js +8 -3
  12. package/lib/cli/configure/modules/tsconfig.js.map +2 -2
  13. package/lib/cli/init/getConfig.d.ts +1 -1
  14. package/lib/cli/init/getConfig.js +1 -1
  15. package/lib/cli/init/getConfig.js.map +2 -2
  16. package/lib/cli/init/prompts.js +1 -1
  17. package/lib/cli/init/prompts.js.map +2 -2
  18. package/lib/cli/lint/annotate/index.d.ts +1 -1
  19. package/lib/cli/lint/annotate/index.js.map +2 -2
  20. package/package.json +71 -71
  21. package/template/base/tsconfig.json +2 -2
  22. package/template/express-rest-api/.nvmrc +1 -1
  23. package/template/express-rest-api/Dockerfile +1 -1
  24. package/template/express-rest-api/Dockerfile.dev-deps +1 -1
  25. package/template/express-rest-api/package.json +14 -14
  26. package/template/greeter/.nvmrc +1 -1
  27. package/template/greeter/Dockerfile +1 -1
  28. package/template/greeter/package.json +11 -11
  29. package/template/koa-rest-api/.nvmrc +1 -1
  30. package/template/koa-rest-api/Dockerfile +1 -1
  31. package/template/koa-rest-api/Dockerfile.dev-deps +1 -1
  32. package/template/koa-rest-api/package.json +15 -15
  33. package/template/koa-rest-api/src/framework/validation.ts +19 -6
  34. package/template/lambda-sqs-worker/.buildkite/pipeline.yml +1 -1
  35. package/template/lambda-sqs-worker/Dockerfile +1 -1
  36. package/template/lambda-sqs-worker/package.json +14 -14
  37. package/template/lambda-sqs-worker/src/framework/validation.ts +8 -2
  38. package/template/lambda-sqs-worker/tsconfig.json +13 -0
  39. package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +1 -1
  40. package/template/lambda-sqs-worker-cdk/Dockerfile +1 -1
  41. package/template/lambda-sqs-worker-cdk/package.json +12 -12
  42. package/template/lambda-sqs-worker-cdk/tsconfig.json +13 -0
  43. package/template/oss-npm-package/.nvmrc +1 -1
  44. package/template/private-npm-package/.nvmrc +1 -1
@@ -34,6 +34,7 @@ var import_prettier = require("prettier");
34
34
  var import_dir = require("../../utils/dir");
35
35
  var import_logging = require("../../utils/logging");
36
36
  var import_manifest = require("../../utils/manifest");
37
+ var import_package = require("../configure/processing/package");
37
38
  let languages;
38
39
  const inferParser = (filepath) => {
39
40
  const filename = import_path.default.basename(filepath).toLowerCase();
@@ -64,6 +65,15 @@ const formatOrLintFile = ({ data, filepath, options }, mode, result) => {
64
65
  result.errored.push({ err, filepath });
65
66
  return;
66
67
  }
68
+ try {
69
+ if (import_path.default.basename(filepath) === "package.json") {
70
+ const packageJson = (0, import_package.parsePackage)(formatted);
71
+ if (packageJson) {
72
+ formatted = (0, import_package.formatPackage)(packageJson);
73
+ }
74
+ }
75
+ } catch {
76
+ }
67
77
  if (formatted === data) {
68
78
  return;
69
79
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/adapter/prettier.ts"],
4
- "sourcesContent": ["import path from 'path';\n\nimport fs from 'fs-extra';\nimport type { Options, SupportLanguage } from 'prettier';\nimport { check, format, getSupportInfo, resolveConfig } from 'prettier';\n\nimport { crawlDirectory } from '../../utils/dir';\nimport type { Logger } from '../../utils/logging';\nimport { pluralise } from '../../utils/logging';\nimport { getConsumerManifest } from '../../utils/manifest';\n\nlet languages: SupportLanguage[] | undefined;\n\n/**\n * Infers a parser for the specified filepath.\n *\n * This is a cut-down version of Prettier's built-in function of the same name;\n * ours operates purely on the `filepath` string and does not perform file I/O.\n * Prettier's internal `getInterpreter` function can open a file to read the\n * shebang, and its file descriptor usage can throw warnings on worker threads:\n *\n * ```console\n * Warning: File descriptor 123 closed but not opened in unmanaged mode\n * at Object.closeSync (node:fs:530:11)\n * at Object.closeSync (node_modules/graceful-fs/graceful-fs.js:74:20)\n * ...\n * ```\n *\n * References:\n *\n * - https://github.com/prettier/prettier/blob/2.4.1/src/main/options.js#L167\n * - seek-oss/skuba#659\n */\nexport const inferParser = (filepath: string): string | undefined => {\n const filename = path.basename(filepath).toLowerCase();\n\n languages ??= getSupportInfo().languages.filter((language) => language.since);\n\n const firstLanguage = languages.find(\n (language) =>\n language.extensions?.some((extension) => filename.endsWith(extension)) ||\n language.filenames?.some((name) => name.toLowerCase() === filename),\n );\n\n return firstLanguage?.parsers[0];\n};\n\ninterface File {\n data: string;\n options: Options;\n filepath: string;\n}\n\ninterface Result {\n count: number;\n errored: Array<{ err?: unknown; filepath: string }>;\n touched: string[];\n unparsed: string[];\n}\n\nconst formatOrLintFile = (\n { data, filepath, options }: File,\n mode: 'format' | 'lint',\n result: Result,\n): string | undefined => {\n if (mode === 'lint') {\n let ok: boolean;\n try {\n ok = check(data, options);\n } catch (err) {\n result.errored.push({ err, filepath });\n return;\n }\n\n if (!ok) {\n result.errored.push({ filepath });\n }\n\n return;\n }\n\n let formatted: string;\n try {\n formatted = format(data, options);\n } catch (err) {\n result.errored.push({ err, filepath });\n return;\n }\n\n if (formatted === data) {\n return;\n }\n\n result.touched.push(filepath);\n return formatted;\n};\n\nexport interface PrettierOutput {\n ok: boolean;\n result: Result;\n}\n\n/**\n * Formats/lints files with Prettier.\n *\n * Prettier doesn't provide a higher-level Node.js API that replicates the\n * behaviour of its CLI, so we have to plumb together its lower-level functions.\n * On the other hand, this affords more flexibility in how we track and report\n * on progress and results.\n */\nexport const runPrettier = async (\n mode: 'format' | 'lint',\n logger: Logger,\n): Promise<PrettierOutput> => {\n logger.debug('Initialising Prettier...');\n\n const start = process.hrtime.bigint();\n\n let directory = process.cwd();\n\n const manifest = await getConsumerManifest();\n if (manifest) {\n directory = path.dirname(manifest.path);\n }\n\n logger.debug(\n manifest ? 'Detected project root:' : 'Detected working directory:',\n directory,\n );\n\n logger.debug('Discovering files...');\n\n // Match Prettier's opinion of not respecting `.gitignore`.\n // This avoids exhibiting different behaviour than a Prettier IDE integration,\n // and the headache of conflicting `.gitignore` and `.prettierignore` rules.\n const filepaths = await crawlDirectory(directory, '.prettierignore');\n\n logger.debug(`Discovered ${pluralise(filepaths.length, 'file')}.`);\n\n const result: Result = {\n count: filepaths.length,\n errored: [],\n touched: [],\n unparsed: [],\n };\n\n logger.debug(mode === 'format' ? 'Formatting' : 'Linting', 'files...');\n\n for (const filepath of filepaths) {\n // Infer parser upfront so we can skip unsupported files.\n const parser = inferParser(filepath);\n\n logger.debug(filepath);\n logger.debug(' parser:', parser ?? '-');\n\n if (!parser) {\n result.unparsed.push(filepath);\n continue;\n }\n\n const [config, data] = await Promise.all([\n resolveConfig(filepath),\n fs.promises.readFile(filepath, 'utf-8'),\n ]);\n\n const file: File = {\n data,\n filepath,\n options: { ...config, filepath },\n };\n\n const formatted = formatOrLintFile(file, mode, result);\n\n if (typeof formatted === 'string') {\n await fs.promises.writeFile(filepath, formatted);\n }\n }\n\n const end = process.hrtime.bigint();\n\n logger.plain(\n `Processed ${pluralise(\n result.count - result.unparsed.length,\n 'file',\n )} in ${logger.timing(start, end)}.`,\n );\n\n if (result.touched.length) {\n logger.plain(`Formatted ${pluralise(result.touched.length, 'file')}:`);\n for (const filepath of result.touched) {\n logger.warn(filepath);\n }\n }\n\n if (result.errored.length) {\n logger.plain(`Flagged ${pluralise(result.errored.length, 'file')}:`);\n for (const { err, filepath } of result.errored) {\n logger.warn(filepath, ...(err ? [String(err)] : []));\n }\n }\n\n return { ok: result.errored.length === 0, result };\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import path from 'path';\n\nimport fs from 'fs-extra';\nimport type { Options, SupportLanguage } from 'prettier';\nimport { check, format, getSupportInfo, resolveConfig } from 'prettier';\n\nimport { crawlDirectory } from '../../utils/dir';\nimport type { Logger } from '../../utils/logging';\nimport { pluralise } from '../../utils/logging';\nimport { getConsumerManifest } from '../../utils/manifest';\nimport { formatPackage, parsePackage } from '../configure/processing/package';\n\nlet languages: SupportLanguage[] | undefined;\n\n/**\n * Infers a parser for the specified filepath.\n *\n * This is a cut-down version of Prettier's built-in function of the same name;\n * ours operates purely on the `filepath` string and does not perform file I/O.\n * Prettier's internal `getInterpreter` function can open a file to read the\n * shebang, and its file descriptor usage can throw warnings on worker threads:\n *\n * ```console\n * Warning: File descriptor 123 closed but not opened in unmanaged mode\n * at Object.closeSync (node:fs:530:11)\n * at Object.closeSync (node_modules/graceful-fs/graceful-fs.js:74:20)\n * ...\n * ```\n *\n * References:\n *\n * - https://github.com/prettier/prettier/blob/2.4.1/src/main/options.js#L167\n * - seek-oss/skuba#659\n */\nexport const inferParser = (filepath: string): string | undefined => {\n const filename = path.basename(filepath).toLowerCase();\n\n languages ??= getSupportInfo().languages.filter((language) => language.since);\n\n const firstLanguage = languages.find(\n (language) =>\n language.extensions?.some((extension) => filename.endsWith(extension)) ||\n language.filenames?.some((name) => name.toLowerCase() === filename),\n );\n\n return firstLanguage?.parsers[0];\n};\n\ninterface File {\n data: string;\n options: Options;\n filepath: string;\n}\n\ninterface Result {\n count: number;\n errored: Array<{ err?: unknown; filepath: string }>;\n touched: string[];\n unparsed: string[];\n}\n\nconst formatOrLintFile = (\n { data, filepath, options }: File,\n mode: 'format' | 'lint',\n result: Result,\n): string | undefined => {\n if (mode === 'lint') {\n let ok: boolean;\n try {\n ok = check(data, options);\n } catch (err) {\n result.errored.push({ err, filepath });\n return;\n }\n\n if (!ok) {\n result.errored.push({ filepath });\n }\n\n return;\n }\n\n let formatted: string;\n try {\n formatted = format(data, options);\n } catch (err) {\n result.errored.push({ err, filepath });\n return;\n }\n\n // Perform additional formatting (i.e. sorting) on a `package.json` manifest.\n try {\n if (path.basename(filepath) === 'package.json') {\n const packageJson = parsePackage(formatted);\n if (packageJson) {\n formatted = formatPackage(packageJson);\n }\n }\n } catch {\n // Our additional formatting is strictly optional; don't throw if it fails.\n }\n\n if (formatted === data) {\n return;\n }\n\n result.touched.push(filepath);\n return formatted;\n};\n\nexport interface PrettierOutput {\n ok: boolean;\n result: Result;\n}\n\n/**\n * Formats/lints files with Prettier.\n *\n * Prettier doesn't provide a higher-level Node.js API that replicates the\n * behaviour of its CLI, so we have to plumb together its lower-level functions.\n * On the other hand, this affords more flexibility in how we track and report\n * on progress and results.\n */\nexport const runPrettier = async (\n mode: 'format' | 'lint',\n logger: Logger,\n): Promise<PrettierOutput> => {\n logger.debug('Initialising Prettier...');\n\n const start = process.hrtime.bigint();\n\n let directory = process.cwd();\n\n const manifest = await getConsumerManifest();\n if (manifest) {\n directory = path.dirname(manifest.path);\n }\n\n logger.debug(\n manifest ? 'Detected project root:' : 'Detected working directory:',\n directory,\n );\n\n logger.debug('Discovering files...');\n\n // Match Prettier's opinion of not respecting `.gitignore`.\n // This avoids exhibiting different behaviour than a Prettier IDE integration,\n // and the headache of conflicting `.gitignore` and `.prettierignore` rules.\n const filepaths = await crawlDirectory(directory, '.prettierignore');\n\n logger.debug(`Discovered ${pluralise(filepaths.length, 'file')}.`);\n\n const result: Result = {\n count: filepaths.length,\n errored: [],\n touched: [],\n unparsed: [],\n };\n\n logger.debug(mode === 'format' ? 'Formatting' : 'Linting', 'files...');\n\n for (const filepath of filepaths) {\n // Infer parser upfront so we can skip unsupported files.\n const parser = inferParser(filepath);\n\n logger.debug(filepath);\n logger.debug(' parser:', parser ?? '-');\n\n if (!parser) {\n result.unparsed.push(filepath);\n continue;\n }\n\n const [config, data] = await Promise.all([\n resolveConfig(filepath),\n fs.promises.readFile(filepath, 'utf-8'),\n ]);\n\n const file: File = {\n data,\n filepath,\n options: { ...config, filepath },\n };\n\n const formatted = formatOrLintFile(file, mode, result);\n\n if (typeof formatted === 'string') {\n await fs.promises.writeFile(filepath, formatted);\n }\n }\n\n const end = process.hrtime.bigint();\n\n logger.plain(\n `Processed ${pluralise(\n result.count - result.unparsed.length,\n 'file',\n )} in ${logger.timing(start, end)}.`,\n );\n\n if (result.touched.length) {\n logger.plain(`Formatted ${pluralise(result.touched.length, 'file')}:`);\n for (const filepath of result.touched) {\n logger.warn(filepath);\n }\n }\n\n if (result.errored.length) {\n logger.plain(`Flagged ${pluralise(result.errored.length, 'file')}:`);\n for (const { err, filepath } of result.errored) {\n logger.warn(filepath, ...(err ? [String(err)] : []));\n }\n }\n\n return { ok: result.errored.length === 0, result };\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["path", "fs"]
7
7
  }
@@ -29,10 +29,10 @@ __export(getEntryPoint_exports, {
29
29
  module.exports = __toCommonJS(getEntryPoint_exports);
30
30
  var import_path = __toESM(require("path"));
31
31
  var import_chalk = __toESM(require("chalk"));
32
- var import_enquirer = require("enquirer");
33
32
  var import_logging = require("../../utils/logging");
34
33
  var import_validation = require("../../utils/validation");
35
34
  var import_files = require("./analysis/files");
35
+ var import_enquirer = require("enquirer");
36
36
  const getEntryPoint = ({
37
37
  destinationRoot,
38
38
  manifest,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/configure/getEntryPoint.ts"],
4
- "sourcesContent": ["import path from 'path';\n\nimport chalk from 'chalk';\nimport { Input } from 'enquirer';\nimport type { NormalizedReadResult } from 'read-pkg-up';\n\nimport { log } from '../../utils/logging';\nimport type { ProjectType } from '../../utils/manifest';\nimport type { TemplateConfig } from '../../utils/template';\nimport { hasStringProp } from '../../utils/validation';\n\nimport { tsFileExists } from './analysis/files';\n\ninterface Props {\n destinationRoot: string;\n manifest: NormalizedReadResult;\n templateConfig: TemplateConfig;\n type: ProjectType;\n}\nexport const getEntryPoint = ({\n destinationRoot,\n manifest,\n templateConfig,\n type,\n}: Props) => {\n if (hasStringProp(manifest.packageJson.skuba, 'entryPoint')) {\n return manifest.packageJson.skuba.entryPoint;\n }\n\n if (templateConfig.entryPoint !== undefined) {\n return templateConfig.entryPoint;\n }\n\n log.newline();\n const entryPointPrompt = new Input({\n initial: type === 'package' ? 'src/index.ts' : 'src/app.ts',\n message: 'Entry point:',\n name: 'entryPoint',\n result: (value) => (value.endsWith('.ts') ? value : `${value}.ts`),\n validate: async (value) => {\n // Support exported function targeting, e.g. `src/module.ts#callMeMaybe`\n const [modulePath] = value.split('#', 2);\n\n const exists = await tsFileExists(path.join(destinationRoot, modulePath));\n\n return exists || `${chalk.bold(value)} is not a TypeScript file.`;\n },\n });\n\n return entryPointPrompt.run();\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,mBAAkB;AAClB,sBAAsB;AAGtB,qBAAoB;AAGpB,wBAA8B;AAE9B,mBAA6B;AAQtB,MAAM,gBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAa;AACX,UAAI,iCAAc,SAAS,YAAY,OAAO,YAAY,GAAG;AAC3D,WAAO,SAAS,YAAY,MAAM;AAAA,EACpC;AAEA,MAAI,eAAe,eAAe,QAAW;AAC3C,WAAO,eAAe;AAAA,EACxB;AAEA,qBAAI,QAAQ;AACZ,QAAM,mBAAmB,IAAI,sBAAM;AAAA,IACjC,SAAS,SAAS,YAAY,iBAAiB;AAAA,IAC/C,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ,CAAC,UAAW,MAAM,SAAS,KAAK,IAAI,QAAQ,GAAG;AAAA,IACvD,UAAU,OAAO,UAAU;AAEzB,YAAM,CAAC,UAAU,IAAI,MAAM,MAAM,KAAK,CAAC;AAEvC,YAAM,SAAS,UAAM,2BAAa,YAAAA,QAAK,KAAK,iBAAiB,UAAU,CAAC;AAExE,aAAO,UAAU,GAAG,aAAAC,QAAM,KAAK,KAAK;AAAA,IACtC;AAAA,EACF,CAAC;AAED,SAAO,iBAAiB,IAAI;AAC9B;",
4
+ "sourcesContent": ["import path from 'path';\n\nimport chalk from 'chalk';\nimport type { NormalizedReadResult } from 'read-pkg-up';\n\nimport { log } from '../../utils/logging';\nimport type { ProjectType } from '../../utils/manifest';\nimport type { TemplateConfig } from '../../utils/template';\nimport { hasStringProp } from '../../utils/validation';\n\nimport { tsFileExists } from './analysis/files';\n\nimport { Input } from 'enquirer';\n\ninterface Props {\n destinationRoot: string;\n manifest: NormalizedReadResult;\n templateConfig: TemplateConfig;\n type: ProjectType;\n}\nexport const getEntryPoint = ({\n destinationRoot,\n manifest,\n templateConfig,\n type,\n}: Props) => {\n if (hasStringProp(manifest.packageJson.skuba, 'entryPoint')) {\n return manifest.packageJson.skuba.entryPoint;\n }\n\n if (templateConfig.entryPoint !== undefined) {\n return templateConfig.entryPoint;\n }\n\n log.newline();\n const entryPointPrompt = new Input({\n initial: type === 'package' ? 'src/index.ts' : 'src/app.ts',\n message: 'Entry point:',\n name: 'entryPoint',\n result: (value) => (value.endsWith('.ts') ? value : `${value}.ts`),\n validate: async (value) => {\n // Support exported function targeting, e.g. `src/module.ts#callMeMaybe`\n const [modulePath] = value.split('#', 2);\n\n const exists = await tsFileExists(path.join(destinationRoot, modulePath));\n\n return exists || `${chalk.bold(value)} is not a TypeScript file.`;\n },\n });\n\n return entryPointPrompt.run();\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,mBAAkB;AAGlB,qBAAoB;AAGpB,wBAA8B;AAE9B,mBAA6B;AAE7B,sBAAsB;AAQf,MAAM,gBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAa;AACX,UAAI,iCAAc,SAAS,YAAY,OAAO,YAAY,GAAG;AAC3D,WAAO,SAAS,YAAY,MAAM;AAAA,EACpC;AAEA,MAAI,eAAe,eAAe,QAAW;AAC3C,WAAO,eAAe;AAAA,EACxB;AAEA,qBAAI,QAAQ;AACZ,QAAM,mBAAmB,IAAI,sBAAM;AAAA,IACjC,SAAS,SAAS,YAAY,iBAAiB;AAAA,IAC/C,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ,CAAC,UAAW,MAAM,SAAS,KAAK,IAAI,QAAQ,GAAG;AAAA,IACvD,UAAU,OAAO,UAAU;AAEzB,YAAM,CAAC,UAAU,IAAI,MAAM,MAAM,KAAK,CAAC;AAEvC,YAAM,SAAS,UAAM,2BAAa,YAAAA,QAAK,KAAK,iBAAiB,UAAU,CAAC;AAExE,aAAO,UAAU,GAAG,aAAAC,QAAM,KAAK,KAAK;AAAA,IACtC;AAAA,EACF,CAAC;AAED,SAAO,iBAAiB,IAAI;AAC9B;",
6
6
  "names": ["path", "chalk"]
7
7
  }
@@ -21,10 +21,10 @@ __export(getProjectType_exports, {
21
21
  getProjectType: () => getProjectType
22
22
  });
23
23
  module.exports = __toCommonJS(getProjectType_exports);
24
- var import_enquirer = require("enquirer");
25
24
  var import_logging = require("../../utils/logging");
26
25
  var import_manifest = require("../../utils/manifest");
27
26
  var import_validation = require("../../utils/validation");
27
+ var import_enquirer = require("enquirer");
28
28
  const getProjectType = async ({
29
29
  manifest,
30
30
  templateConfig
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/configure/getProjectType.ts"],
4
- "sourcesContent": ["import { Select } from 'enquirer';\nimport type { NormalizedReadResult } from 'read-pkg-up';\n\nimport { log } from '../../utils/logging';\nimport { PROJECT_TYPES, ProjectType } from '../../utils/manifest';\nimport type { TemplateConfig } from '../../utils/template';\nimport { hasProp } from '../../utils/validation';\n\ninterface Props {\n manifest: NormalizedReadResult;\n templateConfig: TemplateConfig;\n}\n\nexport const getProjectType = async ({\n manifest,\n templateConfig,\n}: Props): Promise<ProjectType> => {\n if (\n hasProp(manifest.packageJson.skuba, 'type') &&\n ProjectType.guard(manifest.packageJson.skuba.type)\n ) {\n return manifest.packageJson.skuba.type;\n }\n\n if (templateConfig.type !== undefined) {\n return templateConfig.type;\n }\n\n const initial: ProjectType =\n manifest.packageJson.devDependencies?.['@seek/seek-module-toolkit'] ||\n manifest.packageJson.files\n ? 'package'\n : 'application';\n\n log.newline();\n const projectTypePrompt = new Select({\n choices: PROJECT_TYPES,\n message: 'Project type:',\n name: 'projectType',\n initial,\n });\n\n return projectTypePrompt.run();\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAuB;AAGvB,qBAAoB;AACpB,sBAA2C;AAE3C,wBAAwB;AAOjB,MAAM,iBAAiB,OAAO;AAAA,EACnC;AAAA,EACA;AACF,MAAmC;AACjC,UACE,2BAAQ,SAAS,YAAY,OAAO,MAAM,KAC1C,4BAAY,MAAM,SAAS,YAAY,MAAM,IAAI,GACjD;AACA,WAAO,SAAS,YAAY,MAAM;AAAA,EACpC;AAEA,MAAI,eAAe,SAAS,QAAW;AACrC,WAAO,eAAe;AAAA,EACxB;AAEA,QAAM,UACJ,SAAS,YAAY,kBAAkB,gCACvC,SAAS,YAAY,QACjB,YACA;AAEN,qBAAI,QAAQ;AACZ,QAAM,oBAAoB,IAAI,uBAAO;AAAA,IACnC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AAED,SAAO,kBAAkB,IAAI;AAC/B;",
4
+ "sourcesContent": ["import type { NormalizedReadResult } from 'read-pkg-up';\n\nimport { log } from '../../utils/logging';\nimport { PROJECT_TYPES, ProjectType } from '../../utils/manifest';\nimport type { TemplateConfig } from '../../utils/template';\nimport { hasProp } from '../../utils/validation';\n\nimport { Select } from 'enquirer';\n\ninterface Props {\n manifest: NormalizedReadResult;\n templateConfig: TemplateConfig;\n}\n\nexport const getProjectType = async ({\n manifest,\n templateConfig,\n}: Props): Promise<ProjectType> => {\n if (\n hasProp(manifest.packageJson.skuba, 'type') &&\n ProjectType.guard(manifest.packageJson.skuba.type)\n ) {\n return manifest.packageJson.skuba.type;\n }\n\n if (templateConfig.type !== undefined) {\n return templateConfig.type;\n }\n\n const initial: ProjectType =\n manifest.packageJson.devDependencies?.['@seek/seek-module-toolkit'] ||\n manifest.packageJson.files\n ? 'package'\n : 'application';\n\n log.newline();\n const projectTypePrompt = new Select({\n choices: PROJECT_TYPES,\n message: 'Project type:',\n name: 'projectType',\n initial,\n });\n\n return projectTypePrompt.run();\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,qBAAoB;AACpB,sBAA2C;AAE3C,wBAAwB;AAExB,sBAAuB;AAOhB,MAAM,iBAAiB,OAAO;AAAA,EACnC;AAAA,EACA;AACF,MAAmC;AACjC,UACE,2BAAQ,SAAS,YAAY,OAAO,MAAM,KAC1C,4BAAY,MAAM,SAAS,YAAY,MAAM,IAAI,GACjD;AACA,WAAO,SAAS,YAAY,MAAM;AAAA,EACpC;AAEA,MAAI,eAAe,SAAS,QAAW;AACrC,WAAO,eAAe;AAAA,EACxB;AAEA,QAAM,UACJ,SAAS,YAAY,kBAAkB,gCACvC,SAAS,YAAY,QACjB,YACA;AAEN,qBAAI,QAAQ;AACZ,QAAM,oBAAoB,IAAI,uBAAO;AAAA,IACnC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AAED,SAAO,kBAAkB,IAAI;AAC/B;",
6
6
  "names": []
7
7
  }
@@ -28,7 +28,6 @@ __export(configure_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(configure_exports);
30
30
  var import_path = __toESM(require("path"));
31
- var import_enquirer = require("enquirer");
32
31
  var import_dir = require("../../utils/dir");
33
32
  var import_exec = require("../../utils/exec");
34
33
  var import_logging = require("../../utils/logging");
@@ -42,6 +41,7 @@ var import_package = require("./analysis/package");
42
41
  var import_ensureTemplateCompletion = require("./ensureTemplateCompletion");
43
42
  var import_getEntryPoint = require("./getEntryPoint");
44
43
  var import_getProjectType = require("./getProjectType");
44
+ var import_enquirer = require("enquirer");
45
45
  const shouldApply = async (name) => {
46
46
  const prompt = new import_enquirer.Select({
47
47
  choices: ["yes", "no"],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/configure/index.ts"],
4
- "sourcesContent": ["import path from 'path';\n\nimport { Select } from 'enquirer';\n\nimport { createInclusionFilter } from '../../utils/dir';\nimport { createExec, ensureCommands } from '../../utils/exec';\nimport { log } from '../../utils/logging';\nimport { showLogoAndVersionInfo } from '../../utils/logo';\nimport { BASE_TEMPLATE_DIR } from '../../utils/template';\nimport { hasProp } from '../../utils/validation';\n\nimport { analyseConfiguration } from './analyseConfiguration';\nimport { analyseDependencies } from './analyseDependencies';\nimport { auditWorkingTree } from './analysis/git';\nimport { getDestinationManifest } from './analysis/package';\nimport { ensureTemplateCompletion } from './ensureTemplateCompletion';\nimport { getEntryPoint } from './getEntryPoint';\nimport { getProjectType } from './getProjectType';\n\nconst shouldApply = async (name: string) => {\n const prompt = new Select({\n choices: ['yes', 'no'] as const,\n message: 'Apply changes?',\n name,\n });\n\n const result = await prompt.run();\n\n return result === 'yes';\n};\n\nexport const configure = async () => {\n await showLogoAndVersionInfo();\n\n const [manifest] = await Promise.all([\n getDestinationManifest(),\n ensureCommands('yarn'),\n ]);\n\n const destinationRoot = path.dirname(manifest.path);\n\n log.plain('Detected project root:', log.bold(destinationRoot));\n\n const [include] = await Promise.all([\n createInclusionFilter([\n path.join(destinationRoot, '.gitignore'),\n path.join(BASE_TEMPLATE_DIR, '_.gitignore'),\n ]),\n\n auditWorkingTree(destinationRoot),\n ]);\n\n const templateConfig = await ensureTemplateCompletion({\n destinationRoot,\n include,\n manifest,\n });\n\n const type = await getProjectType({\n manifest,\n templateConfig,\n });\n\n const entryPoint = await getEntryPoint({\n destinationRoot,\n manifest,\n templateConfig,\n type,\n });\n\n const fixDependencies = await analyseDependencies({\n destinationRoot,\n include,\n manifest,\n type,\n });\n\n if (fixDependencies) {\n log.newline();\n\n if (await shouldApply('fixDependencies')) {\n await fixDependencies();\n }\n }\n\n const firstRun = hasProp(manifest.packageJson, 'skuba');\n\n const fixConfiguration = await analyseConfiguration({\n destinationRoot,\n entryPoint,\n firstRun,\n type,\n });\n\n if (fixConfiguration) {\n log.newline();\n\n if (await shouldApply('fixConfiguration')) {\n await fixConfiguration();\n }\n }\n\n if (fixDependencies) {\n const exec = createExec({\n stdio: 'pipe',\n streamStdio: 'yarn',\n });\n\n log.newline();\n try {\n await exec('yarn', 'install');\n } catch {\n log.newline();\n log.warn(log.bold('\u2717 Failed to install dependencies. Resume with:'));\n\n log.newline();\n log.plain(log.bold('yarn install'));\n log.plain(log.bold('yarn format'));\n\n log.newline();\n process.exitCode = 1;\n return;\n }\n try {\n await exec('npx', 'yarn-deduplicate', '--strategy=highest');\n } catch {}\n }\n\n if (fixConfiguration || fixDependencies) {\n log.newline();\n log.ok(log.bold('\u2714 All done! Try running:'));\n\n log.newline();\n log.plain(log.bold('yarn format'));\n }\n\n log.newline();\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import path from 'path';\n\nimport { createInclusionFilter } from '../../utils/dir';\nimport { createExec, ensureCommands } from '../../utils/exec';\nimport { log } from '../../utils/logging';\nimport { showLogoAndVersionInfo } from '../../utils/logo';\nimport { BASE_TEMPLATE_DIR } from '../../utils/template';\nimport { hasProp } from '../../utils/validation';\n\nimport { analyseConfiguration } from './analyseConfiguration';\nimport { analyseDependencies } from './analyseDependencies';\nimport { auditWorkingTree } from './analysis/git';\nimport { getDestinationManifest } from './analysis/package';\nimport { ensureTemplateCompletion } from './ensureTemplateCompletion';\nimport { getEntryPoint } from './getEntryPoint';\nimport { getProjectType } from './getProjectType';\n\nimport { Select } from 'enquirer';\n\nconst shouldApply = async (name: string) => {\n const prompt = new Select({\n choices: ['yes', 'no'] as const,\n message: 'Apply changes?',\n name,\n });\n\n const result = await prompt.run();\n\n return result === 'yes';\n};\n\nexport const configure = async () => {\n await showLogoAndVersionInfo();\n\n const [manifest] = await Promise.all([\n getDestinationManifest(),\n ensureCommands('yarn'),\n ]);\n\n const destinationRoot = path.dirname(manifest.path);\n\n log.plain('Detected project root:', log.bold(destinationRoot));\n\n const [include] = await Promise.all([\n createInclusionFilter([\n path.join(destinationRoot, '.gitignore'),\n path.join(BASE_TEMPLATE_DIR, '_.gitignore'),\n ]),\n\n auditWorkingTree(destinationRoot),\n ]);\n\n const templateConfig = await ensureTemplateCompletion({\n destinationRoot,\n include,\n manifest,\n });\n\n const type = await getProjectType({\n manifest,\n templateConfig,\n });\n\n const entryPoint = await getEntryPoint({\n destinationRoot,\n manifest,\n templateConfig,\n type,\n });\n\n const fixDependencies = await analyseDependencies({\n destinationRoot,\n include,\n manifest,\n type,\n });\n\n if (fixDependencies) {\n log.newline();\n\n if (await shouldApply('fixDependencies')) {\n await fixDependencies();\n }\n }\n\n const firstRun = hasProp(manifest.packageJson, 'skuba');\n\n const fixConfiguration = await analyseConfiguration({\n destinationRoot,\n entryPoint,\n firstRun,\n type,\n });\n\n if (fixConfiguration) {\n log.newline();\n\n if (await shouldApply('fixConfiguration')) {\n await fixConfiguration();\n }\n }\n\n if (fixDependencies) {\n const exec = createExec({\n stdio: 'pipe',\n streamStdio: 'yarn',\n });\n\n log.newline();\n try {\n await exec('yarn', 'install');\n } catch {\n log.newline();\n log.warn(log.bold('\u2717 Failed to install dependencies. Resume with:'));\n\n log.newline();\n log.plain(log.bold('yarn install'));\n log.plain(log.bold('yarn format'));\n\n log.newline();\n process.exitCode = 1;\n return;\n }\n try {\n await exec('npx', 'yarn-deduplicate', '--strategy=highest');\n } catch {}\n }\n\n if (fixConfiguration || fixDependencies) {\n log.newline();\n log.ok(log.bold('\u2714 All done! Try running:'));\n\n log.newline();\n log.plain(log.bold('yarn format'));\n }\n\n log.newline();\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["path"]
7
7
  }
@@ -23,7 +23,6 @@ __export(jest_exports, {
23
23
  module.exports = __toCommonJS(jest_exports);
24
24
  var import_template = require("../../../utils/template");
25
25
  var import_deleteFiles = require("../processing/deleteFiles");
26
- var import_loadFiles = require("../processing/loadFiles");
27
26
  var import_package = require("../processing/package");
28
27
  var import_typescript = require("../processing/typescript");
29
28
  const OUTDATED_ISOLATED_MODULES_CONFIG_SNIPPETS = [
@@ -55,8 +54,7 @@ const jestModule = async () => {
55
54
  (0, import_template.readBaseTemplateFile)("jest.setup.ts")
56
55
  ]);
57
56
  return {
58
- ...(0, import_deleteFiles.deleteFiles)("jest.config.js"),
59
- ...(0, import_loadFiles.loadFiles)("jest.setup.js"),
57
+ ...(0, import_deleteFiles.deleteFiles)("jest.config.js", "jest.setup.js"),
60
58
  "jest.config.ts": (tsFile, currentFiles, initialFiles) => {
61
59
  if (tsFile?.includes("skuba")) {
62
60
  return OUTDATED_ISOLATED_MODULES_CONFIG_SNIPPETS.reduce(
@@ -68,7 +66,7 @@ const jestModule = async () => {
68
66
  if (jsFile?.includes("skuba")) {
69
67
  return (0, import_typescript.transformModuleImportsAndExports)(jsFile, (_, p) => p);
70
68
  }
71
- currentFiles["jest.setup.ts"] ?? (currentFiles["jest.setup.ts"] = setupFile);
69
+ currentFiles["jest.setup.ts"] ?? (currentFiles["jest.setup.ts"] = initialFiles["jest.setup.js"] ?? setupFile);
72
70
  const inputFile = tsFile ?? jsFile;
73
71
  const props = inputFile === void 0 ? void 0 : (0, import_typescript.readModuleExports)(inputFile);
74
72
  if (props === void 0) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/configure/modules/jest.ts"],
4
- "sourcesContent": ["import { readBaseTemplateFile } from '../../../utils/template';\nimport { deleteFiles } from '../processing/deleteFiles';\nimport { loadFiles } from '../processing/loadFiles';\nimport { withPackage } from '../processing/package';\nimport {\n createPropAppender,\n createPropFilter,\n readModuleExports,\n transformModuleImportsAndExports,\n} from '../processing/typescript';\nimport type { Module } from '../types';\n\nconst OUTDATED_ISOLATED_MODULES_CONFIG_SNIPPETS = [\n `\n globals: {\n 'ts-jest': {\n // seek-oss/skuba#626\n isolatedModules: true,\n },\n },`,\n `\n globals: {\n 'ts-jest': {\n isolatedModules: true,\n },\n },`,\n];\n\n// Jest options to preserve during migration\nconst filterProps = createPropFilter([\n 'collectCoverageFrom',\n 'coverageThreshold',\n 'globalSetup',\n 'globalTeardown',\n 'setupFiles',\n 'setupFilesAfterEnv',\n]);\n\nexport const jestModule = async (): Promise<Module> => {\n const [configFile, setupFile] = await Promise.all([\n readBaseTemplateFile('jest.config.ts'),\n readBaseTemplateFile('jest.setup.ts'),\n ]);\n\n return {\n ...deleteFiles('jest.config.js'),\n ...loadFiles('jest.setup.js'),\n\n 'jest.config.ts': (tsFile, currentFiles, initialFiles) => {\n // Allow customised TS Jest config that extends skuba\n if (tsFile?.includes('skuba')) {\n return OUTDATED_ISOLATED_MODULES_CONFIG_SNIPPETS.reduce(\n (acc, snippet) => acc.replace(snippet, ''),\n tsFile,\n );\n }\n\n const jsFile = initialFiles['jest.config.js'];\n\n // Migrate a JS config that extends skuba, retaining all existing props\n if (jsFile?.includes('skuba')) {\n return transformModuleImportsAndExports(jsFile, (_, p) => p);\n }\n\n currentFiles['jest.setup.ts'] ??= setupFile;\n\n const inputFile = tsFile ?? jsFile;\n\n const props =\n inputFile === undefined ? undefined : readModuleExports(inputFile);\n\n if (props === undefined) {\n return configFile;\n }\n\n const filteredProps = filterProps(null, props);\n\n const appendProps = createPropAppender(filteredProps);\n\n // Append a subset of custom props to our base `jest.config.ts`\n return transformModuleImportsAndExports(configFile, appendProps);\n },\n\n 'package.json': withPackage(({ jest, ...data }) => data),\n };\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAqC;AACrC,yBAA4B;AAC5B,uBAA0B;AAC1B,qBAA4B;AAC5B,wBAKO;AAGP,MAAM,4CAA4C;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMF;AAGA,MAAM,kBAAc,oCAAiB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,MAAM,aAAa,YAA6B;AACrD,QAAM,CAAC,YAAY,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,QAChD,sCAAqB,gBAAgB;AAAA,QACrC,sCAAqB,eAAe;AAAA,EACtC,CAAC;AAED,SAAO;AAAA,IACL,OAAG,gCAAY,gBAAgB;AAAA,IAC/B,OAAG,4BAAU,eAAe;AAAA,IAE5B,kBAAkB,CAAC,QAAQ,cAAc,iBAAiB;AAExD,UAAI,QAAQ,SAAS,OAAO,GAAG;AAC7B,eAAO,0CAA0C;AAAA,UAC/C,CAAC,KAAK,YAAY,IAAI,QAAQ,SAAS,EAAE;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,aAAa;AAG5B,UAAI,QAAQ,SAAS,OAAO,GAAG;AAC7B,mBAAO,oDAAiC,QAAQ,CAAC,GAAG,MAAM,CAAC;AAAA,MAC7D;AAEA,wEAAkC;AAElC,YAAM,YAAY,UAAU;AAE5B,YAAM,QACJ,cAAc,SAAY,aAAY,qCAAkB,SAAS;AAEnE,UAAI,UAAU,QAAW;AACvB,eAAO;AAAA,MACT;AAEA,YAAM,gBAAgB,YAAY,MAAM,KAAK;AAE7C,YAAM,kBAAc,sCAAmB,aAAa;AAGpD,iBAAO,oDAAiC,YAAY,WAAW;AAAA,IACjE;AAAA,IAEA,oBAAgB,4BAAY,CAAC,EAAE,SAAS,KAAK,MAAM,IAAI;AAAA,EACzD;AACF;",
4
+ "sourcesContent": ["import { readBaseTemplateFile } from '../../../utils/template';\nimport { deleteFiles } from '../processing/deleteFiles';\nimport { withPackage } from '../processing/package';\nimport {\n createPropAppender,\n createPropFilter,\n readModuleExports,\n transformModuleImportsAndExports,\n} from '../processing/typescript';\nimport type { Module } from '../types';\n\nconst OUTDATED_ISOLATED_MODULES_CONFIG_SNIPPETS = [\n `\n globals: {\n 'ts-jest': {\n // seek-oss/skuba#626\n isolatedModules: true,\n },\n },`,\n `\n globals: {\n 'ts-jest': {\n isolatedModules: true,\n },\n },`,\n];\n\n// Jest options to preserve during migration\nconst filterProps = createPropFilter([\n 'collectCoverageFrom',\n 'coverageThreshold',\n 'globalSetup',\n 'globalTeardown',\n 'setupFiles',\n 'setupFilesAfterEnv',\n]);\n\nexport const jestModule = async (): Promise<Module> => {\n const [configFile, setupFile] = await Promise.all([\n readBaseTemplateFile('jest.config.ts'),\n readBaseTemplateFile('jest.setup.ts'),\n ]);\n\n return {\n ...deleteFiles('jest.config.js', 'jest.setup.js'),\n\n 'jest.config.ts': (tsFile, currentFiles, initialFiles) => {\n // Allow customised TS Jest config that extends skuba\n if (tsFile?.includes('skuba')) {\n return OUTDATED_ISOLATED_MODULES_CONFIG_SNIPPETS.reduce(\n (acc, snippet) => acc.replace(snippet, ''),\n tsFile,\n );\n }\n\n const jsFile = initialFiles['jest.config.js'];\n\n // Migrate a JS config that extends skuba, retaining all existing props\n if (jsFile?.includes('skuba')) {\n return transformModuleImportsAndExports(jsFile, (_, p) => p);\n }\n\n currentFiles['jest.setup.ts'] ??=\n initialFiles['jest.setup.js'] ?? setupFile;\n\n const inputFile = tsFile ?? jsFile;\n\n const props =\n inputFile === undefined ? undefined : readModuleExports(inputFile);\n\n if (props === undefined) {\n return configFile;\n }\n\n const filteredProps = filterProps(null, props);\n\n const appendProps = createPropAppender(filteredProps);\n\n // Append a subset of custom props to our base `jest.config.ts`\n return transformModuleImportsAndExports(configFile, appendProps);\n },\n\n 'package.json': withPackage(({ jest, ...data }) => data),\n };\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAqC;AACrC,yBAA4B;AAC5B,qBAA4B;AAC5B,wBAKO;AAGP,MAAM,4CAA4C;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMF;AAGA,MAAM,kBAAc,oCAAiB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,MAAM,aAAa,YAA6B;AACrD,QAAM,CAAC,YAAY,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,QAChD,sCAAqB,gBAAgB;AAAA,QACrC,sCAAqB,eAAe;AAAA,EACtC,CAAC;AAED,SAAO;AAAA,IACL,OAAG,gCAAY,kBAAkB,eAAe;AAAA,IAEhD,kBAAkB,CAAC,QAAQ,cAAc,iBAAiB;AAExD,UAAI,QAAQ,SAAS,OAAO,GAAG;AAC7B,eAAO,0CAA0C;AAAA,UAC/C,CAAC,KAAK,YAAY,IAAI,QAAQ,SAAS,EAAE;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,aAAa;AAG5B,UAAI,QAAQ,SAAS,OAAO,GAAG;AAC7B,mBAAO,oDAAiC,QAAQ,CAAC,GAAG,MAAM,CAAC;AAAA,MAC7D;AAEA,wEACE,aAAa,oBAAoB;AAEnC,YAAM,YAAY,UAAU;AAE5B,YAAM,QACJ,cAAc,SAAY,aAAY,qCAAkB,SAAS;AAEnE,UAAI,UAAU,QAAW;AACvB,eAAO;AAAA,MACT;AAEA,YAAM,gBAAgB,YAAY,MAAM,KAAK;AAE7C,YAAM,kBAAc,sCAAmB,aAAa;AAGpD,iBAAO,oDAAiC,YAAY,WAAW;AAAA,IACjE;AAAA,IAEA,oBAAgB,4BAAY,CAAC,EAAE,SAAS,KAAK,MAAM,IAAI;AAAA,EACzD;AACF;",
6
6
  "names": []
7
7
  }
@@ -35,9 +35,6 @@ const tsconfigModule = async ({
35
35
  (0, import_template.readBaseTemplateFile)("tsconfig.json")
36
36
  ]);
37
37
  const baseData = (0, import_json.parseObject)(baseFile);
38
- if ((0, import_validation.hasProp)(baseData, "compilerOptions") && (0, import_validation.hasProp)(baseData.compilerOptions, "target")) {
39
- delete baseData.compilerOptions.target;
40
- }
41
38
  if (type === "package" && (0, import_validation.hasProp)(baseData, "compilerOptions") && (0, import_validation.isObject)(baseData.compilerOptions)) {
42
39
  delete baseData.compilerOptions.baseUrl;
43
40
  delete baseData.compilerOptions.paths;
@@ -57,6 +54,14 @@ const tsconfigModule = async ({
57
54
  "$1lib$2"
58
55
  );
59
56
  }
57
+ if ((0, import_validation.hasProp)(baseData, "compilerOptions")) {
58
+ if ((0, import_validation.hasProp)(baseData.compilerOptions, "lib") && (0, import_validation.hasProp)(inputData?.compilerOptions, "lib")) {
59
+ delete baseData.compilerOptions.lib;
60
+ }
61
+ if ((0, import_validation.hasProp)(baseData.compilerOptions, "target") && (0, import_validation.hasProp)(inputData?.compilerOptions, "target")) {
62
+ delete baseData.compilerOptions.target;
63
+ }
64
+ }
60
65
  const outputData = (0, import_record.merge)(inputData ?? {}, baseData);
61
66
  if ((0, import_validation.hasProp)(outputData, "exclude") && Array.isArray(outputData.exclude)) {
62
67
  const { exclude } = outputData;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/configure/modules/tsconfig.ts"],
4
- "sourcesContent": ["import { readBaseTemplateFile } from '../../../utils/template';\nimport { hasProp, hasStringProp, isObject } from '../../../utils/validation';\nimport { formatObject, parseObject } from '../processing/json';\nimport { loadFiles } from '../processing/loadFiles';\nimport { merge } from '../processing/record';\nimport type { Module, Options } from '../types';\n\nexport const tsconfigModule = async ({\n firstRun,\n type,\n}: Options): Promise<Module> => {\n const [buildFile, baseFile] = await Promise.all([\n readBaseTemplateFile('tsconfig.build.json'),\n readBaseTemplateFile('tsconfig.json'),\n ]);\n\n const baseData = parseObject(baseFile);\n\n // existing project may target earlier Node.js versions than skuba\n if (\n hasProp(baseData, 'compilerOptions') &&\n hasProp(baseData.compilerOptions, 'target')\n ) {\n delete baseData.compilerOptions.target;\n }\n\n // packages should not use module aliases\n if (\n type === 'package' &&\n hasProp(baseData, 'compilerOptions') &&\n isObject(baseData.compilerOptions)\n ) {\n delete baseData.compilerOptions.baseUrl;\n delete baseData.compilerOptions.paths;\n }\n\n return {\n ...loadFiles('Dockerfile'),\n\n 'tsconfig.build.json': (inputFile) => inputFile ?? buildFile,\n\n 'tsconfig.json': (inputFile, files, initialFiles) => {\n const inputData = parseObject(inputFile);\n\n let outDir: string | undefined;\n\n if (\n hasProp(inputData, 'compilerOptions') &&\n hasStringProp(inputData.compilerOptions, 'outDir')\n ) {\n outDir = inputData.compilerOptions.outDir.replace(/\\/$/, '');\n }\n\n // optimistically rewire Dockerfile for new output directory\n if (outDir !== undefined && outDir !== 'lib') {\n files.Dockerfile = files.Dockerfile?.replace(\n new RegExp(`([^\\\\w])${outDir}([^\\\\w])`, 'g'),\n '$1lib$2',\n );\n }\n\n const outputData = merge(inputData ?? {}, baseData);\n\n // Remove `lib/**/*` and `lib`, which duplicate `lib*/**/*`\n if (hasProp(outputData, 'exclude') && Array.isArray(outputData.exclude)) {\n const { exclude } = outputData;\n\n const hasLibStar = exclude.includes('lib*/**/*');\n\n outputData.exclude = exclude.filter(\n (pattern: unknown) =>\n !(hasLibStar && new Set<unknown>(['lib', 'lib/**/*']).has(pattern)),\n );\n }\n\n // for optimal ESLinting, base config should compile all files and leave\n // exclusions to .eslintignore and tsconfig.build.json\n if (\n hasProp(outputData, 'include') &&\n !initialFiles['tsconfig.json']?.includes('skuba/config/tsconfig.json')\n ) {\n delete outputData.include;\n }\n\n // Retain comments for package documentation\n if (\n firstRun &&\n type === 'package' &&\n isObject(outputData.compilerOptions) &&\n !outputData.compilerOptions.removeComments\n ) {\n outputData.compilerOptions.removeComments = false;\n }\n\n return formatObject(outputData);\n },\n };\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAqC;AACrC,wBAAiD;AACjD,kBAA0C;AAC1C,uBAA0B;AAC1B,oBAAsB;AAGf,MAAM,iBAAiB,OAAO;AAAA,EACnC;AAAA,EACA;AACF,MAAgC;AAC9B,QAAM,CAAC,WAAW,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC9C,sCAAqB,qBAAqB;AAAA,QAC1C,sCAAqB,eAAe;AAAA,EACtC,CAAC;AAED,QAAM,eAAW,yBAAY,QAAQ;AAGrC,UACE,2BAAQ,UAAU,iBAAiB,SACnC,2BAAQ,SAAS,iBAAiB,QAAQ,GAC1C;AACA,WAAO,SAAS,gBAAgB;AAAA,EAClC;AAGA,MACE,SAAS,iBACT,2BAAQ,UAAU,iBAAiB,SACnC,4BAAS,SAAS,eAAe,GACjC;AACA,WAAO,SAAS,gBAAgB;AAChC,WAAO,SAAS,gBAAgB;AAAA,EAClC;AAEA,SAAO;AAAA,IACL,OAAG,4BAAU,YAAY;AAAA,IAEzB,uBAAuB,CAAC,cAAc,aAAa;AAAA,IAEnD,iBAAiB,CAAC,WAAW,OAAO,iBAAiB;AACnD,YAAM,gBAAY,yBAAY,SAAS;AAEvC,UAAI;AAEJ,cACE,2BAAQ,WAAW,iBAAiB,SACpC,iCAAc,UAAU,iBAAiB,QAAQ,GACjD;AACA,iBAAS,UAAU,gBAAgB,OAAO,QAAQ,OAAO,EAAE;AAAA,MAC7D;AAGA,UAAI,WAAW,UAAa,WAAW,OAAO;AAC5C,cAAM,aAAa,MAAM,YAAY;AAAA,UACnC,IAAI,OAAO,WAAW,kBAAkB,GAAG;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAEA,YAAM,iBAAa,qBAAM,aAAa,CAAC,GAAG,QAAQ;AAGlD,cAAI,2BAAQ,YAAY,SAAS,KAAK,MAAM,QAAQ,WAAW,OAAO,GAAG;AACvE,cAAM,EAAE,QAAQ,IAAI;AAEpB,cAAM,aAAa,QAAQ,SAAS,WAAW;AAE/C,mBAAW,UAAU,QAAQ;AAAA,UAC3B,CAAC,YACC,EAAE,eAAc,oBAAI,IAAa,CAAC,OAAO,UAAU,CAAC,GAAE,IAAI,OAAO;AAAA,QACrE;AAAA,MACF;AAIA,cACE,2BAAQ,YAAY,SAAS,KAC7B,CAAC,aAAa,kBAAkB,SAAS,4BAA4B,GACrE;AACA,eAAO,WAAW;AAAA,MACpB;AAGA,UACE,YACA,SAAS,iBACT,4BAAS,WAAW,eAAe,KACnC,CAAC,WAAW,gBAAgB,gBAC5B;AACA,mBAAW,gBAAgB,iBAAiB;AAAA,MAC9C;AAEA,iBAAO,0BAAa,UAAU;AAAA,IAChC;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { readBaseTemplateFile } from '../../../utils/template';\nimport { hasProp, hasStringProp, isObject } from '../../../utils/validation';\nimport { formatObject, parseObject } from '../processing/json';\nimport { loadFiles } from '../processing/loadFiles';\nimport { merge } from '../processing/record';\nimport type { Module, Options } from '../types';\n\nexport const tsconfigModule = async ({\n firstRun,\n type,\n}: Options): Promise<Module> => {\n const [buildFile, baseFile] = await Promise.all([\n readBaseTemplateFile('tsconfig.build.json'),\n readBaseTemplateFile('tsconfig.json'),\n ]);\n\n const baseData = parseObject(baseFile);\n\n // packages should not use module aliases\n if (\n type === 'package' &&\n hasProp(baseData, 'compilerOptions') &&\n isObject(baseData.compilerOptions)\n ) {\n delete baseData.compilerOptions.baseUrl;\n delete baseData.compilerOptions.paths;\n }\n\n return {\n ...loadFiles('Dockerfile'),\n\n 'tsconfig.build.json': (inputFile) => inputFile ?? buildFile,\n\n 'tsconfig.json': (inputFile, files, initialFiles) => {\n const inputData = parseObject(inputFile);\n\n let outDir: string | undefined;\n\n if (\n hasProp(inputData, 'compilerOptions') &&\n hasStringProp(inputData.compilerOptions, 'outDir')\n ) {\n outDir = inputData.compilerOptions.outDir.replace(/\\/$/, '');\n }\n\n // optimistically rewire Dockerfile for new output directory\n if (outDir !== undefined && outDir !== 'lib') {\n files.Dockerfile = files.Dockerfile?.replace(\n new RegExp(`([^\\\\w])${outDir}([^\\\\w])`, 'g'),\n '$1lib$2',\n );\n }\n\n // existing project may target earlier Node.js versions than skuba\n if (hasProp(baseData, 'compilerOptions')) {\n if (\n hasProp(baseData.compilerOptions, 'lib') &&\n hasProp(inputData?.compilerOptions, 'lib')\n ) {\n delete baseData.compilerOptions.lib;\n }\n\n if (\n hasProp(baseData.compilerOptions, 'target') &&\n hasProp(inputData?.compilerOptions, 'target')\n ) {\n delete baseData.compilerOptions.target;\n }\n }\n\n const outputData = merge(inputData ?? {}, baseData);\n\n // Remove `lib/**/*` and `lib`, which duplicate `lib*/**/*`\n if (hasProp(outputData, 'exclude') && Array.isArray(outputData.exclude)) {\n const { exclude } = outputData;\n\n const hasLibStar = exclude.includes('lib*/**/*');\n\n outputData.exclude = exclude.filter(\n (pattern: unknown) =>\n !(hasLibStar && new Set<unknown>(['lib', 'lib/**/*']).has(pattern)),\n );\n }\n\n // for optimal ESLinting, base config should compile all files and leave\n // exclusions to .eslintignore and tsconfig.build.json\n if (\n hasProp(outputData, 'include') &&\n !initialFiles['tsconfig.json']?.includes('skuba/config/tsconfig.json')\n ) {\n delete outputData.include;\n }\n\n // Retain comments for package documentation\n if (\n firstRun &&\n type === 'package' &&\n isObject(outputData.compilerOptions) &&\n !outputData.compilerOptions.removeComments\n ) {\n outputData.compilerOptions.removeComments = false;\n }\n\n return formatObject(outputData);\n },\n };\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAqC;AACrC,wBAAiD;AACjD,kBAA0C;AAC1C,uBAA0B;AAC1B,oBAAsB;AAGf,MAAM,iBAAiB,OAAO;AAAA,EACnC;AAAA,EACA;AACF,MAAgC;AAC9B,QAAM,CAAC,WAAW,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC9C,sCAAqB,qBAAqB;AAAA,QAC1C,sCAAqB,eAAe;AAAA,EACtC,CAAC;AAED,QAAM,eAAW,yBAAY,QAAQ;AAGrC,MACE,SAAS,iBACT,2BAAQ,UAAU,iBAAiB,SACnC,4BAAS,SAAS,eAAe,GACjC;AACA,WAAO,SAAS,gBAAgB;AAChC,WAAO,SAAS,gBAAgB;AAAA,EAClC;AAEA,SAAO;AAAA,IACL,OAAG,4BAAU,YAAY;AAAA,IAEzB,uBAAuB,CAAC,cAAc,aAAa;AAAA,IAEnD,iBAAiB,CAAC,WAAW,OAAO,iBAAiB;AACnD,YAAM,gBAAY,yBAAY,SAAS;AAEvC,UAAI;AAEJ,cACE,2BAAQ,WAAW,iBAAiB,SACpC,iCAAc,UAAU,iBAAiB,QAAQ,GACjD;AACA,iBAAS,UAAU,gBAAgB,OAAO,QAAQ,OAAO,EAAE;AAAA,MAC7D;AAGA,UAAI,WAAW,UAAa,WAAW,OAAO;AAC5C,cAAM,aAAa,MAAM,YAAY;AAAA,UACnC,IAAI,OAAO,WAAW,kBAAkB,GAAG;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAGA,cAAI,2BAAQ,UAAU,iBAAiB,GAAG;AACxC,gBACE,2BAAQ,SAAS,iBAAiB,KAAK,SACvC,2BAAQ,WAAW,iBAAiB,KAAK,GACzC;AACA,iBAAO,SAAS,gBAAgB;AAAA,QAClC;AAEA,gBACE,2BAAQ,SAAS,iBAAiB,QAAQ,SAC1C,2BAAQ,WAAW,iBAAiB,QAAQ,GAC5C;AACA,iBAAO,SAAS,gBAAgB;AAAA,QAClC;AAAA,MACF;AAEA,YAAM,iBAAa,qBAAM,aAAa,CAAC,GAAG,QAAQ;AAGlD,cAAI,2BAAQ,YAAY,SAAS,KAAK,MAAM,QAAQ,WAAW,OAAO,GAAG;AACvE,cAAM,EAAE,QAAQ,IAAI;AAEpB,cAAM,aAAa,QAAQ,SAAS,WAAW;AAE/C,mBAAW,UAAU,QAAQ;AAAA,UAC3B,CAAC,YACC,EAAE,eAAc,oBAAI,IAAa,CAAC,OAAO,UAAU,CAAC,GAAE,IAAI,OAAO;AAAA,QACrE;AAAA,MACF;AAIA,cACE,2BAAQ,YAAY,SAAS,KAC7B,CAAC,aAAa,kBAAkB,SAAS,4BAA4B,GACrE;AACA,eAAO,WAAW;AAAA,MACpB;AAGA,UACE,YACA,SAAS,iBACT,4BAAS,WAAW,eAAe,KACnC,CAAC,WAAW,gBAAgB,gBAC5B;AACA,mBAAW,gBAAgB,iBAAiB;AAAA,MAC9C;AAEA,iBAAO,0BAAa,UAAU;AAAA,IAChC;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
- import type { FormChoice } from 'enquirer';
2
1
  import { TemplateConfig } from '../../utils/template';
3
2
  import type { InitConfig } from './types';
3
+ import type { FormChoice } from 'enquirer';
4
4
  export declare const runForm: <T = Record<string, string>>(props: {
5
5
  choices: Readonly<FormChoice[]>;
6
6
  message: string;
@@ -32,7 +32,6 @@ __export(getConfig_exports, {
32
32
  module.exports = __toCommonJS(getConfig_exports);
33
33
  var import_path = __toESM(require("path"));
34
34
  var import_chalk = __toESM(require("chalk"));
35
- var import_enquirer = require("enquirer");
36
35
  var import_fs_extra = __toESM(require("fs-extra"));
37
36
  var import_copy = require("../../utils/copy");
38
37
  var import_error = require("../../utils/error");
@@ -42,6 +41,7 @@ var import_template = require("../../utils/template");
42
41
  var import_git = require("./git");
43
42
  var import_prompts = require("./prompts");
44
43
  var import_types = require("./types");
44
+ var import_enquirer = require("enquirer");
45
45
  const runForm = (props) => {
46
46
  const { message, name } = props;
47
47
  const choices = props.choices.map((choice) => ({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/init/getConfig.ts"],
4
- "sourcesContent": ["import path from 'path';\n\nimport chalk from 'chalk';\nimport type { FormChoice } from 'enquirer';\nimport { Form } from 'enquirer';\nimport fs from 'fs-extra';\n\nimport { copyFiles } from '../../utils/copy';\nimport { isErrorWithCode } from '../../utils/error';\nimport { log } from '../../utils/logging';\nimport { getRandomPort } from '../../utils/port';\nimport {\n TEMPLATE_CONFIG_FILENAME,\n TEMPLATE_DIR,\n TemplateConfig,\n} from '../../utils/template';\n\nimport { downloadGitHubTemplate } from './git';\nimport type { BaseFields } from './prompts';\nimport {\n BASE_PROMPT_PROPS,\n GIT_PATH_PROMPT,\n SHOULD_CONTINUE_PROMPT,\n TEMPLATE_PROMPT,\n} from './prompts';\nimport type { InitConfig } from './types';\nimport { InitConfigInput } from './types';\n\nexport const runForm = <T = Record<string, string>>(props: {\n choices: Readonly<FormChoice[]>;\n message: string;\n name: string;\n}) => {\n const { message, name } = props;\n\n const choices = props.choices.map((choice) => ({\n ...choice,\n validate: (value: string) => {\n if (value === '' || value === choice.initial) {\n return 'Form is not complete';\n }\n\n return choice.validate?.(value) ?? true;\n },\n }));\n\n const form = new Form<T>({\n choices,\n message,\n name,\n validate: async (values) => {\n const results = await Promise.all(\n choices.map((choice) => choice.validate(values[choice.name])),\n );\n\n return (\n results.find((result) => typeof result === 'string') ??\n results.every((result) => result === true)\n );\n },\n });\n\n return form.run();\n};\n\nconst confirmShouldContinue = async (choices: Readonly<FormChoice[]>) => {\n const fieldsList = choices.map((choice) => choice.message);\n\n log.newline();\n log.plain('This template uses the following information:');\n log.newline();\n fieldsList.forEach((message) => log.subtle(`- ${message}`));\n\n log.newline();\n const result = await SHOULD_CONTINUE_PROMPT.run();\n\n return result === 'yes';\n};\n\nconst createDirectory = async (dir: string) => {\n try {\n await fs.promises.mkdir(dir);\n } catch (err) {\n if (isErrorWithCode(err, 'EEXIST')) {\n log.err(`The directory '${dir}' already exists.`);\n process.exit(1);\n }\n\n throw err;\n }\n};\n\nconst cloneTemplate = async (templateName: string, destinationDir: string) => {\n if (templateName.startsWith('github:')) {\n const gitHubPath = templateName.slice('github:'.length);\n return downloadGitHubTemplate(gitHubPath, destinationDir);\n }\n\n const templateDir = path.join(TEMPLATE_DIR, templateName);\n\n await copyFiles({\n // assume built-in templates have no extraneous files\n include: () => true,\n sourceRoot: templateDir,\n destinationRoot: destinationDir,\n processors: [],\n // built-in templates have files like _package.json\n stripUnderscorePrefix: true,\n });\n};\n\nconst getTemplateName = async () => {\n const templateSelection = await TEMPLATE_PROMPT.run();\n\n if (templateSelection === 'github \u2192') {\n const gitHubPath = await GIT_PATH_PROMPT.run();\n return `github:${gitHubPath}`;\n }\n\n return templateSelection;\n};\n\nconst generatePlaceholders = (choices: FormChoice[]) =>\n Object.fromEntries(\n choices.map(({ name }) => [name, `<%- ${name} %>`] as const),\n );\n\nexport const getTemplateConfig = (dir: string): TemplateConfig => {\n const templateConfigPath = path.join(dir, TEMPLATE_CONFIG_FILENAME);\n\n try {\n /* eslint-disable-next-line @typescript-eslint/no-var-requires */\n const templateConfig = require(templateConfigPath) as unknown;\n\n return TemplateConfig.check(templateConfig);\n } catch (err) {\n if (isErrorWithCode(err, 'MODULE_NOT_FOUND')) {\n return {\n entryPoint: undefined,\n fields: [],\n type: undefined,\n };\n }\n\n throw err;\n }\n};\n\nconst baseToTemplateData = async ({ ownerName, repoName }: BaseFields) => {\n const [orgName, teamName] = ownerName.split('/');\n\n const port = String(await getRandomPort());\n\n return {\n orgName,\n ownerName,\n port,\n repoName,\n // Use standalone username in `teamName` contexts\n teamName: teamName ?? orgName,\n };\n};\n\nexport const configureFromPrompt = async (): Promise<InitConfig> => {\n const { ownerName, repoName } = await runForm(BASE_PROMPT_PROPS);\n log.plain(chalk.cyan(repoName), 'by', chalk.cyan(ownerName));\n\n const templateData = await baseToTemplateData({ ownerName, repoName });\n\n const destinationDir = repoName;\n\n await createDirectory(destinationDir);\n\n log.newline();\n const templateName = await getTemplateName();\n\n await cloneTemplate(templateName, destinationDir);\n\n const { entryPoint, fields, noSkip, type } = getTemplateConfig(\n path.join(process.cwd(), destinationDir),\n );\n\n if (fields.length === 0) {\n return {\n destinationDir,\n entryPoint,\n templateComplete: true,\n templateData,\n templateName,\n type,\n };\n }\n\n const shouldContinue = noSkip ? true : await confirmShouldContinue(fields);\n\n if (shouldContinue) {\n log.newline();\n const customAnswers = await runForm({\n choices: fields,\n message: chalk.bold(`Complete ${chalk.cyan(templateName)}:`),\n name: 'customAnswers',\n });\n\n return {\n destinationDir,\n entryPoint,\n templateComplete: true,\n templateData: { ...templateData, ...customAnswers },\n templateName,\n type,\n };\n }\n\n log.newline();\n log.warn(`Resume this later with ${chalk.bold('yarn skuba configure')}.`);\n\n const customAnswers = generatePlaceholders(fields);\n\n return {\n destinationDir,\n entryPoint,\n templateComplete: false,\n templateData: { ...templateData, ...customAnswers },\n templateName,\n type,\n };\n};\n\nconst configureFromPipe = async (): Promise<InitConfig> => {\n let text = '';\n\n await new Promise((resolve) =>\n process.stdin.on('data', (chunk) => (text += chunk)).once('end', resolve),\n );\n\n text = text.trim();\n\n if (text === '') {\n log.err('No data from stdin.');\n process.exit(1);\n }\n\n let value: unknown;\n\n try {\n value = JSON.parse(text) as unknown;\n } catch {\n log.err('Invalid JSON from stdin.');\n process.exit(1);\n }\n\n const result = InitConfigInput.validate(value);\n\n if (!result.success) {\n log.err('Invalid data from stdin:');\n log.err(result.message);\n process.exit(1);\n }\n\n const { destinationDir, templateComplete, templateName } = result.value;\n\n const templateData = {\n ...(await baseToTemplateData(result.value.templateData)),\n ...result.value.templateData,\n };\n\n await createDirectory(destinationDir);\n\n await cloneTemplate(templateName, destinationDir);\n\n const { entryPoint, fields, noSkip, type } = getTemplateConfig(\n path.join(process.cwd(), destinationDir),\n );\n\n if (!templateComplete) {\n if (noSkip) {\n log.err('Templating for', log.bold(templateName), 'cannot be skipped.');\n process.exit(1);\n }\n\n return {\n ...result.value,\n entryPoint,\n templateData: {\n ...templateData,\n ...generatePlaceholders(fields),\n },\n type,\n };\n }\n\n const required = fields.map(({ name }) => name);\n\n const provided = new Set(Object.keys(templateData));\n\n const missing = required.filter((name) => !provided.has(name));\n\n if (missing.length > 0) {\n log.err('This template uses the following information:');\n log.newline();\n missing.forEach((name) => log.err(`- ${name}`));\n process.exit(1);\n }\n\n return {\n ...result.value,\n entryPoint,\n templateData,\n type,\n };\n};\n\nexport const getConfig = () =>\n process.stdin.isTTY ? configureFromPrompt() : configureFromPipe();\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import path from 'path';\n\nimport chalk from 'chalk';\nimport fs from 'fs-extra';\n\nimport { copyFiles } from '../../utils/copy';\nimport { isErrorWithCode } from '../../utils/error';\nimport { log } from '../../utils/logging';\nimport { getRandomPort } from '../../utils/port';\nimport {\n TEMPLATE_CONFIG_FILENAME,\n TEMPLATE_DIR,\n TemplateConfig,\n} from '../../utils/template';\n\nimport { downloadGitHubTemplate } from './git';\nimport type { BaseFields } from './prompts';\nimport {\n BASE_PROMPT_PROPS,\n GIT_PATH_PROMPT,\n SHOULD_CONTINUE_PROMPT,\n TEMPLATE_PROMPT,\n} from './prompts';\nimport type { InitConfig } from './types';\nimport { InitConfigInput } from './types';\n\nimport { Form } from 'enquirer';\nimport type { FormChoice } from 'enquirer';\n\nexport const runForm = <T = Record<string, string>>(props: {\n choices: Readonly<FormChoice[]>;\n message: string;\n name: string;\n}) => {\n const { message, name } = props;\n\n const choices = props.choices.map((choice) => ({\n ...choice,\n validate: (value: string) => {\n if (value === '' || value === choice.initial) {\n return 'Form is not complete';\n }\n\n return choice.validate?.(value) ?? true;\n },\n }));\n\n const form = new Form<T>({\n choices,\n message,\n name,\n validate: async (values) => {\n const results = await Promise.all(\n choices.map((choice) => choice.validate(values[choice.name])),\n );\n\n return (\n results.find((result) => typeof result === 'string') ??\n results.every((result) => result === true)\n );\n },\n });\n\n return form.run();\n};\n\nconst confirmShouldContinue = async (choices: Readonly<FormChoice[]>) => {\n const fieldsList = choices.map((choice) => choice.message);\n\n log.newline();\n log.plain('This template uses the following information:');\n log.newline();\n fieldsList.forEach((message) => log.subtle(`- ${message}`));\n\n log.newline();\n const result = await SHOULD_CONTINUE_PROMPT.run();\n\n return result === 'yes';\n};\n\nconst createDirectory = async (dir: string) => {\n try {\n await fs.promises.mkdir(dir);\n } catch (err) {\n if (isErrorWithCode(err, 'EEXIST')) {\n log.err(`The directory '${dir}' already exists.`);\n process.exit(1);\n }\n\n throw err;\n }\n};\n\nconst cloneTemplate = async (templateName: string, destinationDir: string) => {\n if (templateName.startsWith('github:')) {\n const gitHubPath = templateName.slice('github:'.length);\n return downloadGitHubTemplate(gitHubPath, destinationDir);\n }\n\n const templateDir = path.join(TEMPLATE_DIR, templateName);\n\n await copyFiles({\n // assume built-in templates have no extraneous files\n include: () => true,\n sourceRoot: templateDir,\n destinationRoot: destinationDir,\n processors: [],\n // built-in templates have files like _package.json\n stripUnderscorePrefix: true,\n });\n};\n\nconst getTemplateName = async () => {\n const templateSelection = await TEMPLATE_PROMPT.run();\n\n if (templateSelection === 'github \u2192') {\n const gitHubPath = await GIT_PATH_PROMPT.run();\n return `github:${gitHubPath}`;\n }\n\n return templateSelection;\n};\n\nconst generatePlaceholders = (choices: FormChoice[]) =>\n Object.fromEntries(\n choices.map(({ name }) => [name, `<%- ${name} %>`] as const),\n );\n\nexport const getTemplateConfig = (dir: string): TemplateConfig => {\n const templateConfigPath = path.join(dir, TEMPLATE_CONFIG_FILENAME);\n\n try {\n /* eslint-disable-next-line @typescript-eslint/no-var-requires */\n const templateConfig = require(templateConfigPath) as unknown;\n\n return TemplateConfig.check(templateConfig);\n } catch (err) {\n if (isErrorWithCode(err, 'MODULE_NOT_FOUND')) {\n return {\n entryPoint: undefined,\n fields: [],\n type: undefined,\n };\n }\n\n throw err;\n }\n};\n\nconst baseToTemplateData = async ({ ownerName, repoName }: BaseFields) => {\n const [orgName, teamName] = ownerName.split('/');\n\n const port = String(await getRandomPort());\n\n return {\n orgName,\n ownerName,\n port,\n repoName,\n // Use standalone username in `teamName` contexts\n teamName: teamName ?? orgName,\n };\n};\n\nexport const configureFromPrompt = async (): Promise<InitConfig> => {\n const { ownerName, repoName } = await runForm(BASE_PROMPT_PROPS);\n log.plain(chalk.cyan(repoName), 'by', chalk.cyan(ownerName));\n\n const templateData = await baseToTemplateData({ ownerName, repoName });\n\n const destinationDir = repoName;\n\n await createDirectory(destinationDir);\n\n log.newline();\n const templateName = await getTemplateName();\n\n await cloneTemplate(templateName, destinationDir);\n\n const { entryPoint, fields, noSkip, type } = getTemplateConfig(\n path.join(process.cwd(), destinationDir),\n );\n\n if (fields.length === 0) {\n return {\n destinationDir,\n entryPoint,\n templateComplete: true,\n templateData,\n templateName,\n type,\n };\n }\n\n const shouldContinue = noSkip ? true : await confirmShouldContinue(fields);\n\n if (shouldContinue) {\n log.newline();\n const customAnswers = await runForm({\n choices: fields,\n message: chalk.bold(`Complete ${chalk.cyan(templateName)}:`),\n name: 'customAnswers',\n });\n\n return {\n destinationDir,\n entryPoint,\n templateComplete: true,\n templateData: { ...templateData, ...customAnswers },\n templateName,\n type,\n };\n }\n\n log.newline();\n log.warn(`Resume this later with ${chalk.bold('yarn skuba configure')}.`);\n\n const customAnswers = generatePlaceholders(fields);\n\n return {\n destinationDir,\n entryPoint,\n templateComplete: false,\n templateData: { ...templateData, ...customAnswers },\n templateName,\n type,\n };\n};\n\nconst configureFromPipe = async (): Promise<InitConfig> => {\n let text = '';\n\n await new Promise((resolve) =>\n process.stdin.on('data', (chunk) => (text += chunk)).once('end', resolve),\n );\n\n text = text.trim();\n\n if (text === '') {\n log.err('No data from stdin.');\n process.exit(1);\n }\n\n let value: unknown;\n\n try {\n value = JSON.parse(text) as unknown;\n } catch {\n log.err('Invalid JSON from stdin.');\n process.exit(1);\n }\n\n const result = InitConfigInput.validate(value);\n\n if (!result.success) {\n log.err('Invalid data from stdin:');\n log.err(result.message);\n process.exit(1);\n }\n\n const { destinationDir, templateComplete, templateName } = result.value;\n\n const templateData = {\n ...(await baseToTemplateData(result.value.templateData)),\n ...result.value.templateData,\n };\n\n await createDirectory(destinationDir);\n\n await cloneTemplate(templateName, destinationDir);\n\n const { entryPoint, fields, noSkip, type } = getTemplateConfig(\n path.join(process.cwd(), destinationDir),\n );\n\n if (!templateComplete) {\n if (noSkip) {\n log.err('Templating for', log.bold(templateName), 'cannot be skipped.');\n process.exit(1);\n }\n\n return {\n ...result.value,\n entryPoint,\n templateData: {\n ...templateData,\n ...generatePlaceholders(fields),\n },\n type,\n };\n }\n\n const required = fields.map(({ name }) => name);\n\n const provided = new Set(Object.keys(templateData));\n\n const missing = required.filter((name) => !provided.has(name));\n\n if (missing.length > 0) {\n log.err('This template uses the following information:');\n log.newline();\n missing.forEach((name) => log.err(`- ${name}`));\n process.exit(1);\n }\n\n return {\n ...result.value,\n entryPoint,\n templateData,\n type,\n };\n};\n\nexport const getConfig = () =>\n process.stdin.isTTY ? configureFromPrompt() : configureFromPipe();\n"],
5
+ "mappings": "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",
6
6
  "names": ["fs", "path", "chalk", "customAnswers"]
7
7
  }
@@ -24,10 +24,10 @@ __export(prompts_exports, {
24
24
  TEMPLATE_PROMPT: () => TEMPLATE_PROMPT
25
25
  });
26
26
  module.exports = __toCommonJS(prompts_exports);
27
- var import_enquirer = require("enquirer");
28
27
  var import_fs_extra = require("fs-extra");
29
28
  var import_template = require("../../utils/template");
30
29
  var import_validation = require("./validation");
30
+ var import_enquirer = require("enquirer");
31
31
  const BASE_CHOICES = [
32
32
  {
33
33
  name: "ownerName",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/init/prompts.ts"],
4
- "sourcesContent": ["import { Input, Select } from 'enquirer';\nimport { pathExists } from 'fs-extra';\n\nimport { TEMPLATE_NAMES_WITH_BYO } from '../../utils/template';\n\nimport { isGitHubOrg, isGitHubRepo, isGitHubTeam } from './validation';\n\nexport type BaseFields = Record<typeof BASE_CHOICES[number]['name'], string>;\n\nconst BASE_CHOICES = [\n {\n name: 'ownerName',\n message: 'Owner',\n initial: 'SEEK-Jobs/my-team',\n validate: (value: unknown) => {\n if (typeof value !== 'string') {\n return 'required';\n }\n\n const [org, team] = value.split('/');\n\n if (!isGitHubOrg(org)) {\n return 'fails GitHub validation';\n }\n\n return (\n team === undefined || isGitHubTeam(team) || 'fails GitHub validation'\n );\n },\n },\n {\n name: 'repoName',\n message: 'Repo',\n initial: 'my-repo',\n validate: async (value: unknown) => {\n if (typeof value !== 'string') {\n return 'required';\n }\n\n if (!isGitHubRepo(value)) {\n return 'fails GitHub validation';\n }\n\n const exists = await pathExists(value);\n\n return !exists || `'${value}' is an existing directory`;\n },\n },\n] as const;\n\nexport const BASE_PROMPT_PROPS = {\n choices: BASE_CHOICES,\n message: 'For starters, some GitHub details:',\n name: 'baseAnswers',\n};\n\nexport const SHOULD_CONTINUE_PROMPT = new Select({\n choices: ['yes', 'no'] as const,\n message: 'Fill this in now?',\n name: 'shouldContinue',\n});\n\nexport const GIT_PATH_PROMPT = new Input({\n message: 'Git path',\n name: 'gitPath',\n initial: 'seek-oss/skuba',\n validate: (value) => /[^/]+\\/[^/]+/.test(value) || 'Path is not valid',\n});\n\nexport const TEMPLATE_PROMPT = new Select({\n choices: TEMPLATE_NAMES_WITH_BYO,\n message: 'Select a template:',\n name: 'templateName',\n});\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA8B;AAC9B,sBAA2B;AAE3B,sBAAwC;AAExC,wBAAwD;AAIxD,MAAM,eAAe;AAAA,EACnB;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU,CAAC,UAAmB;AAC5B,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO;AAAA,MACT;AAEA,YAAM,CAAC,KAAK,IAAI,IAAI,MAAM,MAAM,GAAG;AAEnC,UAAI,KAAC,+BAAY,GAAG,GAAG;AACrB,eAAO;AAAA,MACT;AAEA,aACE,SAAS,cAAa,gCAAa,IAAI,KAAK;AAAA,IAEhD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU,OAAO,UAAmB;AAClC,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO;AAAA,MACT;AAEA,UAAI,KAAC,gCAAa,KAAK,GAAG;AACxB,eAAO;AAAA,MACT;AAEA,YAAM,SAAS,UAAM,4BAAW,KAAK;AAErC,aAAO,CAAC,UAAU,IAAI;AAAA,IACxB;AAAA,EACF;AACF;AAEO,MAAM,oBAAoB;AAAA,EAC/B,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR;AAEO,MAAM,yBAAyB,IAAI,uBAAO;AAAA,EAC/C,SAAS,CAAC,OAAO,IAAI;AAAA,EACrB,SAAS;AAAA,EACT,MAAM;AACR,CAAC;AAEM,MAAM,kBAAkB,IAAI,sBAAM;AAAA,EACvC,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU,CAAC,UAAU,eAAe,KAAK,KAAK,KAAK;AACrD,CAAC;AAEM,MAAM,kBAAkB,IAAI,uBAAO;AAAA,EACxC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR,CAAC;",
4
+ "sourcesContent": ["import { pathExists } from 'fs-extra';\n\nimport { TEMPLATE_NAMES_WITH_BYO } from '../../utils/template';\n\nimport { isGitHubOrg, isGitHubRepo, isGitHubTeam } from './validation';\n\nimport { Input, Select } from 'enquirer';\n\nexport type BaseFields = Record<typeof BASE_CHOICES[number]['name'], string>;\n\nconst BASE_CHOICES = [\n {\n name: 'ownerName',\n message: 'Owner',\n initial: 'SEEK-Jobs/my-team',\n validate: (value: unknown) => {\n if (typeof value !== 'string') {\n return 'required';\n }\n\n const [org, team] = value.split('/');\n\n if (!isGitHubOrg(org)) {\n return 'fails GitHub validation';\n }\n\n return (\n team === undefined || isGitHubTeam(team) || 'fails GitHub validation'\n );\n },\n },\n {\n name: 'repoName',\n message: 'Repo',\n initial: 'my-repo',\n validate: async (value: unknown) => {\n if (typeof value !== 'string') {\n return 'required';\n }\n\n if (!isGitHubRepo(value)) {\n return 'fails GitHub validation';\n }\n\n const exists = await pathExists(value);\n\n return !exists || `'${value}' is an existing directory`;\n },\n },\n] as const;\n\nexport const BASE_PROMPT_PROPS = {\n choices: BASE_CHOICES,\n message: 'For starters, some GitHub details:',\n name: 'baseAnswers',\n};\n\nexport const SHOULD_CONTINUE_PROMPT = new Select({\n choices: ['yes', 'no'] as const,\n message: 'Fill this in now?',\n name: 'shouldContinue',\n});\n\nexport const GIT_PATH_PROMPT = new Input({\n message: 'Git path',\n name: 'gitPath',\n initial: 'seek-oss/skuba',\n validate: (value) => /[^/]+\\/[^/]+/.test(value) || 'Path is not valid',\n});\n\nexport const TEMPLATE_PROMPT = new Select({\n choices: TEMPLATE_NAMES_WITH_BYO,\n message: 'Select a template:',\n name: 'templateName',\n});\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA2B;AAE3B,sBAAwC;AAExC,wBAAwD;AAExD,sBAA8B;AAI9B,MAAM,eAAe;AAAA,EACnB;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU,CAAC,UAAmB;AAC5B,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO;AAAA,MACT;AAEA,YAAM,CAAC,KAAK,IAAI,IAAI,MAAM,MAAM,GAAG;AAEnC,UAAI,KAAC,+BAAY,GAAG,GAAG;AACrB,eAAO;AAAA,MACT;AAEA,aACE,SAAS,cAAa,gCAAa,IAAI,KAAK;AAAA,IAEhD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU,OAAO,UAAmB;AAClC,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO;AAAA,MACT;AAEA,UAAI,KAAC,gCAAa,KAAK,GAAG;AACxB,eAAO;AAAA,MACT;AAEA,YAAM,SAAS,UAAM,4BAAW,KAAK;AAErC,aAAO,CAAC,UAAU,IAAI;AAAA,IACxB;AAAA,EACF;AACF;AAEO,MAAM,oBAAoB;AAAA,EAC/B,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR;AAEO,MAAM,yBAAyB,IAAI,uBAAO;AAAA,EAC/C,SAAS,CAAC,OAAO,IAAI;AAAA,EACrB,SAAS;AAAA,EACT,MAAM;AACR,CAAC;AAEM,MAAM,kBAAkB,IAAI,sBAAM;AAAA,EACvC,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU,CAAC,UAAU,eAAe,KAAK,KAAK,KAAK;AACrD,CAAC;AAEM,MAAM,kBAAkB,IAAI,uBAAO;AAAA,EACxC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
+ import type { StreamInterceptor } from '../external';
1
2
  import type { ESLintOutput } from 'cli/adapter/eslint';
2
3
  import type { PrettierOutput } from 'cli/adapter/prettier';
3
- import type { StreamInterceptor } from '../external';
4
4
  export declare const createAnnotations: (eslint: ESLintOutput, prettier: PrettierOutput, tscOk: boolean, tscOutputStream: StreamInterceptor) => Promise<void>;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/lint/annotate/index.ts"],
4
- "sourcesContent": ["import type { ESLintOutput } from 'cli/adapter/eslint';\nimport type { PrettierOutput } from 'cli/adapter/prettier';\n\nimport type { StreamInterceptor } from '../external';\n\nimport { createBuildkiteAnnotations } from './buildkite';\nimport { createGitHubAnnotations } from './github';\n\nexport const createAnnotations = async (\n eslint: ESLintOutput,\n prettier: PrettierOutput,\n tscOk: boolean,\n tscOutputStream: StreamInterceptor,\n): Promise<void> => {\n await Promise.all([\n createGitHubAnnotations(eslint, prettier, tscOk, tscOutputStream),\n createBuildkiteAnnotations(eslint, prettier, tscOk, tscOutputStream),\n ]);\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,uBAA2C;AAC3C,oBAAwC;AAEjC,MAAM,oBAAoB,OAC/B,QACA,UACA,OACA,oBACkB;AAClB,QAAM,QAAQ,IAAI;AAAA,QAChB,uCAAwB,QAAQ,UAAU,OAAO,eAAe;AAAA,QAChE,6CAA2B,QAAQ,UAAU,OAAO,eAAe;AAAA,EACrE,CAAC;AACH;",
4
+ "sourcesContent": ["import type { StreamInterceptor } from '../external';\n\nimport { createBuildkiteAnnotations } from './buildkite';\nimport { createGitHubAnnotations } from './github';\n\nimport type { ESLintOutput } from 'cli/adapter/eslint';\nimport type { PrettierOutput } from 'cli/adapter/prettier';\n\nexport const createAnnotations = async (\n eslint: ESLintOutput,\n prettier: PrettierOutput,\n tscOk: boolean,\n tscOutputStream: StreamInterceptor,\n): Promise<void> => {\n await Promise.all([\n createGitHubAnnotations(eslint, prettier, tscOk, tscOutputStream),\n createBuildkiteAnnotations(eslint, prettier, tscOk, tscOutputStream),\n ]);\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,uBAA2C;AAC3C,oBAAwC;AAKjC,MAAM,oBAAoB,OAC/B,QACA,UACA,OACA,oBACkB;AAClB,QAAM,QAAQ,IAAI;AAAA,QAChB,uCAAwB,QAAQ,UAAU,OAAO,eAAe;AAAA,QAChE,6CAA2B,QAAQ,UAAU,OAAO,eAAe;AAAA,EACrE,CAAC;AACH;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,9 +1,71 @@
1
1
  {
2
+ "name": "skuba",
3
+ "version": "5.0.0",
4
+ "private": false,
5
+ "description": "SEEK development toolkit for backend applications and packages",
6
+ "homepage": "https://github.com/seek-oss/skuba#readme",
7
+ "bugs": {
8
+ "url": "https://github.com/seek-oss/skuba/issues"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+ssh://git@github.com/seek-oss/skuba.git"
13
+ },
14
+ "license": "MIT",
15
+ "sideEffects": false,
16
+ "main": "lib/index.js",
17
+ "types": "./lib/index.d.ts",
2
18
  "bin": {
3
19
  "skuba": "lib/skuba.js"
4
20
  },
5
- "bugs": {
6
- "url": "https://github.com/seek-oss/skuba/issues"
21
+ "files": [
22
+ "config/**/*",
23
+ "jest/**/*",
24
+ "lib*/**/*.d.ts",
25
+ "lib*/**/*.js",
26
+ "lib*/**/*.js.map",
27
+ "template/**/*",
28
+ "jest-preset.js"
29
+ ],
30
+ "scripts": {
31
+ "build": "scripts/build.sh",
32
+ "deploy": "scripts/deploy.sh",
33
+ "format": "yarn skuba format",
34
+ "lint": "yarn skuba lint && yarn lint:md",
35
+ "lint:md": "remark --frail --quiet .",
36
+ "release": "yarn build && changeset publish",
37
+ "skuba": "yarn build && node lib/skuba",
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",
42
+ "test:template": "scripts/test-template.sh",
43
+ "test:watch": "yarn skuba test --config jest.config.int.ts --runInBand --watch"
44
+ },
45
+ "remarkConfig": {
46
+ "plugins": [
47
+ "remark-preset-lint-recommended",
48
+ [
49
+ "remark-lint-list-item-indent",
50
+ false
51
+ ],
52
+ [
53
+ "remark-lint-no-shortcut-reference-link",
54
+ false
55
+ ],
56
+ [
57
+ "remark-lint-no-undefined-references",
58
+ {
59
+ "allow": [
60
+ " ",
61
+ "x"
62
+ ]
63
+ }
64
+ ]
65
+ ]
66
+ },
67
+ "resolutions": {
68
+ "**/@types/node": ">=14.18"
7
69
  },
8
70
  "dependencies": {
9
71
  "@esbuild-plugins/tsconfig-paths": "^0.0.4",
@@ -56,11 +118,10 @@
56
118
  "typescript": "~4.8.2",
57
119
  "validate-npm-package-name": "^5.0.0"
58
120
  },
59
- "description": "SEEK development toolkit for backend applications and packages",
60
121
  "devDependencies": {
61
- "@changesets/cli": "2.25.0",
122
+ "@changesets/cli": "2.25.2",
62
123
  "@changesets/get-github-info": "0.5.1",
63
- "@jest/reporters": "29.2.1",
124
+ "@jest/reporters": "29.3.0",
64
125
  "@types/ejs": "3.1.1",
65
126
  "@types/express": "4.17.14",
66
127
  "@types/fs-extra": "9.0.13",
@@ -76,29 +137,13 @@
76
137
  "express": "4.18.2",
77
138
  "jsonfile": "6.1.0",
78
139
  "koa": "2.13.4",
79
- "memfs": "3.4.7",
140
+ "memfs": "3.4.10",
80
141
  "remark-cli": "11.0.0",
81
142
  "remark-preset-lint-recommended": "6.1.2",
82
143
  "semver": "7.3.8",
83
- "supertest": "6.3.0",
144
+ "supertest": "6.3.1",
84
145
  "type-fest": "2.19.0"
85
146
  },
86
- "engines": {
87
- "node": ">=14.18"
88
- },
89
- "files": [
90
- "config/**/*",
91
- "jest/**/*",
92
- "lib*/**/*.d.ts",
93
- "lib*/**/*.js",
94
- "lib*/**/*.js.map",
95
- "template/**/*",
96
- "jest-preset.js"
97
- ],
98
- "homepage": "https://github.com/seek-oss/skuba#readme",
99
- "license": "MIT",
100
- "main": "lib/index.js",
101
- "name": "skuba",
102
147
  "peerDependencies": {
103
148
  "skuba-dive": "1 || 2"
104
149
  },
@@ -107,59 +152,14 @@
107
152
  "optional": true
108
153
  }
109
154
  },
110
- "private": false,
111
- "remarkConfig": {
112
- "plugins": [
113
- "remark-preset-lint-recommended",
114
- [
115
- "remark-lint-list-item-indent",
116
- false
117
- ],
118
- [
119
- "remark-lint-no-shortcut-reference-link",
120
- false
121
- ],
122
- [
123
- "remark-lint-no-undefined-references",
124
- {
125
- "allow": [
126
- " ",
127
- "x"
128
- ]
129
- }
130
- ]
131
- ]
132
- },
133
- "repository": {
134
- "type": "git",
135
- "url": "git+ssh://git@github.com/seek-oss/skuba.git"
136
- },
137
- "resolutions": {
138
- "**/@types/node": ">=14.18"
139
- },
140
- "scripts": {
141
- "build": "scripts/build.sh",
142
- "deploy": "scripts/deploy.sh",
143
- "format": "yarn skuba format",
144
- "lint": "yarn skuba lint && yarn lint:md",
145
- "lint:md": "remark --frail --quiet .",
146
- "release": "yarn build && changeset publish",
147
- "stage": "changeset version && yarn format",
148
- "skuba": "yarn build && node lib/skuba",
149
- "test": "yarn skuba test",
150
- "test:ci": "yarn skuba test --config jest.config.int.ts --runInBand",
151
- "test:int": "yarn skuba test --config jest.config.int.ts --runInBand",
152
- "test:template": "scripts/test-template.sh",
153
- "test:watch": "yarn skuba test --config jest.config.int.ts --runInBand --watch"
155
+ "engines": {
156
+ "node": ">=14.18"
154
157
  },
155
- "sideEffects": false,
156
158
  "skuba": {
157
159
  "build": "esbuild",
158
160
  "entryPoint": "src/index.ts",
159
161
  "template": null,
160
162
  "type": "package",
161
163
  "version": "4.0.0"
162
- },
163
- "types": "./lib/index.d.ts",
164
- "version": "5.0.0-beta.0"
164
+ }
165
165
  }
@@ -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"
@@ -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.11.64",
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
  }
@@ -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.11.64",
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 +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,9 +1,21 @@
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",
18
+ "@opentelemetry/instrumentation-aws-sdk": "^0.32.0",
7
19
  "@opentelemetry/instrumentation-http": "^0.33.0",
8
20
  "@opentelemetry/sdk-node": "^0.33.0",
9
21
  "@seek/logger": "^5.0.1",
@@ -22,7 +34,7 @@
22
34
  "@types/koa": "^2.13.4",
23
35
  "@types/koa-bodyparser": "^5.0.2",
24
36
  "@types/koa__router": "^12.0.0",
25
- "@types/node": "16.11.64",
37
+ "@types/node": "^18.11.5",
26
38
  "@types/supertest": "^2.0.11",
27
39
  "chance": "^1.1.8",
28
40
  "pino-pretty": "^9.0.0",
@@ -30,18 +42,6 @@
30
42
  "supertest": "^6.1.6"
31
43
  },
32
44
  "engines": {
33
- "node": ">=16"
34
- },
35
- "license": "UNLICENSED",
36
- "private": true,
37
- "scripts": {
38
- "build": "skuba build",
39
- "format": "skuba format",
40
- "lint": "skuba lint",
41
- "start": "skuba start --port <%- port %>",
42
- "start:debug": "yarn start --inspect-brk",
43
- "test": "skuba test",
44
- "test:ci": "skuba test --coverage",
45
- "test:watch": "skuba test --watch"
45
+ "node": ">=18"
46
46
  }
47
47
  }
@@ -36,15 +36,19 @@ const parseInvalidFieldsFromError = ({
36
36
  errors.map((err) => [`/${err.path.join('/')}`, err.message]),
37
37
  );
38
38
 
39
- export const validate = <T>({
39
+ export const validate = <
40
+ Output,
41
+ Def extends z.ZodTypeDef = z.ZodTypeDef,
42
+ Input = Output,
43
+ >({
40
44
  ctx,
41
45
  input,
42
46
  schema,
43
47
  }: {
44
48
  ctx: Context;
45
49
  input: unknown;
46
- schema: z.ZodSchema<T>;
47
- }) => {
50
+ schema: z.ZodSchema<Output, Def, Input>;
51
+ }): Output => {
48
52
  const parseResult = schema.safeParse(input);
49
53
  if (parseResult.success === false) {
50
54
  return ctx.throw(
@@ -58,7 +62,16 @@ export const validate = <T>({
58
62
  return parseResult.data;
59
63
  };
60
64
 
61
- export const validateRequestBody = <T>(
65
+ export const validateRequestBody = <
66
+ Output,
67
+ Def extends z.ZodTypeDef = z.ZodTypeDef,
68
+ Input = Output,
69
+ >(
62
70
  ctx: Context,
63
- schema: z.ZodSchema<T>,
64
- ): T => validate<T>({ ctx, input: ctx.request.body as unknown, schema });
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
+ });
@@ -66,7 +66,7 @@ steps:
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,4 +1,18 @@
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",
@@ -20,19 +34,5 @@
20
34
  },
21
35
  "engines": {
22
36
  "node": ">=16"
23
- },
24
- "license": "UNLICENSED",
25
- "private": true,
26
- "scripts": {
27
- "build": "skuba build",
28
- "deploy": "serverless deploy --force --verbose",
29
- "format": "skuba format",
30
- "lint": "skuba lint",
31
- "smoke": "serverless invoke --data '{}' --function Worker",
32
- "start": "skuba start --port <%- port %>",
33
- "start:debug": "yarn start --inspect-brk",
34
- "test": "skuba test",
35
- "test:ci": "skuba test --coverage",
36
- "test:watch": "skuba test --watch"
37
37
  }
38
38
  }
@@ -1,4 +1,10 @@
1
1
  import { z } from 'zod';
2
2
 
3
- export const validateJson = <T>(input: string, schema: z.ZodSchema<T>) =>
4
- schema.parse(JSON.parse(input));
3
+ export const validateJson = <
4
+ Output,
5
+ Def extends z.ZodTypeDef = z.ZodTypeDef,
6
+ Input = Output,
7
+ >(
8
+ input: string,
9
+ schema: z.ZodSchema<Output, Def, Input>,
10
+ ): Output => schema.parse(JSON.parse(input));
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "lib": ["ES2020"],
5
+ "outDir": "lib",
6
+ "paths": {
7
+ "src": ["src"]
8
+ },
9
+ "target": "ES2020"
10
+ },
11
+ "exclude": ["lib*/**/*"],
12
+ "extends": "skuba/config/tsconfig.json"
13
+ }
@@ -63,7 +63,7 @@ steps:
63
63
 
64
64
  - agents:
65
65
  queue: <%- devBuildkiteQueueName %>
66
- branches: '!renovate/*'
66
+ branches: '!renovate--*'
67
67
  label: 🧖‍♀️ Warm Dev
68
68
  command: ':'
69
69
  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,4 +1,16 @@
1
1
  {
2
+ "private": true,
3
+ "license": "UNLICENSED",
4
+ "scripts": {
5
+ "build": "skuba build",
6
+ "deploy": "cdk deploy appStack --require-approval never --context stage=${ENVIRONMENT}",
7
+ "format": "skuba format",
8
+ "lint": "skuba lint",
9
+ "package": "yarn install --ignore-optional --ignore-scripts --modules-folder ./lib/node_modules --non-interactive --offline --production",
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
  "zod": "^3.19.1"
@@ -14,17 +26,5 @@
14
26
  },
15
27
  "engines": {
16
28
  "node": ">=16"
17
- },
18
- "license": "UNLICENSED",
19
- "private": true,
20
- "scripts": {
21
- "build": "skuba build",
22
- "deploy": "cdk deploy appStack --require-approval never --context stage=${ENVIRONMENT}",
23
- "format": "skuba format",
24
- "lint": "skuba lint",
25
- "package": "yarn install --ignore-optional --ignore-scripts --modules-folder ./lib/node_modules --non-interactive --offline --production",
26
- "test": "skuba test",
27
- "test:ci": "skuba test --coverage",
28
- "test:watch": "skuba test --watch"
29
29
  }
30
30
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "lib": ["ES2020"],
5
+ "outDir": "lib",
6
+ "paths": {
7
+ "src": ["src"]
8
+ },
9
+ "target": "ES2020"
10
+ },
11
+ "exclude": ["lib*/**/*"],
12
+ "extends": "skuba/config/tsconfig.json"
13
+ }
@@ -1 +1 @@
1
- 16
1
+ 18
@@ -1 +1 @@
1
- 16
1
+ 18