Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmyn committed Jan 10, 2025
0 parents commit 7f23960
Show file tree
Hide file tree
Showing 10 changed files with 593 additions and 0 deletions.
39 changes: 39 additions & 0 deletions .gitignore
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/
4 changes: 4 additions & 0 deletions .husky/pre-commit
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
7 changes: 7 additions & 0 deletions .prettierignore
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
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": true,
"bracketSpacing": false,
"printWidth": 100,
"trailingComma": "none"
}
159 changes: 159 additions & 0 deletions README.md
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
28 changes: 28 additions & 0 deletions eslint.config.js
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
}
}
];
15 changes: 15 additions & 0 deletions lib/index.js
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'
}
}
}
};
92 changes: 92 additions & 0 deletions lib/rules/enforce-package-type.js
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'
});
}
}
};
}
};
Loading

0 comments on commit 7f23960

Please sign in to comment.