deprecate-config.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. "use strict";
  2. const dotProp = require("dot-prop");
  3. const log = require("npmlog");
  4. const path = require("path");
  5. /** @type {(config: { [key: string]: unknown }, filepath: string) => void} */
  6. module.exports.deprecateConfig = compose(
  7. // add new predicates HERE
  8. remap("command.add.includeFilteredDependencies", "command.add.includeDependencies", { alsoRoot: true }),
  9. remap("command.add.includeFilteredDependents", "command.add.includeDependents", { alsoRoot: true }),
  10. remap("command.bootstrap.includeFilteredDependencies", "command.bootstrap.includeDependencies"),
  11. remap("command.bootstrap.includeFilteredDependents", "command.bootstrap.includeDependents"),
  12. remap("command.clean.includeFilteredDependencies", "command.clean.includeDependencies"),
  13. remap("command.clean.includeFilteredDependents", "command.clean.includeDependents"),
  14. remap("command.exec.includeFilteredDependencies", "command.exec.includeDependencies"),
  15. remap("command.exec.includeFilteredDependents", "command.exec.includeDependents"),
  16. remap("command.list.includeFilteredDependencies", "command.list.includeDependencies"),
  17. remap("command.list.includeFilteredDependents", "command.list.includeDependents"),
  18. remap("command.run.includeFilteredDependencies", "command.run.includeDependencies"),
  19. remap("command.run.includeFilteredDependents", "command.run.includeDependents"),
  20. remap("command.version.githubRelease", "command.version.createRelease", {
  21. toValue: (value) => value && "github",
  22. }),
  23. remap("command.publish.githubRelease", "command.version.createRelease", {
  24. alsoRoot: true,
  25. toValue: (value) => value && "github",
  26. }),
  27. remap("command.publish.npmTag", "command.publish.distTag", { alsoRoot: true }),
  28. remap("command.publish.cdVersion", "command.publish.bump", { alsoRoot: true }),
  29. remap("command.publish.ignore", "command.publish.ignoreChanges"),
  30. remap("commands", "command"),
  31. (config, filepath) => ({ config, filepath })
  32. );
  33. /**
  34. * Remap deprecated config properties, if they exist.
  35. * The returned predicate mutates the `config` parameter.
  36. *
  37. * @param {String} search Path to deprecated option
  38. * @param {String} target Path of renamed option
  39. * @param {Object} opts Optional configuration object
  40. * @param {Boolean} opts.alsoRoot Whether to check root config as well
  41. * @param {Function} opts.toValue Return the new config value given the current value
  42. * @return {Function} predicate accepting (config, filepath)
  43. */
  44. function remap(search, target, { alsoRoot, toValue } = {}) {
  45. const pathsToSearch = [search];
  46. if (alsoRoot) {
  47. // root config is overwritten by "more specific" nested config
  48. pathsToSearch.unshift(search.split(".").pop());
  49. }
  50. return (obj) => {
  51. for (const searchPath of pathsToSearch) {
  52. if (dotProp.has(obj.config, searchPath)) {
  53. const fromVal = dotProp.get(obj.config, searchPath);
  54. const toVal = toValue ? toValue(fromVal) : fromVal;
  55. log.warn("project", deprecationMessage(obj, target, searchPath, fromVal, toVal));
  56. dotProp.set(obj.config, target, toVal);
  57. dotProp.delete(obj.config, searchPath);
  58. }
  59. }
  60. return obj;
  61. };
  62. }
  63. /**
  64. * Builds a deprecation message string that specifies
  65. * a deprecated config option and suggests a correction.
  66. *
  67. * @param {Object} obj A config object
  68. * @param {String} target Path of renamed option
  69. * @param {String} searchSearch Path to deprecated option
  70. * @param {Any} fromVal Current value of deprecated option
  71. * @param {Any} toVal Corrected value of deprecated option
  72. * @return {String} deprecation message
  73. */
  74. function deprecationMessage(obj, target, searchPath, fromVal, toVal) {
  75. const localPath = path.relative(".", obj.filepath);
  76. let from;
  77. let to;
  78. if (toVal === fromVal) {
  79. from = `"${searchPath}"`;
  80. to = `"${target}"`;
  81. } else {
  82. from = stringify({ [searchPath]: fromVal });
  83. to = stringify({ [target]: toVal });
  84. }
  85. return `Deprecated key "${searchPath}" found in ${localPath}\nPlease update ${from} => ${to}`;
  86. }
  87. function stringify(obj) {
  88. return JSON.stringify(obj).slice(1, -1);
  89. }
  90. function compose(...funcs) {
  91. return funcs.reduce((a, b) => (...args) => a(b(...args)));
  92. }