npm-package-json-lint
Advanced tools
Comparing version 3.7.0 to 4.0.0-beta.1
@@ -7,9 +7,42 @@ # Change Log | ||
### Added | ||
- Added exception support to the following rules: | ||
- [`no-absolute-version-dependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/no-absolute-version-dependencies) | ||
- [`no-absolute-version-devDependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/no-absolute-version-devDependencies) | ||
- [`no-caret-version-dependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/no-caret-version-dependencies) | ||
- [`no-caret-version-devDependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/no-caret-version-devDependencies) | ||
- [`no-tilde-version-dependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/no-tilde-version-dependencies) | ||
- [`no-tilde-version-devDependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/no-tilde-version-devDependencies) | ||
- [`prefer-absolute-version-dependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-absolute-version-dependencies) | ||
- [`prefer-absolute-version-devDependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-absolute-version-devDependencies) | ||
- [`prefer-caret-version-dependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-caret-version-dependencies) | ||
- [`prefer-caret-version-devDependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-caret-version-devDependencies) | ||
- [`prefer-no-version-zero-dependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-no-version-zero-dependencies) | ||
- [`prefer-no-version-zero-devDependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-no-version-zero-devDependencies) | ||
- [`prefer-tilde-version-dependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-tilde-version-dependencies) | ||
- [`prefer-tilde-version-devDependencies`](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-tilde-version-devDependencies) | ||
> Addresses [#93](https://github.com/tclindner/npm-package-json-lint/issues/93) | ||
### Changed | ||
- [`name-format`](https://github.com/tclindner/npm-package-json-lint/wiki/name-format) now checks the following things: | ||
- Name is lowercase | ||
- Name is less than 214 characters. This includes scope. | ||
- Name doesn't start with a `.` or a `_`. | ||
> Addresses [#115](https://github.com/tclindner/npm-package-json-lint/issues/115) | ||
- Improved schema validation that runs against npm-package-json-lint config files. Highlights include: | ||
- Better error messages. Ex: `- severity must be either "off", "warning", or "error".` | ||
- Array type rules now ensure at least one item is passed. | ||
- Array type rules now validate unique items are passed. | ||
### Fixed | ||
### Removed | ||
- Dropped support for Node 6 and 7. | ||
## [3.7.0] - 2019-06-16 | ||
@@ -16,0 +49,0 @@ ### Added |
@@ -7,4 +7,4 @@ # Contributing | ||
* [Node.js](https://nodejs.org/) - v6.0.0+ | ||
* [npm](https://www.npmjs.com/) - v3.0.0+ | ||
* [Node.js](https://nodejs.org/) - v8.0.0+ | ||
* [npm](https://www.npmjs.com/) - v6.0.0+ | ||
@@ -17,2 +17,7 @@ ## Install project dependencies | ||
#### Branches | ||
* Use the `v3.x.x` branch for fixes to v3. | ||
* Use `master` for new enhancements and breaking changes for v4. | ||
### Install project dependencies | ||
@@ -19,0 +24,0 @@ |
{ | ||
"name": "npm-package-json-lint", | ||
"version": "3.7.0", | ||
"version": "4.0.0-beta.1", | ||
"description": "Configurable linter for package.json files.", | ||
@@ -32,3 +32,4 @@ "keywords": [ | ||
"eslint": "eslint . --format=node_modules/eslint-formatter-pretty", | ||
"lint": "npm run eslint", | ||
"npmpackagejsonlint": "node src/cli.js .", | ||
"lint": "npm run eslint && npm run npmpackagejsonlint", | ||
"test": "jest", | ||
@@ -39,31 +40,32 @@ "test:ci": "jest --runInBand" | ||
"ajv": "^6.10.0", | ||
"ajv-errors": "^1.0.1", | ||
"chalk": "^2.4.2", | ||
"glob": "^7.1.4", | ||
"cosmiconfig": "^5.2.1", | ||
"debug": "^4.1.1", | ||
"globby": "^10.0.1", | ||
"ignore": "^5.1.2", | ||
"is-path-inside": "^2.1.0", | ||
"is-plain-obj": "^1.1.0", | ||
"is-resolvable": "^1.1.0", | ||
"log-symbols": "^2.2.0", | ||
"is-plain-obj": "^2.0.0", | ||
"log-symbols": "^3.0.0", | ||
"meow": "^5.0.0", | ||
"plur": "^3.1.1", | ||
"semver": "^5.6.0", | ||
"strip-json-comments": "^2.0.1", | ||
"validator": "^10.11.0" | ||
"semver": "^6.1.1", | ||
"strip-json-comments": "^3.0.1" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^5.16.0", | ||
"eslint-config-tc": "^6.4.0", | ||
"eslint-config-tc": "^6.5.0", | ||
"eslint-formatter-pretty": "^2.1.1", | ||
"eslint-plugin-import": "^2.17.3", | ||
"eslint-plugin-prettier": "^3.1.0", | ||
"figures": "^2.0.0", | ||
"figures": "^3.0.0", | ||
"jest": "^24.8.0", | ||
"npm-package-json-lint-config-default": "^2.0.0", | ||
"npm-package-json-lint-config-tc": "^2.2.0", | ||
"prettier": "^1.18.2" | ||
}, | ||
"engines": { | ||
"node": ">=6.0.0", | ||
"npm": ">=3.0.0" | ||
"node": ">=8.0.0", | ||
"npm": ">=6.0.0" | ||
}, | ||
"license": "MIT" | ||
} |
@@ -35,4 +35,4 @@ # npm-package-json-lint | ||
* [Node.js](https://nodejs.org/) - v6.0.0+ | ||
* [npm](http://npmjs.com) - v3.0.0+ | ||
* [Node.js](https://nodejs.org/) - v8.0.0+ | ||
* [npm](http://npmjs.com) - v6.0.0+ | ||
@@ -39,0 +39,0 @@ ### Use the cli |
@@ -1,6 +0,5 @@ | ||
/* eslint global-require: 'off' */ | ||
const NpmPackageJsonLint = require('./NpmPackageJsonLint'); | ||
module.exports = { | ||
NpmPackageJsonLint: require('./NpmPackageJsonLint'), | ||
CLIEngine: require('./CLIEngine') | ||
NpmPackageJsonLint | ||
}; |
#!/usr/bin/env node | ||
const chalk = require('chalk'); | ||
const debug = require('debug')('npm-package-json-lint:cli'); | ||
const meow = require('meow'); | ||
const CLIEngine = require('./CLIEngine'); | ||
const NpmPackageJsonLint = require('./NpmPackageJsonLint'); | ||
const Reporter = require('./Reporter'); | ||
@@ -12,3 +13,4 @@ | ||
twoLintErrorsDetected: 2, | ||
runTimeException: 3 | ||
runTimeException: 3, | ||
exceedMaxWarnings: 4 | ||
}; | ||
@@ -27,2 +29,3 @@ | ||
--ignorePath, -i Path to a file containing patterns that describe files to ignore. The path can be absolute or relative to process.cwd(). By default, npm-package-json-lint looks for .npmpackagejsonlintignore in process.cwd(). | ||
--maxWarnings, -mw Maximum number of warnings that can be detected before an error is thrown. | ||
@@ -40,2 +43,4 @@ Examples | ||
$ npmPkgJsonLint . -i .gitignore | ||
$ npmPkgJsonLint . --maxWarnings 10 | ||
$ npmPkgJsonLint . -mw 10 | ||
`, | ||
@@ -63,2 +68,7 @@ { | ||
default: '' | ||
}, | ||
maxWarnings: { | ||
type: 'number', | ||
alias: 'mw', | ||
default: 10000000 | ||
} | ||
@@ -75,3 +85,6 @@ } | ||
debug(`patterns: ${patterns}`); | ||
if (patterns.length === noPatternsProvided) { | ||
debug(`No lint targets provided`); | ||
console.log(chalk.red.bold('No lint targets provided')); | ||
@@ -81,11 +94,2 @@ process.exit(exitCodes.oneMissingTarget); | ||
// CLIEngine Options | ||
const cliEngineOptions = { | ||
configFile: cli.flags.configFile, | ||
cwd: process.cwd(), | ||
useConfigFiles: !cli.flags.noConfigFiles, | ||
ignorePath: cli.flags.ignorePath, | ||
rules: {} | ||
}; | ||
try { | ||
@@ -95,12 +99,25 @@ let exitCode = exitCodes.zeroClean; | ||
const cliEngine = new CLIEngine(cliEngineOptions); | ||
const cliEngineOutput = cliEngine.executeOnPackageJsonFiles(patterns); | ||
debug(`Creating NpmPackageJsonLint instance`); | ||
const npmPackageJsonLint = new NpmPackageJsonLint({ | ||
cwd: process.cwd(), | ||
configFile: cli.flags.configFile, | ||
patterns, | ||
ignorePath: cli.flags.ignorePath, | ||
quiet: cli.flags.quiet | ||
}); | ||
const linterOutput = npmPackageJsonLint.lint(); | ||
if (cli.flags.quiet) { | ||
cliEngineOutput.results = CLIEngine.getErrorResults(cliEngineOutput.results); | ||
debug(`NpmPackageJsonLint.lint complete`); | ||
debug(`Reporter.write starting`); | ||
Reporter.write(linterOutput, cli.flags.quiet); | ||
debug(`Reporter.write complete`); | ||
if (linterOutput.warningCount > cli.flags.maxWarnings) { | ||
debug(`Max warnings exceeded`); | ||
exitCode = exitCodes.exceedMaxWarnings; | ||
} | ||
Reporter.write(cliEngineOutput, cli.flags.quiet); | ||
if (cliEngineOutput.errorCount > noIssues) { | ||
if (linterOutput.errorCount > noIssues) { | ||
debug(`Lint errors detected`); | ||
exitCode = exitCodes.twoLintErrorsDetected; | ||
@@ -107,0 +124,0 @@ } |
@@ -1,33 +0,13 @@ | ||
/* eslint class-methods-use-this: 'off', complexity: 'off' */ | ||
const debug = require('debug')('npm-package-json-lint:Config'); | ||
const cosmiconfig = require('cosmiconfig'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const os = require('os'); | ||
const isPathInside = require('is-path-inside'); | ||
const isResolvable = require('is-resolvable'); | ||
// const ConfigValidator = require('./config/ConfigValidator'); | ||
const cosmicConfigTransformer = require('./config/cosmicConfigTransformer'); | ||
const applyExtendsIfSpecified = require('./config/applyExtendsIfSpecified'); | ||
const applyOverrides = require('./config/applyOverrides'); | ||
const ConfigFile = require('./config/ConfigFile'); | ||
const ConfigFileType = require('./config/ConfigFileType'); | ||
const ConfigValidator = require('./config/ConfigValidator'); | ||
const noRules = 0; | ||
/** | ||
* Determines the base directory for node packages referenced in a config file. | ||
* This does not include node_modules in the path so it can be used for all | ||
* references relative to a config file. | ||
* | ||
* calculates the path of the project including npm-package-json-lint as a dependency | ||
* NOTE: config-file is located in /src/ | ||
* ../ is npm-package-json-lint | ||
* ../ is node_modules directory | ||
* ../ is module referencing npm-package-json-lint | ||
* | ||
* @returns {String} The base directory for the file path. | ||
* @private | ||
*/ | ||
const getProjectDir = () => path.resolve(__dirname, '../../../'); | ||
/** | ||
* Public Config class | ||
* Config class | ||
* @class | ||
@@ -38,169 +18,70 @@ */ | ||
* Constructor | ||
* @param {Object} providedOptions Options object | ||
* @param {Object} linter Instance of npm-package-json-lint linter | ||
*/ | ||
constructor(providedOptions, linter) { | ||
const options = providedOptions || {}; | ||
this.linterContext = linter; | ||
this.options = options; | ||
this.useConfigFiles = options.useConfigFiles; | ||
this.cliConfig = this.options.rules; | ||
ConfigValidator.validateRules(this.cliConfig, 'cli', this.linterContext); | ||
} | ||
/** | ||
* Loads the config options from a config specified on the command line. | ||
* | ||
* @param {String} config A shareable named config or path to a config file. | ||
* @returns {undefined} No return | ||
* @param {string} cwd The current working directory. | ||
* @param {Object} config The user passed config object. | ||
* @param {string} configFile The user passed configFile path. | ||
* @param {string} configBaseDirectory The base directory that config should be pulled from. | ||
*/ | ||
loadCliSpecifiedCfgFile(config) { | ||
let configObj = ConfigFile.createEmptyConfig(); | ||
const firstChar = 0; | ||
constructor(cwd, config, configFile, configBaseDirectory) { | ||
if (config) { | ||
const resolvable = isResolvable(config) || config.charAt(firstChar) === '@'; | ||
const filePath = resolvable ? config : path.resolve(this.options.cwd, config); | ||
configObj = ConfigFile.load(filePath, this); | ||
this.config = applyExtendsIfSpecified(config, 'PassedConfig'); | ||
} | ||
return configObj; | ||
this.cwd = cwd; | ||
this.configFile = configFile; | ||
this.configBaseDirectory = configBaseDirectory; | ||
this.explorer = cosmiconfig('npmpackagejsonlint', { | ||
transform: cosmicConfigTransformer.transform(cwd, configBaseDirectory) | ||
}); | ||
} | ||
/** | ||
* Gets the personal config object from user's home directory. | ||
* Gets the config for a file. | ||
* | ||
* @returns {Object} the personal config object (null if there is no personal config) | ||
* @private | ||
* @param {string} filePath File path of the file being linted. | ||
* @returns {Object} A config object. | ||
* @memberof Config | ||
*/ | ||
getUserHomeConfig() { | ||
if (typeof this.personalConfig === 'undefined') { | ||
const userHomeDir = os.homedir(); | ||
let configObj = {}; | ||
getConfigForFile(filePath) { | ||
debug(`Getting config for ${filePath}`); | ||
const filePathToSearch = filePath; | ||
const jsonRcFilePath = path.join(userHomeDir, ConfigFileType.rcFileName); | ||
const javaScriptConfigFilePath = path.join(userHomeDir, ConfigFileType.javaScriptConfigFileName); | ||
debug(`filePathToSearch: ${filePathToSearch}`); | ||
let config; | ||
if (fs.existsSync(jsonRcFilePath) && fs.statSync(jsonRcFilePath).isFile()) { | ||
configObj = ConfigFile.load(jsonRcFilePath, this); | ||
} else if (fs.existsSync(javaScriptConfigFilePath) && fs.statSync(javaScriptConfigFilePath).isFile()) { | ||
configObj = ConfigFile.load(javaScriptConfigFilePath, this); | ||
if (typeof this.config === 'undefined') { | ||
debug(`User passed config is undefined.`); | ||
if (this.configFile) { | ||
debug(`Config file specified, loading it.`); | ||
config = this.explorer.loadSync(this.configFile); | ||
} else { | ||
debug(`Config file wasn't specified, searching for config.`); | ||
config = this.explorer.searchSync(filePathToSearch); | ||
} | ||
} else { | ||
debug(`User passed config is set, using it.`); | ||
const configBeforeOverrides = this.config; | ||
this.personalConfig = configObj; | ||
debug(`Applying overrides to config for ${filePath}`); | ||
config = applyOverrides(this.cwd, filePath, configBeforeOverrides.rules, configBeforeOverrides.overrides); | ||
debug(`Overrides applied for ${filePath}`); | ||
} | ||
return this.personalConfig; | ||
} | ||
if (!config) { | ||
throw new Error(`No npm-package-json-lint configuration found.\n${filePathToSearch}`); | ||
} | ||
/* eslint-disable max-statements */ | ||
/** | ||
* Finds local config files from the specified directory and its parent directories. | ||
* | ||
* @param {string} filePath a file in whose directory we start looking for a local config | ||
* @returns {Object} Config object | ||
*/ | ||
getProjectHierarchyConfig(filePath) { | ||
let config = ConfigFile.createEmptyConfig(); | ||
if (Object.keys(config).length === noRules) { | ||
throw new Error(`No rules specified in configuration.\n${filePathToSearch}`); | ||
} | ||
const directory = filePath ? path.dirname(filePath) : this.options.cwd; | ||
debug(`Overrides applied for ${filePath}`); | ||
if (directory === getProjectDir() || isPathInside(directory, getProjectDir())) { | ||
const pkgJsonFilePath = path.join(directory, 'package.json'); | ||
const jsonRcFilePath = path.join(directory, ConfigFileType.rcFileName); | ||
const javaScriptConfigFilePath = path.join(directory, ConfigFileType.javaScriptConfigFileName); | ||
// ConfigValidator.validateRules(config, 'cli', this.linter); | ||
if (fs.existsSync(pkgJsonFilePath) && fs.statSync(pkgJsonFilePath).isFile()) { | ||
config = ConfigFile.loadFromPackageJson(pkgJsonFilePath, this); | ||
} | ||
if ( | ||
this.useConfigFiles && | ||
Object.keys(config.rules).length === noRules && | ||
fs.existsSync(jsonRcFilePath) && | ||
fs.statSync(jsonRcFilePath).isFile() | ||
) { | ||
config = ConfigFile.load(jsonRcFilePath, this); | ||
} else if ( | ||
this.useConfigFiles && | ||
Object.keys(config.rules).length === noRules && | ||
fs.existsSync(javaScriptConfigFilePath) && | ||
fs.statSync(javaScriptConfigFilePath).isFile() | ||
) { | ||
config = ConfigFile.load(javaScriptConfigFilePath, this); | ||
} | ||
if (!config.hasOwnProperty('root') || !config.root) { | ||
const parentPackageJsonFile = path.resolve(directory, '../', 'package.json'); | ||
const parentConfig = this.getProjectHierarchyConfig(parentPackageJsonFile); | ||
// Merge base object | ||
const mergedConfig = Object.assign({}, parentConfig, config); | ||
// Merge rules | ||
const rules = Object.assign({}, parentConfig.rules, config.rules); | ||
// Override merged rules | ||
mergedConfig.rules = rules; | ||
config = mergedConfig; | ||
} | ||
} | ||
return config; | ||
} | ||
/** | ||
* Get config object. | ||
* Order of precedence is: | ||
* 1. Config supplied in package.json file | ||
* 2. Config supplied in project hierarchy (files in current directory take precedence over parent directory) | ||
* 3. Config file supplied in CLI argument | ||
* 4. Direct rules supplied to CLI | ||
* | ||
* @param {string} filePath a file in whose directory we start looking for a local config | ||
* @returns {Object} config object | ||
*/ | ||
get(filePath) { | ||
let finalConfig = {}; | ||
// Step 1: Get project hierarchy config from | ||
// package.json property, .npmpackagejsonlintrc.json, and npmpackagejsonlint.config.js files | ||
const projectHierarchyConfig = this.getProjectHierarchyConfig(filePath); | ||
// Step 2: Load cli specified config | ||
const cliSpecifiedCfgFileConfig = this.loadCliSpecifiedCfgFile(this.options.configFile); | ||
// Step 3: Merge config | ||
// NOTE: Object.assign does a shallow copy of objects, so we need to | ||
// do this for all of it properties then create a new final object | ||
const finalRules = Object.assign({}, projectHierarchyConfig.rules, cliSpecifiedCfgFileConfig.rules, this.cliConfig); | ||
finalConfig = {rules: finalRules}; | ||
// Step 4: Check if any config has been found. | ||
// If no, try to load personal config from user home directory | ||
if (!Object.keys(finalConfig.rules).length) { | ||
const personalConfig = this.getUserHomeConfig(); | ||
if (Object.keys(personalConfig).length) { | ||
finalConfig = Object.assign({}, personalConfig); | ||
} else { | ||
// No config found in all locations | ||
const relativeFilePath = `./${path.relative(this.options.cwd, filePath)}`; | ||
throw new Error(`No npm-package-json-lint configuration found.\n${relativeFilePath}`); | ||
} | ||
} | ||
// Step 5: return final config | ||
return finalConfig; | ||
} | ||
} | ||
module.exports = Config; |
@@ -0,36 +1,224 @@ | ||
const Ajv = require('ajv'); | ||
const ajvErrors = require('ajv-errors'); | ||
const ajv = new Ajv({allErrors: true, jsonPointers: true}); | ||
ajvErrors(ajv); | ||
/** | ||
* Top level config properties | ||
* @type {Object} | ||
* Formats an array of schema validation errors. | ||
* | ||
* @param {Array} errors An array of error messages to format. | ||
* @returns {String} Formatted error message | ||
*/ | ||
const topLevelConfigProperties = { | ||
extends: {type: ['string', 'array']}, | ||
rules: {type: 'object'}, | ||
root: {type: 'boolean'} | ||
const formatSchemaErrors = errors => { | ||
return errors.map(error => `\t- ${error.message}\n`).join(''); | ||
}; | ||
/** | ||
* Config schema defintion | ||
* @type {Object} | ||
*/ | ||
const standardRuleSchema = { | ||
type: 'string', | ||
enum: ['off', 'warning', 'error'], | ||
errorMessage: { | ||
type: 'severity must be a string.', | ||
enum: 'severity must be either "off", "warning", or "error".' | ||
} | ||
}; | ||
const arrayRuleSchema = { | ||
type: 'array', | ||
items: [ | ||
standardRuleSchema, | ||
{ | ||
type: 'array', | ||
minItems: 1, | ||
uniqueItems: true, | ||
errorMessage: { | ||
type: 'the second item in an array rule config must be an array.', | ||
minItems: 'the second item in an array rule config must have at least 1 item.', | ||
uniqueItems: 'the second item in an array rule config must have unique items.' | ||
} | ||
} | ||
], | ||
minItems: 2, | ||
maxItems: 2, | ||
additionalItems: false, | ||
errorMessage: { | ||
type: 'rule config must be an array, e.g. ["error", ["value1", "value2"]].', | ||
minItems: 'array rules must have two items, severity and options array. e.g. ["error", ["value1", "value2"]].', | ||
maxItems: 'array rules must have two items, severity and options array. e.g. ["error", ["value1", "value2"]].', | ||
additionalItems: | ||
'array rules are only allowed two items, severity and the list is values. e.g. ["error", ["value1", "value2"]].' | ||
} | ||
}; | ||
const objectRuleSchema = { | ||
type: 'array', | ||
items: [ | ||
standardRuleSchema, | ||
{ | ||
type: 'object', | ||
errorMessage: { | ||
type: 'the second item in an object rule config must be an object.' | ||
} | ||
} | ||
], | ||
minItems: 2, | ||
maxItems: 2, | ||
additionalItems: false, | ||
errorMessage: { | ||
type: 'rule config must be an array, e.g. ["error", {}].', | ||
minItems: 'object rules must have two items, severity and options object. e.g. ["error", {}].', | ||
maxItems: 'object rules must have two items, severity and options object. e.g. ["error", {}].', | ||
additionalItems: 'object rules are only allowed two items, severity and options object. e.g. ["error", {}].' | ||
} | ||
}; | ||
const optionalObjExceptionsSchema = { | ||
type: 'array', | ||
items: [ | ||
{ | ||
type: 'string', | ||
errorMessage: { | ||
type: 'each exception must be a string.' | ||
} | ||
} | ||
], | ||
uniqueItems: true, | ||
minItems: 1, | ||
errorMessage: { | ||
type: 'expections must be an array.', | ||
minItems: 'expections must have at least 1 item.', | ||
uniqueItems: 'expections must have unique items.' | ||
} | ||
}; | ||
const configurationSchema = { | ||
type: 'object', | ||
properties: topLevelConfigProperties, | ||
additionalProperties: false | ||
properties: { | ||
extends: { | ||
type: ['string', 'array'], | ||
items: { | ||
type: 'string' | ||
}, | ||
minItems: 1, | ||
uniqueItems: true, | ||
errorMessage: { | ||
type: 'extends must be either a string or an array of strings.', | ||
minItems: 'extends must have at least one item if it is an array.', | ||
uniqueItems: 'extends must have unique items if it is an array.' | ||
} | ||
}, | ||
rules: { | ||
type: 'object', | ||
errorMessage: { | ||
type: 'rules must be an object.' | ||
} | ||
}, | ||
root: { | ||
type: 'boolean', | ||
errorMessage: { | ||
type: 'root must be a boolean.' | ||
} | ||
} | ||
}, | ||
additionalProperties: false, | ||
errorMessage: { | ||
type: 'npm-package-json-lint config should be an object.', | ||
additionalProperties: | ||
'npm-package-json-lint config has unexpected top-level property. Valid properties include: `extends`, `rules`, and `root`.' | ||
} | ||
}; | ||
/** | ||
* Public ConfigSchema class | ||
* @class | ||
* Validates standard rules config. | ||
* | ||
* @param {Object} ruleConfig The ruleConfig object to validate. | ||
* @returns {boolean} True if valid. Error if not. | ||
*/ | ||
class ConfigSchema { | ||
/** | ||
* Gets configuration schema | ||
* | ||
* @returns {Object} schema object | ||
*/ | ||
static get() { | ||
return configurationSchema; | ||
const isStandardRuleSchemaValid = ruleConfig => { | ||
const validate = ajv.compile(standardRuleSchema); | ||
const isValid = validate(ruleConfig); | ||
if (!isValid) { | ||
throw new Error(`${formatSchemaErrors(validate.errors)}`); | ||
} | ||
} | ||
module.exports = ConfigSchema; | ||
return true; | ||
}; | ||
/** | ||
* Validates array rules config. | ||
* | ||
* @param {Object} ruleConfig The ruleConfig object to validate. | ||
* @returns {boolean} True if valid. Error if not. | ||
*/ | ||
const isArrayRuleSchemaValid = ruleConfig => { | ||
const validate = ajv.compile(arrayRuleSchema); | ||
const isValid = validate(ruleConfig); | ||
if (!isValid) { | ||
throw new Error(`${formatSchemaErrors(validate.errors)}`); | ||
} | ||
return true; | ||
}; | ||
/** | ||
* Validates array rules config. | ||
* | ||
* @param {Object} ruleConfig The ruleConfig object to validate. | ||
* @returns {boolean} True if valid. Error if not. | ||
*/ | ||
const isObjectRuleSchemaValid = ruleConfig => { | ||
const validate = ajv.compile(objectRuleSchema); | ||
const isValid = validate(ruleConfig); | ||
if (!isValid) { | ||
throw new Error(`${formatSchemaErrors(validate.errors)}`); | ||
} | ||
return true; | ||
}; | ||
/** | ||
* Validates optional object exceptions config. | ||
* | ||
* @param {Object} ruleConfig The ruleConfig object to validate. | ||
* @returns {boolean} True if valid. Error if not. | ||
*/ | ||
const isOptionalObjExceptSchemaValid = ruleConfig => { | ||
const validate = ajv.compile(optionalObjExceptionsSchema); | ||
const isValid = validate(ruleConfig); | ||
if (!isValid) { | ||
throw new Error(`${formatSchemaErrors(validate.errors)}`); | ||
} | ||
return true; | ||
}; | ||
/** | ||
* Validates the top level properties of the config object. | ||
* | ||
* @param {Object} config The config object to validate. | ||
* @param {string} source The name of the configuration source to report in any errors. | ||
* @returns {boolean} True if valid. Error if not. | ||
*/ | ||
const isConfigObjectSchemaValid = (config, source) => { | ||
const validate = ajv.compile(configurationSchema); | ||
const isValid = validate(config); | ||
if (!isValid) { | ||
throw new Error(`npm-package-json-lint configuration in ${source} is invalid:\n${formatSchemaErrors(validate.errors)}`); | ||
} | ||
return true; | ||
}; | ||
module.exports = { | ||
isConfigObjectSchemaValid, | ||
isStandardRuleSchemaValid, | ||
isArrayRuleSchemaValid, | ||
isObjectRuleSchemaValid, | ||
isOptionalObjExceptSchemaValid | ||
}; |
@@ -1,75 +0,40 @@ | ||
/* eslint no-else-return: 'off' */ | ||
const Ajv = require('ajv'); | ||
const isPlainObj = require('is-plain-obj'); | ||
const ConfigSchema = require('./ConfigSchema'); | ||
/** | ||
* Formats an array of schema validation errors. | ||
* Validates object rule config | ||
* | ||
* @param {Array} errors An array of error messages to format. | ||
* @returns {String} Formatted error message | ||
* @param {Object} ruleConfig Object rule | ||
* @return {Boolean} True if config is valid, false if not | ||
* @static | ||
*/ | ||
const formatSchemaErrors = errors => { | ||
const secondChar = 1; | ||
const isObjectRuleConfigValid = ruleConfig => { | ||
if (typeof ruleConfig === 'string' && ruleConfig === 'off') { | ||
return true; | ||
} | ||
return errors | ||
.map(error => { | ||
if (error.keyword === 'additionalProperties') { | ||
const formattedPropertyPath = error.dataPath.length | ||
? `${error.dataPath.slice(secondChar)}.${error.params.additionalProperty}` | ||
: error.params.additionalProperty; | ||
if (typeof ruleConfig === 'string' && ruleConfig !== 'off') { | ||
throw new Error('\t- is an object type rule. It must be set to "off" if an object is not supplied.'); | ||
} | ||
return `Unexpected top-level property "${formattedPropertyPath}"`; | ||
} | ||
if (error.keyword === 'type') { | ||
const formattedField = error.dataPath.slice(secondChar); | ||
const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join('/') : error.schema; | ||
const formattedValue = JSON.stringify(error.data); | ||
return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`; | ||
} | ||
const field = error.dataPath[0] === '.' ? error.dataPath.slice(secondChar) : error.dataPath; | ||
return `"${field}" ${error.message}. Value: ${JSON.stringify(error.data)}`; | ||
}) | ||
.map(message => `\t- ${message}.\n`) | ||
.join(''); | ||
return ConfigSchema.isObjectRuleSchemaValid(ruleConfig); | ||
}; | ||
/** | ||
* Validates if the severity config is set correctly | ||
* @param {String} severity Severity the rule is set to | ||
* @return {Boolean} True if the severity is valid. False if the severity is invalid. | ||
* @private | ||
*/ | ||
const isSeverityInvalid = severity => | ||
typeof severity !== 'string' || | ||
(typeof severity === 'string' && severity !== 'error' && severity !== 'warning' && severity !== 'off'); | ||
/** | ||
* Validates object rule config | ||
* Validates optional object rule config | ||
* | ||
* @param {Object} ruleConfig Object rule | ||
* @return {Boolean} True if config is valid, false if not | ||
* @param {Object} ruleConfig Object rule | ||
* @return {Boolean} True if config is valid, false if not | ||
* @static | ||
*/ | ||
const isObjectRuleConfigValid = ruleConfig => { | ||
const severityIndex = 0; | ||
const isOptionalObjRuleConfigValid = ruleConfig => { | ||
const object = 1; | ||
if (typeof ruleConfig === 'string' && ruleConfig === 'off') { | ||
return true; | ||
} else if (typeof ruleConfig === 'string' && ruleConfig !== 'off') { | ||
throw new Error('is an object type rule. It must be set to "off" if an object is not supplied.'); | ||
} else if (typeof ruleConfig[severityIndex] !== 'string' || isSeverityInvalid(ruleConfig[severityIndex])) { | ||
throw new Error( | ||
`first key must be set to "error", "warning", or "off". Currently set to "${ruleConfig[severityIndex]}".` | ||
); | ||
if (typeof ruleConfig === 'string') { | ||
return ConfigSchema.isStandardRuleSchemaValid(ruleConfig); | ||
} | ||
if (!isPlainObj(ruleConfig[object])) { | ||
throw new Error(`second key must be set an object. Currently set to "${ruleConfig[object]}".`); | ||
if (ConfigSchema.isObjectRuleSchemaValid(ruleConfig)) { | ||
if (ruleConfig[object].hasOwnProperty('exceptions')) { | ||
return ConfigSchema.isOptionalObjExceptSchemaValid(ruleConfig[object].exceptions); | ||
} | ||
} | ||
@@ -88,20 +53,11 @@ | ||
const isArrayRuleConfigValid = ruleConfig => { | ||
const severityIndex = 0; | ||
const arrayIndex = 1; | ||
if (typeof ruleConfig === 'string' && ruleConfig === 'off') { | ||
return true; | ||
} else if (typeof ruleConfig === 'string' && ruleConfig !== 'off') { | ||
throw new Error('is an array type rule. It must be set to "off" if an array is not supplied.'); | ||
} else if (typeof ruleConfig[severityIndex] !== 'string' || isSeverityInvalid(ruleConfig[severityIndex])) { | ||
throw new Error( | ||
`first key must be set to "error", "warning", or "off". Currently set to "${ruleConfig[severityIndex]}".` | ||
); | ||
} | ||
if (!Array.isArray(ruleConfig[arrayIndex])) { | ||
throw new Error(`second key must be set an array. Currently set to "${ruleConfig[arrayIndex]}".`); | ||
if (typeof ruleConfig === 'string' && ruleConfig !== 'off') { | ||
throw new Error('\t- is an array type rule. It must be set to "off" if an array is not supplied.'); | ||
} | ||
return true; | ||
return ConfigSchema.isArrayRuleSchemaValid(ruleConfig); | ||
}; | ||
@@ -112,12 +68,8 @@ | ||
* | ||
* @param {Object} ruleConfig Value for standard rule config | ||
* @return {Boolean} True if config is valid, false if not | ||
* @param {Object} ruleConfig Value for standard rule config | ||
* @return {Boolean} True if config is valid, error if not | ||
* @static | ||
*/ | ||
const isStandardRuleConfigValid = ruleConfig => { | ||
if (isSeverityInvalid(ruleConfig)) { | ||
throw new Error(`must be set to "error", "warning", or "off". Currently set to "${ruleConfig}".`); | ||
} | ||
return true; | ||
return ConfigSchema.isStandardRuleSchemaValid(ruleConfig); | ||
}; | ||
@@ -141,2 +93,4 @@ | ||
isObjectRuleConfigValid(userConfig); | ||
} else if (ruleModule.ruleType === 'optionalObject') { | ||
isOptionalObjRuleConfigValid(userConfig); | ||
} else { | ||
@@ -146,3 +100,3 @@ isStandardRuleConfigValid(userConfig); | ||
} catch (err) { | ||
const modifiedErrorMessage = `Configuration for rule "${ruleName}" is invalid:\n\t${err.message}`; | ||
const modifiedErrorMessage = `Configuration for rule "${ruleName}" is invalid:\n${err.message}`; | ||
@@ -159,18 +113,2 @@ if (typeof source === 'string') { | ||
/** | ||
* Validates the top level properties of the config object. | ||
* | ||
* @param {Object} config The config object to validate. | ||
* @param {string} source The name of the configuration source to report in any errors. | ||
* @returns {undefined} No return | ||
*/ | ||
const validateConfigSchema = (config, source) => { | ||
const ajv = new Ajv({allErrors: true}); | ||
const schemaValidateResult = ajv.validate(ConfigSchema.get(), config); | ||
if (!schemaValidateResult) { | ||
throw new Error(`npm-package-json-lint configuration in ${source} is invalid:\n${formatSchemaErrors(ajv.errors)}`); | ||
} | ||
}; | ||
/** | ||
* Public ConfigValidator class | ||
@@ -190,3 +128,3 @@ * @class | ||
static validate(config, source, linterContext) { | ||
validateConfigSchema(config, source); | ||
ConfigSchema.isConfigObjectSchemaValid(config, source); | ||
ConfigValidator.validateRules(config.rules, source, linterContext); | ||
@@ -193,0 +131,0 @@ } |
@@ -6,2 +6,11 @@ const chalk = require('chalk'); | ||
/** | ||
* A lint issue. It could be an error or a warning. | ||
* @typedef {Object} LintIssue | ||
* @property {string} lintId Unique, lowercase, hyphen-separate name for the lint | ||
* @property {string} severity 'error' or 'warning' | ||
* @property {string} node Name of the node in the JSON the lint audits | ||
* @property {string} lintMessage Human-friendly message to users | ||
*/ | ||
/** | ||
* constructor | ||
@@ -12,2 +21,3 @@ * @param {String} lintId Unique, lowercase, hyphen-separate name for the lint | ||
* @param {String} lintMessage Human-friendly message to users | ||
* @returns {LintIssue} An instance of {@link LintIssue}. | ||
*/ | ||
@@ -23,3 +33,3 @@ constructor(lintId, severity, node, lintMessage) { | ||
* Helper to convert the LintIssue to a printable string | ||
* @return {String} Human-friendly message about the lint issue | ||
* @returns {string} Human-friendly message about the lint issue | ||
*/ | ||
@@ -26,0 +36,0 @@ toString() { |
@@ -1,13 +0,110 @@ | ||
/* eslint class-methods-use-this: 'off', max-statements: 'off', guard-for-in: 'off', no-restricted-syntax: 'off' */ | ||
/* eslint max-lines-per-function: 'off', no-param-reassign: 'off', arrow-body-style: 'off' */ | ||
const debug = require('debug')('npm-package-json-lint:NpmPackageJsonLint'); | ||
const isPlainObj = require('is-plain-obj'); | ||
const Config = require('./Config'); | ||
const pkg = require('../package.json'); | ||
const Rules = require('./Rules'); | ||
const pkg = require('./../package.json'); | ||
const linter = require('./linter/linter'); | ||
const getFileList = require('./utils/getFileList'); | ||
const getIgnorer = require('./utils/getIgnorer'); | ||
const noIssues = 0; | ||
/** | ||
* Checks if the given issue is an error issue. | ||
* | ||
* @param {LintIssue} issue npm-package-json-lint issue | ||
* @returns {boolean} True if error, false if warning. | ||
* @private | ||
*/ | ||
const isIssueAnError = issue => { | ||
return issue.severity === 'error'; | ||
}; | ||
const isPackageJsonObjectValid = packageJsonObject => isPlainObj(packageJsonObject); | ||
const areRequiredOptionsValid = (packageJsonObject, patterns) => { | ||
return ( | ||
(!patterns && !isPackageJsonObjectValid(packageJsonObject)) || | ||
(patterns && (packageJsonObject || isPackageJsonObjectValid(packageJsonObject))) | ||
); | ||
}; | ||
/** | ||
* Filters results to only include errors. | ||
* | ||
* @param {LintResult[]} results The results to filter. | ||
* @returns {LintResult[]} The filtered results. | ||
*/ | ||
const getErrorResults = results => { | ||
const filtered = []; | ||
results.forEach(result => { | ||
const filteredIssues = result.issues.filter(isIssueAnError); | ||
if (filteredIssues.length > noIssues) { | ||
const filteredResult = { | ||
issues: filteredIssues, | ||
errorCount: filteredIssues.length, | ||
warningCount: 0 | ||
}; | ||
filtered.push(Object.assign(result, filteredResult)); | ||
} | ||
}); | ||
return filtered; | ||
}; | ||
/** | ||
* CLIEngine configuration object | ||
* | ||
* @typedef {Object} NpmPackageJsonLint | ||
* @property {string} configFile The configuration file to use. | ||
* @property {string} cwd The value to use for the current working directory. | ||
* @property {boolean} useConfigFiles False disables use of .npmpackagejsonlintrc.json files, npmpackagejsonlint.config.js files, and npmPackageJsonLintConfig object in package.json file. | ||
* @property {Object<string,*>} rules An object of rules to use. | ||
*/ | ||
/** | ||
* Public CLIEngine class | ||
* @class | ||
*/ | ||
class NpmPackageJsonLint { | ||
/** | ||
* constructor | ||
* @param {NpmPackageJsonLint} options The options for the CLIEngine. | ||
* @constructor | ||
*/ | ||
constructor() { | ||
constructor({ | ||
cwd, | ||
packageJsonObject, | ||
packageJsonFilePath, | ||
config, | ||
configFile, | ||
configBaseDirectory, | ||
patterns, | ||
quiet, | ||
ignorePath, | ||
fix | ||
}) { | ||
this.cwd = cwd || process.cwd(); | ||
this.packageJsonObject = packageJsonObject; | ||
this.packageJsonFilePath = packageJsonFilePath; | ||
this.patterns = patterns; | ||
this.quiet = quiet || false; | ||
this.ignorePath = ignorePath || ''; | ||
this.fix = fix || false; | ||
this.version = pkg.version; | ||
// if (this.options.rules && Object.keys(this.options.rules).length) { | ||
// ConfigValidator.validateRules(this.options.rules, 'cli', this.linter); | ||
// } | ||
this.configHelper = new Config(this.cwd, config, configFile, configBaseDirectory); | ||
this.rules = new Rules(); | ||
this.version = pkg.version; | ||
this.rules.load(); | ||
@@ -17,59 +114,62 @@ } | ||
/** | ||
* Runs configured rules against the provided package.json object. | ||
* Runs the linter using the config specified in the constructor | ||
* | ||
* @param {Object} packageJsonData Valid package.json data | ||
* @param {Object} configObj Configuration object | ||
* @return {Object} Results object | ||
* @returns {LinterResult} The results {@link LinterResult} from linting a collection of package.json files. | ||
* @memberof NpmPackageJsonLint | ||
*/ | ||
lint(packageJsonData, configObj) { | ||
const lintIssues = []; | ||
lint() { | ||
debug('Starting lint'); | ||
for (const rule in configObj) { | ||
const ruleModule = this.rules.get(rule); | ||
if (areRequiredOptionsValid(this.packageJsonObject, this.patterns)) { | ||
throw new Error( | ||
'You must pass npm-package-json-lint a `patterns` glob or a `packageJsonObject` string, though not both.' | ||
); | ||
} | ||
if (ruleModule.ruleType === 'array' || ruleModule.ruleType === 'object') { | ||
const severity = | ||
typeof configObj[rule] === 'string' && configObj[rule] === 'off' ? configObj[rule] : configObj[rule][0]; | ||
const ruleConfig = configObj[rule][1]; | ||
const ignorer = getIgnorer(this.cwd, this.ignorePath); | ||
let linterOutput; | ||
if (severity !== 'off') { | ||
const lintResult = ruleModule.lint(packageJsonData, severity, ruleConfig); | ||
if (this.patterns) { | ||
debug('Linting using patterns'); | ||
const {patterns} = this; | ||
if (typeof lintResult === 'object') { | ||
lintIssues.push(lintResult); | ||
} | ||
} | ||
} else { | ||
const severity = configObj[rule]; | ||
if (!Array.isArray(patterns)) { | ||
throw new Error('Patterns must be an array.'); | ||
} | ||
if (severity !== 'off') { | ||
const lintResult = ruleModule.lint(packageJsonData, severity); | ||
const fileList = getFileList(patterns, this.cwd); | ||
if (typeof lintResult === 'object') { | ||
lintIssues.push(lintResult); | ||
} | ||
} | ||
} | ||
linterOutput = linter.executeOnPackageJsonFiles({ | ||
cwd: this.cwd, | ||
fileList, | ||
ignorer, | ||
configHelper: this.configHelper, | ||
rules: this.rules | ||
}); | ||
} else { | ||
debug('Linting using passed object.'); | ||
linterOutput = linter.executeOnPackageJsonObject({ | ||
cwd: this.cwd, | ||
packageJsonObject: this.packageJsonObject, | ||
ignorer, | ||
filename: this.packageJsonFilePath, | ||
configHelper: this.configHelper, | ||
rules: this.rules | ||
}); | ||
} | ||
return {issues: lintIssues}; | ||
} | ||
if (this.quiet) { | ||
const errorsOnly = getErrorResults(linterOutput.results); | ||
/** | ||
* Gets entire rule set | ||
* | ||
* @returns {Object} Rule set | ||
*/ | ||
getRules() { | ||
return this.rules.getRules(); | ||
} | ||
return { | ||
results: errorsOnly, | ||
ignoreCount: linterOutput.ignoreCount, | ||
errorCount: linterOutput.errorCount, | ||
warningCount: linterOutput.warningCount | ||
}; | ||
} | ||
/** | ||
* Get the rule definition for a given ruleId (name) | ||
* | ||
* @param {String} rule Rule name | ||
* @returns {Object} Rule object | ||
*/ | ||
getRule(rule) { | ||
return this.rules.get(rule); | ||
debug('lint complete'); | ||
return linterOutput; | ||
} | ||
@@ -76,0 +176,0 @@ } |
@@ -34,7 +34,11 @@ /* eslint no-restricted-syntax: 'off' */ | ||
const printIndividualResultSet = (resultSet, quiet) => { | ||
const {filePath, issues, errorCount, warningCount} = resultSet; | ||
const {filePath, issues, ignored, errorCount, warningCount} = resultSet; | ||
if (errorCount > zeroIssues || (!quiet && warningCount > zeroIssues)) { | ||
if (ignored) { | ||
console.log(''); | ||
console.log(`${chalk.yellow.underline(filePath)} - ignored`); | ||
} else if (errorCount > zeroIssues || (!quiet && warningCount > zeroIssues)) { | ||
console.log(''); | ||
console.log(chalk.underline(filePath)); | ||
@@ -58,3 +62,3 @@ | ||
* | ||
* @param {Object} cliEngineOutput Full results from linting. Includes an array of results and overall counts | ||
* @param {Object} linterOutput Full results from linting. Includes an array of results and overall counts | ||
* @param {Boolean} quiet True suppress warnings, false show warnings | ||
@@ -64,4 +68,4 @@ * @returns {Undefined} No results | ||
*/ | ||
const printTotals = (cliEngineOutput, quiet) => { | ||
const {errorCount, warningCount} = cliEngineOutput; | ||
const printTotals = (linterOutput, quiet) => { | ||
const {errorCount, warningCount, ignoreCount} = linterOutput; | ||
@@ -71,2 +75,3 @@ if (errorCount > zeroIssues || warningCount > zeroIssues) { | ||
const warningCountMessage = `${warningCount} ${plur('warning', warningCount)}`; | ||
const ignoreCountMessage = `${ignoreCount} ${plur('file', ignoreCount)} ignored`; | ||
@@ -79,2 +84,3 @@ console.log(''); | ||
console.log(chalk.yellow.bold(warningCountMessage)); | ||
console.log(chalk.yellow.bold(ignoreCountMessage)); | ||
} | ||
@@ -92,3 +98,3 @@ } | ||
* | ||
* @param {Object} cliEngineOutput An array of LintIssues | ||
* @param {Object} linterOutput An array of LintIssues | ||
* @param {boolean} quiet Flag indicating whether to print warnings. | ||
@@ -98,9 +104,9 @@ * @return {undefined} No return | ||
*/ | ||
static write(cliEngineOutput, quiet) { | ||
for (const result of cliEngineOutput.results) { | ||
static write(linterOutput, quiet) { | ||
for (const result of linterOutput.results) { | ||
printIndividualResultSet(result, quiet); | ||
} | ||
if (cliEngineOutput.results.length > oneFile) { | ||
printTotals(cliEngineOutput, quiet); | ||
if (linterOutput.results.length > oneFile) { | ||
printTotals(linterOutput, quiet); | ||
} | ||
@@ -107,0 +113,0 @@ } |
@@ -17,3 +17,5 @@ const {isObject, isString} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isArray} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isArray} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -39,3 +39,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isArray} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isArray} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isString} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isString} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -18,3 +18,5 @@ const {isArray} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -6,14 +6,30 @@ const {isLowercase} = require('./../validators/format'); | ||
const nodeName = 'name'; | ||
const message = 'Format should be all lowercase'; | ||
const ruleType = 'standard'; | ||
const maxLength = 214; | ||
const lint = (packageJsonData, severity) => { | ||
if (!isLowercase(packageJsonData, nodeName)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
if (!packageJsonData.hasOwnProperty(nodeName)) { | ||
return true; | ||
} | ||
const name = packageJsonData[nodeName]; | ||
if (!isLowercase(name)) { | ||
return new LintIssue(lintId, severity, nodeName, 'Format should be all lowercase'); | ||
} | ||
if (name.length > maxLength) { | ||
return new LintIssue(lintId, severity, nodeName, `name should be less than or equal to ${maxLength} characters.`); | ||
} | ||
if (name.startsWith('.') || name.startsWith('_')) { | ||
return new LintIssue(lintId, severity, nodeName, 'name should not start with . or _'); | ||
} | ||
return true; | ||
}; | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -1,2 +0,2 @@ | ||
const {isVersionAbsolute} = require('./../validators/dependency-audit'); | ||
const {areVersionsAbsolute} = require('./../validators/dependency-audit'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,6 +7,6 @@ | ||
const message = 'You are using an invalid version range. Please do not use absolute versions.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
if (packageJsonData.hasOwnProperty(nodeName) && isVersionAbsolute(packageJsonData, nodeName)) { | ||
const lint = (packageJsonData, severity, config) => { | ||
if (packageJsonData.hasOwnProperty(nodeName) && areVersionsAbsolute(packageJsonData, nodeName, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -18,3 +18,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -1,2 +0,2 @@ | ||
const {isVersionAbsolute} = require('./../validators/dependency-audit'); | ||
const {areVersionsAbsolute} = require('./../validators/dependency-audit'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,6 +7,6 @@ | ||
const message = 'You are using an invalid version range. Please do not use absolute versions.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
if (packageJsonData.hasOwnProperty(nodeName) && isVersionAbsolute(packageJsonData, nodeName)) { | ||
const lint = (packageJsonData, severity, config) => { | ||
if (packageJsonData.hasOwnProperty(nodeName) && areVersionsAbsolute(packageJsonData, nodeName, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -18,3 +18,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -7,8 +7,11 @@ const {doVersContainInvalidRange} = require('./../validators/dependency-audit'); | ||
const message = 'You are using an invalid version range. Please do not use ^.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '^'; | ||
if (packageJsonData.hasOwnProperty(nodeName) && doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier)) { | ||
if ( | ||
packageJsonData.hasOwnProperty(nodeName) && | ||
doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier, config) | ||
) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +23,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -7,8 +7,11 @@ const {doVersContainInvalidRange} = require('./../validators/dependency-audit'); | ||
const message = 'You are using an invalid version range. Please do not use ^.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '^'; | ||
if (packageJsonData.hasOwnProperty(nodeName) && doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier)) { | ||
if ( | ||
packageJsonData.hasOwnProperty(nodeName) && | ||
doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier, config) | ||
) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +23,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {hasDependency} = require('./../validators/dependency-audit'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {hasDependency} = require('./../validators/dependency-audit'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {hasDepPrereleaseVers} = require('./../validators/dependency-audit'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {hasDepPrereleaseVers} = require('./../validators/dependency-audit'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -7,8 +7,11 @@ const {doVersContainInvalidRange} = require('./../validators/dependency-audit'); | ||
const message = 'You are using an invalid version range. Please do not use ~.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '~'; | ||
if (packageJsonData.hasOwnProperty(nodeName) && doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier)) { | ||
if ( | ||
packageJsonData.hasOwnProperty(nodeName) && | ||
doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier, config) | ||
) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +23,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -7,8 +7,11 @@ const {doVersContainInvalidRange} = require('./../validators/dependency-audit'); | ||
const message = 'You are using an invalid version range. Please do not use ~.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '~'; | ||
if (packageJsonData.hasOwnProperty(nodeName) && doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier)) { | ||
if ( | ||
packageJsonData.hasOwnProperty(nodeName) && | ||
doVersContainInvalidRange(packageJsonData, nodeName, rangeSpecifier, config) | ||
) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +23,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isArray} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -1,3 +0,4 @@ | ||
const {isVersionAbsolute} = require('./../validators/dependency-audit'); | ||
const LintIssue = require('./../LintIssue'); | ||
const {doVersContainNonAbsolute} = require('../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('../LintIssue'); | ||
@@ -7,6 +8,6 @@ const lintId = 'prefer-absolute-version-dependencies'; | ||
const message = 'You are using an invalid version range. Please use absolute versions.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
if (!isVersionAbsolute(packageJsonData, nodeName)) { | ||
const lint = (packageJsonData, severity, config) => { | ||
if (exists(packageJsonData, nodeName) && doVersContainNonAbsolute(packageJsonData, nodeName, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -18,3 +19,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -1,3 +0,4 @@ | ||
const {isVersionAbsolute} = require('./../validators/dependency-audit'); | ||
const LintIssue = require('./../LintIssue'); | ||
const {doVersContainNonAbsolute} = require('../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('../LintIssue'); | ||
@@ -7,6 +8,6 @@ const lintId = 'prefer-absolute-version-devDependencies'; | ||
const message = 'You are using an invalid version range. Please use absolute versions.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
if (!isVersionAbsolute(packageJsonData, nodeName)) { | ||
const lint = (packageJsonData, severity, config) => { | ||
if (exists(packageJsonData, nodeName) && doVersContainNonAbsolute(packageJsonData, nodeName, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -18,3 +19,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {isInAlphabeticalOrder} = require('./../validators/alphabetical-sort'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -10,2 +11,6 @@ | ||
const lint = (packageJsonData, severity) => { | ||
if (!exists(packageJsonData, nodeName)) { | ||
return true; | ||
} | ||
const result = isInAlphabeticalOrder(packageJsonData, nodeName); | ||
@@ -25,3 +30,5 @@ | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {isInAlphabeticalOrder} = require('./../validators/alphabetical-sort'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -10,2 +11,6 @@ | ||
const lint = (packageJsonData, severity) => { | ||
if (!exists(packageJsonData, nodeName)) { | ||
return true; | ||
} | ||
const result = isInAlphabeticalOrder(packageJsonData, nodeName); | ||
@@ -25,3 +30,5 @@ | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {isInAlphabeticalOrder} = require('./../validators/alphabetical-sort'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -10,2 +11,6 @@ | ||
const lint = (packageJsonData, severity) => { | ||
if (!exists(packageJsonData, nodeName)) { | ||
return true; | ||
} | ||
const result = isInAlphabeticalOrder(packageJsonData, nodeName); | ||
@@ -25,3 +30,5 @@ | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {isInAlphabeticalOrder} = require('./../validators/alphabetical-sort'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -10,2 +11,6 @@ | ||
const lint = (packageJsonData, severity) => { | ||
if (!exists(packageJsonData, nodeName)) { | ||
return true; | ||
} | ||
const result = isInAlphabeticalOrder(packageJsonData, nodeName); | ||
@@ -25,3 +30,5 @@ | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {isInAlphabeticalOrder} = require('./../validators/alphabetical-sort'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -10,2 +11,6 @@ | ||
const lint = (packageJsonData, severity) => { | ||
if (!exists(packageJsonData, nodeName)) { | ||
return true; | ||
} | ||
const result = isInAlphabeticalOrder(packageJsonData, nodeName); | ||
@@ -25,3 +30,5 @@ | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {areVersRangesValid} = require('./../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,8 +8,8 @@ | ||
const message = 'You are using an invalid version range. Please use ^.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '^'; | ||
if (!areVersRangesValid(packageJsonData, nodeName, rangeSpecifier)) { | ||
if (exists(packageJsonData, nodeName) && !areVersRangesValid(packageJsonData, nodeName, rangeSpecifier, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +21,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {areVersRangesValid} = require('./../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,8 +8,8 @@ | ||
const message = 'You are using an invalid version range. Please use ^.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '^'; | ||
if (!areVersRangesValid(packageJsonData, nodeName, rangeSpecifier)) { | ||
if (exists(packageJsonData, nodeName) && !areVersRangesValid(packageJsonData, nodeName, rangeSpecifier, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +21,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -0,1 +1,2 @@ | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -9,3 +10,3 @@ | ||
const lint = (packageJsonData, severity) => { | ||
if (packageJsonData.hasOwnProperty(nodeName)) { | ||
if (exists(packageJsonData, nodeName)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -17,3 +18,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {hasDepVersZero} = require('./../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,6 +8,6 @@ | ||
const message = 'You have invalid version 0 dependencies. Please use modules with a major version >= 1.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
if (hasDepVersZero(packageJsonData, nodeName)) { | ||
const lint = (packageJsonData, severity, config) => { | ||
if (exists(packageJsonData, nodeName) && hasDepVersZero(packageJsonData, nodeName, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -18,3 +19,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {hasDepVersZero} = require('./../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,6 +8,6 @@ | ||
const message = 'You have invalid version 0 dependencies. Please use modules with a major version >= 1.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
if (hasDepVersZero(packageJsonData, nodeName)) { | ||
const lint = (packageJsonData, severity, config) => { | ||
if (exists(packageJsonData, nodeName) && hasDepVersZero(packageJsonData, nodeName, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -18,3 +19,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -19,3 +19,5 @@ const {isInPreferredOrder} = require('./../validators/property-order'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {areVersRangesValid} = require('./../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,8 +8,8 @@ | ||
const message = 'You are using an invalid version range. Please use ~.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '~'; | ||
if (!areVersRangesValid(packageJsonData, nodeName, rangeSpecifier)) { | ||
if (exists(packageJsonData, nodeName) && !areVersRangesValid(packageJsonData, nodeName, rangeSpecifier, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +21,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
const {areVersRangesValid} = require('./../validators/dependency-audit'); | ||
const {exists} = require('../validators/property'); | ||
const LintIssue = require('./../LintIssue'); | ||
@@ -7,8 +8,8 @@ | ||
const message = 'You are using an invalid version range. Please use ~.'; | ||
const ruleType = 'standard'; | ||
const ruleType = 'optionalObject'; | ||
const lint = (packageJsonData, severity) => { | ||
const lint = (packageJsonData, severity, config) => { | ||
const rangeSpecifier = '~'; | ||
if (!areVersRangesValid(packageJsonData, nodeName, rangeSpecifier)) { | ||
if (exists(packageJsonData, nodeName) && !areVersRangesValid(packageJsonData, nodeName, rangeSpecifier, config)) { | ||
return new LintIssue(lintId, severity, nodeName, message); | ||
@@ -20,3 +21,5 @@ } | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -18,3 +18,5 @@ const {isObject} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -21,3 +21,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -16,3 +16,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -11,4 +11,2 @@ /* eslint no-restricted-syntax: 'off' */ | ||
/* eslint-disable max-statements */ | ||
const lint = (packageJsonData, severity) => { | ||
@@ -37,3 +35,5 @@ if (!isObject(packageJsonData, nodeName)) { | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -33,3 +33,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -43,3 +43,5 @@ /* eslint max-statements: 'off', no-restricted-syntax: 'off', guard-for-in: 'off' */ | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -25,3 +25,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -27,3 +27,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -24,3 +24,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -27,3 +27,5 @@ const LintIssue = require('./../LintIssue'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isValidVersionNumber} = require('./../validators/format'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -17,3 +17,5 @@ const {isString} = require('./../validators/type'); | ||
module.exports.lint = lint; | ||
module.exports.ruleType = ruleType; | ||
module.exports = { | ||
lint, | ||
ruleType | ||
}; |
@@ -10,12 +10,2 @@ const increment = 1; | ||
const isInAlphabeticalOrder = (packageJsonData, nodeName) => { | ||
if (!packageJsonData.hasOwnProperty(nodeName)) { | ||
return { | ||
status: true, | ||
data: { | ||
invalidNode: null, | ||
validNode: null | ||
} | ||
}; | ||
} | ||
let isValid = true; | ||
@@ -46,2 +36,4 @@ let data = { | ||
module.exports.isInAlphabeticalOrder = isInAlphabeticalOrder; | ||
module.exports = { | ||
isInAlphabeticalOrder | ||
}; |
@@ -1,4 +0,8 @@ | ||
/* eslint no-restricted-syntax: 'off', guard-for-in: 'off' */ | ||
/* eslint no-restricted-syntax: 'off', guard-for-in: 'off', no-continue: 'off' */ | ||
const semver = require('semver'); | ||
const hasExceptions = config => { | ||
return typeof config === 'object' && config.hasOwnProperty('exceptions'); | ||
}; | ||
/** | ||
@@ -52,12 +56,13 @@ * Determines whether or not the package has a given dependency | ||
* Determines whether or not the package has a dependency with a major version of 0 | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @return {boolean} True if the package has a dependency with version 0. False if it does not or the node is missing. | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {object} config Rule configuration | ||
* @return {boolean} True if the package has a dependency with version 0. False if it does not or the node is missing. | ||
*/ | ||
const hasDepVersZero = (packageJsonData, nodeName) => { | ||
if (!packageJsonData.hasOwnProperty(nodeName)) { | ||
return false; | ||
} | ||
const hasDepVersZero = (packageJsonData, nodeName, config) => { | ||
for (const dependencyName in packageJsonData[nodeName]) { | ||
if (hasExceptions(config) && config.exceptions.includes(dependencyName)) { | ||
continue; | ||
} | ||
for (const dependencyName in packageJsonData[nodeName]) { | ||
const dependencyVersRange = packageJsonData[nodeName][dependencyName]; | ||
@@ -95,8 +100,9 @@ | ||
* Determines whether or not all dependency version ranges match expected range | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {string} rangeSpecifier A version range specifier | ||
* @return {boolean} False if the package has an invalid range. True if it is not or the node is missing. | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {string} rangeSpecifier A version range specifier | ||
* @param {object} config Rule configuration | ||
* @return {boolean} False if the package has an invalid range. True if it is not or the node is missing. | ||
*/ | ||
const areVersRangesValid = (packageJsonData, nodeName, rangeSpecifier) => { | ||
const areVersRangesValid = (packageJsonData, nodeName, rangeSpecifier, config) => { | ||
if (!packageJsonData.hasOwnProperty(nodeName)) { | ||
@@ -109,2 +115,6 @@ return true; | ||
for (const dependencyName in packageJsonData[nodeName]) { | ||
if (hasExceptions(config) && config.exceptions.includes(dependencyName)) { | ||
continue; | ||
} | ||
const dependencyVersion = packageJsonData[nodeName][dependencyName]; | ||
@@ -122,8 +132,9 @@ | ||
* Determines if any dependencies have a version string that starts with the specified invalid range | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {string} rangeSpecifier A version range specifier | ||
* @return {Boolean} True if any dependencies versions start with the invalid range, false if they don't. | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {string} rangeSpecifier A version range specifier | ||
* @param {object} config Rule configuration | ||
* @return {Boolean} True if any dependencies versions start with the invalid range, false if they don't. | ||
*/ | ||
const doVersContainInvalidRange = (packageJsonData, nodeName, rangeSpecifier) => { | ||
const doVersContainInvalidRange = (packageJsonData, nodeName, rangeSpecifier, config) => { | ||
if (!packageJsonData.hasOwnProperty(nodeName)) { | ||
@@ -136,2 +147,6 @@ return false; | ||
for (const dependencyName in packageJsonData[nodeName]) { | ||
if (hasExceptions(config) && config.exceptions.includes(dependencyName)) { | ||
continue; | ||
} | ||
const dependencyVersion = packageJsonData[nodeName][dependencyName]; | ||
@@ -149,16 +164,18 @@ | ||
* Determines whether or not all dependency versions are absolut | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @return {boolean} False if the package has an non-absolute version. True if it is not or the node is missing. | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {object} config Rule configuration | ||
* @return {boolean} False if the package has an non-absolute version. True if it is not or the node is missing. | ||
*/ | ||
const isVersionAbsolute = (packageJsonData, nodeName) => { | ||
if (!packageJsonData.hasOwnProperty(nodeName)) { | ||
return true; | ||
} | ||
const NOT_FOUND = -1; | ||
const absoluteVersionChecker = (packageJsonData, nodeName, config) => { | ||
const notFound = -1; | ||
const firstCharOfStr = 0; | ||
let rangesValid = true; | ||
let onlyAbsoluteVersionDetected = true; | ||
let dependenciesChecked = 0; | ||
for (const dependencyName in packageJsonData[nodeName]) { | ||
if (hasExceptions(config) && config.exceptions.includes(dependencyName)) { | ||
continue; | ||
} | ||
const dependencyVersion = packageJsonData[nodeName][dependencyName]; | ||
@@ -171,17 +188,51 @@ | ||
dependencyVersion.startsWith('<', firstCharOfStr) || | ||
dependencyVersion.indexOf('*') !== NOT_FOUND | ||
dependencyVersion.indexOf('*') !== notFound | ||
) { | ||
rangesValid = false; | ||
onlyAbsoluteVersionDetected = false; | ||
} | ||
dependenciesChecked += 1; | ||
} | ||
return rangesValid; | ||
return { | ||
onlyAbsoluteVersionDetected, | ||
dependenciesChecked | ||
}; | ||
}; | ||
module.exports.hasDependency = hasDependency; | ||
module.exports.hasDepPrereleaseVers = hasDepPrereleaseVers; | ||
module.exports.hasDepVersZero = hasDepVersZero; | ||
module.exports.doesVersStartsWithRange = doesVersStartsWithRange; | ||
module.exports.areVersRangesValid = areVersRangesValid; | ||
module.exports.doVersContainInvalidRange = doVersContainInvalidRange; | ||
module.exports.isVersionAbsolute = isVersionAbsolute; | ||
/** | ||
* Determines whether or not all dependency versions are absolut | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {object} config Rule configuration | ||
* @return {boolean} False if the package has an non-absolute version. True if it is not or the node is missing. | ||
*/ | ||
const areVersionsAbsolute = (packageJsonData, nodeName, config) => { | ||
const {onlyAbsoluteVersionDetected, dependenciesChecked} = absoluteVersionChecker(packageJsonData, nodeName, config); | ||
return dependenciesChecked > 0 ? onlyAbsoluteVersionDetected : false; | ||
}; | ||
/** | ||
* Determines whether or not all dependency versions are absolut | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @param {object} config Rule configuration | ||
* @return {boolean} False if the package has an non-absolute version. True if it is not or the node is missing. | ||
*/ | ||
const doVersContainNonAbsolute = (packageJsonData, nodeName, config) => { | ||
const {onlyAbsoluteVersionDetected, dependenciesChecked} = absoluteVersionChecker(packageJsonData, nodeName, config); | ||
return dependenciesChecked > 0 ? !onlyAbsoluteVersionDetected : false; | ||
}; | ||
module.exports = { | ||
hasDependency, | ||
hasDepPrereleaseVers, | ||
hasDepVersZero, | ||
doesVersStartsWithRange, | ||
areVersRangesValid, | ||
doVersContainInvalidRange, | ||
areVersionsAbsolute, | ||
doVersContainNonAbsolute | ||
}; |
const semver = require('semver'); | ||
const validator = require('validator'); | ||
/** | ||
* Determines whether or not the node's value is lowercase | ||
* @param {object} packageJsonData Valid JSON | ||
* @param {string} nodeName Name of a node in the package.json file | ||
* @return {boolean} True if the node is lowercase or is missing. False if it is not. | ||
* Determines whether or not the string is lowercase | ||
* @param {string} name Name | ||
* @return {boolean} True if the string is lowercase or is missing. False if it is not. | ||
*/ | ||
const isLowercase = (packageJsonData, nodeName) => { | ||
if (!packageJsonData.hasOwnProperty(nodeName)) { | ||
return true; | ||
} | ||
return validator.isLowercase(packageJsonData[nodeName]); | ||
const isLowercase = name => { | ||
return name === name.toLowerCase(); | ||
}; | ||
@@ -32,3 +26,5 @@ | ||
module.exports.isLowercase = isLowercase; | ||
module.exports.isValidVersionNumber = isValidVersionNumber; | ||
module.exports = { | ||
isLowercase, | ||
isValidVersionNumber | ||
}; |
@@ -93,2 +93,4 @@ /* eslint max-statements: 'off' */ | ||
module.exports.isInPreferredOrder = isInPreferredOrder; | ||
module.exports = { | ||
isInPreferredOrder | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
152599
119
3473
7
10
1
+ Addedajv-errors@^1.0.1
+ Addedcosmiconfig@^5.2.1
+ Addeddebug@^4.1.1
+ Addedglobby@^10.0.1
+ Added@nodelib/fs.scandir@2.1.5(transitive)
+ Added@nodelib/fs.stat@2.0.5(transitive)
+ Added@nodelib/fs.walk@1.2.8(transitive)
+ Added@types/glob@7.2.0(transitive)
+ Added@types/minimatch@5.1.2(transitive)
+ Added@types/node@22.10.2(transitive)
+ Addedajv-errors@1.0.1(transitive)
+ Addedargparse@1.0.10(transitive)
+ Addedarray-union@2.1.0(transitive)
+ Addedbraces@3.0.3(transitive)
+ Addedcaller-callsite@2.0.0(transitive)
+ Addedcaller-path@2.0.0(transitive)
+ Addedcallsites@2.0.0(transitive)
+ Addedcosmiconfig@5.2.1(transitive)
+ Addeddebug@4.4.0(transitive)
+ Addeddir-glob@3.0.1(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedfast-glob@3.3.2(transitive)
+ Addedfastq@1.17.1(transitive)
+ Addedfill-range@7.1.1(transitive)
+ Addedglob-parent@5.1.2(transitive)
+ Addedglobby@10.0.2(transitive)
+ Addedimport-fresh@2.0.0(transitive)
+ Addedis-directory@0.3.1(transitive)
+ Addedis-extglob@2.1.1(transitive)
+ Addedis-glob@4.0.3(transitive)
+ Addedis-number@7.0.0(transitive)
+ Addedis-plain-obj@2.1.0(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedlog-symbols@3.0.0(transitive)
+ Addedmerge2@1.4.1(transitive)
+ Addedmicromatch@4.0.8(transitive)
+ Addedms@2.1.3(transitive)
+ Addedpath-type@4.0.0(transitive)
+ Addedpicomatch@2.3.1(transitive)
+ Addedqueue-microtask@1.2.3(transitive)
+ Addedresolve-from@3.0.0(transitive)
+ Addedreusify@1.0.4(transitive)
+ Addedrun-parallel@1.2.0(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedslash@3.0.0(transitive)
+ Addedsprintf-js@1.0.3(transitive)
+ Addedstrip-json-comments@3.1.1(transitive)
+ Addedto-regex-range@5.0.1(transitive)
+ Addedundici-types@6.20.0(transitive)
- Removedglob@^7.1.4
- Removedis-path-inside@^2.1.0
- Removedis-resolvable@^1.1.0
- Removedvalidator@^10.11.0
- Removedis-path-inside@2.1.0(transitive)
- Removedis-resolvable@1.1.0(transitive)
- Removedlog-symbols@2.2.0(transitive)
- Removedpath-is-inside@1.0.2(transitive)
- Removedstrip-json-comments@2.0.1(transitive)
- Removedvalidator@10.11.0(transitive)
Updatedis-plain-obj@^2.0.0
Updatedlog-symbols@^3.0.0
Updatedsemver@^6.1.1
Updatedstrip-json-comments@^3.0.1