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';
|
||||
|
||||
export default defineConfig({
|
||||
tsconfig: ['./tsconfig.json', './packages/*/tsconfig.json', './packages/*/jsconfig.json'],
|
||||
environment: {
|
||||
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';
|
||||
|
||||
export function defineConfig(config: Config): ESConfig[];
|
||||
export async function defineConfig(config: Config): Promise<ESConfig[]>;
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
"@eslint/js": "^8.44.0",
|
||||
"@types/eslint__js": "^8.42.0",
|
||||
"@types/node": "^20.4.1",
|
||||
"eslint": "^8.44.0"
|
||||
"eslint": "^8.44.0",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/eslintrc": "^2.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.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 js from '@eslint/js';
|
||||
import * as configs from './configs/index.js';
|
||||
import { getTsConfigs } from './tsconfigs.js';
|
||||
|
||||
/**
|
||||
* @param {import('./types').Config} userConfig
|
||||
@@ -12,6 +13,8 @@ import * as configs from './configs/index.js';
|
||||
export async function defineConfig(userConfig) {
|
||||
|
||||
userConfig.strict ??= true;
|
||||
userConfig.rootDir ??= process.cwd();
|
||||
userConfig.tsconfig ??= await getTsConfigs(userConfig.rootDir);
|
||||
|
||||
process.env.READABLE_ESLINT_STRICT = userConfig.strict;
|
||||
process.env.READABLE_ESLINT_OPTIONS = {
|
||||
@@ -33,7 +36,7 @@ export async function defineConfig(userConfig) {
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
files: ['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.cts', '**/*.mts'],
|
||||
plugins: {
|
||||
'@typescript-eslint': tsEslint,
|
||||
},
|
||||
@@ -42,7 +45,7 @@ export async function defineConfig(userConfig) {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
project: userConfig.tsconfig,
|
||||
tsconfigRootDir: userConfig.rootDir ?? process.cwd(),
|
||||
tsconfigRootDir: userConfig.rootDir,
|
||||
},
|
||||
},
|
||||
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:
|
||||
specifier: ^13.20.0
|
||||
version: 13.20.0
|
||||
typescript:
|
||||
specifier: ^5.0.0
|
||||
version: 5.1.6
|
||||
yaml:
|
||||
specifier: ^2.3.1
|
||||
version: 2.3.1
|
||||
devDependencies:
|
||||
'@eslint/js':
|
||||
specifier: ^8.44.0
|
||||
@@ -103,6 +103,9 @@ importers:
|
||||
eslint:
|
||||
specifier: ^8.44.0
|
||||
version: 8.44.0
|
||||
typescript:
|
||||
specifier: ^5.1.6
|
||||
version: 5.1.6
|
||||
|
||||
packages:
|
||||
|
||||
@@ -3476,6 +3479,11 @@ packages:
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/yaml@2.3.1:
|
||||
resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==}
|
||||
engines: {node: '>= 14'}
|
||||
dev: false
|
||||
|
||||
/yargs-parser@18.1.3:
|
||||
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
"alwaysStrict": true,
|
||||
"outDir": "./dir"
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.js"],
|
||||
"include": ["eslint.config.js", "commitlint.config.cjs"],
|
||||
"exclude": ["./node_modules/**", "./dist/**"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user