From c55b291145b2fa0d161bf0e881a80c38ae870517 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 25 Mar 2024 16:48:11 +0530 Subject: [PATCH 01/12] feat/issue-1398: added support for custom configuration --- lib/makeCmdTasks.js | 51 +++++++++++++++++++++++++++++++++----------- lib/resolveTaskFn.js | 2 +- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index 218964db0..40f2a695a 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -1,7 +1,8 @@ import debug from 'debug' import { configurationError } from './messages.js' -import { resolveTaskFn } from './resolveTaskFn.js' +import { makeErr, resolveTaskFn } from './resolveTaskFn.js' +import { getInitialState } from './state.js' const debugLog = debug('lint-staged:makeCmdTasks') @@ -31,20 +32,44 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos const resolvedArray = Array.isArray(resolved) ? resolved : [resolved] // Wrap non-array command as array for (const command of resolvedArray) { - // If the function linter didn't return string | string[] it won't work - // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times - if (isFn && typeof command !== 'string') { - throw new Error( - configurationError( - '[Function]', - 'Function task should return a string or an array of strings', - resolved + if (typeof command === 'object') { + if ( + typeof command.title === 'string' && + typeof command.command === 'string' && + typeof command.task === 'function' + ) { + const task = async (ctx = getInitialState()) => { + try { + await command.task() + } catch (e) { + throw makeErr(command.title, e, ctx) + } + } + cmdTasks.push({ + title: command.title, + command: command.command, + task, + }) + } else { + throw new Error( + configurationError('[Function]', 'Function task should be in proper format', resolved) ) - ) + } + } else { + // If the function linter didn't return string | string[] it won't work + // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times + if (isFn && typeof command !== 'string') { + throw new Error( + configurationError( + '[Function]', + 'Function task should return a string or an array of strings', + resolved + ) + ) + } + const task = resolveTaskFn({ command, cwd, files, gitDir, isFn, shell, verbose }) + cmdTasks.push({ title: command, command, task }) } - - const task = resolveTaskFn({ command, cwd, files, gitDir, isFn, shell, verbose }) - cmdTasks.push({ title: command, command, task }) } } diff --git a/lib/resolveTaskFn.js b/lib/resolveTaskFn.js index 95e2349d3..3ff65a575 100644 --- a/lib/resolveTaskFn.js +++ b/lib/resolveTaskFn.js @@ -108,7 +108,7 @@ const interruptExecutionOnError = (ctx, execaChildProcess) => { * @param {Object} ctx * @returns {Error} */ -const makeErr = (command, result, ctx) => { +export const makeErr = (command, result, ctx) => { ctx.errors.add(TaskError) // https://nodejs.org/api/events.html#error-events From 2626c43b02a9dd260ca4c5d4feecbaad2e850793 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 25 Mar 2024 18:20:22 +0530 Subject: [PATCH 02/12] feat: added check to proceed only with not null/undefined --- lib/makeCmdTasks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index 40f2a695a..e764b1c4f 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -32,7 +32,7 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos const resolvedArray = Array.isArray(resolved) ? resolved : [resolved] // Wrap non-array command as array for (const command of resolvedArray) { - if (typeof command === 'object') { + if (command && typeof command === 'object') { if ( typeof command.title === 'string' && typeof command.command === 'string' && From da2ede0bfdd2ce08eef275aee0e074ee6940b803 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 25 Mar 2024 18:24:37 +0530 Subject: [PATCH 03/12] feat: added check to proceed only if is Function --- lib/makeCmdTasks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index e764b1c4f..e15a14da5 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -32,7 +32,7 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos const resolvedArray = Array.isArray(resolved) ? resolved : [resolved] // Wrap non-array command as array for (const command of resolvedArray) { - if (command && typeof command === 'object') { + if (isFn && command && typeof command === 'object') { if ( typeof command.title === 'string' && typeof command.command === 'string' && From 64c1382c91894bb105965b708a47c85581f7d4a0 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 28 Mar 2024 16:27:49 +0530 Subject: [PATCH 04/12] feat/issue-1398: updated the condition to return the errors early --- lib/makeCmdTasks.js | 23 +++++++++++++---------- test/unit/makeCmdTasks.spec.js | 4 ++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index e15a14da5..2c53299be 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -32,7 +32,17 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos const resolvedArray = Array.isArray(resolved) ? resolved : [resolved] // Wrap non-array command as array for (const command of resolvedArray) { - if (isFn && command && typeof command === 'object') { + // If the function linter didn't return string | string[] | object it won't work + // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times + if ((isFn && typeof command !== 'string' && typeof command !== 'object') || !command) { + throw new Error( + configurationError( + '[Function]', + 'Function task should return a string or an array of strings or an object', + resolved + ) + ) + } else if (isFn && typeof command === 'object') { if ( typeof command.title === 'string' && typeof command.command === 'string' && @@ -51,22 +61,15 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos task, }) } else { - throw new Error( - configurationError('[Function]', 'Function task should be in proper format', resolved) - ) - } - } else { - // If the function linter didn't return string | string[] it won't work - // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times - if (isFn && typeof command !== 'string') { throw new Error( configurationError( '[Function]', - 'Function task should return a string or an array of strings', + 'Function task should return object with title, command and task where title or command should be string and task should be function', resolved ) ) } + } else { const task = resolveTaskFn({ command, cwd, files, gitDir, isFn, shell, verbose }) cmdTasks.push({ title: command, command, task }) } diff --git a/test/unit/makeCmdTasks.spec.js b/test/unit/makeCmdTasks.spec.js index 71cfec165..a5bd3230a 100644 --- a/test/unit/makeCmdTasks.spec.js +++ b/test/unit/makeCmdTasks.spec.js @@ -112,14 +112,14 @@ describe('makeCmdTasks', () => { expect(res[0].title).toEqual('test') }) - it("should throw when function task doesn't return string | string[]", async () => { + it("should throw when function task doesn't return string | string[] | object", async () => { await expect(makeCmdTasks({ commands: () => null, gitDir, files: ['test.js'] })).rejects .toThrowErrorMatchingInlineSnapshot(` "✖ Validation Error: Invalid value for '[Function]': null - Function task should return a string or an array of strings" + Function task should return a string or an array of strings or an object" `) }) From e769fd3dad63e932a3d4bdf67560539f60a66bce Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 2 Apr 2024 09:55:14 +0530 Subject: [PATCH 05/12] feat/issue-1398: removed command field from object requirement --- lib/makeCmdTasks.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index 2c53299be..9b93124ab 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -43,11 +43,7 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos ) ) } else if (isFn && typeof command === 'object') { - if ( - typeof command.title === 'string' && - typeof command.command === 'string' && - typeof command.task === 'function' - ) { + if (typeof command.title === 'string' && typeof command.task === 'function') { const task = async (ctx = getInitialState()) => { try { await command.task() @@ -57,14 +53,13 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos } cmdTasks.push({ title: command.title, - command: command.command, task, }) } else { throw new Error( configurationError( '[Function]', - 'Function task should return object with title, command and task where title or command should be string and task should be function', + 'Function task should return object with title and task where title should be string and task should be function', resolved ) ) From 0682aff361bf294465d04c2456c395d317dda18c Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 2 Apr 2024 13:29:04 +0530 Subject: [PATCH 06/12] feat/issue-1398: refactored makeCmdTasks function and added unit test cases --- lib/makeCmdTasks.js | 136 +++++++++++++++++++++++---------- test/unit/makeCmdTasks.spec.js | 42 ++++++++++ 2 files changed, 136 insertions(+), 42 deletions(-) diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index 9b93124ab..1025d5455 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -6,6 +6,92 @@ import { getInitialState } from './state.js' const debugLog = debug('lint-staged:makeCmdTasks') +/** + * Returns whether the command is a function or not and the resolved command + * + * @param {Function|string} cmd + * @param {Array} files + * @returns {Object} Object containing whether the command is a function and the resolved command + */ +const getResolvedCommand = async (cmd, files) => { + // command function may return array of commands that already include `stagedFiles` + const isFn = typeof cmd === 'function' + /** Pass copy of file list to prevent mutation by function from config file. */ + const resolved = isFn ? await cmd([...files]) : cmd + return { resolved, isFn } +} + +/** + * Validates whether a command is a function and if the command is valid + * + * @param {string|object} command + * @param {boolean} isFn + * @param {string|object} resolved + * @throws {Error} If the command is not valid + */ +const validateCommand = (command, isFn, resolved) => { + if ((isFn && typeof command !== 'string' && typeof command !== 'object') || !command) { + throw new Error( + configurationError( + '[Function]', + 'Function task should return a string or an array of strings or an object', + resolved + ) + ) + } +} + +/** + * Handles function configuration and pushes the tasks into the task array + * + * @param {object} command + * @param {Array} cmdTasks + * @param {string|object} resolved + * @throws {Error} If the function configuration is not valid + */ +const handleFunctionConfig = (command, cmdTasks, resolved) => { + if (typeof command.title === 'string' && typeof command.task === 'function') { + const task = async (ctx = getInitialState()) => { + try { + await command.task() + } catch (e) { + throw makeErr(command.title, e, ctx) + } + } + cmdTasks.push({ + title: command.title, + task, + }) + } else { + throw new Error( + configurationError( + '[Function]', + 'Function task should return object with title and task where title should be string and task should be function', + resolved + ) + ) + } +} + +/** + * Handles regular configuration and pushes the tasks into the task array + * + * @param {object} params + * @param {Array} cmdTasks + */ +const handleRegularConfig = ({ command, cwd, files, gitDir, isFn, shell, verbose }, cmdTasks) => { + const task = resolveTaskFn({ command, cwd, files, gitDir, isFn, shell, verbose }) + cmdTasks.push({ title: command, command, task }) +} + +/** + * Ensures the input is an array. If the input is not an array, it wraps the input inside an array. + * + * @param {Array|string|object} input + * @returns {Array} Returns the input as an array + */ +const ensureArray = (input) => (Array.isArray(input) ? input : [input]) + /** * Creates and returns an array of listr tasks which map to the given commands. * @@ -19,54 +105,20 @@ const debugLog = debug('lint-staged:makeCmdTasks') */ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbose }) => { debugLog('Creating listr tasks for commands %o', commands) - const commandArray = Array.isArray(commands) ? commands : [commands] + const commandArray = ensureArray(commands) const cmdTasks = [] for (const cmd of commandArray) { - // command function may return array of commands that already include `stagedFiles` - const isFn = typeof cmd === 'function' - - /** Pass copy of file list to prevent mutation by function from config file. */ - const resolved = isFn ? await cmd([...files]) : cmd - - const resolvedArray = Array.isArray(resolved) ? resolved : [resolved] // Wrap non-array command as array + const { resolved, isFn } = await getResolvedCommand(cmd, files) + const resolvedArray = ensureArray(resolved) for (const command of resolvedArray) { - // If the function linter didn't return string | string[] | object it won't work - // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times - if ((isFn && typeof command !== 'string' && typeof command !== 'object') || !command) { - throw new Error( - configurationError( - '[Function]', - 'Function task should return a string or an array of strings or an object', - resolved - ) - ) - } else if (isFn && typeof command === 'object') { - if (typeof command.title === 'string' && typeof command.task === 'function') { - const task = async (ctx = getInitialState()) => { - try { - await command.task() - } catch (e) { - throw makeErr(command.title, e, ctx) - } - } - cmdTasks.push({ - title: command.title, - task, - }) - } else { - throw new Error( - configurationError( - '[Function]', - 'Function task should return object with title and task where title should be string and task should be function', - resolved - ) - ) - } + validateCommand(command, isFn, resolved) + + if (isFn && typeof command === 'object') { + handleFunctionConfig(command, cmdTasks, resolved) } else { - const task = resolveTaskFn({ command, cwd, files, gitDir, isFn, shell, verbose }) - cmdTasks.push({ title: command, command, task }) + handleRegularConfig({ command, cwd, files, gitDir, isFn, shell, verbose }, cmdTasks) } } } diff --git a/test/unit/makeCmdTasks.spec.js b/test/unit/makeCmdTasks.spec.js index a5bd3230a..1e67682dd 100644 --- a/test/unit/makeCmdTasks.spec.js +++ b/test/unit/makeCmdTasks.spec.js @@ -143,4 +143,46 @@ describe('makeCmdTasks', () => { /** ...but the original file list was not mutated */ expect(files).toEqual(['test.js']) }) + + it('should work with function task returning an object with title and task', async () => { + const res = await makeCmdTasks({ + commands: () => ({ title: 'test', task: () => {} }), + gitDir, + files: ['test.js'], + }) + expect(res.length).toBe(1) + expect(res[0].title).toEqual('test') + expect(typeof res[0].task).toBe('function') + }) + + it('should throw error when function task returns object without proper title and task', async () => { + await expect( + makeCmdTasks({ + commands: () => ({ title: 'test' }), // Missing task function + gitDir, + files: ['test.js'], + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "✖ Validation Error: + + Invalid value for '[Function]': { title: 'test' } + + Function task should return object with title and task where title should be string and task should be function" + `) + }) + + it('should throw error when function task fails', async () => { + const failingTask = () => { + throw new Error('Task failed') + } + + const res = await makeCmdTasks({ + commands: () => ({ title: 'test', task: failingTask }), + gitDir, + files: ['test.js'], + }) + + const [linter] = res + await expect(linter.task()).rejects.toThrow() + }) }) From eb8dd338bcdb0830c24ef4bee0b4f1348b7f3a71 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 3 Apr 2024 11:01:10 +0530 Subject: [PATCH 07/12] v15.2.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2213df9b..026c812a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lint-staged", - "version": "15.2.2", + "version": "15.2.3", "description": "Lint files staged by git", "license": "MIT", "repository": "https://github.com/okonet/lint-staged", From f27d888fb29fa07dda7c9d735ca41bc2234a360f Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 3 Apr 2024 11:01:11 +0530 Subject: [PATCH 08/12] chore(changeset): release --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index d019fcd23..5b35e6c4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lint-staged", - "version": "15.2.2", + "version": "15.2.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lint-staged", - "version": "15.2.2", + "version": "15.2.3", "license": "MIT", "dependencies": { "chalk": "5.3.0", From 6d82f42ebb7f4f06bb23c55ead67a29d33eb47ea Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 5 Apr 2024 12:59:49 +0530 Subject: [PATCH 09/12] Revert "v15.2.3" This reverts commit eb8dd338bcdb0830c24ef4bee0b4f1348b7f3a71. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 026c812a5..b2213df9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lint-staged", - "version": "15.2.3", + "version": "15.2.2", "description": "Lint files staged by git", "license": "MIT", "repository": "https://github.com/okonet/lint-staged", From 20c3f864cee51e5ee77a88ca9a7f05de77ad955c Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 5 Apr 2024 13:07:24 +0530 Subject: [PATCH 10/12] feat: removed version related changes from package.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b35e6c4f..d019fcd23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lint-staged", - "version": "15.2.3", + "version": "15.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lint-staged", - "version": "15.2.3", + "version": "15.2.2", "license": "MIT", "dependencies": { "chalk": "5.3.0", From d3f72e05f8f0bf1e6c52a35de2060207603a67b9 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 11 Jul 2024 16:44:38 +0530 Subject: [PATCH 11/12] feat: updated the logic to accept the object task --- lib/makeCmdTasks.js | 12 +++++----- lib/validateConfig.js | 19 +++++++++++++-- .../__snapshots__/validateConfig.spec.js.snap | 10 +++++++- test/unit/validateConfig.spec.js | 24 +++++++++++++++++++ 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index 1025d5455..3df5f1cbb 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -45,15 +45,15 @@ const validateCommand = (command, isFn, resolved) => { * Handles function configuration and pushes the tasks into the task array * * @param {object} command + * @param {Array} files * @param {Array} cmdTasks - * @param {string|object} resolved * @throws {Error} If the function configuration is not valid */ -const handleFunctionConfig = (command, cmdTasks, resolved) => { +const handleFunctionConfig = (command, files, cmdTasks) => { if (typeof command.title === 'string' && typeof command.task === 'function') { const task = async (ctx = getInitialState()) => { try { - await command.task() + await command.task(files, ctx) } catch (e) { throw makeErr(command.title, e, ctx) } @@ -67,7 +67,7 @@ const handleFunctionConfig = (command, cmdTasks, resolved) => { configurationError( '[Function]', 'Function task should return object with title and task where title should be string and task should be function', - resolved + command ) ) } @@ -115,8 +115,8 @@ export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbos for (const command of resolvedArray) { validateCommand(command, isFn, resolved) - if (isFn && typeof command === 'object') { - handleFunctionConfig(command, cmdTasks, resolved) + if (typeof command === 'object') { + handleFunctionConfig(command, files, cmdTasks) } else { handleRegularConfig({ command, cwd, files, gitDir, isFn, shell, verbose }, cmdTasks) } diff --git a/lib/validateConfig.js b/lib/validateConfig.js index aca8552c8..e7d3b6bc7 100644 --- a/lib/validateConfig.js +++ b/lib/validateConfig.js @@ -70,12 +70,27 @@ export const validateConfigLogic = (config, configPath, logger) => { (!Array.isArray(task) || task.some((item) => typeof item !== 'string' && typeof item !== 'function')) && typeof task !== 'string' && - typeof task !== 'function' + typeof task !== 'function' && + typeof task !== 'object' ) { errors.push( configurationError( pattern, - 'Should be a string, a function, or an array of strings and functions.', + 'Should be a string, a function, an object or an array of strings and functions.', + task + ) + ) + } + + if ( + !Array.isArray(task) && + typeof task === 'object' && + (typeof task.title !== 'string' || typeof task.task !== 'function') + ) { + errors.push( + configurationError( + pattern, + 'If the task is an object, it should contain `title` and `task` fields, where `title` should be a string and `task` should be a function.', task ) ) diff --git a/test/unit/__snapshots__/validateConfig.spec.js.snap b/test/unit/__snapshots__/validateConfig.spec.js.snap index 18440227a..335d8bd3f 100644 --- a/test/unit/__snapshots__/validateConfig.spec.js.snap +++ b/test/unit/__snapshots__/validateConfig.spec.js.snap @@ -5,11 +5,19 @@ exports[`validateConfig should throw and should print validation errors for inva Invalid value for 'foo': false - Should be a string, a function, or an array of strings and functions." + Should be a string, a function, an object or an array of strings and functions." `; exports[`validateConfig should throw and should print validation errors for invalid config 1 1`] = `"Configuration should be an object or a function"`; +exports[`validateConfig should throw and should print validation errors for invalid object config 1`] = ` +"✖ Validation Error: + + Invalid value for '*.js': { title: 'Running a custom task' } + + If the task is an object, it should contain \`title\` and \`task\` fields, where \`title\` should be a string and \`task\` should be a function." +`; + exports[`validateConfig should throw for empty config 1`] = `"Configuration should not be empty"`; exports[`validateConfig should throw when detecting deprecated advanced configuration 1`] = ` diff --git a/test/unit/validateConfig.spec.js b/test/unit/validateConfig.spec.js index 6d10cdcbd..03fb28b07 100644 --- a/test/unit/validateConfig.spec.js +++ b/test/unit/validateConfig.spec.js @@ -25,6 +25,30 @@ describe('validateConfig', () => { expect(() => validateConfig(invalidConfig, configPath, logger)).toThrowErrorMatchingSnapshot() }) + it('should throw and should print validation errors for invalid object config', () => { + const invalidConfig = { + '*.js': { + title: 'Running a custom task', + }, + } + + expect(() => validateConfig(invalidConfig, configPath, logger)).toThrowErrorMatchingSnapshot() + }) + + it('should not throw and should print nothing for valid object config', () => { + const validObjectConfig = { + '*.js': { + title: 'Running a custom task', + task: async (files) => { + console.log(files) + }, + }, + } + + expect(() => validateConfig(validObjectConfig, configPath, logger)).not.toThrow() + expect(logger.printHistory()).toEqual('') + }) + it('should throw for empty config', () => { expect(() => validateConfig({}, configPath, logger)).toThrowErrorMatchingSnapshot() }) From 907afa5b95e903bcf6732798629bf7a38add904e Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 11 Jul 2024 17:02:03 +0530 Subject: [PATCH 12/12] feat: added changeset --- .changeset/thin-onions-attack.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/thin-onions-attack.md diff --git a/.changeset/thin-onions-attack.md b/.changeset/thin-onions-attack.md new file mode 100644 index 000000000..8c2678a5d --- /dev/null +++ b/.changeset/thin-onions-attack.md @@ -0,0 +1,5 @@ +--- +'lint-staged': minor +--- + +added support for custom configuration