53 Commits

Author SHA1 Message Date
renovate[bot]
6f3f176ec5 fix(deps): update dependency eslint-plugin-perfectionist to v2 2023-09-06 13:19:48 +00:00
Guz013
4a1f38ff24 feat: new rules inspired by standardjs 2023-09-05 12:22:20 -03:00
Guz013
2e1914c733 feat: security related rules 2023-09-04 20:56:00 -03:00
Guz013
dcce924286 feat: add more NodeJS-specific rules 2023-09-04 18:42:15 -03:00
Guz013
8749e51c13 fix: 🐛 'off' rule level being overridden 2023-09-04 17:26:26 -03:00
Guz013
853b868a24 fix: 🐛 no-extra-parens conflicts 2023-09-04 17:25:24 -03:00
Guz013
f4e52b991c feat: default variant for the configs 2023-09-04 17:12:43 -03:00
Guz
15765c8e73 Merge pull request #18 from LoredDev/13-new-config-files
fix: missing commits
2023-09-04 16:51:05 -03:00
Guz
b41d515e7f chore: merge pull request #17
chore(deps): update actions/checkout action to v4
2023-09-04 16:46:07 -03:00
renovate[bot]
3ccab1d5b2 chore(deps): update actions/checkout action to v4 2023-09-04 19:44:33 +00:00
Guz
47eb42405b chore: merge pull request #16
feat/refactor: new configuration files
2023-09-04 16:44:16 -03:00
Guz013
d8fcf7bfe3 feat: group and sort imports rule 2023-09-04 16:43:14 -03:00
Guz013
71442056ce fix: 🐛 add globals to the core config 2023-09-04 16:41:32 -03:00
Guz013
da3429a868 chore: 🔧 add changeset 2023-09-04 16:38:38 -03:00
Guz013
2ca40e1ef1 fix: 🐛 misc fixes
Fixed problems config not being exported and used in the presets and
some rules not configured properly.
2023-09-02 20:33:13 -03:00
Guz013
3434620ff1 docs: 📚️ add docs to all files
Added documentation to all files, configs and presets. Following the new
strict documentation rules.
2023-09-02 20:31:57 -03:00
Guz013
f874ed622e feat: defineConfig helper function 2023-09-02 20:25:32 -03:00
Guz013
ac7c70e81c feat: rules variations 2023-09-02 08:19:33 -03:00
Guz013
ef6b399bb7 feat: eslint-plugin-perfectionist rules 2023-09-02 06:46:32 -03:00
Guz013
8ec97a8b66 feat: add eslint's max-len rule 2023-09-02 06:42:28 -03:00
Guz013
a2cc881053 feat: jsdoc rules and remove old config 2023-09-02 06:20:45 -03:00
Guz013
10c4155283 fix: 🐛 typescript-eslint missing formatting rules 2023-09-02 05:47:00 -03:00
Guz013
da8d4312a0 feat: eslint-plugin-import rules 2023-09-02 04:41:18 -03:00
Guz013
5dfa998860 feat: typescript-eslint rules 2023-09-02 03:05:33 -03:00
Guz013
8c86b748ad chore: 🔧 add vscode workspaces 2023-09-01 18:22:48 -03:00
Guz013
fc2613f874 chore!: 💥 🔧 rename @eslegant/config to @eslegant/js
Renamed @eslegant/config to @eslegant/js, reflecting the new structure and
purpose of it just having rules related to javascript and
typescript

Moved said package to the new ./configs/ directory. Packages under the
./packages/ directory will be related to ones that aren't related to
ESLint itself and/or its configuration.
2023-09-01 18:08:56 -03:00
Guz013
a64062f3a5 refactor: ♻️ type declarations and exports 2023-09-01 17:40:15 -03:00
Guz013
b6ebbf9eb8 chore: 🔧 commit overrides file (wip config) 2023-09-01 17:28:37 -03:00
Guz013
dd1d0276b0 feat: 🦄 unicorn rules 2023-09-01 17:27:27 -03:00
Guz013
5a6102ff45 fix: 🐛 config merging/extending 2023-09-01 15:10:37 -03:00
Guz013
8f77f4591f docs: 📚️ add small documentation for each config 2023-08-31 17:30:47 -03:00
Guz013
e20c7e6425 feat: strict preset 2023-08-31 17:12:45 -03:00
Guz013
88412b067d feat: "suggestions" and "problems" rules 2023-08-31 17:11:50 -03:00
Guz013
d5e30078d4 feat: new formatting rules 2023-08-31 13:10:21 -03:00
Guz013
b28c7d2c62 refactor!: 💥 ♻️ restructure the config and presets
Now each config is related to a specific language and or purpose,
having different "flavors" or levels of strictness for them

Presets now have the purpose of simply grouping said configs for easier
of them.

BREAKING CHANGE
2023-08-30 15:31:13 -03:00
Guz013
9043156913 chore: 🔧 fix packages names in changesets 2023-08-29 15:52:34 -03:00
Guz013
3f773f5636 chore: 🔧 add changeset 2023-08-29 15:50:25 -03:00
Guz013
aad3b68f65 ci: 👷 update actions with new name 2023-08-29 15:48:22 -03:00
Guz
c3b34735dd chore: merge #15 branch 2023-08-29 15:41:58 -03:00
Guz013
3c23f0b07c chore: 🔧 rename fixtures packages 2023-08-29 15:41:00 -03:00
Guz013
ff44d8b56e chore: 🔧 update links 2023-08-29 15:39:01 -03:00
Guz013
c1aa5d0235 refactor!: 💥 ♻️ rename packages
Renamed all packages and dependencies from "eslit" to "eslegant"

BREAKING CHANGE
2023-08-29 15:31:57 -03:00
Guz
0be127d50a Merge pull request #14 from LoredDev:improve-cli-api
Move configs array to it's own package
2023-08-29 15:14:47 -03:00
Guz013
c061fdc8cd feat!: 💥 export cli api and remove configs array
Removed the configs array from the cli package, as it now is handled by
the eslegant package.
Exported the Cli class so it can be run by other packages

BREAKING CHANGE
2023-08-29 15:08:29 -03:00
Guz013
26f29009d6 feat: create the eslegant package 2023-08-29 15:06:24 -03:00
Guz013
da21030000 feat: add eslint-plugin-i 2023-08-25 17:31:56 -03:00
Guz013
39d323a3ce ci: 👷 add scope to node setup 2023-08-23 12:09:24 -03:00
Guz013
3e866ee562 ci: 👷 fix npm token 2023-08-23 12:03:16 -03:00
Guz013
3bedc6d1ba ci: 👷 fix missing token 2023-08-23 11:55:11 -03:00
Guz013
64a45cd86a style: 🎨 lint project 2023-08-23 11:50:22 -03:00
Guz013
10e543094f chore(deps): 🔗 update dependencies 2023-08-23 11:45:04 -03:00
Guz013
b257ed000f fix(cli): 🐛 small fixes when prompts are canceled 2023-08-23 11:40:16 -03:00
github-actions[bot]
5537a71bf3 ci: 👷 update dev branch 2023-08-23 14:14:41 +00:00
100 changed files with 3299 additions and 965 deletions

View File

@@ -0,0 +1,12 @@
---
"@eslegant/js": minor
---
Added rules for NodeJS environments, using the eslint-plugin-n and eslint-plugin-security.
The added configs in the `recommended` object helps preventing issues
such as using deprecated or unsupported APIs and warns about security issues.
Building on top of the recommended configs of the plugins.
In the `strict` object they helps making the code more node-explicit, such as importing
global variables (e.g. `process` needs to be imported from `node:process`).

View File

@@ -0,0 +1,5 @@
---
"@eslegant/js": minor
---
Added new ESLint rules inspired by StandardJS.

View File

@@ -0,0 +1,12 @@
---
"@eslegant/js": minor
---
New rules structure.
Now all configs have at least `recommended` and `strict` variants, each having `error`, `warn` and `disabled`/`off` rule levels.
They are exported under the `configs` object, and are separated by purpose.
Presets are now exported under the `presets` object, being a easier way of enabling multiple configs at once.
The package has a more defined purpose, and will be used just for rules/configs related to
JavaScript and TypeScript.

View File

@@ -0,0 +1,6 @@
---
"@eslegant/cli": minor
---
Now the cli exports a API that runs the application and the configs object needs to be passed to the Cli class, this way any other package can run and have their configs array.
With this, the new command line interface that handles the actual configs of this repo is the "eslegant" package.

View File

@@ -0,0 +1,6 @@
---
"@eslegant/js": patch
"@eslegant/cli": patch
---
Updated dependencies

View File

@@ -0,0 +1,5 @@
---
"eslegant": patch
---
Created the ESLegant package, being now the actual command that runs the CLI with the ESLegant's configs

View File

@@ -0,0 +1,5 @@
---
"@eslegant/js": minor
---
Configs now export a `default` variation, where rule leves aren't overriden.

View File

@@ -0,0 +1,5 @@
---
"@eslegant/cli": patch
---
Fixed some small errors that could be thrown when prompts are canceled. Also fixed --merge-to-root cli argument not working and added list of packages that are installed on confirmation prompt.

View File

@@ -0,0 +1,5 @@
---
"create-eslegant": patch
---
Created the "create-eslegant" package, as a _alias_ to the eslegant package, so it is compatible with `npm init` or `npm create` commands

View File

@@ -0,0 +1,6 @@
---
"@eslegant/js": minor
---
New rules related to possible security vulnerabilities in JavaScript.
Provided by `eslint-plugin-security` and `eslint-plugin-no-secrets`

View File

@@ -0,0 +1,8 @@
---
"create-eslegant": minor
"eslegant": minor
"@eslegant/js": minor
"@eslegant/cli": minor
---
Renamed all packages from "eslit" to "eslegant"

View File

@@ -0,0 +1,5 @@
---
"@eslegant/js": patch
---
Renamed @eslegant/config to @eslegant/js

View File

@@ -2,7 +2,7 @@ root = true
[*]
indent_style = tab
indent_size = 2
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true

View File

@@ -13,6 +13,10 @@ inputs:
required: false
type: boolean
default: true
scope:
required: false
type: string
default: '@eslegant'
runs:
using: composite
@@ -21,6 +25,8 @@ runs:
uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'
scope: ${{ inputs.scope }}
- name: Install PNPM
uses: pnpm/action-setup@v2

View File

@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 2
@@ -40,7 +40,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 2

View File

@@ -8,8 +8,8 @@ on:
jobs:
mirror:
if: github.repository == 'loreddev/eslit'
if: github.repository == 'loreddev/eslegant'
uses: loreddev/.github/.github/workflows/mirrors.yml@main
secrets: inherit
with:
codeberg-repo: https://codeberg.org/LoredDev/ESLit
codeberg-repo: https://codeberg.org/LoredDev/ESLegant

View File

@@ -10,7 +10,7 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
update-release:
if: ${{ github.repository == 'loreddev/eslit' }}
if: ${{ github.repository == 'loreddev/eslegant' }}
runs-on: ubuntu-latest
permissions:
contents: write
@@ -20,7 +20,7 @@ jobs:
HUSKY: 0
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

View File

@@ -11,14 +11,14 @@ on:
jobs:
release:
if: ${{ github.event.workflow_run.conclusion == 'success' && github.repository == 'loreddev/eslit' }}
if: ${{ github.event.workflow_run.conclusion == 'success' && github.repository == 'loreddev/eslegant' }}
name: Release preview
env:
HUSKY: 0
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -27,8 +27,10 @@ jobs:
- name: Update versions
run: pnpm changeset version --snapshot next
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release packages
run: pnpm run release --tag next
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -10,10 +10,10 @@ on:
jobs:
generate-changeset:
runs-on: ubuntu-latest
if: github.actor == 'renovate[bot]' && github.repository == 'loreddev/eslit'
if: github.actor == 'renovate[bot]' && github.repository == 'loreddev/eslegant'
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Configure Git

53
.vscode/project.code-workspace vendored Normal file
View File

@@ -0,0 +1,53 @@
{
"folders": [
{
"name": "configs/js",
"path": "../configs/js"
},
{
"name": "packages/cli",
"path": "../packages/cli"
},
{
"name": "packages/create-eslegant",
"path": "../packages/create-eslegant"
},
{
"name": "packages/eslegant",
"path": "../packages/eslegant"
},
{
"name": "ROOT",
"path": "../"
}
],
"settings": {
"eslint.workingDirectories": ["./"],
"eslint.experimental.useFlatConfig": true,
"prettier.enable": false,
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": false,
},
// The following is optional.
// It's better to put under project setting `.vscode/settings.json`
// to avoid conflicts with working with different eslint configs
// that does not support all formats.
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml"
],
"cSpell.words": [
"eslegant"
]
}
}

View File

@@ -23,6 +23,6 @@
"yaml"
],
"cSpell.words": [
"ESLIT"
"eslegant"
]
}

View File

@@ -0,0 +1,48 @@
# Duplicated rules
This is a list of rules that implements the same features and/or end
up fixing the same errors.
- **[`@typescript/member-ordering`][ts/member-ordering], [`@typescript/sort-type-constituents`][ts/sort-type-constituents], [`import/order`][im/order]**:
implements the same functions from [`eslint-plugin-perfectionist`][plugin-perfectionist]
- **[`unicorn/no-for-loop`][un/no-for-loop] and [`@typescript/prefer-for-of`][ts/prefer-for-of]**:
`unicorn/no-for-loop` was used as it also reports when `i`/`index` is used.
- **[`unicorn/prefer-includes`][un/prefer-includes] and [`@typescript/prefer-includes`][ts/prefer-includes]**:
`unicorn/prefer-includes` was used as it not needs type information to run.
- **[`@typescript/prefer-regexp-exec`][ts/prefer-regexp-exec] and [`unicorn/prefer-regexp-test`][un/prefer-regexp-test]**:
`unicorn/prefer-regexp-exec` was used, because it reports on `RegExp#exec()` and `String#match()`
- **[`import/extensions`][im/extensions] and [`n/file-extension-in-import`][n/file-extension-in-import]**:
`import/extensions` was used, as it is not a node-specific issue.
- **[`import/no-extraneous-dependencies`][im/no-extraneous-dependencies], [`n/no-extraneous-require`][n/no-extraneous-require] and [`n/no-extraneous-import`][n/no-extraneous-import]**:
`import/no-extraneous-dependencies` was used, as it is not a node-specific issue.
- **[`import/no-unresolved`][im/no-unresolved], [`n/no-missing-require`][n/no-missing-require] and [`n/no-missing-import`][n/no-missing-import]**:
`import/no-unresolved` was used, as it is not a node-specific issue.
[ts/member-ordering]: <https://typescript-eslint.io/rules/member-ordering>
[ts/prefer-for-of]: <https://typescript-eslint.io/rules/prefer-for-of>
[ts/prefer-includes]: <https://typescript-eslint.io/rules/prefer-includes>
[ts/prefer-regexp-exec]: <https://typescript-eslint.io/rules/prefer-regexp-exec>
[ts/sort-type-constituents]: <https://typescript-eslint.io/rules/sort-type-constituents>
[un/no-for-loop]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-for-loop.md>
[un/prefer-includes]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-includes.md>
[un/prefer-regexp-test]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md>
[im/order]: <https://github.com/import-js/eslint-plugin-import/blob/maib/docs/rules/order.md>
[im/extensions]: <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/extensions.md>
[im/no-extraneous-dependencies]: <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-extraneous-dependencies.md>
[im/no-unresolved]: <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-unresolved.md>
[n/file-extension-in-import]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/file-extension-in-import.md>
[n/no-extraneous-import]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-extraneous-import.md>
[n/no-extraneous-require]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-extraneous-require.md>
[n/no-missing-import]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-missing-import.md>
[n/no-missing-require]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-missing-require.md>
[plugin-perfectionist]: <https://eslint-plugin-perfectionist.azat.io/>

5
configs/js/jsconfig.json Normal file
View File

@@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.json",
"exclude": ["./node_modules/**", "./dist/**"],
"include": ["src/index.d.ts", "./src/**/*.ts", "./src/**/*.js", "src/index.js"],
}

View File

@@ -1,5 +1,5 @@
{
"name": "@eslit/config",
"name": "@eslegant/js",
"version": "0.2.0",
"description": "",
"main": "index.js",
@@ -9,11 +9,11 @@
"src",
"index.d.ts"
],
"homepage": "https://github.com/LoredDev/ESLit",
"homepage": "https://github.com/LoredDev/ESLegant",
"exports": {
"default": "./src/index.js",
"import": "./src/index.js",
"types": "./index.d.ts"
"types": "./src/index.d.ts"
},
"type": "module",
"types": "./src/index.js",
@@ -22,9 +22,9 @@
"lint": "eslint ."
},
"repository": {
"directory": "packages/config",
"directory": "configs/js",
"type": "git",
"url": "https://github.com/LoredDev/ESLit"
"url": "https://github.com/LoredDev/ESLegant"
},
"author": {
"email": "contact.guz013@gmail.com",
@@ -34,17 +34,24 @@
"license": "MIT",
"devDependencies": {
"@types/eslint__js": "^8.42.0",
"@types/node": "^20.4.2",
"eslint": "^8.45.0",
"@types/node": "^20.5.3",
"eslint": "^8.47.0",
"typescript": "^5.1.6"
},
"dependencies": {
"@eslint/eslintrc": "^2.1.0",
"@eslint/js": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^6.1.0",
"@typescript-eslint/parser": "^6.1.0",
"eslint-plugin-jsdoc": "^46.4.4",
"globals": "^13.20.0"
"@eslint/eslintrc": "^2.1.2",
"@eslint/js": "^8.47.0",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"eslint-import-resolver-typescript": "^3.6.0",
"eslint-plugin-i": "2.28.0-2",
"eslint-plugin-jsdoc": "^46.5.0",
"eslint-plugin-n": "^16.0.2",
"eslint-plugin-no-secrets": "^0.8.9",
"eslint-plugin-perfectionist": "^2.0.0",
"eslint-plugin-security": "^1.7.1",
"eslint-plugin-unicorn": "^48.0.1",
"globals": "^13.21.0"
},
"peerDependencies": {
"eslint": "^8.45.0",

View File

@@ -0,0 +1,35 @@
/**
* @file
* Type declaration for the `eslint-plugin-i` package in a attempt to make it
* compatible with the new flat config.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
// eslint-disable-next-line unicorn/prevent-abbreviations
import type { ESLint, Linter } from 'eslint';
/**
* @summary ESLint plugin with rules that help validate proper imports.
*
* ---
* **Note:** Types in this project where overridden to be compatible with
* ESLint new flat config types. ESlint already has backwards compatibility
* for plugins not created in the new flat config.
* @see {@link https://www.npmjs.com/package/eslint-plugin-import npm package}
*/
declare module 'eslint-plugin-i' {
interface importEslintPlugin extends ESLint.Plugin {
configs: {
recommended: {
rules: Linter.RulesRecord,
},
typescript: {
rules: Linter.RulesRecord,
},
},
}
declare const plugin: importEslintPlugin;
export default plugin;
}

View File

@@ -0,0 +1,34 @@
/**
* @file
* Type declaration for the `eslint-plugin-jsdoc` package in a attempt to make it
* compatible with the new flat config.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { ESLint } from 'eslint';
/**
* @summary JSDoc specific linting rules for ESLint.
*
* ---
* **Note:** Types in this project where overridden to be compatible with
* ESLint new flat config types. ESlint already has backwards compatibility
* for plugins not created in the new flat config.
* @see {@link https://www.npmjs.org/package/eslint-plugin-jsdoc npm package}
*/
declare module 'eslint-plugin-jsdoc' {
// eslint-disable-next-line unicorn/prevent-abbreviations
interface jsDocESlintPlugin extends ESLint.Plugin {
configs: ESLint.Plugin['configs'] & {
recommended: ESLint.ConfigData,
'recommended-error': ESLint.ConfigData,
'recommended-typescript': ESLint.ConfigData,
'recommended-typescript-error': ESLint.ConfigData,
'recommended-typescript-flavor': ESLint.ConfigData,
'recommended-typescript-flavor-error': ESLint.ConfigData,
},
}
declare const plugin: jsDocESlintPlugin;
export default plugin;
}

View File

@@ -0,0 +1,24 @@
/**
* @file
* Type declaration for the `eslint-plugin-n` package in a attempt to make it
* compatible with the new flat config.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { ESLint } from 'eslint';
/**
* @summary Additional ESLint's rules for Node.js.
*
* ---
* **Note:** Types in this project where overridden to be compatible with
* ESLint new flat config types. ESlint already has backwards compatibility
* for plugins not created in the new flat config.
* @see {@link https://www.npmjs.com/package/eslint-plugin-n npm package}
*/
declare module 'eslint-plugin-n' {
declare const plugin: ESLint.Plugin;
export default plugin;
}

View File

@@ -0,0 +1,24 @@
/**
* @file
* Type declaration for the `eslint-plugin-no-secrets` package in a attempt to make it
* compatible with the new flat config.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { ESLint } from 'eslint';
/**
* @summary An eslint plugin to find strings that might be secrets/credentials.
*
* ---
* **Note:** Types in this project where overridden to be compatible with
* ESLint new flat config types. ESlint already has backwards compatibility
* for plugins not created in the new flat config.
* @see {@link https://www.npmjs.com/package/eslint-plugin-no-secrets npm package}
*/
declare module 'eslint-plugin-no-secrets' {
declare const plugin: ESLint.Plugin;
export default plugin;
}

View File

@@ -0,0 +1,24 @@
/**
* @file
* Type declaration for the `eslint-plugin-security` package in a attempt to make it
* compatible with the new flat config.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { ESLint } from 'eslint';
/**
* @summary ESLint rules for Node Security.
*
* ---
* **Note:** Types in this project where overridden to be compatible with
* ESLint new flat config types. ESlint already has backwards compatibility
* for plugins not created in the new flat config.
* @see {@link https://www.npmjs.com/package/eslint-plugin-security npm package}
*/
declare module 'eslint-plugin-security' {
declare const plugin: ESLint.Plugin;
export default plugin;
}

18
configs/js/src/@types/globals.d.ts vendored Normal file
View File

@@ -0,0 +1,18 @@
/**
* @file
* Type declaration for the `globals` package in a attempt to make it
* compatible with the new flat config.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
declare module 'globals' {
const globals: {
browser: { [rule: string]: boolean, },
builtin: { [rule: string]: boolean, },
commonjs: { [rule: string]: boolean, },
node: { [rule: string]: boolean, },
nodeBuiltin: { [rule: string]: boolean, },
};
export default globals;
}

View File

@@ -1,46 +1,53 @@
/**
* @file
* Type declaration for the `@typescript-eslint/eslint-plugin` and
* `@typescript-eslint/parser` packages in a attempt to make it
* compatible with the new flat config.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { ESLint, Linter } from 'eslint';
/**
* @see {@link https://www.npmjs.com/package/@typescript-eslint/eslint-plugin npm package}
*
* @summary An ESLint plugin which provides lint rules for TypeScript codebases.
*
* ---
* **Note:** Types in this project where overridden to be compatible with ESLint new flat
* config types. ESlint already has backwards compatibility for plugins not created in the
* new flat config.
* **Note:** Types in this project where overridden to be compatible with ESLint
* new flat config types. ESlint already has backwards compatibility for plugins
* not created in the new flat config.
* @see {@link https://www.npmjs.com/package/@typescript-eslint/eslint-plugin npm package}
*/
declare module '@typescript-eslint/eslint-plugin' {
interface typescriptEslintPlugin extends ESLint.Plugin {
configs: {
recommended: {
rules: Linter.RulesRecord
}
'recommended-requiring-type-checking': {
rules: Linter.RulesRecord
}
'eslint-recommended': {
rules: Linter.RulesRecord
}
rules: Linter.RulesRecord,
},
recommended: {
rules: Linter.RulesRecord,
},
'recommended-requiring-type-checking': {
rules: Linter.RulesRecord,
},
strict: {
rules: Linter.RulesRecord
}
}
rules: Linter.RulesRecord,
},
},
}
declare const plugin: typescriptEslintPlugin;
export default plugin;
}
/**
* @see {@link https://www.npmjs.com/package/@typescript-eslint/parser npm package}
*
* @summary An ESLint parser which leverages TypeScript ESTree to allow for ESLint
* to lint TypeScript source code.
* @summary An ESLint parser which leverages TypeScript ESTree to
* allow for ESLint to lint TypeScript source code.
*
* ---
* **Note:** Types in this project where overridden to be compatible with ESLint new flat
* config types. ESlint already has backwards compatibility for parsers not created in the
* new flat config.
* **Note:** Types in this project where overridden to be compatible
* with ESLint new flat config types. ESlint already has backwards
* compatibility for parsers not created in the new flat config.
* @see {@link https://www.npmjs.com/package/@typescript-eslint/parser npm package}
*/
declare module '@typescript-eslint/parser' {
declare const parser: Linter.ParserModule;

View File

@@ -0,0 +1,64 @@
/**
* @file
* Configuration object that adds necessary plugins for the other objects.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import process from 'node:process';
import tsESLint from '@typescript-eslint/eslint-plugin';
import securityPlugin from 'eslint-plugin-security';
import unicornPlugin from 'eslint-plugin-unicorn';
// @ts-expect-error because the package doesn't export correct types
import tsParser from '@typescript-eslint/parser';
import jsdocPlugin from 'eslint-plugin-jsdoc';
import importPlugin from 'eslint-plugin-i';
import globals from 'globals';
// eslint-disable-next-line import/no-relative-parent-imports
import { jsFiles, tsFiles } from '../constants.js';
/** @type {import('eslint').Linter.FlatConfig} */
const config = {
files: [...tsFiles, ...jsFiles],
languageOptions: {
globals: {
...globals.builtin,
},
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
parser: tsParser,
parserOptions: {
project: process.env.ESLEGANT_TSCONFIG ?? [
'./{ts,js}config{.eslint,}.json',
'./*/{ts,js}config{.eslint,}.json',
'./*/*/{ts,js}config{.eslint,}.json',
],
tsconfigRootDir: process.env.ESLEGANT_ROOT ?? process.cwd(),
},
},
plugins: {
'@typescript-eslint': tsESLint,
'import': importPlugin,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
'jsdoc': jsdocPlugin,
// @ts-expect-error because eslint-plugin-security doesn't export correct types
'security': securityPlugin,
// @ts-expect-error because eslint-plugin-unicorn doesn't export correct types
'unicorn': unicornPlugin,
},
settings: {
'import/extensions': [...tsFiles, ...jsFiles],
'import/parsers': {
'@typescript-eslint/parser': [...tsFiles, ...jsFiles ],
},
'import/resolver': {
node: true,
typescript: true,
},
'jsdoc/mode': 'typescript',
},
};
export default config;

View File

@@ -0,0 +1,56 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects that helps document your code.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import { createVariations } from '../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../constants.js';
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
rules: {
...{}, // Plugin: eslint-plugin-jsdoc
'jsdoc/match-description': 'error',
'jsdoc/require-description-complete-sentence': 'error',
'jsdoc/require-hyphen-before-param-description': ['error', 'always'],
'jsdoc/require-param-description': 'error',
'jsdoc/require-property-description': 'error',
'jsdoc/require-returns-check': 'error',
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
...{}, // Plugin: eslint-plugin-jsdoc
'jsdoc/require-description': 'error',
'jsdoc/require-file-overview': ['error', { tags: {
author: {
mustExist: true,
},
copyright: {
initialCommentsOnly: true,
},
file: {
initialCommentsOnly: true,
mustExist: true,
preventDuplicates: true,
},
license: {
initialCommentsOnly: true,
mustExist: true,
preventDuplicates: true,
},
} }],
},
});
const documentation = { recommended, strict };
export default documentation;

View File

@@ -0,0 +1,37 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects for the browser environment.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import { createVariations } from '../../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../../constants.js';
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
rules: {
...{}, // Plugin: eslint-plugin-unicorn
'unicorn/prefer-add-event-listener': 'error',
'unicorn/prefer-dom-node-append': 'error',
'unicorn/prefer-dom-node-dataset': 'error',
'unicorn/prefer-dom-node-remove': 'error',
'unicorn/prefer-dom-node-text-content': 'error',
'unicorn/prefer-keyboard-event-key': 'error',
'unicorn/prefer-modern-dom-apis': 'error',
'unicorn/prefer-query-selector': 'error',
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
},
});
const node = { recommended, strict };
export default node;

View File

@@ -0,0 +1,12 @@
/**
* @file
* Configuration object for the all the environment.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import browser from './browser.js';
import node from './node.js';
const environments = { browser, node };
export default environments;

View File

@@ -0,0 +1,116 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects for the NodeJS environment.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import nodePlugin from 'eslint-plugin-n';
import globals from 'globals';
import { createVariations } from '../../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../../constants.js';
const commonjs = createVariations({
files: ['**/*.cts', '**/*.cjs'],
languageOptions: {
globals: {
...globals.nodeBuiltin,
...globals.commonjs,
},
},
plugins: {
// @ts-expect-error because types are not defined in 'eslint-plugin-n'
n: nodePlugin,
},
rules: {
...{}, // Plugin: @typescript-eslint/eslint-plugin
'@typescript-eslint/no-require-imports': 'off',
'@typescript-eslint/no-var-requires': 'off',
...{}, // Plugin: eslint-plugin-unicorn
'unicorn/prefer-module': 'off',
...{}, // Plugin: eslint-plugin-import
'import/no-commonjs': 'off',
...{}, // Plugin: eslint-plugin-n
'n/global-require': 'error',
'n/no-exports-assign': 'error',
...{}, // Plugin: eslint-plugin-security
'security/detect-non-literal-require': 'error',
},
});
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
languageOptions: {
globals: {
...globals.nodeBuiltin,
},
},
plugins: {
// @ts-expect-error because types are not defined in 'eslint-plugin-n'
n: nodePlugin,
},
rules: {
...{}, // Plugin: eslint-plugin-unicorn
'unicorn/prefer-node-protocol': 'error',
...{}, // Plugin: eslint-plugin-import
'import/no-dynamic-require': 'error',
...{}, // Plugin: eslint-plugin-n
'n/no-deprecated-api': 'error',
'n/no-process-exit': 'error',
'n/no-unpublished-bin': 'error',
'n/no-unpublished-import': 'error',
'n/no-unpublished-require': 'error',
'n/no-unsupported-features/es-builtins': 'error',
'n/no-unsupported-features/es-syntax': 'error',
'n/no-unsupported-features/node-builtins': 'error',
'n/process-exit-as-throw': 'error',
'n/shebang': 'error',
...{}, // Plugin: eslint-plugin-security
'security/detect-buffer-noassert': 'warn',
'security/detect-child-process': 'warn',
'security/detect-new-buffer': 'warn',
'security/detect-no-csrf-before-method-override': 'warn',
'security/detect-non-literal-fs-filename': 'warn',
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
...{}, // Plugin: eslint-plugin-n
'n/no-new-require': 'error',
'n/no-path-concat': 'error',
'n/prefer-global/buffer': ['error', 'never'],
'n/prefer-global/console': ['error', 'always'],
'n/prefer-global/process': ['error', 'never'],
'n/prefer-global/text-decoder': ['error', 'always'],
'n/prefer-global/text-encoder': ['error', 'always'],
'n/prefer-global/url': ['error', 'always'],
'n/prefer-global/url-search-params': ['error', 'always'],
'n/prefer-promises/dns': 'error',
'n/prefer-promises/fs': 'error',
...{}, // Plugin: eslint-plugin-security
'security/detect-buffer-noassert': 'error',
'security/detect-child-process': 'error',
'security/detect-new-buffer': 'error',
'security/detect-no-csrf-before-method-override': 'error',
'security/detect-non-literal-fs-filename': 'warn',
},
});
const node = { commonjs, recommended, strict };
export default node;

View File

@@ -0,0 +1,192 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects for code formatting and style in JavaScript and TypeScript.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import perfectionistPlugin from 'eslint-plugin-perfectionist';
import { createVariations } from '../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../constants.js';
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
plugins: {
// @ts-expect-error because plugin doesn't export correct type
perfectionist: perfectionistPlugin,
},
rules: {
...{}, // ESLint rules
'arrow-parens': ['error', 'as-needed', { requireForBlockBody: true }],
'comma-style': 'error',
'curly': ['error', 'multi-or-nest', 'consistent'],
'dot-location': 'error',
'eol-last': 'error',
'generator-star-spacing': ['error', 'before'],
'no-mixed-spaces-and-tabs': 'error',
'no-multi-spaces': 'error',
'no-whitespace-before-property': 'error',
'padded-blocks': 'error',
'rest-spread-spacing': 'error',
'semi-spacing': 'error',
'space-in-parens': 'error',
'space-unary-ops': 'error',
'spaced-comment': ['error', 'always', {
block: {
balanced: true,
exceptions: ['*'],
markers: ['!'],
},
line: {
exceptions: ['/', '#'],
markers: ['/'],
},
}],
'template-curly-spacing': ['error', 'never'],
...{}, // Plugin: @typescript-eslint/eslint-plugin
'@typescript-eslint/block-spacing': ['error', 'always'],
'@typescript-eslint/brace-style': ['error', 'stroustrup', {
allowSingleLine: true,
}],
'@typescript-eslint/comma-dangle': ['error', 'always-multiline'],
'@typescript-eslint/comma-spacing': 'error',
'@typescript-eslint/dot-notation': 'error',
'@typescript-eslint/func-call-spacing': 'error',
'@typescript-eslint/indent': ['error', 'tab', { ArrayExpression: 1,
CallExpression: { arguments: 1 },
FunctionDeclaration: { body: 1,
parameters: 1 },
FunctionExpression: { body: 1,
parameters: 1 },
ImportDeclaration: 1,
MemberExpression: 1,
ObjectExpression: 1,
SwitchCase: 1,
VariableDeclarator: 1,
flatTernaryExpressions: false,
ignoreComments: false, ignoredNodes: [
'TemplateLiteral *',
'JSXElement',
'JSXElement > *',
'JSXAttribute',
'JSXIdentifier',
'JSXNamespacedName',
'JSXMemberExpression',
'JSXSpreadAttribute',
'JSXExpressionContainer',
'JSXOpeningElement',
'Element',
'JSXFragment',
'JSXOpeningFragment',
'JSXClosingFragment',
'JSXText',
'JSXEmptyExpression',
'JSXSpreadChild',
'TSTypeParameterInstantiation',
'FunctionExpression > .params[decorators.length > 0]',
// eslint-disable-next-line max-len
'FunctionExpression > .params > :matches(Decorator, :not(:first-child))',
// eslint-disable-next-line max-len
'ClassBody.body > PropertyDefinition[decorators.length > 0] > .key',
], offsetTernaryExpressions: true, outerIIFEBody: 1,
}],
'@typescript-eslint/key-spacing': ['error', {
afterColon: true,
beforeColon: false,
}],
'@typescript-eslint/keyword-spacing': ['error', {
after: true,
before: true,
}],
'@typescript-eslint/lines-between-class-members': ['error'],
'@typescript-eslint/member-delimiter-style': ['error', {
multiline: { delimiter: 'comma', requireLast: true },
singleline: { delimiter: 'comma', requireLast: true },
}],
'@typescript-eslint/no-extra-parens': ['error', 'functions'],
'@typescript-eslint/object-curly-spacing': ['error', 'always'],
'@typescript-eslint/quotes': ['error', 'single'],
'@typescript-eslint/semi': ['error', 'always'],
'@typescript-eslint/space-before-blocks': ['error', 'always'],
'@typescript-eslint/space-before-function-paren': ['error', {
anonymous: 'always',
asyncArrow: 'always',
named: 'never',
}],
'@typescript-eslint/space-infix-ops': 'error',
'@typescript-eslint/type-annotation-spacing': ['error', {
after: true,
before: false,
overrides: {
arrow: { after: true, before: true },
},
}],
'block-spacing': 'off',
'brace-style': 'off',
'comma-dangle': 'off',
'comma-spacing': 'off',
'dot-notation': 'off',
'func-call-spacing': 'off',
'indent': 'off',
'key-spacing': 'off',
'keyword-spacing': 'off',
'lines-between-class-members': 'off',
'object-curly-spacing': 'off',
'quotes': 'off',
'semi': 'off',
'space-before-blocks': 'off',
'space-before-function-paren': 'off',
'space-infix-ops': 'off',
...{}, // Plugin: eslint-plugin-import
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'import/exports-last': 'error',
'import/first': 'error',
'import/group-exports': 'error',
...{}, // Plugin: eslint-plugin-perfectionist
'perfectionist/sort-array-includes': ['error', { type: 'natural' }],
'perfectionist/sort-classes': ['error', { type: 'natural' }],
'perfectionist/sort-enums': ['error', { type: 'natural' }],
'perfectionist/sort-exports': ['error', { type: 'line-length' }],
'perfectionist/sort-imports': ['error', {
groups: [
'type',
'builtin',
'external',
'internal-type',
'internal',
['parent-type', 'sibling-type', 'index-type'],
['parent', 'sibling', 'index'],
'object',
'unknown',
],
order: 'desc',
type: 'line-length',
}],
'perfectionist/sort-interfaces': ['error', { type: 'natural' }],
'perfectionist/sort-jsx-props': ['error', { type: 'natural' }],
'perfectionist/sort-map-elements': ['error', { type: 'natural' }],
'perfectionist/sort-named-exports': ['error', { type: 'natural' }],
'perfectionist/sort-named-imports': ['error', { type: 'natural' }],
'perfectionist/sort-object-types': ['error', { type: 'natural' }],
'perfectionist/sort-objects': ['error', { type: 'natural' }],
'perfectionist/sort-union-types': ['error', { type: 'natural' }],
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
},
});
const formatting = { recommended, strict };
export default formatting;

318
configs/js/src/configs/index.d.ts vendored Normal file
View File

@@ -0,0 +1,318 @@
/**
* @file
* Type declarations and documentations for all configs objects.
* All these types are public to the user.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { Linter } from 'eslint';
interface ConfigVariations {
/**
* @summary
* Enable rules with the predefined levels of the package.
* @description
* Most of the rules in ESLegant are on `error` level. This
* was preferred so it is harder to ignore them. But it has
* some small exceptions where rules will be at `warn` level,
* being more as a "reminder" than a actual rule.
*
* If you want to **every** rule in the config to have an
* `error` or `warn` level, you can use the other variants.
*/
default: Linter.FlatConfig,
/**
* @description
* Enable all rules with `error` level.
*/
error: Linter.FlatConfig,
/**
* @description
* Disable all rules in this config.
*/
off: Linter.FlatConfig,
/**
* @description
* Enable all rules with `warn` level.
*/
warn: Linter.FlatConfig,
}
const configs: Readonly<{
/**
* @summary
* **Add this configuration at the start of your array**.
* @description
* This config adds necessary plugins and configuration for ESLint
* to use in the other configs **This should always be in the top
* of the configuration array**.
*/
core: Linter.FlatConfig,
/**
* @description
* This configuration helps you document your code with JSDoc.
*/
documentation: {
/**
* @summary
* Recommended rules from the original plugins.
* @description
* Less strict rules, that nots enforces documentation on
* every aspect/function of your code. Recommended rules for
* projects in prototyping or starting phases, or apps that
* doesn't needs massive documentations.
*/
recommended: ConfigVariations,
/**
* @summary
* More opinionated configuration, created for ESLegant and Lored's projects.
* @borrows Builds on top of the recommended configuration
* @description
* Enforces some documentation of every function and file.
* Better for libraries (in more production-ready phases),
* large codebase's and/or projects with multiple teams/people.
*/
strict: ConfigVariations,
},
/**
* @summary
* Configurations related to specific JavaScript/TypeScript environments,
* such as Node, Deno and the Browser.
* @description
* Adds global variables and rules related to code on said environments.
* **They can and should be combined** depending on the codebase you're
* working with.
*/
environments: {
/**
* @description
* Browser environment configuration, use this if you are working
* on a pure client-side or mixed codebase environment.
*/
browser: {
/**
* @description
* Recommends end enforces the use of newer web APIs
* on your codebase.
*/
recommended: ConfigVariations,
/**
* @borrows Builds on top of the recommended configuration
* @todo
* For now, the strict rules is a alias of the recommended,
* as it not currently adds any new rules.
*/
strict: ConfigVariations,
},
node: {
/**
* @summary
* Configuration overrides for CommonJS files.
* @description
* ESLegant recommends the use of ESModules and newer syntax
* for javascript files. This configuration should mostly be
* used for exceptions, like config files that don't support
* ESM.
*
* This configuration just affects files ending in `*.cjs`
* and `*.cts` extensions. If you want to use in other files
* consider creating a config object.
* @example <caption>Example of using the config for specific CommonJS files</caption>
* import { configs } from '@eslegant/js';
*
* export default [
* {
* ...configs.environments.node.commonjs.error
* files: ['*.config.js'],
* }
* ]
*/
commonjs: ConfigVariations,
/**
* @description
* Recommends newer and best practices on NodeJS projects.
*/
recommended: ConfigVariations,
/**
* @borrows Builds on top of the recommended configuration
* @todo
* For now, the strict rules is a alias of the recommended,
* as it not currently adds any new rules.
*/
strict: ConfigVariations,
},
},
/**
* @summary
* This config relates to code formatting and style in JavaScript and TypeScript.
* @description
* This configuration enforces a specific code formatting and style in JavaScript
* and TypeScript. The purpose of it can sometimes overlap with the `suggestions`
* config, so to separate better, this tries to mostly enforces just rules for
* how the code looks and is organized than coding style/way of handling something.
*/
formatting: {
/**
* @summary
* ESLegant / Lored's code style configuration.
* @description
* This configuration recommends a opinionated code and formatting style, which
* is mostly similar to other styles in the JavaScript environment.
* It is based on the work and config of Anthony's ESLint config (`antfu/eslint-config`),
* with the most notable changes being the use of `tabs` instead of 2 space indentation
* and the use of semicolons.
* @see {@link https://github.com/antfu/eslint-config Anthony's config}
*/
recommended: ConfigVariations,
/**
* @borrows Builds on top of the recommended configuration
* @todo
* For now, the strict rules is a alias of the recommended,
* as it not currently adds any new rules.
*/
strict: ConfigVariations,
},
/**
* @description
* This configuration enforces a specific naming convention for the codebase.
* With the object of making the code more readable and understandable.
*/
naming: {
/**
* @summary
* Prevents bad naming conventions and behavior.
* @description
* This configuration prevents bad names and behaviors such as abbreviations.
* It does not enforces specific names or naming structure/strategies.
* **With the exception of** file names being enforces to be `kebab-case`.
*/
recommended: ConfigVariations,
/**
* @summary
* Enforces specific naming structure/strategies.
* @borrows Builds on top of the recommended configuration
* @description
* This configuration enforces specific names or naming structure/strategies for your
* code. Enforcing things such using verbs and nouns in specif orders and
* when abbreviations are accepted or not.
*/
strict: ConfigVariations,
},
overrides: {
'inferrable-types': ConfigVariations,
performance: ConfigVariations,
},
/**
* @summary
* Prevents possible syntax errors in your code.
* @description
* This configuration object prevents possible syntax and code logic
* errors on your file. Mostly not opinionated.
*/
problems: {
/**
* @description
* Rules which prevents most errors in your code. Based
* mostly on ESLint's recommended configuration.
*/
recommended: ConfigVariations,
/**
* @borrows Builds on top of the recommended configuration
* @description
* Extra-safety rules, reporting possible forgettable errors
* or errors in typing.
*/
strict: ConfigVariations,
},
/**
* @summary
* Prevents possible vulnerabilities.
* @description
* This configuration tries to prevent possible vulnerabilities
* in you code, such as hard-coded secrets, personal information in comments,
* XSS attacks, etc.
*/
security: {
/**
* @description
* Rules which warns you about possible security vulnerabilities.
*/
recommended: ConfigVariations,
/**
* @borrows Builds on top of the recommended configuration
* @description
* Similar to recommended config, but with rules in error-level
* to make possible vulnerabilities harder to ignore.
*/
strict: ConfigVariations,
},
/**
* @summary
* Enforces different ways of coding in JavaScript and TypeScript.
* @description
* This configuration enforces different ways doing things, coding style and/or
* code logic patterns. Preferring over explicit and declarative code than
* implicit.
*/
suggestions: {
/**
* @summary
* Recommended for projects in prototyping/starting phases.
* @description
* This configuration enforces mostly best practices,
* based on the `recommended` options of the plugins.
*/
recommended: ConfigVariations,
/**
* @summary
* Strict rules that takes "guarding rails" for your code.
* @borrows Builds on top of the recommended configuration
* @description
* **This will get in the way of your programming**. This configuration
* tries prevent possible bad code smells and practices that could built
* up when your project grows. Enforcing you to refactor more the code
* and separating and or reorganizing functions and code logic.
* @see {@link https://youtu.be/CFRhGnuXG-4 Example: Why You Shouldn't Nest Your Code - by: CodeAesthetic}
* - The maximum depth allowed is 4. (`max-depth: [error, 4]`)
* @see {@link https://youtu.be/J1f5b4vcxCQ Example: Dependency Injection, The Best Pattern - by: CodeAesthetic}
* - Files should be organized in a tree-like structure, and shouldn't import modules
* in parent directories. This helps you organize your code and suggests using
* dependency injection more.
*/
strict: ConfigVariations,
},
/**
* @summary
* Rules for TypeScript files specifically. **Use this if
* you have Typescript files in your project**.
* Affects `*.ts`, `*.tsx`, `*.mts` and `*.cts` files.
* @description
* Most of TypeScript rules can be applied to type-checked JavaScript
* files also. But some can just be fixed in TypeScript syntax, so they
* where disabled and moved to this specific configuration.
*
* It also disable things that aren't useful when using TypeScript, such
* as types in JSDoc comments.
*
* **This should be placed after the `suggestion` config.**.
*
*/
'suggestions-typescript': {
/**
* @summary
* Rules similar to {@link configs.suggestions.recommended `suggestions#recommended`},
* but for TypeScript.
*/
recommended: ConfigVariations,
/**
* @summary
* Rules similar to {@link configs.suggestions.strict `suggestions#strict`},
* but for TypeScript.
*/
strict: ConfigVariations,
},
}>;
export default configs;
export type { ConfigVariations };

View File

@@ -0,0 +1,31 @@
/**
* @file
* Main export files for all the configs objects, merging then in one `configs` object.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import typescript from './suggestions-typescript.js';
import environments from './environments/index.js';
import documentation from './documentation.js';
import suggestions from './suggestions.js';
import formatting from './formatting.js';
import overrides from './overrides.js';
import security from './security.js';
import problems from './problems.js';
import naming from './naming.js';
import core from './core.js';
const configs = {
core,
documentation,
environments,
formatting,
naming,
overrides,
problems,
security,
suggestions,
'suggestions-typescript': typescript,
};
export default configs;

View File

@@ -0,0 +1,37 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects which enforces a specific naming convention for the codebase.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import { createVariations } from '../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../constants.js';
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
rules: {
...{}, // Plugin: eslint-plugin-unicorn
'unicorn/filename-case': ['error', { case: 'kebabCase' }],
'unicorn/prevent-abbreviations': 'error',
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
...{}, // Plugin: @typescript-eslint/eslint-plugin
// '@typescript-eslint/naming-convention': 'error',
...{}, // Plugin: eslint-plugin-unicorn
'unicorn/no-keyword-prefix': 'error',
},
});
const suggestions = { recommended, strict };
export default suggestions;

View File

@@ -0,0 +1,35 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Overrides for specific scenarios or preferences of users. The objects
* are supposed to be placed on the end of the arrays and can
* change configs of multiple other categories.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
* @todo This file is not completed fully.
*/
import { createVariations } from '../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../constants.js';
// TODO [>=1.0.0]: Create a separate config for performance related practices
const performance = createVariations({
files: [...tsFiles, ...jsFiles],
rules: {
'prefer-object-spread': 'off',
'prefer-spread': 'off',
},
});
const inferrableTypes = createVariations({
files: [...tsFiles],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-inferrable-types': 'error',
'@typescript-eslint/typedef': 'off',
},
});
const overrides = { 'inferrable-types': inferrableTypes, performance };
export default overrides;

View File

@@ -0,0 +1,109 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects for preventing possible syntax errors.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import { createVariations } from '../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../constants.js';
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
rules: {
...{}, // ESLint rules
'constructor-super': 'error',
'for-direction': 'error',
'getter-return': 'error',
'no-async-promise-executor': 'error',
'no-class-assign': 'error',
'no-compare-neg-zero': 'error',
'no-cond-assign': 'error',
'no-const-assign': 'error',
'no-constant-condition': 'error',
'no-control-regex': 'error',
'no-debugger': 'error',
'no-delete-var': 'error',
'no-dupe-args': 'error',
'no-dupe-class-members': 'error',
'no-dupe-else-if': 'error',
'no-dupe-keys': 'error',
'no-duplicate-case': 'error',
'no-empty-character-class': 'error',
'no-empty-pattern': 'error',
'no-ex-assign': 'error',
'no-fallthrough': 'error',
'no-func-assign': 'error',
'no-global-assign': 'error',
'no-import-assign': 'error',
'no-inner-declarations': 'error',
'no-invalid-regexp': 'error',
'no-irregular-whitespace': 'error',
'no-misleading-character-class': 'error',
'no-nonoctal-decimal-escape': 'error',
'no-obj-calls': 'error',
'no-octal': 'error',
'no-octal-escape': 'error',
'no-prototype-builtins': 'error',
'no-regex-spaces': 'error',
'no-self-assign': 'error',
'no-setter-return': 'error',
'no-shadow-restricted-names': 'error',
'no-sparse-arrays': 'error',
'no-this-before-super': 'error',
'no-undef': 'error',
'no-unexpected-multiline': 'error',
'no-unreachable': 'error',
'no-unsafe-finally': 'error',
'no-unsafe-negation': 'error',
'no-unsafe-optional-chaining': 'error',
'no-unused-labels': 'error',
'no-useless-backreference': 'error',
'use-isnan': 'error',
'valid-typeof': 'error',
...{}, // Plugin: @typescript-eslint/eslint-plugin
'@typescript-eslint/no-loss-of-precision': 'error',
'@typescript-eslint/no-redeclare': 'error',
'@typescript-eslint/no-unused-vars': 'error',
'no-loss-of-precision': 'off',
'no-redeclare': 'off',
'no-unused-vars': 'off',
...{}, // Plugin: eslint-plugin-import
'import/default': 'error',
'import/export': 'error',
'import/named': 'error',
'import/namespace': 'error',
'import/no-unresolved': 'error',
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
...{}, // ESLint rules
'no-constant-binary-expression': 'error',
'no-duplicate-imports': 'error',
'no-new-native-nonconstructor': 'error',
'no-promise-executor-return': 'error',
'no-self-compare': 'error',
'no-sequences': 'error',
'no-template-curly-in-string': 'error',
'no-unmodified-loop-condition': 'error',
'no-unreachable-loop': 'error',
'no-unused-private-class-members': 'error',
'require-atomic-updates': 'error',
...{}, // Plugin: eslint-plugin-import
'import/no-extraneous-dependencies': 'error',
},
});
const problems = { recommended, strict };
export default problems;

View File

@@ -0,0 +1,61 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects for preventing possible security vulnerabilities.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import noSecretsPluginRegexes from 'eslint-plugin-no-secrets/regexes.js';
import noSecretsPlugin from 'eslint-plugin-no-secrets';
import { createVariations } from '../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../constants.js';
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
plugins: {
'no-secrets': noSecretsPlugin,
},
rules: {
...{}, // Plugin: eslint-plugin-security
'security/detect-bidi-characters': 'warn',
'security/detect-disable-mustache-escape': 'warn',
'security/detect-eval-with-expression': 'warn',
'security/detect-non-literal-regexp': 'warn',
'security/detect-object-injection': 'warn',
'security/detect-possible-timing-attacks': 'warn',
'security/detect-pseudoRandomBytes': 'warn',
'security/detect-unsafe-regex': 'warn',
...{}, // Plugin: eslint-plugin-no-secrets
'no-secrets/no-secrets': 'warn',
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
...{}, // Plugin: eslint-plugin-security
'security/detect-bidi-characters': 'error',
'security/detect-disable-mustache-escape': 'error',
'security/detect-eval-with-expression': 'error',
'security/detect-non-literal-regexp': 'error',
'security/detect-object-injection': 'warn',
'security/detect-possible-timing-attacks': 'warn',
'security/detect-pseudoRandomBytes': 'error',
'security/detect-unsafe-regex': 'error',
...{}, // Plugin: eslint-plugin-no-secrets
'no-secrets/no-secrets': ['error', {
additionalRegexes: noSecretsPluginRegexes,
}],
},
});
const security = { recommended, strict };
export default security;

View File

@@ -0,0 +1,40 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects that enforces different ways of coding in TypeScript specifically.
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import { createVariations } from '../lib/rule-variations.js';
import { tsFiles } from '../constants.js';
const recommended = createVariations({
files: [...tsFiles],
rules: {
...{}, // Plugin: @typescript-eslint/eslint-plugin
'@typescript-eslint/explicit-function-return-type': 'error',
...{}, // Plugin: eslint-plugin-jsdoc
'jsdoc/check-tag-names': ['error', { typed: true }],
'jsdoc/no-types': 'error',
'jsdoc/require-param-type': 'off',
'jsdoc/require-property-type': 'off',
'jsdoc/require-returns-type': 'off',
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
...{}, // Plugin: @typescript-eslint/eslint-plugin
'@typescript-eslint/explicit-member-accessibility': 'error',
'@typescript-eslint/explicit-module-boundary-types': 'error',
},
});
const typescript = { recommended, strict };
export default typescript;

View File

@@ -0,0 +1,451 @@
/* eslint-disable import/no-relative-parent-imports */
/* eslint-disable unicorn/no-useless-spread */
/**
* @file
* Configuration objects that enforces different ways of coding in JavaScript and TypeScript..
* See more info on the configs type declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import { createVariations } from '../lib/rule-variations.js';
import { jsFiles, tsFiles } from '../constants.js';
const recommended = createVariations({
files: [...tsFiles, ...jsFiles],
rules: {
'camelcase': 'error',
'max-len': ['error', { code: 80, comments: 100, ignoreUrls: true }],
'no-case-declarations': 'error',
'no-confusing-arrow': 'error',
'no-console': 'error',
'no-constant-condition': 'error',
'no-delete-var': 'error',
'no-empty': 'error',
'no-lonely-if': 'error',
'no-new-symbol': 'error',
'no-redeclare': 'error',
'no-useless-catch': 'error',
'no-useless-escape': 'error',
'no-var': 'error',
'no-with': 'error',
'object-shorthand': ['error', 'always', {
avoidQuotes: true,
ignoreConstructors: false,
}],
'prefer-exponentiation-operator': 'error',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'prefer-template': 'error',
'quote-props': ['error', 'consistent-as-needed'],
'require-yield': 'error',
...{}, // Plugin: @typescript-eslint/eslint-plugin
/*
* '@typescript-eslint/adjacent-overload-signatures': 'error',
* Incompatible with perfectionist/sort-interfaces and
* perfectionist/sort-object-types.
*/
'@typescript-eslint/array-type': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/ban-ts-comment': 'error',
'@typescript-eslint/ban-tslint-comment': 'error',
'@typescript-eslint/ban-types': 'error',
'@typescript-eslint/class-literal-property-style': 'error',
'@typescript-eslint/consistent-generic-constructors': 'error',
// eslint-disable-next-line max-len
'@typescript-eslint/consistent-indexed-object-style': ['error', 'index-signature'],
'@typescript-eslint/consistent-type-assertions': 'error',
'@typescript-eslint/consistent-type-definitions': 'error',
'@typescript-eslint/no-base-to-string': 'error',
'@typescript-eslint/no-confusing-non-null-assertion': 'error',
'@typescript-eslint/no-confusing-void-expression': 'error',
'@typescript-eslint/no-duplicate-enum-values': 'error',
'@typescript-eslint/no-duplicate-type-constituents': 'error',
'@typescript-eslint/no-dynamic-delete': 'error',
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-extra-non-null-assertion': 'error',
'@typescript-eslint/no-extraneous-class': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-for-in-array': 'error',
'@typescript-eslint/no-import-type-side-effects': 'error',
'@typescript-eslint/no-invalid-void-type': 'error',
'@typescript-eslint/no-meaningless-void-operator': 'error',
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/no-mixed-enums': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-redundant-type-constituents': 'error',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-this-alias': 'error',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
'@typescript-eslint/no-unnecessary-condition': 'error',
'@typescript-eslint/no-unnecessary-type-arguments': 'error',
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
'@typescript-eslint/no-unnecessary-type-constraint': 'error',
'@typescript-eslint/no-unsafe-argument': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-declaration-merging': 'error',
'@typescript-eslint/no-unsafe-enum-comparison': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
'@typescript-eslint/no-var-requires': 'error',
'@typescript-eslint/non-nullable-type-assertion-style': 'error',
'@typescript-eslint/prefer-as-const': 'error',
'@typescript-eslint/prefer-function-type': 'error',
'@typescript-eslint/prefer-literal-enum-member': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
'@typescript-eslint/prefer-return-this-type': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
'@typescript-eslint/prefer-ts-expect-error': 'error',
'@typescript-eslint/restrict-plus-operands': 'error',
'@typescript-eslint/restrict-template-expressions': 'error',
'@typescript-eslint/triple-slash-reference': 'error',
'@typescript-eslint/unbound-method': 'error',
'@typescript-eslint/unified-signatures': 'error',
...{}, // Plugin: eslint-plugin-unicorn
'unicorn/better-regex': 'error',
'unicorn/catch-error-name': 'error',
'unicorn/consistent-destructuring': 'error',
'unicorn/consistent-function-scoping': 'error',
'unicorn/empty-brace-spaces': 'error',
'unicorn/error-message': 'error',
'unicorn/escape-case': 'error',
'unicorn/expiring-todo-comments': ['error', {
allowWarningComments: false,
}],
'unicorn/explicit-length-check': 'error',
'unicorn/new-for-builtins': 'error',
'unicorn/no-abusive-eslint-disable': 'error',
'unicorn/no-array-callback-reference': 'error',
'unicorn/no-array-for-each': 'error',
'unicorn/no-array-method-this-argument': 'error',
'unicorn/no-array-push-push': 'error',
'unicorn/no-array-reduce': 'error',
'unicorn/no-await-expression-member': 'error',
'unicorn/no-console-spaces': 'error',
'unicorn/no-document-cookie': 'error',
'unicorn/no-empty-file': 'error',
'unicorn/no-for-loop': 'error',
'unicorn/no-hex-escape': 'error',
'unicorn/no-instanceof-array': 'error',
'unicorn/no-invalid-remove-event-listener': 'error',
'unicorn/no-lonely-if': 'error',
'unicorn/no-new-array': 'error',
'unicorn/no-new-buffer': 'error',
'unicorn/no-object-as-default-parameter': 'error',
'unicorn/no-process-exit': 'error',
'unicorn/no-static-only-class': 'error',
'unicorn/no-thenable': 'error',
'unicorn/no-this-assignment': 'error',
'unicorn/no-typeof-undefined': 'error',
'unicorn/no-unnecessary-await': 'error',
'unicorn/no-unreadable-array-destructuring': 'error',
'unicorn/no-unreadable-iife': 'error',
'unicorn/no-useless-fallback-in-spread': 'error',
'unicorn/no-useless-length-check': 'error',
'unicorn/no-useless-promise-resolve-reject': 'error',
'unicorn/no-useless-spread': 'error',
'unicorn/no-useless-switch-case': 'error',
/*
* TODO (@guz013) [>=1.0.0]: 'unicorn/no-useless-undefined' rule
* It could be better to use a invert to this rule instead, as
* explicity code could be better then implicitly.
*/
'unicorn/no-zero-fractions': 'error',
'unicorn/number-literal-case': 'error',
'unicorn/numeric-separators-style': 'error',
'unicorn/prefer-array-find': ['error', { checkFromLast: true }],
'unicorn/prefer-array-flat': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-array-index-of': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-at': 'error',
'unicorn/prefer-blob-reading-methods': 'error',
'unicorn/prefer-code-point': 'error',
'unicorn/prefer-date-now': 'error',
'unicorn/prefer-default-parameters': 'error',
'unicorn/prefer-event-target': 'error',
'unicorn/prefer-export-from': 'error',
'unicorn/prefer-includes': 'error',
'unicorn/prefer-logical-operator-over-ternary': 'error',
'unicorn/prefer-math-trunc': 'error',
'unicorn/prefer-modern-math-apis': 'error',
'unicorn/prefer-module': 'error',
'unicorn/prefer-native-coercion-functions': 'error',
'unicorn/prefer-negative-index': 'error',
'unicorn/prefer-number-properties': 'error',
'unicorn/prefer-optional-catch-binding': 'error',
'unicorn/prefer-prototype-methods': 'error',
'unicorn/prefer-reflect-apply': 'error',
'unicorn/prefer-regexp-test': 'error',
'unicorn/prefer-set-has': 'error',
// TODO [>=1.0.0]: Should this be on a "performance" preset?
'unicorn/prefer-set-size': 'error',
// TODO [>=1.0.0]: Should this be disabled on a "performance" preset?
'unicorn/prefer-spread': 'error',
'unicorn/prefer-string-replace-all': 'error',
'unicorn/prefer-string-slice': 'error',
'unicorn/prefer-string-starts-ends-with': 'error',
'unicorn/prefer-string-trim-start-end': 'error',
'unicorn/prefer-switch': ['error', {
emptyDefaultCase: 'do-nothing-comment',
}],
'unicorn/prefer-ternary': 'error',
'unicorn/prefer-top-level-await': 'error',
'unicorn/prefer-type-error': 'error',
'unicorn/relative-url-style': 'error',
'unicorn/require-array-join-separator': 'error',
'unicorn/require-number-to-fixed-digits-argument': 'error',
'unicorn/switch-case-braces': 'error',
'unicorn/text-encoding-identifier-case': 'error',
'unicorn/throw-new-error': 'error',
...{}, // Plugin: eslint-plugin-import
'import/no-amd': 'error',
'import/no-commonjs': 'error',
'import/no-deprecated': 'error',
'import/no-duplicates': 'error',
'import/no-empty-named-blocks': 'error',
'import/no-named-as-default': 'error',
'import/no-named-as-default-member': 'error',
'import/no-self-import': 'error',
'import/no-useless-path-segments': 'error',
...{}, // Plugin: eslint-plugin-jsdoc
'jsdoc/check-alignment': 'error',
'jsdoc/check-param-names': 'error',
'jsdoc/check-property-names': 'error',
'jsdoc/check-syntax': 'error',
'jsdoc/check-tag-names': 'error',
'jsdoc/check-types': 'error',
'jsdoc/check-values': 'error',
'jsdoc/empty-tags': 'error',
'jsdoc/implements-on-classes': 'error',
'jsdoc/multiline-blocks': 'error',
'jsdoc/no-multi-asterisks': ['error', { allowWhitespace: true }],
'jsdoc/require-asterisk-prefix': ['error', 'always'],
'jsdoc/require-jsdoc': 'error',
'jsdoc/require-param': 'error',
'jsdoc/require-param-name': 'error',
'jsdoc/require-param-type': 'error',
'jsdoc/require-property': 'error',
'jsdoc/require-property-name': 'error',
'jsdoc/require-property-type': 'error',
'jsdoc/require-returns': 'error',
'jsdoc/require-returns-check': 'error',
'jsdoc/require-returns-type': 'error',
'jsdoc/require-throws': 'error',
'jsdoc/require-yields': 'error',
'jsdoc/require-yields-check': 'error',
'jsdoc/sort-tags': 'error',
// 'jsdoc/valid-types': 'error', This is already handled by Typescript type checking mostly
},
});
const strict = createVariations({
...recommended.error,
rules: {
...recommended.error.rules,
...{}, // ESLint rules
'accessor-pairs': 'error',
'arrow-body-style': ['error', 'as-needed'],
'block-scoped-var': 'error',
'capitalized-comments': 'error',
'complexity': ['error', 10],
'consistent-return': 'error',
'consistent-this': 'error',
'default-case': 'error',
'default-case-last': 'error',
'eqeqeq': 'error',
'func-name-matching': 'error',
'func-names': ['error', 'as-needed'],
'func-style': ['error', 'declaration'],
'grouped-accessor-pairs': ['error', 'setBeforeGet'],
'handle-callback-err': 'error',
'logical-assignment-operators': ['error', 'always', {
enforceForIfStatements: true,
}],
'max-classes-per-file': ['error', 1],
'max-depth': ['error', 4],
'max-lines': ['error', 500],
'max-lines-per-function': ['error', {
max: 60,
skipBlankLines: true,
skipComments: true,
}],
'max-nested-callbacks': ['error', 10],
'max-params': ['error', 4],
'max-statements': ['error', 10],
'multiline-comment-style': ['error', 'starred-block'],
'new-cap': 'error',
'new-parens': 'error',
'no-alert': 'error',
'no-await-in-loop': 'error',
'no-bitwise': 'error',
'no-caller': 'error',
'no-continue': 'error',
'no-div-regex': 'error',
'no-else-return': 'error',
'no-empty-static-block': 'error',
'no-eval': 'error',
'no-extend-native': 'error',
'no-extra-bind': 'error',
'no-extra-boolean-cast': 'error',
'no-extra-parens': ['error', 'all', {
enforceForArrowConditionals: false,
nestedBinaryExpressions: false,
ternaryOperandBinaryExpressions: false,
}],
'no-floating-decimal': 'error',
'no-implicit-coercion': 'error',
'no-implied-eval': 'error',
'no-iterator': 'error',
'no-labels': 'error',
'no-lone-blocks': 'error',
'no-mixed-operators': 'error',
'no-multi-assign': 'error',
'no-multi-str': 'error',
'no-multiple-empty-lines': 'error',
'no-negated-condition': 'error',
'no-new': 'error',
'no-new-func': 'error',
'no-new-object': 'error',
'no-new-wrappers': 'error',
'no-path-concat': 'error',
'no-proto': 'error',
'no-return-assign': 'error',
'no-script-url': 'error',
'no-sequences': 'error',
'no-undef-init': 'error',
'no-underscore-dangle': 'error',
'no-unneeded-ternary': 'error',
'no-unused-expressions': 'error',
'no-use-before-define': 'error',
'no-useless-call': 'error',
'no-useless-computed-key': 'error',
'no-useless-rename': 'error',
'no-useless-return': 'error',
'one-var': ['error', 'never'],
'operator-assignment': ['error', 'always'],
'operator-linebreak': 'error',
'prefer-arrow-callback': 'error',
'prefer-const': 'error',
'prefer-named-capture-group': 'error',
'prefer-numeric-literals': 'error',
'prefer-object-has-own': 'error',
'prefer-object-spread': 'error',
'prefer-promise-reject-errors': 'error',
'prefer-regex-literals': 'error',
'radix': ['error', 'always'],
'require-unicode-regexp': 'error',
'symbol-description': 'error',
'wrap-iife': 'error',
'yoda': ['error', 'never'],
...{}, // Plugin: @typescript-eslint/eslint-plugin
'@typescript-eslint/class-methods-use-this': 'error',
'@typescript-eslint/consistent-type-exports': ['error', {
fixMixedExportsWithInlineTypeSpecifier: false,
}],
'@typescript-eslint/consistent-type-imports': ['error', {
disallowTypeAnnotations: true,
fixStyle: 'separate-type-imports',
prefer: 'type-imports',
}],
'@typescript-eslint/default-param-last': 'error',
'@typescript-eslint/dot-notation': 'error',
'@typescript-eslint/method-signature-style': ['error', 'method'],
'@typescript-eslint/no-array-constructor': 'error',
'@typescript-eslint/no-empty-function': 'error',
'@typescript-eslint/no-extra-semi': 'error',
'@typescript-eslint/no-invalid-this': 'error',
'@typescript-eslint/no-loop-func': 'error',
'@typescript-eslint/no-shadow': 'error',
'@typescript-eslint/no-throw-literal': 'error',
'@typescript-eslint/no-unnecessary-qualifier': 'error',
'@typescript-eslint/no-use-before-define': 'error',
'@typescript-eslint/no-useless-constructor': 'error',
'@typescript-eslint/no-useless-empty-export': 'error',
'@typescript-eslint/parameter-properties': 'error',
'@typescript-eslint/prefer-enum-initializers': 'error',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/promise-function-async': 'error',
'@typescript-eslint/require-array-sort-compare': 'error',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/switch-exhaustiveness-check': 'error',
'@typescript-eslint/typedef': 'error',
// '@typescript-eslint/no-magic-numbers': ['error'],
'class-methods-use-this': 'off',
'default-param-last': 'off',
'no-array-constructor': 'off',
'no-empty-function': 'off',
'no-extra-semi': 'off',
'no-invalid-this': 'off',
'no-loop-func': 'off',
'no-shadow': 'off',
'no-throw-literal': 'off',
'no-use-before-defined': 'off',
'no-useless-constructor': 'off',
'require-await': 'off',
// 'no-magic-numbers': 'off',
...{}, // Plugin: eslint-plugin-unicorn
'no-nested-ternary': 'off',
'unicorn/custom-error-definition': 'error',
'unicorn/no-negated-condition': 'error',
'unicorn/no-nested-ternary': 'error',
/*
* TODO (@guz013) [>=1.0.0]: 'unicorn/no-null' rule
* It could be better to use a invert to this rule instead,
* because the null type could be a better representation to
* "no value" then undefined.
*/
'unicorn/no-unsafe-regex': 'error',
'unicorn/no-unused-properties': 'error',
...{}, // Plugin: eslint-plugin-import
'import/extensions': ['error', 'always', { ignorePackages: true }],
'import/max-dependencies': ['error', {
ignoreTypeImports: true,
max: 10,
}],
'import/no-absolute-path': 'error',
'import/no-anonymous-default-export': 'error',
'import/no-cycle': 'error',
'import/no-import-module-exports': 'error',
'import/no-mutable-exports': 'error',
'import/no-named-default': 'error',
'import/no-relative-packages': 'error',
'import/no-relative-parent-imports': 'error',
'import/no-unassigned-import': ['error', {
allow: ['**/*.css', '**/*.scss', '**/*.less'],
}],
'import/prefer-default-export': 'error',
'import/unambiguous': 'error',
...{}, // Plugin: eslint-plugin-jsdoc
'jsdoc/check-access': 'error',
'jsdoc/check-indentation': 'error',
'jsdoc/informative-docs': 'error',
'jsdoc/multiline-blocks': ['error', { noSingleLineBlocks: true }],
'jsdoc/no-bad-blocks': 'error',
'jsdoc/no-blank-block-descriptions': 'error',
'jsdoc/no-blank-blocks': 'error',
},
});
const suggestions = { recommended, strict };
export default suggestions;

View File

@@ -0,0 +1,11 @@
/**
* @file
* Constant values used around the package.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
const jsFiles = ['**/*.js', '**/*.mjs', '**/*.cjs', '**/*.jsx'];
const tsFiles = ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.tsx'];
export { jsFiles, tsFiles };

22
configs/js/src/index.d.ts vendored Normal file
View File

@@ -0,0 +1,22 @@
/**
* @file
* Types entrypoint of the package.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { Linter } from 'eslint';
export { default as presets } from './presets/index.d.ts';
export { default as configs } from './configs/index.d.ts';
/**
* Helper function to provide type-checking when defining
* ESLint's configuration.
*
* @param config - The configuration array to be returned.
* @returns The configuration array passed on the first parameter.
*/
export function defineConfig(
config: Linter.FlatConfig[],
): Linter.FlatConfig[];

27
configs/js/src/index.js Normal file
View File

@@ -0,0 +1,27 @@
/**
* @file
* Main file entrypoint of the package.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import presets from './presets/index.js';
import configs from './configs/index.js';
/**
* Helper function to provide type-checking when defining
* ESLint's configuration.
*
* @param {import('eslint').Linter.FlatConfig[]} config
* - The configuration array to be returned.
* @returns {import('eslint').Linter.FlatConfig[]}
*/
function defineConfig(config) {
return config;
}
const eslegant = { configs, presets };
export { defineConfig, eslegant as default };
export { default as configs } from './configs/index.js';
export { default as presets } from './presets/index.js';

View File

@@ -0,0 +1,104 @@
/**
* @file Utility functions used in the package to manipulate rules records.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
/**
* @typedef {import('../configs/index').ConfigVariations} ConfigVariations
* @typedef {import('eslint').Linter.RuleEntry} RuleEntry
* @typedef {import('eslint').Linter.RuleLevel} RuleLevel
* @typedef {import('eslint').Linter.FlatConfig} FlatConfig
*/
/**
* Changes the level of a rule entry. Checking if it
* is a Array or a simple RuleLevel entry.
*
* Useful in conjunction with {@link iterateRules `iterateRules()`} function.
*
* @param {Readonly<RuleEntry>} ruleEntry
* - The rule entry to be modified.
* @param {RuleLevel} level
* - The new level to be passed to the rule.
* @returns {RuleEntry}
*/
function changeLevel(ruleEntry, level) {
if (typeof level === 'number') {
/** @type {RuleLevel[]} */
const levels = ['error', 'off', 'warn'];
level = levels[level];
}
if (Array.isArray(ruleEntry))
return [level, ruleEntry[1]];
return level;
}
/**
* Iterates through a rule entry record, using the handler
* on each entry and returns the resulting object.
*
* Useful for applying plugin prefixes or changing the rule
* level of the entries.
*
* @param {Readonly<{[name: string]: RuleEntry}>} rules
* - The object to be iterated through.
* @param {([name, entry]: [string, RuleEntry]) => [string, RuleEntry]} handler
* - Function to run on every rule entry.
* @returns {{[name: string]: RuleEntry}} - The resulting object.
*/
function iterateRules(rules, handler) {
const entries = Object.entries(rules);
entries.map(entry => handler(entry));
return Object.fromEntries(entries);
}
/**
* Creates {@link ConfigVariations variations} for the given configuration object.
* With `error`, `warn` and `off` rule levels.
*
* Used in the configuration objects of this package.
*
* @param {Readonly<FlatConfig>} config
* - The configuration object to create `error`, `warn`, and `off` variations.
* @returns {ConfigVariations}
*/
function createVariations(config) {
const configError = {
...config,
rules: iterateRules(config.rules ?? {}, ([key, entry]) =>
(entry === 'off' || (Array.isArray(entry) && entry[0] === 'off')
? [key, entry]
: [key, changeLevel(entry, 'error')]),
),
};
const configWarning = {
...config,
rules: iterateRules(config.rules ?? {}, ([key, entry]) =>
(entry === 'off' || (Array.isArray(entry) && entry[0] === 'off')
? [key, entry]
: [key, changeLevel(entry, 'warn')]),
),
};
const configDisabled = {
...config,
rules: iterateRules(
config.rules ?? {},
([key, entry]) => [key, changeLevel(entry, 'off')],
),
};
return {
default: config,
error: configError,
off: configDisabled,
warn: configWarning,
};
}
export { createVariations, iterateRules };

51
configs/js/src/presets/index.d.ts vendored Normal file
View File

@@ -0,0 +1,51 @@
/**
* @file
* Types declarations and documentation for the presets object.
* All these types are public to the user.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import type { Linter } from 'eslint';
const presets: Readonly<{
/**
* @summary
* Preset recommended for projects in a prototyping or starting phase.
* @description
* This preset is mostly recommended for projects in the start of
* their development, being more flexible and less opinionated.
* Useful for preventing errors.
*
* Configs used:
* - `problems#recommended`;
* - `suggestions#recommended`;
* - `suggestions-typescript#recommended`;
* - `formatting#recommended`;
* - `naming#recommended`;
* - `documentation#recommended`;
*
* All configs are set on level `error`.
*/
recommended: Linter.FlatConfig[],
/**
* @summary
* Preset recommended for projects in a production or large scale.
* @description
* This preset is more strict and opinionated, focusing on making
* your code follow a specific structure and pattern.
*
* Configs used:
* - `problems#strict`;
* - `suggestions#strict`;
* - `suggestions-typescript#strict`;
* - `formatting#strict`;
* - `naming#strict`;
* - `documentation#recommended`;
*
* All configs are set on level `error`.
*/
strict: Linter.FlatConfig[],
}>;
export default presets;

View File

@@ -0,0 +1,12 @@
/**
* @file
* Presets object export.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
import recommended from './recommended.js';
import strict from './strict.js';
const presets = { recommended, strict };
export default presets;

View File

@@ -0,0 +1,23 @@
/**
* @file
* Recommended preset object. More info and docs on the type
* declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
// eslint-disable-next-line import/no-relative-parent-imports
import configs from '../configs/index.js';
/** @type {import('eslint').Linter.FlatConfig[]} */
const recommended = [
configs.core,
configs.problems.recommended.default,
configs.suggestions.recommended.default,
configs['suggestions-typescript'].recommended.default,
configs.formatting.recommended.default,
configs.naming.recommended.default,
configs.documentation.recommended.default,
configs.security.recommended.default,
];
export default recommended;

View File

@@ -0,0 +1,23 @@
/**
* @file
* Strict preset object. More info and docs on the type
* declaration file.
* @license MIT
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
*/
// eslint-disable-next-line import/no-relative-parent-imports
import configs from '../configs/index.js';
/** @type {import('eslint').Linter.FlatConfig[]} */
const strict = [
configs.core,
configs.problems.strict.default,
configs.suggestions.strict.default,
configs['suggestions-typescript'].strict.default,
configs.formatting.strict.default,
configs.naming.strict.default,
configs.documentation.recommended.default,
configs.security.strict.default,
];
export default strict;

View File

@@ -1,6 +1,16 @@
import { configs, defineConfig, presets } from '@eslit/config';
import { configs, defineConfig, presets } from '@eslegant/js';
export default defineConfig([
...presets.default,
configs.environments.node,
...presets.strict,
configs.environments.node.strict.error,
{
...configs.documentation.strict.error,
files: ['configs/**/*.js', 'configs/**/*.ts'],
},
{
files: ['**/*.{js,ts,cjs,tjs,mjs,mts,jsx,tsx}'],
rules: {
'jsdoc/check-values': ['error', { allowedLicenses: ['MIT'] }],
},
},
]);

View File

@@ -1,5 +1,5 @@
{
"name": "@eslit-fixtures/library",
"name": "fixtures/library",
"version": "1.0.1",
"description": "",
"main": "index.js",
@@ -8,7 +8,7 @@
"test": "pnpm cli"
},
"dependencies": {
"@eslit/cli": "workspace:*"
"@eslegant/cli": "workspace:*"
},
"keywords": [],
"author": "",

View File

@@ -4,10 +4,10 @@
"test:cli": "pnpm cli"
},
"devDependencies": {
"@eslit/cli": "workspace:*"
"@eslegant/cli": "workspace:*"
},
"packageManager": "pnpm@8.6.10",
"name": "monorepo",
"name": "fixtures/monorepo",
"workspaces": [
"apps/*",
"packages/*"

View File

@@ -1,5 +1,5 @@
{
"name": "@eslit-fixtures/svelte",
"name": "fixtures/svelte",
"private": true,
"scripts": {
"dev": "vite dev",
@@ -11,7 +11,7 @@
"test:cli": "pnpm cli"
},
"devDependencies": {
"@eslit/cli": "workspace:*",
"@eslegant/cli": "workspace:*",
"@fontsource/fira-mono": "^4.5.10",
"@neoconfetti/svelte": "^1.0.0",
"@sveltejs/adapter-auto": "^2.0.0",

View File

@@ -1,5 +1,5 @@
{
"name": "eslit-monorepo",
"name": "eslegant-monorepo",
"private": true,
"scripts": {
"lint": "turbo run lint",
@@ -11,16 +11,16 @@
"license": "MIT",
"type": "module",
"dependencies": {
"@eslit/config": "workspace:*"
"@eslegant/js": "workspace:*"
},
"devDependencies": {
"@eslit/cli": "workspace:*",
"@changesets/cli": "^2.26.2",
"@commitlint/config-conventional": "^17.6.6",
"@commitlint/config-conventional": "^17.7.0",
"@commitlint/types": "^17.4.4",
"eslegant": "workspace:*",
"@svitejs/changesets-changelog-github-compact": "^1.1.0",
"eslint": "^8.44.0",
"husky": "^8.0.0",
"turbo": "^1.10.9"
"eslint": "^8.47.0",
"husky": "^8.0.3",
"turbo": "^1.10.12"
}
}

17
packages/cli/index.d.ts vendored Normal file
View File

@@ -0,0 +1,17 @@
import type { CliArgs } from './src/types';
/**
* Class that handles the creation and running the ESLegant command line interface
*/
export default class Cli {
/**
* @param args Arguments to pass to the cli when its runs
*/
constructor(args: CliArgs);
/**
* Runs the cli with the given arguments
*/
async run(): Promise<void>;
}
export type { CliArgs, Config } from './src/types.d.ts';

1
packages/cli/index.js Normal file
View File

@@ -0,0 +1 @@
export { default as default } from './src/cli.js';

View File

@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"exclude": ["./node_modules/**", "./dist/**"],
"include": ["./index.d.ts", "./src/**/*.ts", "./src/**/*.js"],
"include": ["**/*.ts", "**/*.js"],
}

View File

@@ -1,5 +1,5 @@
{
"name": "@eslit/cli",
"name": "@eslegant/cli",
"version": "0.1.0",
"description": "",
"scripts": {
@@ -16,16 +16,16 @@
"source": "./src/index.js",
"files": [
"src",
"index.js",
"index.d.ts"
],
"homepage": "https://github.com/LoredDev/ESLit",
"homepage": "https://github.com/LoredDev/ESLegant",
"type": "module",
"repository": {
"directory": "packages/config",
"type": "git",
"url": "https://github.com/LoredDev/ESLit"
"url": "https://github.com/LoredDev/ESLegant"
},
"bin": "./src/index.js",
"license": "MIT",
"dependencies": {
"cardinal": "^2.1.1",
@@ -34,13 +34,13 @@
"picocolors": "^1.0.0",
"picomatch": "^2.3.1",
"prompts": "^2.4.2",
"recast": "^0.23.3",
"recast": "^0.23.4",
"sisteransi": "^1.0.5",
"yaml": "^2.3.1"
},
"devDependencies": {
"@types/estree": "^1.0.1",
"@types/node": "^20.4.2",
"@types/node": "^20.5.3",
"@types/prompts": "^2.4.4"
},
"publishConfig": {

View File

@@ -1,6 +1,5 @@
import { Command } from 'commander';
import ConfigsProcessor from './configsProcessor.js';
import configs from './configs.js';
import Workspace from './workspace.js';
import c from 'picocolors';
import path from 'node:path';
@@ -8,8 +7,8 @@ import { createSpinner } from 'nanospinner';
import count from './lib/count.js';
import prompts from 'prompts';
import ConfigsFile from './configsFile.js';
import * as cardinal from 'cardinal';
import ansi from 'sisteransi';
import cardinal from 'cardinal';
import { erase } from 'sisteransi';
import PackageInstaller from './packageInstaller.js';
import notNull from './lib/notNull.js';
@@ -22,6 +21,7 @@ export default class Cli {
/** @type {import('./types').CliArgs} */
args = {
dir: process.cwd(),
configs: [],
};
/**
@@ -29,6 +29,7 @@ export default class Cli {
*/
constructor(args) {
this.#program
.argument('[url-to-config]')
.option('--packages <string...>')
.option('--dir <path>', undefined)
.option('--merge-to-root')
@@ -44,13 +45,13 @@ export default class Cli {
this.args.dir = !this.args.dir.startsWith('/')
? path.join(process.cwd(), this.args.dir)
: this.args.dir;
}
async run() {
process.chdir(this.args.dir);
const configs = this.args.configs;
const spinner = createSpinner('Detecting workspace configuration');
const processor = new ConfigsProcessor({ configs });
@@ -71,7 +72,7 @@ export default class Cli {
c.dim(`${count.packagesWithConfigs(packages)} configs founded\n`),
});
const merge = this.args.mergeToRoot ?? packages.length > 1 ?
const merge = this.args.mergeToRoot !== undefined ? this.args.mergeToRoot : packages.length > 1 ?
/** @type {{merge: boolean}} */
(await prompts({
name: 'merge',
@@ -109,7 +110,7 @@ export default class Cli {
initial: true,
})).write;
stdout.write(ansi.erase.lines(pkg.configFile.content.split('\n').length + 2));
stdout.write(erase.lines(pkg.configFile.content.split('\n').length + 2));
if (shouldWrite) await fileHandler.write(pkg.configFile.path, pkg.configFile.content);
@@ -124,7 +125,7 @@ export default class Cli {
(await prompts({
name: 'install',
message:
`Would you like to ESLit to install the npm packages with ${c.green(installer.packageManager.name)}?`,
`Would you like to ESLit to install the npm packages with ${c.green(installer.packageManager.name)}?\n${c.reset(c.dim(` Packages to install: ${[...new Set([...packagesMap.values()])].join(' ')}\n`))}`,
choices: [
{ title: 'Yes, install all packages', value: true, description: installer.packageManager.description },
{ title: 'No, I will install them manually', value: false },
@@ -144,6 +145,9 @@ export default class Cli {
type: 'select',
});
installer.packageManager = installer.packageManagers[prompt.manager];
if (!installer.packageManager) throw console.log(c.red('You must select a package manager'));
installPkgs = true;
}

View File

@@ -1,6 +1,6 @@
import path from 'node:path';
import notNull from './lib/notNull.js';
import * as recast from 'recast';
import { parse, prettyPrint } from 'recast';
import fs from 'node:fs/promises';
import { existsSync } from 'node:fs';
import astUtils from './lib/astUtils.js';
@@ -160,7 +160,7 @@ export default class ConfigsWriter {
/** @type {{program: Program}} */
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
const { program: exportTemplateAst } = recast.parse([
const { program: exportTemplateAst } = parse([
'/** @type {import(\'eslint\').Linter.FlatConfig[]} */',
'export default [',
'',
@@ -304,7 +304,7 @@ export default class ConfigsWriter {
/** @type {{program: Program}} */
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { program: ast } = recast.parse(existingConfig, { parser: (await import('recast/parsers/babel.js')) });
const { program: ast } = parse(existingConfig, { parser: (await import('recast/parsers/babel.js')) });
await this.addDefaultExport(ast);
@@ -327,7 +327,7 @@ export default class ConfigsWriter {
this.addElementsToExport(ast, elements);
this.addPackageImports(ast, config.imports);
const finalCode = recast.prettyPrint(ast, { parser: (await import('recast/parsers/babel.js')) }).code;
const finalCode = prettyPrint(ast, { parser: (await import('recast/parsers/babel.js')) }).code;
return finalCode;
}

View File

@@ -3,7 +3,7 @@ import path from 'node:path';
import glob from 'picomatch';
import prompts from 'prompts';
import c from 'picocolors';
import str from './lib/str.js';
import capitalize from './lib/capitalize.js';
export default class ConfigsProcessor {
/** @type {string} */
@@ -75,13 +75,13 @@ export default class ConfigsProcessor {
for (const config of configs) {
/** @type {import('prompts').Choice[]} */
const configChoices = config.options.map(option => {return { title: `${str.capitalize(option.name)}`, value: option.name };});
const configChoices = config.options.map(option => {return { title: `${capitalize(option.name)}`, value: option.name };});
/** @type {Record<string, string[]>} */
const selectedOptions = await prompts({
name: config.name,
type: config.type === 'multiple' ? 'multiselect' : 'select',
message: str.capitalize(config.name),
message: capitalize(config.name),
choices: config.type === 'confirm' ? [
{
title: 'Yes',
@@ -96,7 +96,7 @@ export default class ConfigsProcessor {
instructions: instructions + c.dim(c.italic('\nSelect none if you don\'t want to use this configuration\n')),
});
if (selectedOptions[config.name] === null) continue;
if (!selectedOptions[config.name]) continue;
if (selectedOptions[config.name].length === 0) continue;

View File

@@ -1,4 +0,0 @@
import Cli from './cli.js';
const cli = new Cli();
await cli.run();

View File

@@ -1,4 +1,4 @@
import * as recast from 'recast';
import { parse, print } from 'recast';
/**
* @typedef {(
@@ -23,7 +23,7 @@ import * as recast from 'recast';
* @param {VariableInit} [init] Initial value of the variable
* @returns {VariableDeclaration} The variable declaration ast node object
*/
export function createVariable(identifier, kind = 'const', init) {
function createVariable(identifier, kind = 'const', init) {
return {
type: 'VariableDeclaration',
kind,
@@ -39,10 +39,10 @@ export function createVariable(identifier, kind = 'const', init) {
* @param {string} string The expression in string
* @returns {ExpressionOrIdentifier | undefined} The expression or identifier node of that string (undefined if string is not a expression)
*/
export function stringToExpression(string) {
function stringToExpression(string) {
/** @type {ExpressionOrIdentifier} */
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
const e = recast.parse(string).program.body[0].expression;
const e = parse(string).program.body[0].expression;
if (['MemberExpression', 'Identifier', 'CallExpression', 'NewExpression'].includes(e.type)) return e;
else return undefined;
}
@@ -52,7 +52,7 @@ export function stringToExpression(string) {
* @param {ExpressionOrIdentifier | SpreadElement} element The element to be search
* @returns {ExpressionOrIdentifier | undefined} The element of the array founded, undefined if it isn't found
*/
export function findInArray(array, element) {
function findInArray(array, element) {
/** @type {ExpressionOrIdentifier[]} */
// @ts-expect-error The array should have just tge type above
@@ -66,8 +66,8 @@ export function findInArray(array, element) {
return n;
}).filter(n => n && n.type === element.type);
const toStringElements = filteredElements.map(n => recast.print(n).code);
const toStringElement = recast.print(element).code;
const toStringElements = filteredElements.map(n => print(n).code);
const toStringElement = print(element).code;
const idx = toStringElements.findIndex(e => e === toStringElement);
return filteredElements[idx];
@@ -77,7 +77,7 @@ export function findInArray(array, element) {
* @param {ExpressionOrIdentifier} expression The expression to be spread
* @returns {SpreadElement} The spread element node
*/
export function toSpreadElement(expression) {
function toSpreadElement(expression) {
return {
type: 'SpreadElement',
argument: expression,
@@ -95,7 +95,7 @@ export function toSpreadElement(expression) {
* @param {import('estree').ImportDeclaration} [body] The body of the import declaration to start with
* @returns {ImportDeclarationHelper} A helper object for manipulating the import declaration
*/
export function createImportDeclaration(source, defaultImported, body) {
function createImportDeclaration(source, defaultImported, body) {
const helper = {
/** @type {import('estree').ImportDeclaration} */
body: body ?? {
@@ -161,10 +161,11 @@ export function createImportDeclaration(source, defaultImported, body) {
}
export default {
const astUtils = {
createVariable,
stringToExpression,
toSpreadElement,
findInArray,
createImportDeclaration,
};
export default astUtils;

View File

@@ -3,8 +3,6 @@
* @param {string} str - The string to capitalize
* @returns {string} The capitalized string
*/
function capitalize(str) {
export default function capitalize(str) {
return str[0].toUpperCase() + str.slice(1);
}
export default { capitalize };

View File

@@ -9,4 +9,5 @@ function packagesWithConfigs(packages) {
).reduce((partial, sum) => partial + sum, 0);
}
export default { packagesWithConfigs };
const count = { packagesWithConfigs };
export default count;

View File

@@ -1,11 +1,10 @@
import { existsSync } from 'node:fs';
import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { exec } from 'node:child_process';
import { createSpinner } from 'nanospinner';
import c from 'picocolors';
import * as recast from 'recast';
import { parse, prettyPrint } from 'recast';
import { readFile, writeFile } from 'node:fs/promises';
import { readFileSync } from 'node:fs';
/**
@@ -78,7 +77,7 @@ class DenoHandler {
const configFile = await readFile(configPath, 'utf8');
/** @type {{program: import('estree').Program}}*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { program: ast } = recast.parse(configFile, { parser: (await import('recast/parsers/babel.js')) });
const { program: ast } = parse(configFile, { parser: (await import('recast/parsers/babel.js')) });
ast.body.map((node) => {
if (node.type !== 'ImportDeclaration') return node;
@@ -89,7 +88,7 @@ class DenoHandler {
return node;
});
await writeFile(configPath, recast.prettyPrint(ast).code, 'utf-8');
await writeFile(configPath, prettyPrint(ast).code, 'utf-8');
console.log(c.green('Added npm: specifier to dependencies'));

View File

@@ -1,15 +1,20 @@
import type { OptionValues } from 'commander';
export type PackageManagerName = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'deno';
type PackageManagerName = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'deno';
export type CliArgs = {
type CliArgs = {
packages?: string[]
mergeToRoot?: boolean
installPkgs?: boolean | PackageManagerName
dir: string
configs: Config[]
} & OptionValues;
export type Config = {
interface PackageManagerHandler {
install(path: string, packages: string[]): Promise<void> | void
}
type Config = {
name: string
type: 'single' | 'multiple'
manual?: boolean
@@ -37,7 +42,7 @@ export type Config = {
}]
};
export interface Package {
interface Package {
root?: boolean
name: string
path: string
@@ -47,7 +52,7 @@ export interface Package {
configFile?: ConfigFile
}
export interface ConfigFile {
interface ConfigFile {
path: string
imports: Map<string, string | (string | [string, string])[]>
configs: string[]
@@ -56,6 +61,4 @@ export interface ConfigFile {
content?: string
}
export interface PackageManagerHandler {
install(path: string, packages: string[]): Promise<void> | void
}
export type { PackageManagerName, PackageManagerHandler, CliArgs, Config, Package, ConfigFile };

View File

@@ -2,7 +2,6 @@ import fs from 'node:fs/promises';
import { existsSync } from 'node:fs';
import YAML from 'yaml';
import path, { join } from 'node:path';
import glob from 'picomatch';
import picomatch from 'picomatch';
@@ -85,7 +84,7 @@ export default class Workspace {
const paths = (await fs.readdir(directory))
.map((f) => path.normalize(join(directory, f)))
.filter((p) => !glob.isMatch(p, ignores));
.filter((p) => !picomatch.isMatch(p, ignores));
/** @type {string[]} */
const files = [];

View File

@@ -1,56 +0,0 @@
import type { Config, EnvOptions } from './src/types';
import type { Linter } from 'eslint';
/**
* Helper functions for creating/configuring ESLint.
*
* @param config - Array or function returning an array of ESLint's configuration objects array to be used.
* @param environment - An object with environment variables to be declared and used by the configuration.
* @returns The array of ESLint's configuration objects.
*/
export async function defineConfig(config: Config, environment?: EnvOptions): Promise<Linter.FlatConfig[]>;
export const configs: Readonly<{
/**
* **This configuration is necessary to be used before any other one**.
* Common configuration for using ESLit rules overrides.
*/
common: Linter.FlatConfig
/**
* Recommended configuration overrides of ESLit
*/
recommended: Linter.FlatConfig
/**
* Formatting rules/configuration overrides for Javascript and Typescript
*/
formatting: Linter.FlatConfig
/**
* Typescript specific configuration overrides
*/
typescript: Linter.FlatConfig
/**
* Configuration objects for different development environments.
*/
environments: {
/**
* Configuration for Node development environment
*/
node: Linter.FlatConfig
/**
* Configuration for Deno development environment
*/
deno: Linter.FlatConfig
/**
* Configuration for browser development environment
*/
browser: Linter.FlatConfig
}
/**
* JSDoc rules overrides
*/
jsdoc: Linter.FlatConfig
}>;
export const presets: Readonly<{
default: Linter.FlatConfig[]
}>;

View File

@@ -1,26 +0,0 @@
import type { ESLint } from 'eslint';
/**
* @see {@link https://www.npmjs.org/package/eslint-plugin-jsdoc npm package}
*
* @summary JSDoc specific linting rules for ESLint.
*
* ---
* **Note:** Types in this project where overridden to be compatible with ESLint new flat
* config types. ESlint already has backwards compatibility for plugins not created in the
* new flat config.
*/
declare module 'eslint-plugin-jsdoc' {
interface jsDocESlintPlugin extends ESLint.Plugin {
configs: ESLint.Plugin['configs'] & {
recommended: ESLint.ConfigData
'recommended-error': ESLint.ConfigData
'recommended-typescript': ESLint.ConfigData
'recommended-typescript-error': ESLint.ConfigData
'recommended-typescript-flavor': ESLint.ConfigData
'recommended-typescript-flavor-error': ESLint.ConfigData
}
}
declare const plugin: jsDocESlintPlugin;
export default plugin;
}

View File

@@ -1,10 +0,0 @@
declare module 'globals' {
const globals: {
builtin: Record<string, boolean>
browser: Record<string, boolean>
node: Record<string, boolean>
nodeBuiltin: Record<string, boolean>
commonjs: Record<string, boolean>
};
export default globals;
}

View File

@@ -1,36 +0,0 @@
import tsESLint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import jsdoc from 'eslint-plugin-jsdoc';
/**
* **This configuration is necessary to be used before any other one**.
* Common configuration for using ESLit rules overrides.
*
* @type {Readonly<import('eslint').Linter.FlatConfig>}
*/
const config = {
files: ['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.cts', '**/*.mts'],
plugins: {
'@typescript-eslint': tsESLint,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
'jsdoc': jsdoc,
},
languageOptions: {
parser: tsParser,
parserOptions: {
project: process.env.ESLIT_TSCONFIG ?? [
'./{ts,js}config{.eslint,}.json',
'./packages/*/{ts,js}config{.eslint,}.json',
'./apps/*/{ts,js}config{.eslint,}.json',
],
tsconfigRootDir: process.env.ESLIT_ROOT ?? process.cwd(),
},
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
ecmaVersion: (
/** @type {import('eslint').Linter.ParserOptions['ecmaVersion']} */
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
() => {return JSON.parse(process.env.ESLIT_ECMASCRIPT ?? '"latest"');}
)(),
},
};
export default config;

View File

@@ -1,47 +0,0 @@
import globals from 'globals';
/**
* Configuration for Node development environment
*
* @type {import('eslint').Linter.FlatConfig}
*/
const node = {
files: ['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.cts', '**/*.mts'],
languageOptions: {
globals: {
...globals.nodeBuiltin,
},
},
};
/**
* Configuration for Deno development environment
*
* @type {import('eslint').Linter.FlatConfig}
*/
const deno = {
files: ['**/*.js', '**/*.ts'],
languageOptions: {
globals: {
Deno: true,
...globals.browser,
},
},
};
/**
* Configuration for browser development environment
*
* @type {import('eslint').Linter.FlatConfig}
*/
const browser = {
files: ['**/*.js', '**/*.ts'],
languageOptions: {
globals: {
Deno: true,
...globals.browser,
},
},
};
export default { node, deno, browser };

View File

@@ -1,97 +0,0 @@
/**
* Formatting rules/configuration overrides for Javascript and Typescript
*
* @type {Readonly<import('eslint').Linter.FlatConfig>}
*/
const config = {
files: ['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.cts', '**/*.mts'],
rules: {
// Formatting rules
'brace-style': 'off',
'@typescript-eslint/brace-style': ['error', 'stroustrup', { allowSingleLine: true }],
'comma-dangle': 'off',
'@typescript-eslint/comma-dangle': ['error', 'always-multiline'],
'indent': 'off',
'@typescript-eslint/indent': ['error', (() => {
/** @type {import('../types').EnvOptions['ESLIT_INDENT']} */
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const indent = JSON.parse(process.env.ESLINT_INDENT ?? '"tab"');
if (indent === 'space') return 2;
else return indent;
})(), {
SwitchCase: 1,
VariableDeclarator: 1,
outerIIFEBody: 1,
MemberExpression: 1,
FunctionDeclaration: { parameters: 1, body: 1 },
FunctionExpression: { parameters: 1, body: 1 },
CallExpression: { arguments: 1 },
ArrayExpression: 1,
ObjectExpression: 1,
ImportDeclaration: 1,
flatTernaryExpressions: false,
offsetTernaryExpressions: true,
ignoreComments: false,
ignoredNodes: [
'TemplateLiteral *',
'JSXElement',
'JSXElement > *',
'JSXAttribute',
'JSXIdentifier',
'JSXNamespacedName',
'JSXMemberExpression',
'JSXSpreadAttribute',
'JSXExpressionContainer',
'JSXOpeningElement',
'JSXClosingElement',
'JSXFragment',
'JSXOpeningFragment',
'JSXClosingFragment',
'JSXText',
'JSXEmptyExpression',
'JSXSpreadChild',
'TSTypeParameterInstantiation',
'FunctionExpression > .params[decorators.length > 0]',
'FunctionExpression > .params > :matches(Decorator, :not(:first-child))',
'ClassBody.body > PropertyDefinition[decorators.length > 0] > .key',
],
}],
'keyword-spacing': 'off',
'@typescript-eslint/keyword-spacing': ['error', { before: true, after: true }],
'lines-between-class-members': 'off',
'@typescript-eslint/lines-between-class-members': ['error'],
'no-extra-parens': 'off',
'@typescript-eslint/no-extra-parens': ['error', 'functions'],
'object-curly-spacing': 'off',
'@typescript-eslint/object-curly-spacing': ['error', 'always'],
'quotes': 'off',
'@typescript-eslint/quotes': ['error', process.env.ESLINT_QUOTES ?? 'single'],
'semi': 'off',
'@typescript-eslint/semi': ['error', 'always'],
'space-before-blocks': 'off',
'@typescript-eslint/space-before-blocks': ['error', process.env.ESLIT_SEMI ?? 'always'],
'space-before-function-paren': 'off',
'@typescript-eslint/space-before-function-paren': ['error', {
anonymous: 'always',
named: 'never',
asyncArrow: 'always',
}],
'space-infix-ops': 'off',
'@typescript-eslint/space-infix-ops': 'error',
},
};
export default config;

View File

@@ -1,8 +0,0 @@
import formatting from './formatting.js';
import jsdoc from './jsdoc.js';
import typescript from './typescript.js';
import recommended from './recommended.js';
import environments from './environments.js';
import common from './common.js';
export default { formatting, jsdoc, typescript, recommended, environments, common };

View File

@@ -1,15 +0,0 @@
import jsdoc from 'eslint-plugin-jsdoc';
/**
* JSDoc rules overrides
* @type {Readonly<import('eslint').Linter.FlatConfig>}
*/
const config = {
files: ['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.cts', '**/*.mts'],
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
rules: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
...jsdoc.configs['recommended-typescript-flavor-error'].rules,
},
};
export default config;

View File

@@ -1,42 +0,0 @@
import tsESlint from '@typescript-eslint/eslint-plugin';
import js from '@eslint/js';
/**
* Recommended configuration overrides of ESLit
*
* @type {Readonly<import('eslint').Linter.FlatConfig>}
*/
const config = {
rules: {
...js.configs.recommended.rules,
...tsESlint.configs.recommended.rules,
...tsESlint.configs['recommended-requiring-type-checking'].rules,
...tsESlint.configs['eslint-recommended'].rules,
...tsESlint.configs.strict.rules,
'@typescript-eslint/ban-ts-comment': ['error', {
'ts-ignore': 'allow-with-description',
}],
'@typescript-eslint/ban-tslint-comment': 'error',
'@typescript-eslint/no-require-imports': 'error',
// Extension rules
'no-dupe-class-members': 'off',
'@typescript-eslint/no-dupe-class-members': 'error',
'no-invalid-this': 'off',
'@typescript-eslint/no-invalid-this': 'error',
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': 'error',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'error',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': 'error',
},
};
export default config;

View File

@@ -1,65 +0,0 @@
import jsdoc from 'eslint-plugin-jsdoc';
/**
* Typescript specific configuration overrides
*
* @type {Readonly<import('eslint').Linter.FlatConfig>}
*/
const config = {
files: ['**/*.ts', '**/*.cts', '**/*.mts'],
// See plugins['jsdoc'] on index.js for more info on this error
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
rules: {
// See plugins['jsdoc'] on index.js for more info on this error
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
...jsdoc.configs['recommended-typescript-error'].rules,
'@typescript-eslint/adjacent-overload-signatures': 'error',
'@typescript-eslint/array-type': 'error',
'@typescript-eslint/class-literal-property-style': 'error',
'@typescript-eslint/consistent-generic-constructors': 'error',
'@typescript-eslint/consistent-indexed-object-style': 'error',
'@typescript-eslint/consistent-type-assertions': 'error',
'@typescript-eslint/consistent-type-definitions': 'error',
'@typescript-eslint/consistent-type-exports': ['error'],
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports', disallowTypeAnnotations: true }],
'@typescript-eslint/no-confusing-non-null-assertion': 'error',
'@typescript-eslint/member-delimiter-style': ['error', { multiline: { delimiter: 'none' } }],
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/prefer-function-type': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
...(
/** @type {() => import('eslint').Linter.RulesRecord} */
() => {
/** @type {import('../types').inferrableTypesOptions} */
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const inferrableTypes = JSON.parse(process.env.ESLIT_INFER_TYPES ?? '"never"');
if (typeof inferrableTypes === 'string') {
return {
'@typescript-eslint/explicit-function-return-type': inferrableTypes === 'always' ? 'off' : 'error',
'@typescript-eslint/no-inferrable-types': inferrableTypes === 'always' ? 'off' : 'error',
};
}
else {
return {
'@typescript-eslint/explicit-function-return-type': inferrableTypes[1].returnValues ? 'off' : 'error',
'@typescript-eslint/no-inferrable-types': [
inferrableTypes[0] === 'always' ? 'off' : 'error',
{
ignoreParameters: inferrableTypes[1].parameters ?? false,
ignoreProperties: inferrableTypes[1].properties ?? false,
},
],
};
}
}
)(),
},
};
export default config;

View File

@@ -1,15 +0,0 @@
import { FlatCompat } from '@eslint/eslintrc';
import javascript from '@eslint/js';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
// mimic CommonJS variables
export const __filename = fileURLToPath(import.meta.url);
export const __dirname = path.dirname(__filename);
export const eslintrc = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: javascript.configs.recommended,
allConfig: javascript.configs.all,
});

View File

@@ -1,22 +0,0 @@
import { eslintrc } from './eslintrc-compact.js';
/**
* @param {import('./types').Config} config
* Array or function returning an array of ESLint's configuration objects array to be used.
*
* @param {import('./types').EnvOptions | undefined} environment
* An object with environment variables to be declared and used by the configuration.
*
* @returns {Promise<import('eslint').Linter.FlatConfig[]>}
* The array of ESLint's configuration objects.
*/
export async function defineConfig(config, environment = {}) {
for (const [key, value] of Object.entries(environment)) {
process.env[key] = JSON.stringify(value);
}
return typeof config === 'function' ? await config(eslintrc) : config;
}
export { default as configs } from './configs/index.js';
export { default as presets } from './presets/index.js';

View File

@@ -1,23 +0,0 @@
import configs from '../configs/index.js';
/**
* @type {Readonly<import('eslint').Linter.FlatConfig[]>}
*/
const preset = [
{
ignores: [
'**/node_modules',
'**/dist',
'**/fixtures',
'**/pnpm-lock.yaml',
'**/yarn.lock',
'**/package-lock.json',
],
},
configs.common,
configs.recommended,
configs.formatting,
configs.jsdoc,
configs.typescript,
];
export default preset;

View File

@@ -1,4 +0,0 @@
import defaultPreset from './default.js';
export default { default: defaultPreset };

View File

@@ -1,56 +0,0 @@
import type { FlatCompat } from '@eslint/eslintrc';
import type { Linter } from 'eslint';
type MaybePromise<T> = Promise<T> | T;
export type Config = Linter.FlatConfig[] | ((eslintrc: FlatCompat) => MaybePromise<Linter.FlatConfig[]>);
export interface EnvOptions {
ESLIT_TSCONFIG?: string | string[] | true
ESLIT_ROOT?: string
ESLIT_INDENT?: 'tab' | 'space' | number
ESLIT_ECMASCRIPT?: Linter.ParserOptions['ecmaVersion']
ESLIT_QUOTES?: 'single' | 'double'
ESLIT_SEMI?: 'never' | 'always'
/**
* Typescript's type-checking is able to infer types from parameters.
* So using an explicit `:` type annotation isn't obligatory.
*
* But, **by default in strict mode**, type annotations are always mandated to make
* the code more readable, explicit and robust to changes.
*
* See {@link https://typescript-eslint.io/rules/no-inferrable-types typescript-eslint documentation }
* for more info.
* ---
* **Option: `never`** (default)
* Types are always explicit in Typescript
*
* @example ```ts
// Typescript
const id: number = 10;
const name: string = 'foo';
```
* ---
* **Option: `always`**
* Types are always inferred in Typescript
*
* @example ```ts
// Typescript
const id = 10;
const name = 'foo';
```
*/
ESLIT_INFER_TYPES?: inferrableTypesOptions
[ENV: string]: unknown
}
export type inferrableTypesOptions = [
'never' | 'always',
{
/** @see {@link https://typescript-eslint.io/rules/no-inferrable-types#ignoreparameters} */
parameters?: boolean
/** @see {@link https://typescript-eslint.io/rules/no-inferrable-types#ignoreproperties} */
properties?: boolean
/** @see {@link https://typescript-eslint.io/rules/explicit-function-return-type} */
returnValues?: boolean
},
] | 'never' | 'always';

View File

@@ -0,0 +1,4 @@
import Cli from '@eslegant/cli';
const cli = new Cli({ configs: (await import('./configs.js')).default, dir: process.cwd() });
await cli.run();

View File

@@ -1,6 +1,6 @@
/** @type {import('./types').Config[]} */
export default [
/** @type {import('@eslegant/cli').Config[]} */
const cliConfig = [
{
name: 'framework',
type: 'multiple',
@@ -31,3 +31,4 @@ export default [
}],
},
];
export default cliConfig;

View File

@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"exclude": ["./node_modules/**", "./dist/**"],
"include": ["./index.d.ts", "./src/**/*.ts", "./src/**/*.js"],
"include": ["**/*.ts", "**/*.js"],
}

View File

@@ -0,0 +1,33 @@
{
"name": "create-eslegant",
"version": "0.1.0",
"description": "",
"keywords": [],
"author": {
"email": "contact.guz013@gmail.com",
"name": "Gustavo \"Guz\" L. de Mello",
"url": "https://guz.one"
},
"files": [
"./bin.js",
"./configs.js"
],
"dependencies": {
"@eslegant/cli": "workspace:*"
},
"homepage": "https://github.com/LoredDev/ESLegant",
"type": "module",
"repository": {
"directory": "packages/create-eslegant",
"type": "git",
"url": "https://github.com/LoredDev/ESLegant"
},
"bin": "./bin.js",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@types/node": "^20.5.3"
}
}

4
packages/eslegant/bin.js Executable file
View File

@@ -0,0 +1,4 @@
import Cli from '@eslegant/cli';
const cli = new Cli({ configs: (await import('./configs.js')).default, dir: process.cwd() });
await cli.run();

View File

@@ -0,0 +1,34 @@
/** @type {import('@eslegant/cli').Config[]} */
const cliConfig = [
{
name: 'framework',
type: 'multiple',
description: 'The UI frameworks being used in the project',
options: [
{
name: 'svelte',
packages: { 'svelte': 'svelte' },
configs: ['svelte.recommended'],
detect: ['**/*.svelte', 'svelte.config.{js,ts,cjs,cts}'],
},
{
name: 'vue',
packages: { 'vue': ['vue', ['hello', 'world']], 'svelte': ['hello'] },
configs: ['vue.recommended'],
detect: ['nuxt.config.{js,ts,cjs,cts}', '**/*.vue'],
},
],
},
{
name: 'strict',
type: 'confirm',
manual: true,
options: [{
name: 'yes',
packages: { 'eslint': 'config', 'svelte': ['test1'] },
configs: ['config.strict'],
}],
},
];
export default cliConfig;

View File

@@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.json",
"exclude": ["./node_modules/**", "./dist/**"],
"include": ["**/*.ts", "**/*.js"],
}

View File

@@ -0,0 +1,33 @@
{
"name": "eslegant",
"version": "0.1.0",
"description": "",
"keywords": [],
"author": {
"email": "contact.guz013@gmail.com",
"name": "Gustavo \"Guz\" L. de Mello",
"url": "https://guz.one"
},
"files": [
"./bin.js",
"./configs.js"
],
"dependencies": {
"@eslegant/cli": "workspace:*"
},
"homepage": "https://github.com/LoredDev/ESLegant",
"type": "module",
"repository": {
"directory": "packages/eslegant",
"type": "git",
"url": "https://github.com/LoredDev/ESLegant"
},
"bin": "./bin.js",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@types/node": "^20.5.3"
}
}

1151
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
packages:
- 'packages/*'
- 'fixtures/*'
- 'configs/*'

View File

@@ -13,6 +13,6 @@
"alwaysStrict": true,
"outDir": "./dir"
},
"include": ["eslint.config.js", "commitlint.config.cjs"],
"include": ["./eslint.config.js", "./commitlint.config.cjs"],
"exclude": ["./node_modules/**", "./dist/**"]
}