🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

@eslint/config-array

Package Overview
Dependencies
Maintainers
2
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eslint/config-array - npm Package Compare versions

Comparing version

to
0.21.0

5

dist/cjs/types.ts

@@ -8,2 +8,7 @@ /**

/**
* The base path for files and ignores.
*/
basePath?: string;
/**
* The files to include.

@@ -10,0 +15,0 @@ */

4

dist/esm/index.d.ts

@@ -60,5 +60,5 @@ export { ObjectSchema } from "@eslint/object-schema";

* globbing operation to be faster.
* @returns {string[]} An array of string patterns and functions to be ignored.
* @returns {Object[]} An array of config objects representing global ignores.
*/
get ignores(): string[];
get ignores(): any[];
/**

@@ -65,0 +65,0 @@ * Indicates if the config array has been normalized.

@@ -57,2 +57,3 @@ // @ts-self-types="./index.d.ts"

},
basePath: NOOP_STRATEGY,
files: NOOP_STRATEGY,

@@ -129,2 +130,13 @@ ignores: NOOP_STRATEGY,

const filesAndIgnoresSchema = Object.freeze({
basePath: {
required: false,
merge() {
return undefined;
},
validate(value) {
if (typeof value !== "string") {
throw new TypeError("Expected value to be a string.");
}
},
},
files: {

@@ -226,3 +238,3 @@ required: false,

*/
const META_FIELDS = new Set(["name"]);
const META_FIELDS = new Set(["name", "basePath"]);

@@ -353,2 +365,6 @@ /**

if ("basePath" in config) {
validateConfig.basePath = config.basePath;
}
if ("files" in config) {

@@ -432,5 +448,7 @@ validateConfig.files = config.files;

* @param {Object} config The config object to normalize patterns in.
* @param {string} namespacedBasePath The namespaced base path of the directory to which config base path is relative.
* @param {PathImpl} path Path-handling implementation.
* @returns {Object} The normalized config object.
*/
function normalizeConfigPatterns(config) {
function normalizeConfigPatterns(config, namespacedBasePath, path) {
if (!config) {

@@ -440,5 +458,11 @@ return config;

const hasBasePath = typeof config.basePath === "string";
let needsNormalization = false;
if (Array.isArray(config.files)) {
if (hasBasePath) {
needsNormalization = true;
}
if (!needsNormalization && Array.isArray(config.files)) {
needsNormalization = config.files.some(pattern => {

@@ -462,2 +486,13 @@ if (Array.isArray(pattern)) {

if (hasBasePath) {
if (path.isAbsolute(config.basePath)) {
newConfig.basePath = path.toNamespacedPath(config.basePath);
} else {
newConfig.basePath = path.resolve(
namespacedBasePath,
config.basePath,
);
}
}
if (Array.isArray(newConfig.files)) {

@@ -486,6 +521,14 @@ newConfig.files = newConfig.files.map(pattern => {

* @param {Array<string>} extraConfigTypes The config types to check.
* @param {string} namespacedBasePath The namespaced base path of the directory to which config base paths are relative.
* @param {PathImpl} path Path-handling implementation.
* @returns {Promise<Array>} A flattened array containing only config objects.
* @throws {TypeError} When a config function returns a function.
*/
async function normalize(items, context, extraConfigTypes) {
async function normalize(
items,
context,
extraConfigTypes,
namespacedBasePath,
path,
) {
const allowFunctions = extraConfigTypes.includes("function");

@@ -530,3 +573,3 @@ const allowArrays = extraConfigTypes.includes("array");

for await (const config of asyncIterable) {
configs.push(normalizeConfigPatterns(config));
configs.push(normalizeConfigPatterns(config, namespacedBasePath, path));
}

@@ -544,6 +587,14 @@

* @param {Array<string>} extraConfigTypes The config types to check.
* @param {string} namespacedBasePath The namespaced base path of the directory to which config base paths are relative.
* @param {PathImpl} path Path-handling implementation
* @returns {Array} A flattened array containing only config objects.
* @throws {TypeError} When a config function returns a function.
*/
function normalizeSync(items, context, extraConfigTypes) {
function normalizeSync(
items,
context,
extraConfigTypes,
namespacedBasePath,
path,
) {
const allowFunctions = extraConfigTypes.includes("function");

@@ -586,3 +637,3 @@ const allowArrays = extraConfigTypes.includes("array");

for (const config of flatTraverse(items)) {
configs.push(normalizeConfigPatterns(config));
configs.push(normalizeConfigPatterns(config, namespacedBasePath, path));
}

@@ -594,52 +645,83 @@

/**
* Converts a given path to a relative path with all separator characters replaced by forward slashes (`"/"`).
* @param {string} fileOrDirPath The unprocessed path to convert.
* @param {string} namespacedBasePath The namespaced base path of the directory to which the calculated path shall be relative.
* @param {PathImpl} path Path-handling implementations.
* @returns {string} A relative path with all separator characters replaced by forward slashes.
*/
function toRelativePath(fileOrDirPath, namespacedBasePath, path) {
const fullPath = path.resolve(namespacedBasePath, fileOrDirPath);
const namespacedFullPath = path.toNamespacedPath(fullPath);
const relativePath = path.relative(namespacedBasePath, namespacedFullPath);
return relativePath.replaceAll(path.SEPARATOR, "/");
}
/**
* Determines if a given file path should be ignored based on the given
* matcher.
* @param {Array<string|((string) => boolean)>} ignores The ignore patterns to check.
* @param {Array<{ basePath?: string, ignores: Array<string|((string) => boolean)>}>} configs Configuration objects containing `ignores`.
* @param {string} filePath The unprocessed file path to check.
* @param {string} relativeFilePath The path of the file to check relative to the base path,
* using forward slash (`"/"`) as a separator.
* @param {Object} [basePathData] Additional data needed to recalculate paths for configuration objects
* that have `basePath` property.
* @param {string} [basePathData.basePath] Namespaced path to witch `relativeFilePath` is relative.
* @param {PathImpl} [basePathData.path] Path-handling implementation.
* @returns {boolean} True if the path should be ignored and false if not.
*/
function shouldIgnorePath(ignores, filePath, relativeFilePath) {
return ignores.reduce((ignored, matcher) => {
if (!ignored) {
if (typeof matcher === "function") {
return matcher(filePath);
function shouldIgnorePath(
configs,
filePath,
relativeFilePath,
{ basePath, path } = {},
) {
let shouldIgnore = false;
for (const config of configs) {
let relativeFilePathToCheck = relativeFilePath;
if (config.basePath) {
relativeFilePathToCheck = toRelativePath(
path.resolve(basePath, relativeFilePath),
config.basePath,
path,
);
if (
relativeFilePathToCheck === "" ||
EXTERNAL_PATH_REGEX.test(relativeFilePathToCheck)
) {
continue;
}
// don't check negated patterns because we're not ignored yet
if (!matcher.startsWith("!")) {
return doMatch(relativeFilePath, matcher);
if (relativeFilePath.endsWith("/")) {
relativeFilePathToCheck += "/";
}
// otherwise we're still not ignored
return false;
}
shouldIgnore = config.ignores.reduce((ignored, matcher) => {
if (!ignored) {
if (typeof matcher === "function") {
return matcher(filePath);
}
// only need to check negated patterns because we're ignored
if (typeof matcher === "string" && matcher.startsWith("!")) {
return !doMatch(relativeFilePath, matcher, {
flipNegate: true,
});
}
// don't check negated patterns because we're not ignored yet
if (!matcher.startsWith("!")) {
return doMatch(relativeFilePathToCheck, matcher);
}
return ignored;
}, false);
}
// otherwise we're still not ignored
return false;
}
/**
* Determines if a given file path is matched by a config based on
* `ignores` only.
* @param {string} filePath The unprocessed file path to check.
* @param {string} relativeFilePath The path of the file to check relative to the base path,
* using forward slash (`"/"`) as a separator.
* @param {Object} config The config object to check.
* @returns {boolean} True if the file path is matched by the config,
* false if not.
*/
function pathMatchesIgnores(filePath, relativeFilePath, config) {
return (
Object.keys(config).filter(key => !META_FIELDS.has(key)).length > 1 &&
!shouldIgnorePath(config.ignores, filePath, relativeFilePath)
);
// only need to check negated patterns because we're ignored
if (typeof matcher === "string" && matcher.startsWith("!")) {
return !doMatch(relativeFilePathToCheck, matcher, {
flipNegate: true,
});
}
return ignored;
}, shouldIgnore);
}
return shouldIgnore;
}

@@ -687,4 +769,8 @@

if (filePathMatchesPattern && config.ignores) {
/*
* Pass config object without `basePath`, because `relativeFilePath` is already
* calculated as relative to it.
*/
filePathMatchesPattern = !shouldIgnorePath(
config.ignores,
[{ ignores: config.ignores }],
filePath,

@@ -759,16 +845,2 @@ relativeFilePath,

/**
* Converts a given path to a relative path with all separator characters replaced by forward slashes (`"/"`).
* @param {string} fileOrDirPath The unprocessed path to convert.
* @param {string} namespacedBasePath The namespaced base path of the directory to which the calculated path shall be relative.
* @param {PathImpl} path Path-handling implementations.
* @returns {string} A relative path with all separator characters replaced by forward slashes.
*/
function toRelativePath(fileOrDirPath, namespacedBasePath, path) {
const fullPath = path.resolve(namespacedBasePath, fileOrDirPath);
const namespacedFullPath = path.toNamespacedPath(fullPath);
const relativePath = path.relative(namespacedBasePath, namespacedFullPath);
return relativePath.replaceAll(path.SEPARATOR, "/");
}
//------------------------------------------------------------------------------

@@ -954,3 +1026,3 @@ // Public Interface

* globbing operation to be faster.
* @returns {string[]} An array of string patterns and functions to be ignored.
* @returns {Object[]} An array of config objects representing global ignores.
*/

@@ -982,3 +1054,3 @@ get ignores() {

) {
result.push(...config.ignores);
result.push(config);
}

@@ -1014,2 +1086,4 @@ }

this.extraConfigTypes,
this.#namespacedBasePath,
this.#path,
);

@@ -1044,2 +1118,4 @@ this.length = 0;

this.extraConfigTypes,
this.#namespacedBasePath,
this.#path,
);

@@ -1109,3 +1185,3 @@ this.length = 0;

const relativeFilePath = toRelativePath(
const relativeToBaseFilePath = toRelativePath(
filePath,

@@ -1116,3 +1192,3 @@ this.#namespacedBasePath,

if (EXTERNAL_PATH_REGEX.test(relativeFilePath)) {
if (EXTERNAL_PATH_REGEX.test(relativeToBaseFilePath)) {
debug(`No config for file ${filePath} outside of base path`);

@@ -1136,3 +1212,8 @@

if (shouldIgnorePath(this.ignores, filePath, relativeFilePath)) {
if (
shouldIgnorePath(this.ignores, filePath, relativeToBaseFilePath, {
basePath: this.#namespacedBasePath,
path: this.#path,
})
) {
debug(`Ignoring ${filePath} based on file pattern`);

@@ -1152,2 +1233,17 @@

this.forEach((config, index) => {
const relativeFilePath = config.basePath
? toRelativePath(
this.#path.resolve(this.#namespacedBasePath, filePath),
config.basePath,
this.#path,
)
: relativeToBaseFilePath;
if (config.basePath && EXTERNAL_PATH_REGEX.test(relativeFilePath)) {
debug(
`Skipped config found for ${filePath} (based on config's base path: ${config.basePath}`,
);
return;
}
if (!config.files) {

@@ -1160,13 +1256,33 @@ if (!config.ignores) {

if (pathMatchesIgnores(filePath, relativeFilePath, config)) {
if (
Object.keys(config).filter(key => !META_FIELDS.has(key))
.length === 1
) {
debug(
`Matching config found for ${filePath} (based on ignores: ${config.ignores})`,
`Skipped config found for ${filePath} (global ignores)`,
);
matchingConfigIndices.push(index);
return;
}
/*
* Pass config object without `basePath`, because `relativeFilePath` is already
* calculated as relative to it.
*/
if (
shouldIgnorePath(
[{ ignores: config.ignores }],
filePath,
relativeFilePath,
)
) {
debug(
`Skipped config found for ${filePath} (based on ignores: ${config.ignores})`,
);
return;
}
debug(
`Skipped config found for ${filePath} (based on ignores: ${config.ignores})`,
`Matching config found for ${filePath} (based on ignores: ${config.ignores})`,
);
matchingConfigIndices.push(index);
return;

@@ -1400,2 +1516,6 @@ }

relativeDirectoryToCheck,
{
basePath: this.#namespacedBasePath,
path: this.#path,
},
);

@@ -1402,0 +1522,0 @@

@@ -7,2 +7,6 @@ /**

/**
* The base path for files and ignores.
*/
basePath?: string;
/**
* The files to include.

@@ -9,0 +13,0 @@ */

@@ -8,2 +8,7 @@ /**

/**
* The base path for files and ignores.
*/
basePath?: string;
/**
* The files to include.

@@ -10,0 +15,0 @@ */

{
"name": "@eslint/config-array",
"version": "0.20.1",
"version": "0.21.0",
"description": "General purpose glob-based configuration matching.",

@@ -58,7 +58,3 @@ "author": "Nicholas C. Zakas",

"@types/minimatch": "^3.0.5",
"c8": "^9.1.0",
"mocha": "^10.4.0",
"rollup": "^4.16.2",
"rollup-plugin-copy": "^3.5.0",
"typescript": "^5.4.5"
"rollup-plugin-copy": "^3.5.0"
},

@@ -65,0 +61,0 @@ "engines": {

@@ -79,3 +79,3 @@ # Config Array

This example reads in an object or array from `my.config.js` and passes it into the `ConfigArray` constructor as the first argument. The second argument is an object specifying the `basePath` (the directory in which `my.config.js` is found) and a `schema` to define the additional properties of a config object beyond `files`, `ignores`, and `name`.
This example reads in an object or array from `my.config.js` and passes it into the `ConfigArray` constructor as the first argument. The second argument is an object specifying the `basePath` (the directory in which `my.config.js` is found) and a `schema` to define the additional properties of a config object beyond `files`, `ignores`, `basePath`, and `name`.

@@ -169,2 +169,12 @@ ### Specifying a Schema

},
// specific settings for files inside `src` directory
{
name: "Source files",
basePath: "src",
files: ["**/*"],
settings: {
source: true,
},
},
];

@@ -289,3 +299,3 @@ ```

- If a filename is not an absolute path, it will be resolved relative to the base path directory.
- The returned config object never has `files`, `ignores`, or `name` properties; the only properties on the object will be the other configuration options specified.
- The returned config object never has `files`, `ignores`, `basePath`, or `name` properties; the only properties on the object will be the other configuration options specified.
- The config array caches configs, so subsequent calls to `getConfig()` with the same filename will return in a fast lookup rather than another calculation.

@@ -292,0 +302,0 @@ - A config will only be generated if the filename matches an entry in a `files` key. A config will not be generated without matching a `files` key (configs without a `files` key are only applied when another config with a `files` key is applied; configs without `files` are never applied on their own). Any config with a `files` key entry that is `*` or ends with `/**` or `/*` will only be applied if another entry in the same `files` key matches or another config matches.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet