skuba 12.2.0-try-again-conditions-20250813002801 → 12.3.0-add-minimumReleaseAge-20250919032927

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 (34) hide show
  1. package/jest/moduleNameMapper.js +3 -0
  2. package/lib/cli/build/tsc.js +14 -16
  3. package/lib/cli/build/tsc.js.map +3 -3
  4. package/lib/cli/configure/processing/configFile.d.ts +1 -1
  5. package/lib/cli/configure/processing/configFile.js +47 -6
  6. package/lib/cli/configure/processing/configFile.js.map +3 -3
  7. package/lib/cli/lint/internalLints/patchRenovateConfig.js +2 -2
  8. package/lib/cli/lint/internalLints/patchRenovateConfig.js.map +1 -1
  9. package/lib/cli/lint/internalLints/refreshConfigFiles.js +5 -3
  10. package/lib/cli/lint/internalLints/refreshConfigFiles.js.map +2 -2
  11. package/lib/cli/lint/internalLints/upgrade/patches/12.1.1/index.d.ts +2 -0
  12. package/lib/cli/lint/internalLints/upgrade/patches/12.1.1/index.js +35 -0
  13. package/lib/cli/lint/internalLints/upgrade/patches/12.1.1/index.js.map +7 -0
  14. package/lib/cli/lint/internalLints/upgrade/patches/12.1.1/patchJestSnapshots.d.ts +3 -0
  15. package/lib/cli/lint/internalLints/upgrade/patches/12.1.1/patchJestSnapshots.js +105 -0
  16. package/lib/cli/lint/internalLints/upgrade/patches/12.1.1/patchJestSnapshots.js.map +7 -0
  17. package/lib/utils/template.d.ts +1 -1
  18. package/package.json +10 -13
  19. package/template/base/_pnpm-workspace.yaml +5 -0
  20. package/template/express-rest-api/Dockerfile.dev-deps +1 -1
  21. package/template/express-rest-api/package.json +6 -6
  22. package/template/greeter/Dockerfile +1 -1
  23. package/template/greeter/package.json +2 -2
  24. package/template/koa-rest-api/Dockerfile.dev-deps +1 -1
  25. package/template/koa-rest-api/package.json +6 -6
  26. package/template/lambda-sqs-worker-cdk/Dockerfile +1 -1
  27. package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +4 -16
  28. package/template/lambda-sqs-worker-cdk/infra/appStack.test.ts +0 -14
  29. package/template/lambda-sqs-worker-cdk/infra/appStack.ts +2 -5
  30. package/template/lambda-sqs-worker-cdk/infra/config.ts +4 -2
  31. package/template/lambda-sqs-worker-cdk/package.json +3 -5
  32. package/template/oss-npm-package/.github/workflows/release.yml +5 -6
  33. package/template/oss-npm-package/.github/workflows/validate.yml +5 -5
  34. package/template/oss-npm-package/_package.json +0 -3
@@ -47,6 +47,9 @@ module.exports.createModuleNameMapper = (getConfig) => {
47
47
  useESM: true,
48
48
  });
49
49
 
50
+ // Always try finding the file with extension before trying without
51
+ moduleNameMapper['^(\\.{1,2}/.*)\\.js$'] = ['$1.js', '$1'];
52
+
50
53
  // Normalise away any `..`s that may crop up from `baseUrl` usage.
51
54
  // For example, a `baseUrl` of `src` and a path of `../cli` will result in
52
55
  // `<rootDir>/src/../cli`, which can be normalised to `<rootDir>/cli`.
@@ -34,6 +34,7 @@ __export(tsc_exports, {
34
34
  tsc: () => tsc
35
35
  });
36
36
  module.exports = __toCommonJS(tsc_exports);
37
+ var import_path = __toESM(require("path"));
37
38
  var import_typescript = __toESM(require("typescript"));
38
39
  var import_exec = require("../../utils/exec.js");
39
40
  var import_logging = require("../../utils/logging.js");
@@ -45,7 +46,6 @@ const formatHost = {
45
46
  getNewLine: () => import_typescript.default.sys.newLine
46
47
  };
47
48
  const tsconfigCache = /* @__PURE__ */ new Map();
48
- const computeCacheKey = (args) => Array.from(args).sort().toString();
49
49
  const tsc = async (args = process.argv.slice(2)) => {
50
50
  const tscArgs = (0, import_args.parseTscArgs)(args);
51
51
  const defaultArgs = tscArgs.build || tscArgs.project ? [] : DEFAULT_ARGS;
@@ -60,12 +60,18 @@ const readTsBuildConfig = (args = process.argv.slice(2), log) => {
60
60
  )
61
61
  );
62
62
  log.debug(tscArgs.pathname);
63
- const parsedCommandLine = readTsConfig({
63
+ const parsedConfig = readTsConfig({
64
64
  dir: tscArgs.dirname,
65
65
  fileName: tscArgs.basename,
66
66
  log
67
67
  });
68
- return parsedCommandLine;
68
+ if (parsedConfig?.errors.length) {
69
+ log.err(`Could not parse ${tscArgs.basename}.`);
70
+ log.subtle(import_typescript.default.formatDiagnostics(parsedConfig.errors, formatHost));
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+ return parsedConfig;
69
75
  };
70
76
  const readTsConfig = ({
71
77
  dir,
@@ -73,8 +79,8 @@ const readTsConfig = ({
73
79
  log,
74
80
  silentlyFail = false
75
81
  }) => {
76
- const cacheKey = computeCacheKey([dir, fileName]);
77
- const cachedConfig = tsconfigCache.get(cacheKey);
82
+ const pathName = import_path.default.join(dir, fileName);
83
+ const cachedConfig = tsconfigCache.get(pathName);
78
84
  if (cachedConfig) {
79
85
  return cachedConfig;
80
86
  }
@@ -85,7 +91,7 @@ const readTsConfig = ({
85
91
  );
86
92
  if (!tsconfigFile) {
87
93
  if (!silentlyFail) {
88
- log.err(`Could not find ${fileName}.`);
94
+ log.err(`Could not find ${pathName}.`);
89
95
  process.exitCode = 1;
90
96
  }
91
97
  return;
@@ -96,7 +102,7 @@ const readTsConfig = ({
96
102
  );
97
103
  if (readConfigFile.error) {
98
104
  if (!silentlyFail) {
99
- log.err(`Could not read ${fileName}.`);
105
+ log.err(`Could not read ${pathName}.`);
100
106
  log.subtle(import_typescript.default.formatDiagnostic(readConfigFile.error, formatHost));
101
107
  process.exitCode = 1;
102
108
  }
@@ -107,15 +113,7 @@ const readTsConfig = ({
107
113
  import_typescript.default.sys,
108
114
  dir
109
115
  );
110
- if (parsedConfig.errors.length) {
111
- if (!silentlyFail) {
112
- log.err(`Could not parse ${fileName}.`);
113
- log.subtle(import_typescript.default.formatDiagnostics(parsedConfig.errors, formatHost));
114
- process.exitCode = 1;
115
- }
116
- return;
117
- }
118
- tsconfigCache.set(cacheKey, parsedConfig);
116
+ tsconfigCache.set(pathName, parsedConfig);
119
117
  return parsedConfig;
120
118
  };
121
119
  const getCustomConditions = () => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/build/tsc.ts"],
4
- "sourcesContent": ["import ts from 'typescript';\n\nimport { exec } from '../../utils/exec.js';\nimport { type Logger, log as logger } from '../../utils/logging.js';\n\nimport { parseTscArgs } from './args.js';\n\nconst DEFAULT_ARGS = ['--project', 'tsconfig.build.json'] as const;\n\nconst formatHost: ts.FormatDiagnosticsHost = {\n getCanonicalFileName: (fileName) => fileName,\n getCurrentDirectory: ts.sys.getCurrentDirectory.bind(undefined),\n getNewLine: () => ts.sys.newLine,\n};\n\nconst tsconfigCache = new Map<string, ts.ParsedCommandLine>();\nconst computeCacheKey = (args: string[]) => Array.from(args).sort().toString();\n\nexport const tsc = async (args = process.argv.slice(2)) => {\n const tscArgs = parseTscArgs(args);\n\n // Build flag is incompatible with project flag.\n const defaultArgs = tscArgs.build || tscArgs.project ? [] : DEFAULT_ARGS;\n\n return exec('tsc', ...defaultArgs, ...args);\n};\n\nexport const readTsBuildConfig = (\n args = process.argv.slice(2),\n log: Logger,\n) => {\n const tscArgs = parseTscArgs(args);\n\n log.debug(\n log.bold(\n 'tsconfig',\n ...(tscArgs.project ? ['--project', tscArgs.project] : []),\n ),\n );\n log.debug(tscArgs.pathname);\n\n const parsedCommandLine = readTsConfig({\n dir: tscArgs.dirname,\n fileName: tscArgs.basename,\n log,\n });\n\n return parsedCommandLine;\n};\n\nexport const readTsConfig = ({\n dir,\n fileName,\n log,\n silentlyFail = false,\n}: {\n dir: string;\n fileName: string;\n log: Logger;\n silentlyFail?: boolean;\n}) => {\n const cacheKey = computeCacheKey([dir, fileName]);\n\n const cachedConfig = tsconfigCache.get(cacheKey);\n\n if (cachedConfig) {\n return cachedConfig;\n }\n\n const tsconfigFile = ts.findConfigFile(\n dir,\n ts.sys.fileExists.bind(undefined),\n fileName,\n );\n if (!tsconfigFile) {\n if (!silentlyFail) {\n log.err(`Could not find ${fileName}.`);\n process.exitCode = 1;\n }\n return;\n }\n\n const readConfigFile = ts.readConfigFile(\n tsconfigFile,\n ts.sys.readFile.bind(undefined),\n );\n if (readConfigFile.error) {\n if (!silentlyFail) {\n log.err(`Could not read ${fileName}.`);\n log.subtle(ts.formatDiagnostic(readConfigFile.error, formatHost));\n process.exitCode = 1;\n }\n return;\n }\n\n const parsedConfig = ts.parseJsonConfigFileContent(\n readConfigFile.config,\n ts.sys,\n dir,\n );\n\n if (parsedConfig.errors.length) {\n if (!silentlyFail) {\n log.err(`Could not parse ${fileName}.`);\n log.subtle(ts.formatDiagnostics(parsedConfig.errors, formatHost));\n process.exitCode = 1;\n }\n return;\n }\n\n tsconfigCache.set(cacheKey, parsedConfig);\n\n return parsedConfig;\n};\n\nexport const getCustomConditions = () => {\n const parsedConfig = readTsConfig({\n dir: process.cwd(),\n fileName: 'tsconfig.json',\n log: logger,\n silentlyFail: true,\n });\n\n if (!parsedConfig) {\n return [];\n }\n\n return parsedConfig.options.customConditions ?? [];\n};\n"],
5
- "mappings": "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",
6
- "names": ["ts", "logger"]
4
+ "sourcesContent": ["import path from 'path';\n\nimport ts from 'typescript';\n\nimport { exec } from '../../utils/exec.js';\nimport { type Logger, log as logger } from '../../utils/logging.js';\n\nimport { parseTscArgs } from './args.js';\n\nconst DEFAULT_ARGS = ['--project', 'tsconfig.build.json'] as const;\n\nconst formatHost: ts.FormatDiagnosticsHost = {\n getCanonicalFileName: (fileName) => fileName,\n getCurrentDirectory: ts.sys.getCurrentDirectory.bind(undefined),\n getNewLine: () => ts.sys.newLine,\n};\n\nconst tsconfigCache = new Map<string, ts.ParsedCommandLine>();\n\nexport const tsc = async (args = process.argv.slice(2)) => {\n const tscArgs = parseTscArgs(args);\n\n // Build flag is incompatible with project flag.\n const defaultArgs = tscArgs.build || tscArgs.project ? [] : DEFAULT_ARGS;\n\n return exec('tsc', ...defaultArgs, ...args);\n};\n\nexport const readTsBuildConfig = (\n args = process.argv.slice(2),\n log: Logger,\n) => {\n const tscArgs = parseTscArgs(args);\n\n log.debug(\n log.bold(\n 'tsconfig',\n ...(tscArgs.project ? ['--project', tscArgs.project] : []),\n ),\n );\n log.debug(tscArgs.pathname);\n\n const parsedConfig = readTsConfig({\n dir: tscArgs.dirname,\n fileName: tscArgs.basename,\n log,\n });\n\n if (parsedConfig?.errors.length) {\n log.err(`Could not parse ${tscArgs.basename}.`);\n log.subtle(ts.formatDiagnostics(parsedConfig.errors, formatHost));\n process.exitCode = 1;\n return;\n }\n\n return parsedConfig;\n};\n\nexport const readTsConfig = ({\n dir,\n fileName,\n log,\n silentlyFail = false,\n}: {\n dir: string;\n fileName: string;\n log: Logger;\n silentlyFail?: boolean;\n}) => {\n const pathName = path.join(dir, fileName);\n\n const cachedConfig = tsconfigCache.get(pathName);\n\n if (cachedConfig) {\n return cachedConfig;\n }\n\n const tsconfigFile = ts.findConfigFile(\n dir,\n ts.sys.fileExists.bind(undefined),\n fileName,\n );\n if (!tsconfigFile) {\n if (!silentlyFail) {\n log.err(`Could not find ${pathName}.`);\n process.exitCode = 1;\n }\n return;\n }\n\n const readConfigFile = ts.readConfigFile(\n tsconfigFile,\n ts.sys.readFile.bind(undefined),\n );\n if (readConfigFile.error) {\n if (!silentlyFail) {\n log.err(`Could not read ${pathName}.`);\n log.subtle(ts.formatDiagnostic(readConfigFile.error, formatHost));\n process.exitCode = 1;\n }\n return;\n }\n\n const parsedConfig = ts.parseJsonConfigFileContent(\n readConfigFile.config,\n ts.sys,\n dir,\n );\n\n tsconfigCache.set(pathName, parsedConfig);\n\n return parsedConfig;\n};\n\nexport const getCustomConditions = () => {\n const parsedConfig = readTsConfig({\n dir: process.cwd(),\n fileName: 'tsconfig.json',\n log: logger,\n silentlyFail: true,\n });\n\n if (!parsedConfig) {\n return [];\n }\n\n return parsedConfig.options.customConditions ?? [];\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,wBAAe;AAEf,kBAAqB;AACrB,qBAA2C;AAE3C,kBAA6B;AAE7B,MAAM,eAAe,CAAC,aAAa,qBAAqB;AAExD,MAAM,aAAuC;AAAA,EAC3C,sBAAsB,CAAC,aAAa;AAAA,EACpC,qBAAqB,kBAAAA,QAAG,IAAI,oBAAoB,KAAK,MAAS;AAAA,EAC9D,YAAY,MAAM,kBAAAA,QAAG,IAAI;AAC3B;AAEA,MAAM,gBAAgB,oBAAI,IAAkC;AAErD,MAAM,MAAM,OAAO,OAAO,QAAQ,KAAK,MAAM,CAAC,MAAM;AACzD,QAAM,cAAU,0BAAa,IAAI;AAGjC,QAAM,cAAc,QAAQ,SAAS,QAAQ,UAAU,CAAC,IAAI;AAE5D,aAAO,kBAAK,OAAO,GAAG,aAAa,GAAG,IAAI;AAC5C;AAEO,MAAM,oBAAoB,CAC/B,OAAO,QAAQ,KAAK,MAAM,CAAC,GAC3B,QACG;AACH,QAAM,cAAU,0BAAa,IAAI;AAEjC,MAAI;AAAA,IACF,IAAI;AAAA,MACF;AAAA,MACA,GAAI,QAAQ,UAAU,CAAC,aAAa,QAAQ,OAAO,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AACA,MAAI,MAAM,QAAQ,QAAQ;AAE1B,QAAM,eAAe,aAAa;AAAA,IAChC,KAAK,QAAQ;AAAA,IACb,UAAU,QAAQ;AAAA,IAClB;AAAA,EACF,CAAC;AAED,MAAI,cAAc,OAAO,QAAQ;AAC/B,QAAI,IAAI,mBAAmB,QAAQ,QAAQ,GAAG;AAC9C,QAAI,OAAO,kBAAAA,QAAG,kBAAkB,aAAa,QAAQ,UAAU,CAAC;AAChE,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,SAAO;AACT;AAEO,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AACjB,MAKM;AACJ,QAAM,WAAW,YAAAC,QAAK,KAAK,KAAK,QAAQ;AAExC,QAAM,eAAe,cAAc,IAAI,QAAQ;AAE/C,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,kBAAAD,QAAG;AAAA,IACtB;AAAA,IACA,kBAAAA,QAAG,IAAI,WAAW,KAAK,MAAS;AAAA,IAChC;AAAA,EACF;AACA,MAAI,CAAC,cAAc;AACjB,QAAI,CAAC,cAAc;AACjB,UAAI,IAAI,kBAAkB,QAAQ,GAAG;AACrC,cAAQ,WAAW;AAAA,IACrB;AACA;AAAA,EACF;AAEA,QAAM,iBAAiB,kBAAAA,QAAG;AAAA,IACxB;AAAA,IACA,kBAAAA,QAAG,IAAI,SAAS,KAAK,MAAS;AAAA,EAChC;AACA,MAAI,eAAe,OAAO;AACxB,QAAI,CAAC,cAAc;AACjB,UAAI,IAAI,kBAAkB,QAAQ,GAAG;AACrC,UAAI,OAAO,kBAAAA,QAAG,iBAAiB,eAAe,OAAO,UAAU,CAAC;AAChE,cAAQ,WAAW;AAAA,IACrB;AACA;AAAA,EACF;AAEA,QAAM,eAAe,kBAAAA,QAAG;AAAA,IACtB,eAAe;AAAA,IACf,kBAAAA,QAAG;AAAA,IACH;AAAA,EACF;AAEA,gBAAc,IAAI,UAAU,YAAY;AAExC,SAAO;AACT;AAEO,MAAM,sBAAsB,MAAM;AACvC,QAAM,eAAe,aAAa;AAAA,IAChC,KAAK,QAAQ,IAAI;AAAA,IACjB,UAAU;AAAA,IACV,KAAK,eAAAE;AAAA,IACL,cAAc;AAAA,EAChB,CAAC;AAED,MAAI,CAAC,cAAc;AACjB,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,aAAa,QAAQ,oBAAoB,CAAC;AACnD;",
6
+ "names": ["ts", "path", "logger"]
7
7
  }
@@ -6,4 +6,4 @@
6
6
  */
7
7
  export declare const generateIgnoreFileSimpleVariants: (patterns: string[]) => Set<string>;
8
8
  export declare const replaceManagedSection: (input: string, template: string) => string;
9
- export declare const mergeWithConfigFile: (rawTemplateFile: string, fileType?: "ignore" | "pnpm-workspace") => (rawInputFile?: string) => string;
9
+ export declare const mergeWithConfigFile: (rawTemplateFile: string, fileType?: "ignore" | "pnpm-workspace", packageJson?: string) => (rawInputFile?: string) => string;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var configFile_exports = {};
20
30
  __export(configFile_exports, {
@@ -23,6 +33,7 @@ __export(configFile_exports, {
23
33
  replaceManagedSection: () => replaceManagedSection
24
34
  });
25
35
  module.exports = __toCommonJS(configFile_exports);
36
+ var import_v4 = __toESM(require("zod/v4"));
26
37
  const OUTDATED_PATTERNS = ["node_modules_bak/", "tmp-*/"];
27
38
  const ASTERISKS = /\*/g;
28
39
  const LEADING_SLASH = /^\//;
@@ -46,9 +57,36 @@ const generateIgnoreFileSimpleVariants = (patterns) => {
46
57
  set.delete("");
47
58
  return set;
48
59
  };
60
+ const ammendPnpmWorkspaceTemplate = (templateFile, packageJson) => {
61
+ const lines = templateFile.split("\n");
62
+ const result = [];
63
+ for (const line of lines) {
64
+ result.push(line);
65
+ if (!packageJson || !line.startsWith("minimumReleaseAgeExclude:")) {
66
+ continue;
67
+ }
68
+ let rawJSON;
69
+ try {
70
+ rawJSON = JSON.parse(packageJson);
71
+ } catch {
72
+ throw new Error("package.json is not valid JSON");
73
+ }
74
+ const parsed = import_v4.default.object({
75
+ minimumReleaseAgeExcludeOverload: import_v4.default.array(import_v4.default.string()).optional()
76
+ }).safeParse(rawJSON);
77
+ const excludes = parsed.data?.minimumReleaseAgeExcludeOverload;
78
+ if (!excludes || Array.isArray(excludes) === false || excludes.some((e) => typeof e !== "string")) {
79
+ continue;
80
+ }
81
+ for (const exclude of excludes) {
82
+ result.push(` - '${exclude}'`);
83
+ }
84
+ }
85
+ return result.join("\n");
86
+ };
49
87
  const replaceManagedSection = (input, template) => input.replace(/# managed by skuba[\s\S]*# end managed by skuba/, template);
50
- const mergeWithConfigFile = (rawTemplateFile, fileType = "ignore") => {
51
- const templateFile = rawTemplateFile.trim();
88
+ const mergeWithConfigFile = (rawTemplateFile, fileType = "ignore", packageJson) => {
89
+ const templateFile = fileType === "pnpm-workspace" ? ammendPnpmWorkspaceTemplate(rawTemplateFile.trim(), packageJson) : rawTemplateFile.trim();
52
90
  let generator;
53
91
  switch (fileType) {
54
92
  case "ignore":
@@ -58,10 +96,13 @@ const mergeWithConfigFile = (rawTemplateFile, fileType = "ignore") => {
58
96
  generator = () => /* @__PURE__ */ new Set();
59
97
  break;
60
98
  }
61
- const templatePatterns = generator([
62
- ...OUTDATED_PATTERNS,
63
- ...templateFile.split("\n").map((line) => line.trim())
64
- ]);
99
+ const templatePatterns = generator(
100
+ [
101
+ ...OUTDATED_PATTERNS,
102
+ ...templateFile.split("\n").map((line) => line.trim())
103
+ ],
104
+ packageJson
105
+ );
65
106
  return (rawInputFile) => {
66
107
  if (rawInputFile === void 0) {
67
108
  return `${templateFile}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/configure/processing/configFile.ts"],
4
- "sourcesContent": ["/**\n * Patterns that are superseded by skuba's bundled ignore file patterns and are\n * non-trivial to derive using e.g. `generateSimpleVariants`.\n */\nconst OUTDATED_PATTERNS = ['node_modules_bak/', 'tmp-*/'];\n\nconst ASTERISKS = /\\*/g;\nconst LEADING_SLASH = /^\\//;\nconst TRAILING_SLASH = /\\/$/;\n\n/**\n * Generate simple variants of an ignore pattern for exact matching purposes.\n *\n * Note that these patterns are not actually equivalent (e.g. `lib` matches more\n * than `lib/`) but they generally represent the same _intent_.\n */\nexport const generateIgnoreFileSimpleVariants = (patterns: string[]) => {\n const set = new Set<string>();\n\n for (const pattern of patterns) {\n const deAsterisked = pattern.replace(ASTERISKS, '');\n const stripped = deAsterisked\n .replace(LEADING_SLASH, '')\n .replace(TRAILING_SLASH, '');\n\n set.add(pattern);\n set.add(deAsterisked);\n set.add(deAsterisked.replace(LEADING_SLASH, ''));\n set.add(deAsterisked.replace(TRAILING_SLASH, ''));\n set.add(stripped);\n\n if (stripped !== '') {\n set.add(`/${stripped}`);\n set.add(`${stripped}/`);\n set.add(`/${stripped}/`);\n }\n }\n\n set.delete('');\n\n return set;\n};\n\nexport const replaceManagedSection = (input: string, template: string) =>\n input.replace(/# managed by skuba[\\s\\S]*# end managed by skuba/, template);\n\nexport const mergeWithConfigFile = (\n rawTemplateFile: string,\n fileType: 'ignore' | 'pnpm-workspace' = 'ignore',\n) => {\n const templateFile = rawTemplateFile.trim();\n\n let generator: (s: string[]) => Set<string>;\n\n switch (fileType) {\n case 'ignore':\n generator = generateIgnoreFileSimpleVariants;\n break;\n case 'pnpm-workspace':\n generator = () => new Set<string>();\n break;\n }\n\n const templatePatterns = generator([\n ...OUTDATED_PATTERNS,\n ...templateFile.split('\\n').map((line) => line.trim()),\n ]);\n\n return (rawInputFile?: string) => {\n if (rawInputFile === undefined) {\n return `${templateFile}\\n`;\n }\n\n const replacedFile = replaceManagedSection(\n rawInputFile.replace(/\\r?\\n/g, '\\n'),\n templateFile,\n );\n\n if (replacedFile.includes(templateFile)) {\n return replacedFile;\n }\n\n // Crunch the existing lines of a non-skuba config.\n const migratedFile = replacedFile\n .split('\\n')\n .filter((line) => !templatePatterns.has(line))\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n\n const outputFile = [templateFile, migratedFile].join('\\n\\n').trim();\n\n return `${outputFile}\\n`;\n };\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,MAAM,oBAAoB,CAAC,qBAAqB,QAAQ;AAExD,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AAQhB,MAAM,mCAAmC,CAAC,aAAuB;AACtE,QAAM,MAAM,oBAAI,IAAY;AAE5B,aAAW,WAAW,UAAU;AAC9B,UAAM,eAAe,QAAQ,QAAQ,WAAW,EAAE;AAClD,UAAM,WAAW,aACd,QAAQ,eAAe,EAAE,EACzB,QAAQ,gBAAgB,EAAE;AAE7B,QAAI,IAAI,OAAO;AACf,QAAI,IAAI,YAAY;AACpB,QAAI,IAAI,aAAa,QAAQ,eAAe,EAAE,CAAC;AAC/C,QAAI,IAAI,aAAa,QAAQ,gBAAgB,EAAE,CAAC;AAChD,QAAI,IAAI,QAAQ;AAEhB,QAAI,aAAa,IAAI;AACnB,UAAI,IAAI,IAAI,QAAQ,EAAE;AACtB,UAAI,IAAI,GAAG,QAAQ,GAAG;AACtB,UAAI,IAAI,IAAI,QAAQ,GAAG;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,OAAO,EAAE;AAEb,SAAO;AACT;AAEO,MAAM,wBAAwB,CAAC,OAAe,aACnD,MAAM,QAAQ,mDAAmD,QAAQ;AAEpE,MAAM,sBAAsB,CACjC,iBACA,WAAwC,aACrC;AACH,QAAM,eAAe,gBAAgB,KAAK;AAE1C,MAAI;AAEJ,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,kBAAY;AACZ;AAAA,IACF,KAAK;AACH,kBAAY,MAAM,oBAAI,IAAY;AAClC;AAAA,EACJ;AAEA,QAAM,mBAAmB,UAAU;AAAA,IACjC,GAAG;AAAA,IACH,GAAG,aAAa,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AAAA,EACvD,CAAC;AAED,SAAO,CAAC,iBAA0B;AAChC,QAAI,iBAAiB,QAAW;AAC9B,aAAO,GAAG,YAAY;AAAA;AAAA,IACxB;AAEA,UAAM,eAAe;AAAA,MACnB,aAAa,QAAQ,UAAU,IAAI;AAAA,MACnC;AAAA,IACF;AAEA,QAAI,aAAa,SAAS,YAAY,GAAG;AACvC,aAAO;AAAA,IACT;AAGA,UAAM,eAAe,aAClB,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,CAAC,iBAAiB,IAAI,IAAI,CAAC,EAC5C,KAAK,IAAI,EACT,QAAQ,WAAW,MAAM,EACzB,KAAK;AAER,UAAM,aAAa,CAAC,cAAc,YAAY,EAAE,KAAK,MAAM,EAAE,KAAK;AAElE,WAAO,GAAG,UAAU;AAAA;AAAA,EACtB;AACF;",
6
- "names": []
4
+ "sourcesContent": ["import z from 'zod/v4';\n\n/**\n * Patterns that are superseded by skuba's bundled ignore file patterns and are\n * non-trivial to derive using e.g. `generateSimpleVariants`.\n */\nconst OUTDATED_PATTERNS = ['node_modules_bak/', 'tmp-*/'];\n\nconst ASTERISKS = /\\*/g;\nconst LEADING_SLASH = /^\\//;\nconst TRAILING_SLASH = /\\/$/;\n\n/**\n * Generate simple variants of an ignore pattern for exact matching purposes.\n *\n * Note that these patterns are not actually equivalent (e.g. `lib` matches more\n * than `lib/`) but they generally represent the same _intent_.\n */\nexport const generateIgnoreFileSimpleVariants = (patterns: string[]) => {\n const set = new Set<string>();\n\n for (const pattern of patterns) {\n const deAsterisked = pattern.replace(ASTERISKS, '');\n const stripped = deAsterisked\n .replace(LEADING_SLASH, '')\n .replace(TRAILING_SLASH, '');\n\n set.add(pattern);\n set.add(deAsterisked);\n set.add(deAsterisked.replace(LEADING_SLASH, ''));\n set.add(deAsterisked.replace(TRAILING_SLASH, ''));\n set.add(stripped);\n\n if (stripped !== '') {\n set.add(`/${stripped}`);\n set.add(`${stripped}/`);\n set.add(`/${stripped}/`);\n }\n }\n\n set.delete('');\n\n return set;\n};\n\nconst ammendPnpmWorkspaceTemplate = (\n templateFile: string,\n packageJson?: string,\n) => {\n const lines = templateFile.split('\\n');\n const result: string[] = [];\n for (const line of lines) {\n result.push(line);\n if (!packageJson || !line.startsWith('minimumReleaseAgeExclude:')) {\n continue;\n }\n\n let rawJSON;\n try {\n rawJSON = JSON.parse(packageJson) as unknown;\n } catch {\n throw new Error('package.json is not valid JSON');\n }\n const parsed = z\n .object({\n minimumReleaseAgeExcludeOverload: z.array(z.string()).optional(),\n })\n .safeParse(rawJSON);\n\n const excludes = parsed.data?.minimumReleaseAgeExcludeOverload;\n\n if (\n !excludes ||\n Array.isArray(excludes) === false ||\n excludes.some((e) => typeof e !== 'string')\n ) {\n continue;\n }\n for (const exclude of excludes) {\n result.push(` - '${exclude}'`);\n }\n }\n\n return result.join('\\n');\n};\n\nexport const replaceManagedSection = (input: string, template: string) =>\n input.replace(/# managed by skuba[\\s\\S]*# end managed by skuba/, template);\n\nexport const mergeWithConfigFile = (\n rawTemplateFile: string,\n fileType: 'ignore' | 'pnpm-workspace' = 'ignore',\n packageJson?: string,\n) => {\n const templateFile =\n fileType === 'pnpm-workspace'\n ? ammendPnpmWorkspaceTemplate(rawTemplateFile.trim(), packageJson)\n : rawTemplateFile.trim();\n\n let generator: (s: string[], packageJson?: string) => Set<string>;\n\n switch (fileType) {\n case 'ignore':\n generator = generateIgnoreFileSimpleVariants;\n break;\n case 'pnpm-workspace':\n generator = () => new Set<string>();\n break;\n }\n\n const templatePatterns = generator(\n [\n ...OUTDATED_PATTERNS,\n ...templateFile.split('\\n').map((line) => line.trim()),\n ],\n packageJson,\n );\n\n return (rawInputFile?: string) => {\n if (rawInputFile === undefined) {\n return `${templateFile}\\n`;\n }\n\n const replacedFile = replaceManagedSection(\n rawInputFile.replace(/\\r?\\n/g, '\\n'),\n templateFile,\n );\n\n if (replacedFile.includes(templateFile)) {\n return replacedFile;\n }\n\n // Crunch the existing lines of a non-skuba config.\n const migratedFile = replacedFile\n .split('\\n')\n .filter((line) => !templatePatterns.has(line))\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n\n const outputFile = [templateFile, migratedFile].join('\\n\\n').trim();\n\n return `${outputFile}\\n`;\n };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["z"]
7
7
  }
@@ -129,7 +129,7 @@ const patchRenovateConfig = async (mode, dir) => {
129
129
  });
130
130
  return { result: "apply" };
131
131
  };
132
- const tryPatchRenovateConfig = async ({
132
+ const tryPatchRenovateConfig = (async ({
133
133
  mode,
134
134
  dir = process.cwd()
135
135
  }) => {
@@ -144,7 +144,7 @@ const tryPatchRenovateConfig = async ({
144
144
  import_logging.log.subtle((0, import_util.inspect)(err));
145
145
  return { result: "skip", reason: "due to an error" };
146
146
  }
147
- };
147
+ });
148
148
  // Annotate the CommonJS export names for ESM import in node:
149
149
  0 && (module.exports = {
150
150
  tryPatchRenovateConfig
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/lint/internalLints/patchRenovateConfig.ts"],
4
4
  "sourcesContent": ["import path from 'path';\nimport { inspect } from 'util';\n\nimport fs from 'fs-extra';\nimport * as fleece from 'golden-fleece';\nimport * as z from 'zod/v4';\n\nimport * as Git from '../../../api/git/index.js';\nimport { log } from '../../../utils/logging.js';\nimport { createDestinationFileReader } from '../../configure/analysis/project.js';\nimport { RENOVATE_CONFIG_FILENAMES } from '../../configure/modules/renovate.js';\nimport { formatPrettier } from '../../configure/processing/prettier.js';\n\nimport type { PatchFunction, PatchReturnType } from './upgrade/index.js';\n\nconst EXISTING_REPO_PRESET_REGEX = /(github|local)>(seek-jobs|seekasia)\\//;\n\ntype RenovateFiletype = 'json' | 'json5';\n\ntype RenovatePreset =\n | 'local>seekasia/renovate-config'\n | 'local>seek-jobs/renovate-config';\n\nconst renovateConfigSchema = z.object({\n extends: z.array(z.string()),\n});\n\nconst ownerToRenovatePreset = (owner: string): RenovatePreset | undefined => {\n const lowercaseOwner = owner.toLowerCase();\n\n switch (lowercaseOwner) {\n case 'seekasia':\n return 'local>seekasia/renovate-config';\n\n case 'seek-jobs':\n return 'local>seek-jobs/renovate-config';\n\n default:\n return;\n }\n};\n\ntype PatchFile = (props: {\n filepath: string;\n input: string;\n presetToAdd: RenovatePreset;\n}) => Promise<void>;\n\nconst patchJson: PatchFile = async ({ filepath, input, presetToAdd }) => {\n const json: unknown = JSON.parse(input);\n\n const config = renovateConfigSchema.safeParse(json);\n\n if (!config.success) {\n return;\n }\n\n config.data.extends.unshift(presetToAdd);\n\n await fs.promises.writeFile(\n filepath,\n await formatPrettier(JSON.stringify(config.data), { parser: 'json' }),\n );\n\n return;\n};\n\nconst patchJson5: PatchFile = async ({ filepath, input, presetToAdd }) => {\n const json: unknown = fleece.evaluate(input);\n\n const config = renovateConfigSchema.safeParse(json);\n\n if (!config.success) {\n return;\n }\n\n config.data.extends.unshift(presetToAdd);\n\n await fs.promises.writeFile(\n filepath,\n await formatPrettier(fleece.patch(input, config.data), { parser: 'json5' }),\n );\n\n return;\n};\n\nconst patchByFiletype: Record<RenovateFiletype, PatchFile> = {\n json: patchJson,\n json5: patchJson5,\n};\n\nconst patchRenovateConfig = async (\n mode: 'format' | 'lint',\n dir: string,\n): Promise<PatchReturnType> => {\n const readFile = createDestinationFileReader(dir);\n\n const { owner } = await Git.getOwnerAndRepo({ dir });\n\n const presetToAdd = ownerToRenovatePreset(owner);\n\n if (!presetToAdd) {\n return {\n result: 'skip',\n reason: 'owner does not map to a SEEK preset',\n };\n }\n\n const maybeConfigs = await Promise.all(\n RENOVATE_CONFIG_FILENAMES.map(async (filepath) => ({\n input: await readFile(filepath),\n filepath,\n })),\n );\n\n const config = maybeConfigs.find((maybeConfig) => Boolean(maybeConfig.input));\n if (!config?.input) {\n return { result: 'skip', reason: 'no config found' };\n }\n\n if (\n // The file appears to mention the baseline preset for the configured Git\n // owner. This is a naive check for simplicity.\n config.input.includes(presetToAdd) ||\n // Ignore any renovate configuration which already extends a SEEK-Jobs or seekasia config\n EXISTING_REPO_PRESET_REGEX.exec(config.input)\n ) {\n return {\n result: 'skip',\n reason: 'config already has a SEEK preset',\n };\n }\n\n if (mode === 'lint') {\n return { result: 'apply' };\n }\n\n const filetype: RenovateFiletype = config.filepath\n .toLowerCase()\n .endsWith('.json5')\n ? 'json5'\n : 'json';\n\n const patchFile = patchByFiletype[filetype];\n\n await patchFile({\n filepath: path.resolve(dir, config.filepath),\n input: config.input,\n presetToAdd,\n });\n\n return { result: 'apply' };\n};\n\nexport const tryPatchRenovateConfig = (async ({\n mode,\n dir = process.cwd(),\n}) => {\n try {\n // In a monorepo we may be invoked within a subdirectory, but we are working\n // with Renovate config that should be relative to the repository root.\n const gitRoot = await Git.findRoot({ dir });\n if (!gitRoot) {\n return { result: 'skip', reason: 'no Git root found' };\n }\n\n return await patchRenovateConfig(mode, gitRoot);\n } catch (err) {\n log.warn('Failed to patch Renovate config.');\n log.subtle(inspect(err));\n return { result: 'skip', reason: 'due to an error' };\n }\n}) satisfies PatchFunction;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,kBAAwB;AAExB,sBAAe;AACf,aAAwB;AACxB,QAAmB;AAEnB,UAAqB;AACrB,qBAAoB;AACpB,qBAA4C;AAC5C,sBAA0C;AAC1C,sBAA+B;AAI/B,MAAM,6BAA6B;AAQnC,MAAM,uBAAuB,EAAE,OAAO;AAAA,EACpC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;AAC7B,CAAC;AAED,MAAM,wBAAwB,CAAC,UAA8C;AAC3E,QAAM,iBAAiB,MAAM,YAAY;AAEzC,UAAQ,gBAAgB;AAAA,IACtB,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET;AACE;AAAA,EACJ;AACF;AAQA,MAAM,YAAuB,OAAO,EAAE,UAAU,OAAO,YAAY,MAAM;AACvE,QAAM,OAAgB,KAAK,MAAM,KAAK;AAEtC,QAAM,SAAS,qBAAqB,UAAU,IAAI;AAElD,MAAI,CAAC,OAAO,SAAS;AACnB;AAAA,EACF;AAEA,SAAO,KAAK,QAAQ,QAAQ,WAAW;AAEvC,QAAM,gBAAAA,QAAG,SAAS;AAAA,IAChB;AAAA,IACA,UAAM,gCAAe,KAAK,UAAU,OAAO,IAAI,GAAG,EAAE,QAAQ,OAAO,CAAC;AAAA,EACtE;AAEA;AACF;AAEA,MAAM,aAAwB,OAAO,EAAE,UAAU,OAAO,YAAY,MAAM;AACxE,QAAM,OAAgB,OAAO,SAAS,KAAK;AAE3C,QAAM,SAAS,qBAAqB,UAAU,IAAI;AAElD,MAAI,CAAC,OAAO,SAAS;AACnB;AAAA,EACF;AAEA,SAAO,KAAK,QAAQ,QAAQ,WAAW;AAEvC,QAAM,gBAAAA,QAAG,SAAS;AAAA,IAChB;AAAA,IACA,UAAM,gCAAe,OAAO,MAAM,OAAO,OAAO,IAAI,GAAG,EAAE,QAAQ,QAAQ,CAAC;AAAA,EAC5E;AAEA;AACF;AAEA,MAAM,kBAAuD;AAAA,EAC3D,MAAM;AAAA,EACN,OAAO;AACT;AAEA,MAAM,sBAAsB,OAC1B,MACA,QAC6B;AAC7B,QAAM,eAAW,4CAA4B,GAAG;AAEhD,QAAM,EAAE,MAAM,IAAI,MAAM,IAAI,gBAAgB,EAAE,IAAI,CAAC;AAEnD,QAAM,cAAc,sBAAsB,KAAK;AAE/C,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,eAAe,MAAM,QAAQ;AAAA,IACjC,0CAA0B,IAAI,OAAO,cAAc;AAAA,MACjD,OAAO,MAAM,SAAS,QAAQ;AAAA,MAC9B;AAAA,IACF,EAAE;AAAA,EACJ;AAEA,QAAM,SAAS,aAAa,KAAK,CAAC,gBAAgB,QAAQ,YAAY,KAAK,CAAC;AAC5E,MAAI,CAAC,QAAQ,OAAO;AAClB,WAAO,EAAE,QAAQ,QAAQ,QAAQ,kBAAkB;AAAA,EACrD;AAEA;AAAA;AAAA;AAAA,IAGE,OAAO,MAAM,SAAS,WAAW;AAAA,IAEjC,2BAA2B,KAAK,OAAO,KAAK;AAAA,IAC5C;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,SAAS,QAAQ;AACnB,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AAEA,QAAM,WAA6B,OAAO,SACvC,YAAY,EACZ,SAAS,QAAQ,IAChB,UACA;AAEJ,QAAM,YAAY,gBAAgB,QAAQ;AAE1C,QAAM,UAAU;AAAA,IACd,UAAU,YAAAC,QAAK,QAAQ,KAAK,OAAO,QAAQ;AAAA,IAC3C,OAAO,OAAO;AAAA,IACd;AAAA,EACF,CAAC;AAED,SAAO,EAAE,QAAQ,QAAQ;AAC3B;AAEO,MAAM,yBAA0B,OAAO;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,IAAI;AACpB,MAAM;AACJ,MAAI;AAGF,UAAM,UAAU,MAAM,IAAI,SAAS,EAAE,IAAI,CAAC;AAC1C,QAAI,CAAC,SAAS;AACZ,aAAO,EAAE,QAAQ,QAAQ,QAAQ,oBAAoB;AAAA,IACvD;AAEA,WAAO,MAAM,oBAAoB,MAAM,OAAO;AAAA,EAChD,SAAS,KAAK;AACZ,uBAAI,KAAK,kCAAkC;AAC3C,uBAAI,WAAO,qBAAQ,GAAG,CAAC;AACvB,WAAO,EAAE,QAAQ,QAAQ,QAAQ,kBAAkB;AAAA,EACrD;AACF;",
5
+ "mappings": "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",
6
6
  "names": ["fs", "path"]
7
7
  }
@@ -87,19 +87,21 @@ const refreshConfigFiles = async (mode, logger) => {
87
87
  if (!condition(conditionOptions)) {
88
88
  return { needsChange: false };
89
89
  }
90
- const [inputFile, templateFile, isGitIgnored] = await Promise.all([
90
+ const maybeReadPackageJson = async (type) => type === "pnpm-workspace" ? await readDestinationFile("package.json") : void 0;
91
+ const [inputFile, templateFile, isGitIgnored, packageJson] = await Promise.all([
91
92
  readDestinationFile(filename),
92
93
  (0, import_template.readBaseTemplateFile)(`_${filename}`),
93
94
  gitRoot ? import__.Git.isFileGitIgnored({
94
95
  gitRoot,
95
96
  absolutePath: import_path.default.join(destinationRoot, filename)
96
- }) : false
97
+ }) : false,
98
+ maybeReadPackageJson(fileType)
97
99
  ]);
98
100
  if (inputFile === void 0 && isGitIgnored) {
99
101
  return { needsChange: false };
100
102
  }
101
103
  const data = additionalMapping(
102
- inputFile ? (0, import_configFile.mergeWithConfigFile)(templateFile, fileType)(inputFile) : templateFile,
104
+ inputFile ? (0, import_configFile.mergeWithConfigFile)(templateFile, fileType, packageJson)(inputFile) : templateFile,
103
105
  packageManager
104
106
  );
105
107
  const filepath = import_path.default.join(destinationRoot, filename);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/lint/internalLints/refreshConfigFiles.ts"],
4
- "sourcesContent": ["import path from 'path';\nimport { inspect, stripVTControlCharacters as stripAnsi } from 'util';\n\nimport fs from 'fs-extra';\n\nimport { Git } from '../../../index.js';\nimport {\n findCurrentWorkspaceProjectRoot,\n findWorkspaceRoot,\n} from '../../../utils/dir.js';\nimport type { Logger } from '../../../utils/logging.js';\nimport {\n type PackageManagerConfig,\n detectPackageManager,\n} from '../../../utils/packageManager.js';\nimport { readBaseTemplateFile } from '../../../utils/template.js';\nimport { getDestinationManifest } from '../../configure/analysis/package.js';\nimport { createDestinationFileReader } from '../../configure/analysis/project.js';\nimport { mergeWithConfigFile } from '../../configure/processing/configFile.js';\nimport type { InternalLintResult } from '../internal.js';\n\ntype ConditionOptions = {\n packageManager: PackageManagerConfig;\n isInWorkspaceRoot: boolean;\n};\n\ntype RefreshableConfigFile = {\n name: string;\n type: 'ignore' | 'pnpm-workspace';\n additionalMapping?: (\n s: string,\n packageManager: PackageManagerConfig,\n ) => string;\n if?: (options: ConditionOptions) => boolean;\n};\n\nconst OLD_IGNORE_WARNING = `# Ignore .npmrc. This is no longer managed by skuba as pnpm projects use a managed .npmrc.\n# IMPORTANT: if migrating to pnpm, remove this line and add an .npmrc IN THE SAME COMMIT.\n# You can use \\`skuba format\\` to generate the file or otherwise commit an empty file.\n# Doing so will conflict with a local .npmrc and make it more difficult to unintentionally commit auth secrets.\n.npmrc\n`;\n\nconst removeOldWarning = (contents: string) =>\n contents.includes(OLD_IGNORE_WARNING)\n ? `${contents.replace(OLD_IGNORE_WARNING, '').trim()}\\n`\n : contents;\n\nexport const REFRESHABLE_CONFIG_FILES: RefreshableConfigFile[] = [\n {\n name: '.gitignore',\n type: 'ignore',\n additionalMapping: removeOldWarning,\n },\n { name: '.prettierignore', type: 'ignore' },\n {\n name: 'pnpm-workspace.yaml',\n type: 'pnpm-workspace',\n if: ({ packageManager, isInWorkspaceRoot }) =>\n isInWorkspaceRoot && packageManager.command === 'pnpm',\n },\n {\n name: '.dockerignore',\n type: 'ignore',\n additionalMapping: removeOldWarning,\n },\n];\n\nexport const refreshConfigFiles = async (\n mode: 'format' | 'lint',\n logger: Logger,\n) => {\n const [manifest, gitRoot, workspaceRoot, currentWorkspaceProjectRoot] =\n await Promise.all([\n getDestinationManifest(),\n Git.findRoot({ dir: process.cwd() }),\n findWorkspaceRoot(),\n findCurrentWorkspaceProjectRoot(),\n ]);\n\n const destinationRoot = path.dirname(manifest.path);\n\n const readDestinationFile = createDestinationFileReader(destinationRoot);\n\n const refreshConfigFile = async (\n {\n name: filename,\n type: fileType,\n additionalMapping = (s) => s,\n if: condition = () => true,\n }: RefreshableConfigFile,\n conditionOptions: ConditionOptions,\n ) => {\n if (!condition(conditionOptions)) {\n return { needsChange: false };\n }\n\n const [inputFile, templateFile, isGitIgnored] = await Promise.all([\n readDestinationFile(filename),\n readBaseTemplateFile(`_${filename}`),\n gitRoot\n ? Git.isFileGitIgnored({\n gitRoot,\n absolutePath: path.join(destinationRoot, filename),\n })\n : false,\n ]);\n\n // If the file is gitignored and doesn't exist, don't make it\n if (inputFile === undefined && isGitIgnored) {\n return { needsChange: false };\n }\n\n const data = additionalMapping(\n inputFile\n ? mergeWithConfigFile(templateFile, fileType)(inputFile)\n : templateFile,\n packageManager,\n );\n\n const filepath = path.join(destinationRoot, filename);\n\n if (mode === 'format') {\n if (data === inputFile) {\n return { needsChange: false };\n }\n\n await fs.writeFile(filepath, data);\n return {\n needsChange: false,\n msg: `Refreshed ${logger.bold(filename)}.`,\n filename,\n };\n }\n\n if (data !== inputFile) {\n return {\n needsChange: true,\n msg: `The ${logger.bold(\n filename,\n )} file is out of date. Run \\`${logger.bold(\n packageManager.print.exec,\n 'skuba',\n 'format',\n )}\\` to update it.`,\n filename,\n };\n }\n\n return { needsChange: false };\n };\n\n const packageManager = await detectPackageManager(destinationRoot);\n\n const results = await Promise.all(\n REFRESHABLE_CONFIG_FILES.map((conf) =>\n refreshConfigFile(conf, {\n packageManager,\n isInWorkspaceRoot: workspaceRoot === currentWorkspaceProjectRoot,\n }),\n ),\n );\n\n // Log after for reproducible test output ordering\n results.forEach((result) => {\n if (result.msg) {\n logger.warn(result.msg);\n }\n });\n\n const anyNeedChanging = results.some(({ needsChange }) => needsChange);\n\n return {\n ok: !anyNeedChanging,\n fixable: anyNeedChanging,\n annotations: results.flatMap(({ needsChange, filename, msg }) =>\n needsChange && msg\n ? [\n {\n path: filename,\n message: stripAnsi(msg),\n },\n ]\n : [],\n ),\n };\n};\n\nexport const tryRefreshConfigFiles = async (\n mode: 'format' | 'lint',\n logger: Logger,\n): Promise<InternalLintResult> => {\n try {\n return await refreshConfigFiles(mode, logger);\n } catch (err) {\n logger.warn('Failed to refresh config files.');\n logger.subtle(inspect(err));\n\n return {\n ok: false,\n fixable: false,\n annotations: [],\n };\n }\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,kBAA+D;AAE/D,sBAAe;AAEf,eAAoB;AACpB,iBAGO;AAEP,4BAGO;AACP,sBAAqC;AACrC,qBAAuC;AACvC,qBAA4C;AAC5C,wBAAoC;AAkBpC,MAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAO3B,MAAM,mBAAmB,CAAC,aACxB,SAAS,SAAS,kBAAkB,IAChC,GAAG,SAAS,QAAQ,oBAAoB,EAAE,EAAE,KAAK,CAAC;AAAA,IAClD;AAEC,MAAM,2BAAoD;AAAA,EAC/D;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,mBAAmB;AAAA,EACrB;AAAA,EACA,EAAE,MAAM,mBAAmB,MAAM,SAAS;AAAA,EAC1C;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,IAAI,CAAC,EAAE,gBAAgB,kBAAkB,MACvC,qBAAqB,eAAe,YAAY;AAAA,EACpD;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,mBAAmB;AAAA,EACrB;AACF;AAEO,MAAM,qBAAqB,OAChC,MACA,WACG;AACH,QAAM,CAAC,UAAU,SAAS,eAAe,2BAA2B,IAClE,MAAM,QAAQ,IAAI;AAAA,QAChB,uCAAuB;AAAA,IACvB,aAAI,SAAS,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC;AAAA,QACnC,8BAAkB;AAAA,QAClB,4CAAgC;AAAA,EAClC,CAAC;AAEH,QAAM,kBAAkB,YAAAA,QAAK,QAAQ,SAAS,IAAI;AAElD,QAAM,0BAAsB,4CAA4B,eAAe;AAEvE,QAAM,oBAAoB,OACxB;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,oBAAoB,CAAC,MAAM;AAAA,IAC3B,IAAI,YAAY,MAAM;AAAA,EACxB,GACA,qBACG;AACH,QAAI,CAAC,UAAU,gBAAgB,GAAG;AAChC,aAAO,EAAE,aAAa,MAAM;AAAA,IAC9B;AAEA,UAAM,CAAC,WAAW,cAAc,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,MAChE,oBAAoB,QAAQ;AAAA,UAC5B,sCAAqB,IAAI,QAAQ,EAAE;AAAA,MACnC,UACI,aAAI,iBAAiB;AAAA,QACnB;AAAA,QACA,cAAc,YAAAA,QAAK,KAAK,iBAAiB,QAAQ;AAAA,MACnD,CAAC,IACD;AAAA,IACN,CAAC;AAGD,QAAI,cAAc,UAAa,cAAc;AAC3C,aAAO,EAAE,aAAa,MAAM;AAAA,IAC9B;AAEA,UAAM,OAAO;AAAA,MACX,gBACI,uCAAoB,cAAc,QAAQ,EAAE,SAAS,IACrD;AAAA,MACJ;AAAA,IACF;AAEA,UAAM,WAAW,YAAAA,QAAK,KAAK,iBAAiB,QAAQ;AAEpD,QAAI,SAAS,UAAU;AACrB,UAAI,SAAS,WAAW;AACtB,eAAO,EAAE,aAAa,MAAM;AAAA,MAC9B;AAEA,YAAM,gBAAAC,QAAG,UAAU,UAAU,IAAI;AACjC,aAAO;AAAA,QACL,aAAa;AAAA,QACb,KAAK,aAAa,OAAO,KAAK,QAAQ,CAAC;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,WAAW;AACtB,aAAO;AAAA,QACL,aAAa;AAAA,QACb,KAAK,OAAO,OAAO;AAAA,UACjB;AAAA,QACF,CAAC,+BAA+B,OAAO;AAAA,UACrC,eAAe,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,aAAa,MAAM;AAAA,EAC9B;AAEA,QAAM,iBAAiB,UAAM,4CAAqB,eAAe;AAEjE,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,yBAAyB;AAAA,MAAI,CAAC,SAC5B,kBAAkB,MAAM;AAAA,QACtB;AAAA,QACA,mBAAmB,kBAAkB;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,EACF;AAGA,UAAQ,QAAQ,CAAC,WAAW;AAC1B,QAAI,OAAO,KAAK;AACd,aAAO,KAAK,OAAO,GAAG;AAAA,IACxB;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,QAAQ,KAAK,CAAC,EAAE,YAAY,MAAM,WAAW;AAErE,SAAO;AAAA,IACL,IAAI,CAAC;AAAA,IACL,SAAS;AAAA,IACT,aAAa,QAAQ;AAAA,MAAQ,CAAC,EAAE,aAAa,UAAU,IAAI,MACzD,eAAe,MACX;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,aAAS,YAAAC,0BAAU,GAAG;AAAA,QACxB;AAAA,MACF,IACA,CAAC;AAAA,IACP;AAAA,EACF;AACF;AAEO,MAAM,wBAAwB,OACnC,MACA,WACgC;AAChC,MAAI;AACF,WAAO,MAAM,mBAAmB,MAAM,MAAM;AAAA,EAC9C,SAAS,KAAK;AACZ,WAAO,KAAK,iCAAiC;AAC7C,WAAO,WAAO,qBAAQ,GAAG,CAAC;AAE1B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,aAAa,CAAC;AAAA,IAChB;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import path from 'path';\nimport { inspect, stripVTControlCharacters as stripAnsi } from 'util';\n\nimport fs from 'fs-extra';\n\nimport { Git } from '../../../index.js';\nimport {\n findCurrentWorkspaceProjectRoot,\n findWorkspaceRoot,\n} from '../../../utils/dir.js';\nimport type { Logger } from '../../../utils/logging.js';\nimport {\n type PackageManagerConfig,\n detectPackageManager,\n} from '../../../utils/packageManager.js';\nimport { readBaseTemplateFile } from '../../../utils/template.js';\nimport { getDestinationManifest } from '../../configure/analysis/package.js';\nimport { createDestinationFileReader } from '../../configure/analysis/project.js';\nimport { mergeWithConfigFile } from '../../configure/processing/configFile.js';\nimport type { InternalLintResult } from '../internal.js';\n\ntype ConditionOptions = {\n packageManager: PackageManagerConfig;\n isInWorkspaceRoot: boolean;\n};\n\ntype RefreshableConfigFile = {\n name: string;\n type: 'ignore' | 'pnpm-workspace';\n additionalMapping?: (\n s: string,\n packageManager: PackageManagerConfig,\n ) => string;\n if?: (options: ConditionOptions) => boolean;\n};\n\nconst OLD_IGNORE_WARNING = `# Ignore .npmrc. This is no longer managed by skuba as pnpm projects use a managed .npmrc.\n# IMPORTANT: if migrating to pnpm, remove this line and add an .npmrc IN THE SAME COMMIT.\n# You can use \\`skuba format\\` to generate the file or otherwise commit an empty file.\n# Doing so will conflict with a local .npmrc and make it more difficult to unintentionally commit auth secrets.\n.npmrc\n`;\n\nconst removeOldWarning = (contents: string) =>\n contents.includes(OLD_IGNORE_WARNING)\n ? `${contents.replace(OLD_IGNORE_WARNING, '').trim()}\\n`\n : contents;\n\nexport const REFRESHABLE_CONFIG_FILES: RefreshableConfigFile[] = [\n {\n name: '.gitignore',\n type: 'ignore',\n additionalMapping: removeOldWarning,\n },\n { name: '.prettierignore', type: 'ignore' },\n {\n name: 'pnpm-workspace.yaml',\n type: 'pnpm-workspace',\n if: ({ packageManager, isInWorkspaceRoot }) =>\n isInWorkspaceRoot && packageManager.command === 'pnpm',\n },\n {\n name: '.dockerignore',\n type: 'ignore',\n additionalMapping: removeOldWarning,\n },\n];\n\nexport const refreshConfigFiles = async (\n mode: 'format' | 'lint',\n logger: Logger,\n) => {\n const [manifest, gitRoot, workspaceRoot, currentWorkspaceProjectRoot] =\n await Promise.all([\n getDestinationManifest(),\n Git.findRoot({ dir: process.cwd() }),\n findWorkspaceRoot(),\n findCurrentWorkspaceProjectRoot(),\n ]);\n\n const destinationRoot = path.dirname(manifest.path);\n\n const readDestinationFile = createDestinationFileReader(destinationRoot);\n\n const refreshConfigFile = async (\n {\n name: filename,\n type: fileType,\n additionalMapping = (s) => s,\n if: condition = () => true,\n }: RefreshableConfigFile,\n conditionOptions: ConditionOptions,\n ) => {\n if (!condition(conditionOptions)) {\n return { needsChange: false };\n }\n\n const maybeReadPackageJson = async (type: RefreshableConfigFile['type']) =>\n type === 'pnpm-workspace'\n ? await readDestinationFile('package.json')\n : undefined;\n\n const [inputFile, templateFile, isGitIgnored, packageJson] =\n await Promise.all([\n readDestinationFile(filename),\n readBaseTemplateFile(`_${filename}`),\n gitRoot\n ? Git.isFileGitIgnored({\n gitRoot,\n absolutePath: path.join(destinationRoot, filename),\n })\n : false,\n maybeReadPackageJson(fileType),\n ]);\n\n // If the file is gitignored and doesn't exist, don't make it\n if (inputFile === undefined && isGitIgnored) {\n return { needsChange: false };\n }\n\n const data = additionalMapping(\n inputFile\n ? mergeWithConfigFile(templateFile, fileType, packageJson)(inputFile)\n : templateFile,\n packageManager,\n );\n\n const filepath = path.join(destinationRoot, filename);\n\n if (mode === 'format') {\n if (data === inputFile) {\n return { needsChange: false };\n }\n\n await fs.writeFile(filepath, data);\n return {\n needsChange: false,\n msg: `Refreshed ${logger.bold(filename)}.`,\n filename,\n };\n }\n\n if (data !== inputFile) {\n return {\n needsChange: true,\n msg: `The ${logger.bold(\n filename,\n )} file is out of date. Run \\`${logger.bold(\n packageManager.print.exec,\n 'skuba',\n 'format',\n )}\\` to update it.`,\n filename,\n };\n }\n\n return { needsChange: false };\n };\n\n const packageManager = await detectPackageManager(destinationRoot);\n\n const results = await Promise.all(\n REFRESHABLE_CONFIG_FILES.map((conf) =>\n refreshConfigFile(conf, {\n packageManager,\n isInWorkspaceRoot: workspaceRoot === currentWorkspaceProjectRoot,\n }),\n ),\n );\n\n // Log after for reproducible test output ordering\n results.forEach((result) => {\n if (result.msg) {\n logger.warn(result.msg);\n }\n });\n\n const anyNeedChanging = results.some(({ needsChange }) => needsChange);\n\n return {\n ok: !anyNeedChanging,\n fixable: anyNeedChanging,\n annotations: results.flatMap(({ needsChange, filename, msg }) =>\n needsChange && msg\n ? [\n {\n path: filename,\n message: stripAnsi(msg),\n },\n ]\n : [],\n ),\n };\n};\n\nexport const tryRefreshConfigFiles = async (\n mode: 'format' | 'lint',\n logger: Logger,\n): Promise<InternalLintResult> => {\n try {\n return await refreshConfigFiles(mode, logger);\n } catch (err) {\n logger.warn('Failed to refresh config files.');\n logger.subtle(inspect(err));\n\n return {\n ok: false,\n fixable: false,\n annotations: [],\n };\n }\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["path", "fs", "stripAnsi"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import type { Patches } from '../../index.js';
2
+ export declare const patches: Patches;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __exports = {};
20
+ __export(__exports, {
21
+ patches: () => patches
22
+ });
23
+ module.exports = __toCommonJS(__exports);
24
+ var import_patchJestSnapshots = require("./patchJestSnapshots.js");
25
+ const patches = [
26
+ {
27
+ apply: import_patchJestSnapshots.tryPatchJestSnapshots,
28
+ description: "Update Jest snapshot URLs to the new documentation site"
29
+ }
30
+ ];
31
+ // Annotate the CommonJS export names for ESM import in node:
32
+ 0 && (module.exports = {
33
+ patches
34
+ });
35
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/cli/lint/internalLints/upgrade/patches/12.1.1/index.ts"],
4
+ "sourcesContent": ["import type { Patches } from '../../index.js';\n\nimport { tryPatchJestSnapshots } from './patchJestSnapshots.js';\n\nexport const patches: Patches = [\n {\n apply: tryPatchJestSnapshots,\n description: 'Update Jest snapshot URLs to the new documentation site',\n },\n];\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,gCAAsC;AAE/B,MAAM,UAAmB;AAAA,EAC9B;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,3 @@
1
+ import type { PatchFunction, PatchReturnType } from '../../index.js';
2
+ export declare const patchJestSnapshots: (mode: "lint" | "format") => Promise<PatchReturnType>;
3
+ export declare const tryPatchJestSnapshots: PatchFunction;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var patchJestSnapshots_exports = {};
30
+ __export(patchJestSnapshots_exports, {
31
+ patchJestSnapshots: () => patchJestSnapshots,
32
+ tryPatchJestSnapshots: () => tryPatchJestSnapshots
33
+ });
34
+ module.exports = __toCommonJS(patchJestSnapshots_exports);
35
+ var import_util = require("util");
36
+ var import_fast_glob = __toESM(require("fast-glob"));
37
+ var import_fs_extra = __toESM(require("fs-extra"));
38
+ var import_logging = require("../../../../../../utils/logging.js");
39
+ const JEST_SNAPSHOT_OLD_URL = "https://goo.gl/fbAQLP";
40
+ const JEST_SNAPSHOT_NEW_URL = "https://jestjs.io/docs/snapshot-testing";
41
+ const patchJestSnapshots = async (mode) => {
42
+ const testFilePaths = await (0, import_fast_glob.default)(["**/*.test.ts", "**/*.test.ts.snap"], {
43
+ ignore: [
44
+ "**/.git",
45
+ "**/node_modules",
46
+ "src/cli/lint/internalLints/upgrade/patches/12.1.1/patchJestSnapshots.test.ts"
47
+ ]
48
+ });
49
+ if (testFilePaths.length === 0) {
50
+ return {
51
+ result: "skip",
52
+ reason: "no test files found"
53
+ };
54
+ }
55
+ const testsFiles = await Promise.all(
56
+ testFilePaths.map(async (file) => {
57
+ const contents = await import_fs_extra.default.readFile(file, "utf8");
58
+ return {
59
+ file,
60
+ contents
61
+ };
62
+ })
63
+ );
64
+ const testFilesToPatch = testsFiles.filter(
65
+ ({ contents }) => contents.includes(JEST_SNAPSHOT_OLD_URL)
66
+ );
67
+ if (testFilesToPatch.length === 0) {
68
+ return {
69
+ result: "skip",
70
+ reason: "no test files to patch"
71
+ };
72
+ }
73
+ if (mode === "lint") {
74
+ return {
75
+ result: "apply"
76
+ };
77
+ }
78
+ await Promise.all(
79
+ testFilesToPatch.map(async ({ file, contents }) => {
80
+ const updatedContents = contents.replaceAll(
81
+ JEST_SNAPSHOT_OLD_URL,
82
+ JEST_SNAPSHOT_NEW_URL
83
+ );
84
+ await import_fs_extra.default.writeFile(file, updatedContents, "utf8");
85
+ })
86
+ );
87
+ return {
88
+ result: "apply"
89
+ };
90
+ };
91
+ const tryPatchJestSnapshots = async ({ mode }) => {
92
+ try {
93
+ return await patchJestSnapshots(mode);
94
+ } catch (err) {
95
+ import_logging.log.warn("Failed to apply Jest snapshot URL patch.");
96
+ import_logging.log.subtle((0, import_util.inspect)(err));
97
+ return { result: "skip", reason: "due to an error" };
98
+ }
99
+ };
100
+ // Annotate the CommonJS export names for ESM import in node:
101
+ 0 && (module.exports = {
102
+ patchJestSnapshots,
103
+ tryPatchJestSnapshots
104
+ });
105
+ //# sourceMappingURL=patchJestSnapshots.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/cli/lint/internalLints/upgrade/patches/12.1.1/patchJestSnapshots.ts"],
4
+ "sourcesContent": ["import { inspect } from 'util';\n\nimport fg from 'fast-glob';\nimport fs from 'fs-extra';\n\nimport { log } from '../../../../../../utils/logging.js';\nimport type { PatchFunction, PatchReturnType } from '../../index.js';\n\nconst JEST_SNAPSHOT_OLD_URL = 'https://goo.gl/fbAQLP';\nconst JEST_SNAPSHOT_NEW_URL = 'https://jestjs.io/docs/snapshot-testing';\n\nexport const patchJestSnapshots = async (\n mode: 'lint' | 'format',\n): Promise<PatchReturnType> => {\n const testFilePaths = await fg(['**/*.test.ts', '**/*.test.ts.snap'], {\n ignore: [\n '**/.git',\n '**/node_modules',\n 'src/cli/lint/internalLints/upgrade/patches/12.1.1/patchJestSnapshots.test.ts',\n ],\n });\n\n if (testFilePaths.length === 0) {\n return {\n result: 'skip',\n reason: 'no test files found',\n };\n }\n\n const testsFiles = await Promise.all(\n testFilePaths.map(async (file) => {\n const contents = await fs.readFile(file, 'utf8');\n\n return {\n file,\n contents,\n };\n }),\n );\n\n const testFilesToPatch = testsFiles.filter(({ contents }) =>\n contents.includes(JEST_SNAPSHOT_OLD_URL),\n );\n\n if (testFilesToPatch.length === 0) {\n return {\n result: 'skip',\n reason: 'no test files to patch',\n };\n }\n\n if (mode === 'lint') {\n return {\n result: 'apply',\n };\n }\n\n await Promise.all(\n testFilesToPatch.map(async ({ file, contents }) => {\n const updatedContents = contents.replaceAll(\n JEST_SNAPSHOT_OLD_URL,\n JEST_SNAPSHOT_NEW_URL,\n );\n await fs.writeFile(file, updatedContents, 'utf8');\n }),\n );\n\n return {\n result: 'apply',\n };\n};\n\nexport const tryPatchJestSnapshots: PatchFunction = async ({ mode }) => {\n try {\n return await patchJestSnapshots(mode);\n } catch (err) {\n log.warn('Failed to apply Jest snapshot URL patch.');\n log.subtle(inspect(err));\n return { result: 'skip', reason: 'due to an error' };\n }\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAwB;AAExB,uBAAe;AACf,sBAAe;AAEf,qBAAoB;AAGpB,MAAM,wBAAwB;AAC9B,MAAM,wBAAwB;AAEvB,MAAM,qBAAqB,OAChC,SAC6B;AAC7B,QAAM,gBAAgB,UAAM,iBAAAA,SAAG,CAAC,gBAAgB,mBAAmB,GAAG;AAAA,IACpE,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,QAAQ;AAAA,IAC/B,cAAc,IAAI,OAAO,SAAS;AAChC,YAAM,WAAW,MAAM,gBAAAC,QAAG,SAAS,MAAM,MAAM;AAE/C,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,WAAW;AAAA,IAAO,CAAC,EAAE,SAAS,MACrD,SAAS,SAAS,qBAAqB;AAAA,EACzC;AAEA,MAAI,iBAAiB,WAAW,GAAG;AACjC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,MACL,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ,iBAAiB,IAAI,OAAO,EAAE,MAAM,SAAS,MAAM;AACjD,YAAM,kBAAkB,SAAS;AAAA,QAC/B;AAAA,QACA;AAAA,MACF;AACA,YAAM,gBAAAA,QAAG,UAAU,MAAM,iBAAiB,MAAM;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,EACV;AACF;AAEO,MAAM,wBAAuC,OAAO,EAAE,KAAK,MAAM;AACtE,MAAI;AACF,WAAO,MAAM,mBAAmB,IAAI;AAAA,EACtC,SAAS,KAAK;AACZ,uBAAI,KAAK,0CAA0C;AACnD,uBAAI,WAAO,qBAAQ,GAAG,CAAC;AACvB,WAAO,EAAE,QAAQ,QAAQ,QAAQ,kBAAkB;AAAA,EACrD;AACF;",
6
+ "names": ["fg", "fs"]
7
+ }
@@ -23,7 +23,7 @@ export declare const templateConfigSchema: z.ZodObject<{
23
23
  name: z.ZodString;
24
24
  message: z.ZodString;
25
25
  initial: z.ZodString;
26
- validate: z.ZodOptional<z.ZodPipe<z.ZodCustom<z.core.$InferInnerFunctionType<z.core.$ZodTuple<[z.ZodString], null>, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>, z.core.$InferInnerFunctionType<z.core.$ZodTuple<[z.ZodString], null>, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>, z.ZodTransform<(args_0: string) => string | boolean, z.core.$InferInnerFunctionType<z.core.$ZodTuple<[z.ZodString], null>, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>>>;
26
+ validate: z.ZodOptional<z.ZodPipe<z.ZodCustom<z.core.$InferInnerFunctionType<z.ZodTuple<readonly [z.ZodString], null>, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>, z.core.$InferInnerFunctionType<z.ZodTuple<readonly [z.ZodString], null>, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>, z.ZodTransform<(args_0: string) => string | boolean, z.core.$InferInnerFunctionType<z.ZodTuple<readonly [z.ZodString], null>, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>>>;
27
27
  }, z.core.$strip>>;
28
28
  entryPoint: z.ZodOptional<z.ZodString>;
29
29
  noSkip: z.ZodOptional<z.ZodBoolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skuba",
3
- "version": "12.2.0-try-again-conditions-20250813002801",
3
+ "version": "12.3.0-add-minimumReleaseAge-20250919032927",
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",
@@ -97,13 +97,13 @@
97
97
  "tsx": "^4.16.2",
98
98
  "typescript": "~5.9.0",
99
99
  "zod": "^4.0.0",
100
- "eslint-config-skuba": "7.1.0"
100
+ "eslint-config-skuba": "7.1.2-add-minimumReleaseAge-20250919032927"
101
101
  },
102
102
  "devDependencies": {
103
- "@changesets/cli": "2.29.5",
103
+ "@changesets/cli": "2.29.6",
104
104
  "@changesets/get-github-info": "0.6.0",
105
- "@jest/reporters": "30.0.5",
106
- "@jest/test-result": "30.0.5",
105
+ "@jest/reporters": "30.1.3",
106
+ "@jest/test-result": "30.1.3",
107
107
  "@types/ejs": "3.1.5",
108
108
  "@types/express": "5.0.3",
109
109
  "@types/fs-extra": "11.0.4",
@@ -114,15 +114,15 @@
114
114
  "@types/npm-registry-fetch": "8.0.8",
115
115
  "@types/npm-which": "3.0.4",
116
116
  "@types/picomatch": "4.0.2",
117
- "@types/semver": "7.7.0",
117
+ "@types/semver": "7.7.1",
118
118
  "@types/supertest": "6.0.3",
119
119
  "enhanced-resolve": "5.18.3",
120
120
  "express": "5.1.0",
121
121
  "fastify": "5.5.0",
122
- "jest-diff": "30.0.5",
123
- "jsonfile": "6.1.0",
122
+ "jest-diff": "30.1.2",
123
+ "jsonfile": "6.2.0",
124
124
  "koa": "3.0.1",
125
- "memfs": "4.36.0",
125
+ "memfs": "4.38.2",
126
126
  "remark-cli": "12.0.1",
127
127
  "remark-preset-lint-recommended": "7.0.1",
128
128
  "semver": "7.7.2",
@@ -140,15 +140,12 @@
140
140
  "engines": {
141
141
  "node": ">=20.9.0"
142
142
  },
143
- "publishConfig": {
144
- "provenance": true
145
- },
146
143
  "skuba": {
147
144
  "build": "esbuild",
148
145
  "entryPoint": "src/index.ts",
149
146
  "template": null,
150
147
  "type": "package",
151
- "version": "12.1.0"
148
+ "version": "12.2.0"
152
149
  },
153
150
  "scripts": {
154
151
  "build": "scripts/build.sh",
@@ -1,4 +1,9 @@
1
1
  # managed by skuba
2
+ minimumReleaseAge: 1440
3
+ minimumReleaseAgeExclude:
4
+ - '@seek/*'
5
+ - '*skuba*'
6
+ - '*seek*'
2
7
  packageManagerStrictVersion: true
3
8
  publicHoistPattern:
4
9
  - '@types*'
@@ -1,4 +1,4 @@
1
- # syntax=docker/dockerfile:1.17
1
+ # syntax=docker/dockerfile:1.18
2
2
 
3
3
  FROM public.ecr.aws/docker/library/node:22-alpine AS dev-deps
4
4
 
@@ -15,12 +15,12 @@
15
15
  "dependencies": {
16
16
  "@opentelemetry/api": "^1.9.0",
17
17
  "@opentelemetry/core": "^2.0.0",
18
- "@opentelemetry/exporter-trace-otlp-grpc": "^0.203.0",
19
- "@opentelemetry/instrumentation-aws-sdk": "^0.56.0",
20
- "@opentelemetry/instrumentation-http": "^0.203.0",
18
+ "@opentelemetry/exporter-trace-otlp-grpc": "^0.204.0",
19
+ "@opentelemetry/instrumentation-aws-sdk": "^0.59.0",
20
+ "@opentelemetry/instrumentation-http": "^0.204.0",
21
21
  "@opentelemetry/propagator-b3": "^2.0.0",
22
- "@opentelemetry/sdk-node": "^0.203.0",
23
- "@seek/logger": "11.0.0",
22
+ "@opentelemetry/sdk-node": "^0.204.0",
23
+ "@seek/logger": "^11.1.0",
24
24
  "express": "^5.0.0",
25
25
  "hot-shots": "^11.0.0",
26
26
  "seek-datadog-custom-metrics": "^6.0.0",
@@ -34,7 +34,7 @@
34
34
  "skuba": "*",
35
35
  "supertest": "^7.0.0"
36
36
  },
37
- "packageManager": "pnpm@10.14.0",
37
+ "packageManager": "pnpm@10.17.0",
38
38
  "engines": {
39
39
  "node": ">=22"
40
40
  }
@@ -1,4 +1,4 @@
1
- # syntax=docker/dockerfile:1.17
1
+ # syntax=docker/dockerfile:1.18
2
2
 
3
3
  FROM public.ecr.aws/docker/library/node:22-alpine AS dev-deps
4
4
 
@@ -17,9 +17,9 @@
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/node": "^22.13.10",
20
- "skuba": "12.2.0-try-again-conditions-20250813002801"
20
+ "skuba": "12.3.0-add-minimumReleaseAge-20250919032927"
21
21
  },
22
- "packageManager": "pnpm@10.14.0",
22
+ "packageManager": "pnpm@10.17.0",
23
23
  "engines": {
24
24
  "node": ">=22"
25
25
  }
@@ -1,4 +1,4 @@
1
- # syntax=docker/dockerfile:1.17
1
+ # syntax=docker/dockerfile:1.18
2
2
 
3
3
  FROM public.ecr.aws/docker/library/node:22-alpine AS dev-deps
4
4
 
@@ -17,12 +17,12 @@
17
17
  "@koa/router": "^14.0.0",
18
18
  "@opentelemetry/api": "^1.9.0",
19
19
  "@opentelemetry/core": "^2.0.0",
20
- "@opentelemetry/exporter-trace-otlp-grpc": "^0.203.0",
21
- "@opentelemetry/instrumentation-aws-sdk": "^0.56.0",
22
- "@opentelemetry/instrumentation-http": "^0.203.0",
20
+ "@opentelemetry/exporter-trace-otlp-grpc": "^0.204.0",
21
+ "@opentelemetry/instrumentation-aws-sdk": "^0.59.0",
22
+ "@opentelemetry/instrumentation-http": "^0.204.0",
23
23
  "@opentelemetry/propagator-b3": "^2.0.0",
24
- "@opentelemetry/sdk-node": "^0.203.0",
25
- "@seek/logger": "11.0.0",
24
+ "@opentelemetry/sdk-node": "^0.204.0",
25
+ "@seek/logger": "^11.1.0",
26
26
  "hot-shots": "^11.0.0",
27
27
  "koa": "^3.0.1",
28
28
  "koa-compose": "^4.1.0",
@@ -43,7 +43,7 @@
43
43
  "skuba": "*",
44
44
  "supertest": "^7.0.0"
45
45
  },
46
- "packageManager": "pnpm@10.14.0",
46
+ "packageManager": "pnpm@10.17.0",
47
47
  "engines": {
48
48
  "node": ">=22"
49
49
  }
@@ -1,4 +1,4 @@
1
- # syntax=docker/dockerfile:1.17
1
+ # syntax=docker/dockerfile:1.18
2
2
 
3
3
  FROM public.ecr.aws/docker/library/node:22-alpine AS dev-deps
4
4
 
@@ -173,7 +173,6 @@ exports[`returns expected CloudFormation stack for dev 1`] = `
173
173
  },
174
174
  "S3Key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.zip",
175
175
  },
176
- "Description": "Updated at 1212-12-12T12:12:12.121Z",
177
176
  "Environment": {
178
177
  "Variables": {
179
178
  "DD_API_KEY_SECRET_ARN": {
@@ -235,6 +234,7 @@ exports[`returns expected CloudFormation stack for dev 1`] = `
235
234
  ],
236
235
  },
237
236
  ],
237
+ "MemorySize": 512,
238
238
  "ReservedConcurrentExecutions": 3,
239
239
  "Role": {
240
240
  "Fn::GetAtt": [
@@ -763,14 +763,6 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
763
763
  },
764
764
  },
765
765
  "Resources": {
766
- "datadogapikeysecret046FEF06": {
767
- "DeletionPolicy": "Delete",
768
- "Properties": {
769
- "GenerateSecretString": {},
770
- },
771
- "Type": "AWS::SecretsManager::Secret",
772
- "UpdateReplacePolicy": "Delete",
773
- },
774
766
  "destinationtopicDCE2E0B8": {
775
767
  "Properties": {
776
768
  "KmsMasterKeyId": {
@@ -926,12 +918,9 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
926
918
  },
927
919
  "S3Key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.zip",
928
920
  },
929
- "Description": "Updated at 1212-12-12T12:12:12.121Z",
930
921
  "Environment": {
931
922
  "Variables": {
932
- "DD_API_KEY_SECRET_ARN": {
933
- "Ref": "datadogapikeysecret046FEF06",
934
- },
923
+ "DD_API_KEY_SECRET_ARN": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:TODO_SECRET_NAME",
935
924
  "DD_CAPTURE_LAMBDA_PAYLOAD": "false",
936
925
  "DD_ENV": "production",
937
926
  "DD_FLUSH_TO_LOG": "false",
@@ -988,6 +977,7 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
988
977
  ],
989
978
  },
990
979
  ],
980
+ "MemorySize": 512,
991
981
  "ReservedConcurrentExecutions": 20,
992
982
  "Role": {
993
983
  "Fn::GetAtt": [
@@ -1394,9 +1384,7 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
1394
1384
  "secretsmanager:DescribeSecret",
1395
1385
  ],
1396
1386
  "Effect": "Allow",
1397
- "Resource": {
1398
- "Ref": "datadogapikeysecret046FEF06",
1399
- },
1387
+ "Resource": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:TODO_SECRET_NAME-??????",
1400
1388
  },
1401
1389
  {
1402
1390
  "Action": [
@@ -1,20 +1,6 @@
1
1
  import { App, aws_secretsmanager, aws_sns } from 'aws-cdk-lib';
2
2
  import { Template } from 'aws-cdk-lib/assertions';
3
3
 
4
- const currentDate = '1212-12-12T12:12:12.121Z';
5
-
6
- jest.useFakeTimers({
7
- legacyFakeTimers: false,
8
- doNotFake: [
9
- 'nextTick',
10
- 'setInterval',
11
- 'clearInterval',
12
- 'setTimeout',
13
- 'clearTimeout',
14
- ],
15
- now: new Date(currentDate),
16
- });
17
-
18
4
  const originalDeployment = process.env.DEPLOYMENT;
19
5
  const originalVersion = process.env.VERSION;
20
6
 
@@ -19,7 +19,7 @@ import { DatadogLambda } from 'datadog-cdk-constructs-v2';
19
19
  import { config } from './config.js';
20
20
 
21
21
  // Updated by https://github.com/seek-oss/rynovate
22
- const DATADOG_EXTENSION_LAYER_VERSION = 84;
22
+ const DATADOG_EXTENSION_LAYER_VERSION = 86;
23
23
 
24
24
  // Updated by https://github.com/seek-oss/rynovate
25
25
  const DATADOG_NODE_LAYER_VERSION = 126;
@@ -87,6 +87,7 @@ export class AppStack extends Stack {
87
87
  const worker = new aws_lambda_nodejs.NodejsFunction(this, 'worker', {
88
88
  architecture: aws_lambda.Architecture[architecture],
89
89
  runtime: aws_lambda.Runtime.NODEJS_22_X,
90
+ memorySize: 512,
90
91
  environmentEncryption: kmsKey,
91
92
  // aws-sdk-v3 sets this to true by default, so it is not necessary to set the environment variable
92
93
  // https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html
@@ -113,10 +114,6 @@ export class AppStack extends Stack {
113
114
  }
114
115
  : {}),
115
116
  },
116
- // https://github.com/aws/aws-cdk/issues/28237
117
- // This forces the lambda to be updated on every deployment
118
- // If you do not wish to use hotswap, you can remove the new Date().toISOString() from the description
119
- description: `Updated at ${new Date().toISOString()}`,
120
117
  reservedConcurrentExecutions: config.workerLambda.reservedConcurrency,
121
118
  });
122
119
 
@@ -40,7 +40,8 @@ const configs: Record<Deployment, Config> = {
40
40
  },
41
41
  },
42
42
 
43
- datadogApiKeySecretArn: 'TODO: datadogApiKeySecretArn',
43
+ datadogApiKeySecretArn:
44
+ 'arn:aws:secretsmanager:<Region>:<AccountId>:secret:TODO_SECRET_NAME',
44
45
  sourceSnsTopicArn: 'TODO: sourceSnsTopicArn',
45
46
  },
46
47
  prod: {
@@ -56,7 +57,8 @@ const configs: Record<Deployment, Config> = {
56
57
  },
57
58
  },
58
59
 
59
- datadogApiKeySecretArn: 'TODO: datadogApiKeySecretArn',
60
+ datadogApiKeySecretArn:
61
+ 'arn:aws:secretsmanager:<Region>:<AccountId>:secret:TODO_SECRET_NAME',
60
62
  sourceSnsTopicArn: 'TODO: sourceSnsTopicArn',
61
63
  },
62
64
  };
@@ -4,8 +4,6 @@
4
4
  "license": "UNLICENSED",
5
5
  "scripts": {
6
6
  "deploy": "cdk deploy appStack --require-approval never",
7
- "deploy:hotswap": "pnpm --silent run deploy --hotswap",
8
- "deploy:watch": "pnpm --silent deploy:hotswap --watch",
9
7
  "format": "skuba format",
10
8
  "lint": "skuba lint",
11
9
  "start": "skuba start --port <%- port %>",
@@ -18,7 +16,7 @@
18
16
  "@aws-sdk/client-lambda": "^3.363.0",
19
17
  "@aws-sdk/client-sns": "^3.363.0",
20
18
  "@seek/aws-codedeploy-hooks": "^2.0.0",
21
- "@seek/logger": "11.0.0",
19
+ "@seek/logger": "^11.1.0",
22
20
  "skuba-dive": "^2.0.0",
23
21
  "zod": "^4.0.0"
24
22
  },
@@ -37,9 +35,9 @@
37
35
  "datadog-lambda-js": "^12.0.0",
38
36
  "dd-trace": "^5.0.0",
39
37
  "pino-pretty": "^13.0.0",
40
- "skuba": "12.2.0-try-again-conditions-20250813002801"
38
+ "skuba": "12.3.0-add-minimumReleaseAge-20250919032927"
41
39
  },
42
- "packageManager": "pnpm@10.14.0",
40
+ "packageManager": "pnpm@10.17.0",
43
41
  "engines": {
44
42
  "node": ">=22"
45
43
  }
@@ -22,13 +22,13 @@ jobs:
22
22
  with:
23
23
  fetch-depth: 0
24
24
 
25
+ - name: Set up pnpm
26
+ uses: pnpm/action-setup@v4
27
+
25
28
  - name: Set up Node.js
26
- uses: actions/setup-node@v4
29
+ uses: actions/setup-node@v5
27
30
  with:
28
- node-version: ^22.14
29
-
30
- - name: Set up pnpm
31
- run: corepack enable pnpm && corepack install
31
+ node-version-file: .nvmrc
32
32
 
33
33
  - name: Install dependencies
34
34
  run: pnpm install --frozen-lockfile
@@ -37,4 +37,3 @@ jobs:
37
37
  run: pnpm release
38
38
  env:
39
39
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -18,13 +18,13 @@ jobs:
18
18
  - name: Check out repo
19
19
  uses: actions/checkout@v5
20
20
 
21
+ - name: Set up pnpm
22
+ uses: pnpm/action-setup@v4
23
+
21
24
  - name: Set up Node.js
22
- uses: actions/setup-node@v4
25
+ uses: actions/setup-node@v5
23
26
  with:
24
- node-version: ^22.14
25
-
26
- - name: Set up pnpm
27
- run: corepack enable pnpm && corepack install
27
+ node-version-file: .nvmrc
28
28
 
29
29
  - name: Install dependencies
30
30
  run: pnpm install --frozen-lockfile
@@ -41,8 +41,5 @@
41
41
  "packageManager": "pnpm@10.7.0",
42
42
  "engines": {
43
43
  "node": ">=20.9.0"
44
- },
45
- "publishConfig": {
46
- "provenance": true
47
44
  }
48
45
  }