no-unpublished-bin.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /**
  2. * @author Toru Nagashima
  3. * @copyright 2016 Toru Nagashima. All rights reserved.
  4. * See LICENSE file in root directory for full license.
  5. */
  6. "use strict"
  7. //------------------------------------------------------------------------------
  8. // Requirements
  9. //------------------------------------------------------------------------------
  10. const path = require("path")
  11. const getConvertPath = require("../util/get-convert-path")
  12. const getNpmignore = require("../util/get-npmignore")
  13. const getPackageJson = require("../util/get-package-json")
  14. //------------------------------------------------------------------------------
  15. // Helpers
  16. //------------------------------------------------------------------------------
  17. /**
  18. * Checks whether or not a given path is a `bin` file.
  19. *
  20. * @param {string} filePath - A file path to check.
  21. * @param {string|object|undefined} binField - A value of the `bin` field of `package.json`.
  22. * @param {string} basedir - A directory path that `package.json` exists.
  23. * @returns {boolean} `true` if the file is a `bin` file.
  24. */
  25. function isBinFile(filePath, binField, basedir) {
  26. if (!binField) {
  27. return false
  28. }
  29. if (typeof binField === "string") {
  30. return filePath === path.resolve(basedir, binField)
  31. }
  32. return Object.keys(binField).some(key => filePath === path.resolve(basedir, binField[key]))
  33. }
  34. /**
  35. * The definition of this rule.
  36. *
  37. * @param {RuleContext} context - The rule context to check.
  38. * @returns {object} The definition of this rule.
  39. */
  40. function create(context) {
  41. return {
  42. Program(node) {
  43. // Check file path.
  44. let rawFilePath = context.getFilename()
  45. if (rawFilePath === "<input>") {
  46. return
  47. }
  48. rawFilePath = path.resolve(rawFilePath)
  49. // Find package.json
  50. const p = getPackageJson(rawFilePath)
  51. if (!p) {
  52. return
  53. }
  54. // Convert by convertPath option
  55. const basedir = path.dirname(p.filePath)
  56. const relativePath = getConvertPath(context)(
  57. path.relative(basedir, rawFilePath).replace(/\\/g, "/")
  58. )
  59. const filePath = path.join(basedir, relativePath)
  60. // Check this file is bin.
  61. if (!isBinFile(filePath, p.bin, basedir)) {
  62. return
  63. }
  64. // Check ignored or not
  65. const npmignore = getNpmignore(filePath)
  66. if (!npmignore.match(relativePath)) {
  67. return
  68. }
  69. // Report.
  70. context.report({
  71. node,
  72. message:
  73. "npm ignores '{{name}}'. " +
  74. "Check 'files' field of 'package.json' or '.npmignore'.",
  75. data: {name: relativePath},
  76. })
  77. },
  78. }
  79. }
  80. //------------------------------------------------------------------------------
  81. // Rule Definition
  82. //------------------------------------------------------------------------------
  83. module.exports = {
  84. create,
  85. meta: {
  86. docs: {
  87. description: "disallow 'bin' files which are ignored by npm",
  88. category: "Possible Errors",
  89. recommended: true,
  90. },
  91. fixable: false,
  92. schema: [
  93. {
  94. type: "object",
  95. properties: { //
  96. convertPath: getConvertPath.schema,
  97. },
  98. },
  99. ],
  100. },
  101. }