feat: automatic workspace config
Added feature to detect automatically monorepos and it's tsconfig.json and jsconfig.json files
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import { defineConfig } from 'readable';
|
import { defineConfig } from 'readable';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
tsconfig: ['./tsconfig.json', './packages/*/tsconfig.json', './packages/*/jsconfig.json'],
|
|
||||||
environment: {
|
environment: {
|
||||||
node: true,
|
node: true,
|
||||||
},
|
},
|
||||||
|
|||||||
2
packages/core/index.d.ts
vendored
2
packages/core/index.d.ts
vendored
@@ -1,3 +1,3 @@
|
|||||||
import type { Config, ESConfig } from './src/types';
|
import type { Config, ESConfig } from './src/types';
|
||||||
|
|
||||||
export function defineConfig(config: Config): ESConfig[];
|
export async function defineConfig(config: Config): Promise<ESConfig[]>;
|
||||||
|
|||||||
@@ -23,13 +23,14 @@
|
|||||||
"@eslint/js": "^8.44.0",
|
"@eslint/js": "^8.44.0",
|
||||||
"@types/eslint__js": "^8.42.0",
|
"@types/eslint__js": "^8.42.0",
|
||||||
"@types/node": "^20.4.1",
|
"@types/node": "^20.4.1",
|
||||||
"eslint": "^8.44.0"
|
"eslint": "^8.44.0",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/eslintrc": "^2.1.0",
|
"@eslint/eslintrc": "^2.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "^5.45.0",
|
"@typescript-eslint/parser": "^5.45.0",
|
||||||
"globals": "^13.20.0",
|
"globals": "^13.20.0",
|
||||||
"typescript": "^5.0.0"
|
"yaml": "^2.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
packages/core/src/@types/globals.d.ts
vendored
Normal file
10
packages/core/src/@types/globals.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import tsEslint from '@typescript-eslint/eslint-plugin';
|
|||||||
import tsParser from '@typescript-eslint/parser';
|
import tsParser from '@typescript-eslint/parser';
|
||||||
import js from '@eslint/js';
|
import js from '@eslint/js';
|
||||||
import * as configs from './configs/index.js';
|
import * as configs from './configs/index.js';
|
||||||
|
import { getTsConfigs } from './tsconfigs.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import('./types').Config} userConfig
|
* @param {import('./types').Config} userConfig
|
||||||
@@ -12,6 +13,8 @@ import * as configs from './configs/index.js';
|
|||||||
export async function defineConfig(userConfig) {
|
export async function defineConfig(userConfig) {
|
||||||
|
|
||||||
userConfig.strict ??= true;
|
userConfig.strict ??= true;
|
||||||
|
userConfig.rootDir ??= process.cwd();
|
||||||
|
userConfig.tsconfig ??= await getTsConfigs(userConfig.rootDir);
|
||||||
|
|
||||||
process.env.READABLE_ESLINT_STRICT = userConfig.strict;
|
process.env.READABLE_ESLINT_STRICT = userConfig.strict;
|
||||||
process.env.READABLE_ESLINT_OPTIONS = {
|
process.env.READABLE_ESLINT_OPTIONS = {
|
||||||
@@ -33,7 +36,7 @@ export async function defineConfig(userConfig) {
|
|||||||
},
|
},
|
||||||
js.configs.recommended,
|
js.configs.recommended,
|
||||||
{
|
{
|
||||||
files: ['**/*.js', '**/*.ts'],
|
files: ['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.cts', '**/*.mts'],
|
||||||
plugins: {
|
plugins: {
|
||||||
'@typescript-eslint': tsEslint,
|
'@typescript-eslint': tsEslint,
|
||||||
},
|
},
|
||||||
@@ -42,7 +45,7 @@ export async function defineConfig(userConfig) {
|
|||||||
parser: tsParser,
|
parser: tsParser,
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: userConfig.tsconfig,
|
project: userConfig.tsconfig,
|
||||||
tsconfigRootDir: userConfig.rootDir ?? process.cwd(),
|
tsconfigRootDir: userConfig.rootDir,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
|
|||||||
87
packages/core/src/tsconfigs.js
Normal file
87
packages/core/src/tsconfigs.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { existsSync } from 'node:fs';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
import { join, normalize } from 'node:path';
|
||||||
|
|
||||||
|
/** @type {(...path: string[]) => string} */
|
||||||
|
function toPath(...path) {
|
||||||
|
return normalize(join(...path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {(...path: string[]) => boolean} */
|
||||||
|
function exists(...path) {
|
||||||
|
return existsSync(toPath(...path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} directory
|
||||||
|
* @returns {Promise<string[]>}
|
||||||
|
*/
|
||||||
|
async function getMonorepoConfigs(directory) {
|
||||||
|
|
||||||
|
/** @type {string[]} */
|
||||||
|
const paths = [];
|
||||||
|
|
||||||
|
if (exists(directory, 'pnpm-workspace.yaml') || exists(directory, 'pnpm-workspace.yml')) {
|
||||||
|
|
||||||
|
const YAML = await import('yaml');
|
||||||
|
|
||||||
|
const yamlFilePath = exists(directory, 'pnpm-workspace.yaml')
|
||||||
|
? join(directory, 'pnpm-workspace.yaml')
|
||||||
|
: join(directory, 'pnpm-workspace.yml');
|
||||||
|
|
||||||
|
/** @type {{packages?: string[], [properties: string]: unknown}} */
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
|
const pnpmWorkspaces = YAML.parse(await readFile(yamlFilePath, 'utf-8'));
|
||||||
|
|
||||||
|
const files = pnpmWorkspaces.packages?.map(w => [
|
||||||
|
toPath(directory, w, 'tsconfig.json'),
|
||||||
|
toPath(directory, w, 'jsconfig.json'),
|
||||||
|
]).flat() ?? [];
|
||||||
|
|
||||||
|
paths.push(...files);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (exists(directory, 'package.json')) {
|
||||||
|
/** @type {{workspaces?: string[], [properties: string]: unknown}} */
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
|
const packageJson = JSON.parse(await readFile(join(directory, 'package.json'), 'utf-8'));
|
||||||
|
|
||||||
|
const files = packageJson.workspaces?.map(w => [
|
||||||
|
toPath(directory, w, 'tsconfig.json'),
|
||||||
|
toPath(directory, w, 'jsconfig.json'),
|
||||||
|
]).flat() ?? [];
|
||||||
|
|
||||||
|
paths.push(...files);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} directory
|
||||||
|
* @returns {Promise<string[]>}
|
||||||
|
*/
|
||||||
|
export async function getTsConfigs(directory) {
|
||||||
|
|
||||||
|
const rootTSConfig = exists(directory, 'tsconfig.eslint.json')
|
||||||
|
? toPath(directory, 'tsconfig.eslint.json')
|
||||||
|
: exists(directory, 'tsconfig.json')
|
||||||
|
? toPath(directory, 'tsconfig.json')
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const rootJSConfig = exists(directory, 'jsconfig.eslint.json')
|
||||||
|
? toPath(directory, 'jsconfig.eslint.json')
|
||||||
|
: exists(directory, 'jsconfig.json')
|
||||||
|
? toPath(directory, 'jsconfig.json')
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const monorepoConfigs = await getMonorepoConfigs(directory);
|
||||||
|
|
||||||
|
const paths = /** @type {string[]} */
|
||||||
|
([rootTSConfig, rootJSConfig, ...monorepoConfigs]).filter(p => p);
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
|
||||||
|
}
|
||||||
14
pnpm-lock.yaml
generated
14
pnpm-lock.yaml
generated
@@ -87,9 +87,9 @@ importers:
|
|||||||
globals:
|
globals:
|
||||||
specifier: ^13.20.0
|
specifier: ^13.20.0
|
||||||
version: 13.20.0
|
version: 13.20.0
|
||||||
typescript:
|
yaml:
|
||||||
specifier: ^5.0.0
|
specifier: ^2.3.1
|
||||||
version: 5.1.6
|
version: 2.3.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^8.44.0
|
specifier: ^8.44.0
|
||||||
@@ -103,6 +103,9 @@ importers:
|
|||||||
eslint:
|
eslint:
|
||||||
specifier: ^8.44.0
|
specifier: ^8.44.0
|
||||||
version: 8.44.0
|
version: 8.44.0
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.1.6
|
||||||
|
version: 5.1.6
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -3476,6 +3479,11 @@ packages:
|
|||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/yaml@2.3.1:
|
||||||
|
resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==}
|
||||||
|
engines: {node: '>= 14'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/yargs-parser@18.1.3:
|
/yargs-parser@18.1.3:
|
||||||
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
|
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
"alwaysStrict": true,
|
"alwaysStrict": true,
|
||||||
"outDir": "./dir"
|
"outDir": "./dir"
|
||||||
},
|
},
|
||||||
"include": ["**/*.ts", "**/*.js"],
|
"include": ["eslint.config.js", "commitlint.config.cjs"],
|
||||||
"exclude": ["./node_modules/**", "./dist/**"]
|
"exclude": ["./node_modules/**", "./dist/**"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user