-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7f23960
Showing
10 changed files
with
593 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Dependencies | ||
node_modules/ | ||
package-lock.json | ||
yarn.lock | ||
pnpm-lock.yaml | ||
|
||
# Build outputs | ||
dist/ | ||
build/ | ||
coverage/ | ||
|
||
# IDE and editor files | ||
.idea/ | ||
.vscode/ | ||
*.swp | ||
*.swo | ||
.DS_Store | ||
|
||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
lerna-debug.log* | ||
|
||
# Environment variables | ||
.env | ||
.env.local | ||
.env.*.local | ||
|
||
# Test coverage | ||
coverage/ | ||
.nyc_output/ | ||
|
||
# Temporary files | ||
*.tmp | ||
*.temp | ||
.cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env sh | ||
. "$(dirname -- "$0")/_/husky.sh" | ||
|
||
npx lint-staged |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
node_modules/ | ||
dist/ | ||
coverage/ | ||
.git/ | ||
pnpm-lock.yaml | ||
package-lock.json | ||
yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"singleQuote": true, | ||
"bracketSpacing": false, | ||
"printWidth": 100, | ||
"trailingComma": "none" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# eslint-enforce-package-type | ||
|
||
ESLint plugin to enforce package.json type field to be either "module" or "commonjs". | ||
|
||
## Installation | ||
|
||
```bash | ||
npm install --save-dev eslint-enforce-package-type | ||
``` | ||
|
||
## Usage | ||
|
||
Add the plugin to your ESLint configuration: | ||
|
||
```js | ||
// eslint.config.js | ||
import enforcePackageType from 'eslint-enforce-package-type'; | ||
|
||
export default [ | ||
// Use recommended configuration (enforces "module" by default) | ||
enforcePackageType.configs.recommended, | ||
|
||
// Or configure manually | ||
{ | ||
plugins: { | ||
'enforce-package-type': enforcePackageType | ||
}, | ||
rules: { | ||
// Default to 'module' | ||
'enforce-package-type/enforce-package-type': 'error', | ||
|
||
// Or enforce 'commonjs' | ||
'enforce-package-type/enforce-package-type': ['error', {enforceType: 'commonjs'}] | ||
} | ||
} | ||
]; | ||
``` | ||
|
||
## Rule Details | ||
|
||
This rule enforces that the `type` field in package.json is set to either "module" or "commonjs". | ||
|
||
### Options | ||
|
||
The rule accepts an options object with the following properties: | ||
|
||
- `enforceType`: The type to enforce ("module" or "commonjs"). Defaults to "module". | ||
|
||
### Examples | ||
|
||
#### Valid | ||
|
||
```json | ||
{ | ||
"name": "my-package", | ||
"type": "module" | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"name": "my-package", | ||
"type": "commonjs" | ||
} | ||
``` | ||
|
||
#### Invalid | ||
|
||
```json | ||
{ | ||
"name": "my-package" | ||
// Missing type field | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"name": "my-package", | ||
"type": "commonjs" // When enforceType is set to "module" | ||
} | ||
``` | ||
|
||
## Features | ||
|
||
- ✅ Enforces "type" field in package.json | ||
- ✅ Supports both "module" and "commonjs" types | ||
- ✅ Provides auto-fix functionality | ||
- ✅ Configurable default type | ||
- ✅ Ignores package.json files in node_modules | ||
- ✅ Works with ESLint flat config | ||
|
||
## Development | ||
|
||
### Prerequisites | ||
|
||
- Node.js >= 18 | ||
- npm >= 9 | ||
|
||
### Setup | ||
|
||
```bash | ||
# Clone the repository | ||
git clone https://github.com/MONEI/eslint-enforce-package-type.git | ||
cd eslint-enforce-package-type | ||
|
||
# Install dependencies | ||
npm install | ||
|
||
# Run tests | ||
npm test | ||
|
||
# Run tests in watch mode | ||
npm run test:watch | ||
|
||
# Lint files | ||
npm run lint | ||
|
||
# Format files | ||
npm run format | ||
``` | ||
|
||
### Git Hooks | ||
|
||
This project uses [husky](https://github.com/typicode/husky) and [lint-staged](https://github.com/okonet/lint-staged) to ensure code quality before commits: | ||
|
||
- All staged files are formatted with Prettier | ||
- JavaScript files are linted with ESLint | ||
- All tests must pass | ||
|
||
These checks run automatically before each commit. | ||
|
||
### Testing | ||
|
||
Tests are written using Vitest and follow ESLint's testing conventions. Run tests with: | ||
|
||
```bash | ||
npm test | ||
``` | ||
|
||
The test suite includes: | ||
|
||
- Rule metadata validation | ||
- Basic functionality tests | ||
- Edge cases (malformed JSON, invalid types) | ||
- Auto-fix functionality tests | ||
|
||
### Contributing | ||
|
||
1. Fork the repository | ||
2. Create your feature branch (`git checkout -b feature/amazing-feature`) | ||
3. Make your changes | ||
4. Run tests and linting | ||
5. Commit your changes (`git commit -m 'Add amazing feature'`) | ||
6. Push to the branch (`git push origin feature/amazing-feature`) | ||
7. Open a Pull Request | ||
|
||
## License | ||
|
||
MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import js from '@eslint/js'; | ||
|
||
export default [ | ||
js.configs.recommended, | ||
{ | ||
files: ['**/*.js'], | ||
languageOptions: { | ||
ecmaVersion: 2022, | ||
sourceType: 'module' | ||
} | ||
}, | ||
{ | ||
files: ['package.json'], | ||
plugins: { | ||
'enforce-package-type': { | ||
rules: { | ||
'enforce-package-type': (await import('./lib/rules/enforce-package-type.js')).default | ||
} | ||
} | ||
}, | ||
rules: { | ||
'enforce-package-type/enforce-package-type': 'error' | ||
}, | ||
languageOptions: { | ||
parser: (await import('jsonc-eslint-parser')).default | ||
} | ||
} | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import enforcePackageType from './rules/enforce-package-type.js'; | ||
|
||
export default { | ||
rules: { | ||
'enforce-package-type': enforcePackageType | ||
}, | ||
configs: { | ||
recommended: { | ||
plugins: ['enforce-package-type'], | ||
rules: { | ||
'enforce-package-type/enforce-package-type': 'error' | ||
} | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/** @type {import('eslint').Rule.RuleModule} */ | ||
export default { | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: 'Enforce package.json type field to be either "module" or "commonjs"', | ||
recommended: true, | ||
url: 'https://github.com/MONEI/eslint-enforce-package-type/blob/main/docs/rules/enforce-package-type.md' | ||
}, | ||
fixable: 'code', | ||
schema: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
enforceType: { | ||
enum: ['module', 'commonjs'] | ||
} | ||
}, | ||
additionalProperties: false | ||
} | ||
], | ||
messages: { | ||
missingType: 'Missing "type" field in package.json', | ||
invalidType: '"type" field must be "{{ expected }}", but found "{{ actual }}"' | ||
} | ||
}, | ||
|
||
create(context) { | ||
return { | ||
Program(node) { | ||
// Only process package.json files | ||
const filename = context.getFilename(); | ||
if ( | ||
!filename.endsWith('package.json') || | ||
filename === 'not-package.json' || | ||
filename.includes('node_modules') | ||
) { | ||
return; | ||
} | ||
|
||
try { | ||
const options = context.options[0] || {}; | ||
const enforceType = options.enforceType || 'module'; | ||
const source = context.getSourceCode().getText(); | ||
|
||
// Try to parse package.json content | ||
let packageJson; | ||
try { | ||
packageJson = JSON.parse(source); | ||
} catch { | ||
// If JSON is invalid, report missing type but don't try to fix | ||
context.report({ | ||
node, | ||
messageId: 'missingType' | ||
}); | ||
return; | ||
} | ||
|
||
if (!packageJson.type) { | ||
context.report({ | ||
node, | ||
messageId: 'missingType', | ||
fix(fixer) { | ||
const newPackageJson = {...packageJson, type: enforceType}; | ||
return fixer.replaceText(node, JSON.stringify(newPackageJson, null, 2)); | ||
} | ||
}); | ||
} else if (packageJson.type !== enforceType) { | ||
context.report({ | ||
node, | ||
messageId: 'invalidType', | ||
data: { | ||
expected: enforceType, | ||
actual: packageJson.type | ||
}, | ||
fix(fixer) { | ||
const newPackageJson = {...packageJson, type: enforceType}; | ||
return fixer.replaceText(node, JSON.stringify(newPackageJson, null, 2)); | ||
} | ||
}); | ||
} | ||
} catch { | ||
// Handle any other unexpected errors | ||
context.report({ | ||
node, | ||
messageId: 'missingType' | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
}; |
Oops, something went wrong.