no-unpublished-bin.js 3.0 KB

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