|
| 1 | +/** |
| 2 | + * @fileoverview Rule to check whether or not `require()` is valid. |
| 3 | + * @author Toru Nagashima |
| 4 | + * @copyright 2015 Toru Nagashima. All rights reserved. |
| 5 | + * See LICENSE file in root directory for full license. |
| 6 | + */ |
| 7 | + |
| 8 | +"use strict"; |
| 9 | + |
| 10 | +//------------------------------------------------------------------------------ |
| 11 | +// Requirements |
| 12 | +//------------------------------------------------------------------------------ |
| 13 | + |
| 14 | +var path = require("path"); |
| 15 | +var minimatch = require("minimatch"); |
| 16 | +var assign = require("object-assign"); |
| 17 | +var getPackageJson = require("./get-package-json"); |
| 18 | + |
| 19 | +//------------------------------------------------------------------------------ |
| 20 | +// Helpers |
| 21 | +//------------------------------------------------------------------------------ |
| 22 | + |
| 23 | +/** |
| 24 | + * Gets the module name of a given path. |
| 25 | + * |
| 26 | + * e.g. `eslint/lib/ast-utils` -> `eslint` |
| 27 | + * |
| 28 | + * @param {string} nameOrPath - A path to get. |
| 29 | + * @returns {string} The module name of the path. |
| 30 | + */ |
| 31 | +function getModuleName(nameOrPath) { |
| 32 | + var end = nameOrPath.indexOf("/"); |
| 33 | + if (end !== -1 && nameOrPath[0] === "@") { |
| 34 | + end = nameOrPath.indexOf("/", 1 + end); |
| 35 | + } |
| 36 | + |
| 37 | + return end === -1 ? nameOrPath : nameOrPath.slice(0, end); |
| 38 | +} |
| 39 | + |
| 40 | +//------------------------------------------------------------------------------ |
| 41 | +// Public Interface |
| 42 | +//------------------------------------------------------------------------------ |
| 43 | + |
| 44 | +/** |
| 45 | + * @typedef object TargetInfo |
| 46 | + * @property {ASTNode} node - The `Identifier` node of the target. |
| 47 | + * @property {string} name - The target name. |
| 48 | + * @property {boolean} relative - The flag which shows the target name is a relative path. |
| 49 | + */ |
| 50 | + |
| 51 | +/** |
| 52 | + * Checks whether or not each requirement target is published via package.json. |
| 53 | + * |
| 54 | + * It reads package.json and checks the target exists in `dependencies`. |
| 55 | + * |
| 56 | + * @param {RuleContext} context - A context to report. |
| 57 | + * @param {string} filePath - The current file path. |
| 58 | + * @param {TargetInfo[]} targets - A list of target information to check. |
| 59 | + * @returns {void} |
| 60 | + */ |
| 61 | +module.exports = function checkForPublish(context, filePath, targets) { |
| 62 | + var option = context.options[0]; |
| 63 | + if ((option && option.publish) === null) { |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + var packageInfo = getPackageJson(filePath); |
| 68 | + if (!packageInfo) { |
| 69 | + return; |
| 70 | + } |
| 71 | + |
| 72 | + var publish = minimatch( |
| 73 | + path.relative(packageInfo.filePath, filePath).replace(/\\/g, "/"), |
| 74 | + (option && option.publish) || "+(./*|./{bin,lib,src}/**)", |
| 75 | + {matchBase: true} |
| 76 | + ); |
| 77 | + var deps = assign( |
| 78 | + {}, |
| 79 | + packageInfo.peerDependencies || {}, |
| 80 | + packageInfo.dependencies || {}, |
| 81 | + (!publish && packageInfo.devDependencies) || {} |
| 82 | + ); |
| 83 | + |
| 84 | + for (var i = 0; i < targets.length; ++i) { |
| 85 | + var target = targets[i]; |
| 86 | + |
| 87 | + if (!target.relative && !deps.hasOwnProperty(getModuleName(target.name))) { |
| 88 | + context.report({ |
| 89 | + node: target.node, |
| 90 | + message: "\"{{name}}\" is not published.", |
| 91 | + data: target |
| 92 | + }); |
| 93 | + } |
| 94 | + } |
| 95 | +}; |
0 commit comments