@isentinel/eslint-config 6.0.0-beta.42 → 6.0.0-beta.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -0
- package/dist/cli.mjs +5 -2
- package/dist/index.d.mts +73 -3
- package/dist/index.mjs +75 -8
- package/dist/lint-cli.mjs +73 -13
- package/dist/oxlint.d.mts +67 -1
- package/dist/oxlint.mjs +6 -2
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -890,6 +890,49 @@ otherwise, you can install them manually:
|
|
|
890
890
|
pnpm i -D eslint-plugin-eslint-plugin
|
|
891
891
|
```
|
|
892
892
|
|
|
893
|
+
#### Co-located Tests
|
|
894
|
+
|
|
895
|
+
`projectStructure` requires every source file to sit next to its test file,
|
|
896
|
+
through
|
|
897
|
+
[eslint-plugin-project-structure](https://github.com/Igorkowalski94/eslint-plugin-project-structure).
|
|
898
|
+
`src/place-service.ts` then has to be joined by `src/place-service.spec.ts`.
|
|
899
|
+
Only `enforceExistence` is driven here, so the rule never enforces naming:
|
|
900
|
+
|
|
901
|
+
```ts
|
|
902
|
+
// eslint.config.ts
|
|
903
|
+
import isentinel from "@isentinel/eslint-config";
|
|
904
|
+
|
|
905
|
+
export default isentinel({
|
|
906
|
+
projectStructure: {
|
|
907
|
+
// The plugin's name placeholders, plus `{ext}` for the extension of the
|
|
908
|
+
// file that matched. Default: ["{node-name}.spec.{ext}"]
|
|
909
|
+
enforceExistence: "__tests__/{node-name}.test.{ext}",
|
|
910
|
+
// Default: every source file the preset lints
|
|
911
|
+
files: ["src/**/*.{ts,tsx}"],
|
|
912
|
+
// Default: tests, `.d.ts` files and build configs
|
|
913
|
+
ignores: ["**/index.ts"],
|
|
914
|
+
// Default: `process.cwd()`
|
|
915
|
+
projectRoot: import.meta.dirname,
|
|
916
|
+
// Restricts the check to one subtree. Default: all of `projectRoot`
|
|
917
|
+
structureRoot: "src",
|
|
918
|
+
},
|
|
919
|
+
});
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
```bash
|
|
923
|
+
pnpm i -D eslint-plugin-project-structure
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
`{node-name}` matches the kebab-case filenames the preset enforces; the others
|
|
927
|
+
are `{nodeName}`, `{NodeName}`, `{node_name}` and `{NODE_NAME}`. A file already
|
|
928
|
+
matching a template is exempt from it. A source file with no test disables the
|
|
929
|
+
rule at the source.
|
|
930
|
+
|
|
931
|
+
Two caveats. Deleting `foo.spec.ts` does not change `foo.ts`, so a cached run
|
|
932
|
+
replays the old clean result — the check is only sound uncached. And the plugin
|
|
933
|
+
writes `projectStructure.cache.json` into `projectRoot` while it has something
|
|
934
|
+
to report, so gitignore it.
|
|
935
|
+
|
|
893
936
|
### Git hooks
|
|
894
937
|
|
|
895
938
|
If you want to apply lint and auto-fix before every commit, use
|
package/dist/cli.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import path from "node:path";
|
|
|
9
9
|
import { existsSync, readFileSync } from "fs";
|
|
10
10
|
import { execSync } from "node:child_process";
|
|
11
11
|
//#region package.json
|
|
12
|
-
var version = "6.0.0-beta.
|
|
12
|
+
var version = "6.0.0-beta.43";
|
|
13
13
|
var package_default = {
|
|
14
14
|
name: "@isentinel/eslint-config",
|
|
15
15
|
version,
|
|
@@ -155,6 +155,7 @@ var package_default = {
|
|
|
155
155
|
"eslint-plugin-jest": "catalog:peer",
|
|
156
156
|
"eslint-plugin-jest-extended": "catalog:peer",
|
|
157
157
|
"eslint-plugin-n": "catalog:peer",
|
|
158
|
+
"eslint-plugin-project-structure": "catalog:peer",
|
|
158
159
|
"eslint-plugin-react-jsx": "catalog:peer",
|
|
159
160
|
"eslint-plugin-react-naming-convention": "catalog:peer",
|
|
160
161
|
"eslint-plugin-react-x": "catalog:peer",
|
|
@@ -179,6 +180,7 @@ var package_default = {
|
|
|
179
180
|
"eslint-plugin-jest": "^29.15.0",
|
|
180
181
|
"eslint-plugin-jest-extended": "^3.0.0",
|
|
181
182
|
"eslint-plugin-n": "^17.0.0 || ^18.0.0",
|
|
183
|
+
"eslint-plugin-project-structure": "^3.14.0",
|
|
182
184
|
"eslint-plugin-react-jsx": "^5.10.0",
|
|
183
185
|
"eslint-plugin-react-naming-convention": "^5.10.0",
|
|
184
186
|
"eslint-plugin-react-x": "^5.10.0",
|
|
@@ -192,6 +194,7 @@ var package_default = {
|
|
|
192
194
|
"eslint-plugin-jest": { "optional": true },
|
|
193
195
|
"eslint-plugin-jest-extended": { "optional": true },
|
|
194
196
|
"eslint-plugin-n": { "optional": true },
|
|
197
|
+
"eslint-plugin-project-structure": { "optional": true },
|
|
195
198
|
"eslint-plugin-react-jsx": { "optional": true },
|
|
196
199
|
"eslint-plugin-react-naming-convention": { "optional": true },
|
|
197
200
|
"eslint-plugin-react-x": { "optional": true },
|
|
@@ -531,7 +534,7 @@ async function updateEslintFiles(result) {
|
|
|
531
534
|
//#endregion
|
|
532
535
|
//#region src/cli/constants-generated.ts
|
|
533
536
|
const versionsMap = {
|
|
534
|
-
"eslint": "10.
|
|
537
|
+
"eslint": "10.8.1",
|
|
535
538
|
"eslint-plugin-jest": "29.16.0",
|
|
536
539
|
"eslint-plugin-react-jsx": "5.17.3",
|
|
537
540
|
"eslint-plugin-react-naming-convention": "5.17.3",
|
package/dist/index.d.mts
CHANGED
|
@@ -6488,6 +6488,7 @@ interface OverrideSiteChains {
|
|
|
6488
6488
|
jsonc: [JsoncRuleDefaults];
|
|
6489
6489
|
markdown: [MarkdownRuleDefaults];
|
|
6490
6490
|
naming: FeatureChain;
|
|
6491
|
+
projectStructure: FeatureChain;
|
|
6491
6492
|
react: ReactChain;
|
|
6492
6493
|
roblox: MainChain;
|
|
6493
6494
|
toml: [TomlRuleDefaults];
|
|
@@ -6497,7 +6498,7 @@ interface OverrideSiteChains {
|
|
|
6497
6498
|
type TestChain = [TestRuleDefaults, SourceFeatureRuleDefaults, MainRuleDefaults];
|
|
6498
6499
|
type ValidateOptionsWith<O, VK extends VariantKey> = ValidateSite<O, "rules", MainChain, VK> & ValidateSubOptionsFromTable<O, OverrideSiteChains, VK> & ValidateTestOption<O, TestChain, VK>;
|
|
6499
6500
|
//#endregion
|
|
6500
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/
|
|
6501
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/0a594adbd94ca75e2950b1104992894d49bc93f4f2bc935ad192d7104e4c271e/node_modules/eslint-config-flat-gitignore/dist/index.d.mts
|
|
6501
6502
|
interface FlatGitignoreOptions {
|
|
6502
6503
|
/**
|
|
6503
6504
|
* Name of the configuration.
|
|
@@ -10470,6 +10471,21 @@ interface RuleOptions {
|
|
|
10470
10471
|
* @see https://eslint.org/docs/latest/rules/preserve-caught-error
|
|
10471
10472
|
*/
|
|
10472
10473
|
'preserve-caught-error'?: Linter.RuleEntry<PreserveCaughtError>;
|
|
10474
|
+
/**
|
|
10475
|
+
* Enforce advanced naming rules and prohibit the use of given selectors in a given file. Have full control over what your file can contain and the naming conventions it must follow.
|
|
10476
|
+
* @see https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bfile%E2%80%91composition#root
|
|
10477
|
+
*/
|
|
10478
|
+
'project-structure/file-composition'?: Linter.RuleEntry<ProjectStructureFileComposition>;
|
|
10479
|
+
/**
|
|
10480
|
+
* Enforce rules on folder structure to keep your repository consistent, orderly and well thought out.
|
|
10481
|
+
* @see https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bfolder%E2%80%91structure#root
|
|
10482
|
+
*/
|
|
10483
|
+
'project-structure/folder-structure'?: Linter.RuleEntry<ProjectStructureFolderStructure>;
|
|
10484
|
+
/**
|
|
10485
|
+
* A key principle of a healthy project is to prevent the creation of a massive dependency tree, where removing or editing one feature triggers a chain reaction that impacts the entire project. Create independent modules to keep your project scalable and easy to maintain. Get rid of dependencies between modules and create truly independent functionalities.
|
|
10486
|
+
* @see https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bindependent%E2%80%91modules#root
|
|
10487
|
+
*/
|
|
10488
|
+
'project-structure/independent-modules'?: Linter.RuleEntry<ProjectStructureIndependentModules>;
|
|
10473
10489
|
/**
|
|
10474
10490
|
* Require returning inside each `then()` to create readable and reusable Promise chains.
|
|
10475
10491
|
* @see https://github.com/eslint-community/eslint-plugin-promise/blob/main/docs/rules/always-return.md
|
|
@@ -23278,6 +23294,18 @@ type PreserveCaughtError = [] | [{
|
|
|
23278
23294
|
argumentPosition: number;
|
|
23279
23295
|
})[];
|
|
23280
23296
|
}];
|
|
23297
|
+
// ----- project-structure/file-composition -----
|
|
23298
|
+
type ProjectStructureFileComposition = [] | [{
|
|
23299
|
+
[k: string]: unknown | undefined;
|
|
23300
|
+
}];
|
|
23301
|
+
// ----- project-structure/folder-structure -----
|
|
23302
|
+
type ProjectStructureFolderStructure = [] | [{
|
|
23303
|
+
[k: string]: unknown | undefined;
|
|
23304
|
+
}];
|
|
23305
|
+
// ----- project-structure/independent-modules -----
|
|
23306
|
+
type ProjectStructureIndependentModules = [] | [{
|
|
23307
|
+
[k: string]: unknown | undefined;
|
|
23308
|
+
}];
|
|
23281
23309
|
// ----- promise/always-return -----
|
|
23282
23310
|
type PromiseAlwaysReturn = [] | [{
|
|
23283
23311
|
ignoreLastCallback?: boolean;
|
|
@@ -27158,7 +27186,7 @@ type Yoda = [] | [("always" | "never")] | [("always" | "never"), {
|
|
|
27158
27186
|
onlyEquality?: boolean;
|
|
27159
27187
|
}];
|
|
27160
27188
|
// Names of all the configs
|
|
27161
|
-
type ConfigNames = 'isentinel/eslint/comments' | 'isentinel/eslint/comments/src' | 'isentinel/e18e/rules' | 'isentinel/eslint-plugin/setup' | 'isentinel/eslint-plugin/rules' | 'isentinel/flawless/setup' | 'isentinel/flawless/rules' | 'isentinel/flawless/markdown-code' | 'isentinel/flawless/rules-type-aware' | 'isentinel/gitignore' | 'isentinel/ignores' | 'isentinel/imports/rules' | 'isentinel/imports/game' | 'isentinel/javascript/setup' | 'isentinel/javascript/rules' | 'isentinel/jsdoc/setup' | 'isentinel/jsdoc' | 'isentinel/jsonc/setup' | 'isentinel/jsonc/rules' | 'isentinel/jsonc/tsconfig' | 'isentinel/markdown/setup' | 'isentinel/markdown/processor' | 'isentinel/markdown/parser' | 'isentinel/markdown/disables' | 'isentinel/naming/setup' | 'isentinel/naming/ts/rules-type-aware' | 'isentinel/naming/tsx/rules-type-aware' | 'isentinel/node/rules' | 'isentinel/oxfmt/setup' | 'isentinel/oxfmt/javascript' | 'isentinel/oxfmt/typescript' | 'isentinel/oxfmt/css' | 'isentinel/oxfmt/scss' | 'isentinel/oxfmt/less' | 'isentinel/oxfmt/html' | 'isentinel/oxfmt/markdown' | 'isentinel/oxfmt/graphql' | 'isentinel/oxfmt/json' | 'isentinel/oxfmt/yaml' | 'isentinel/package-json/setup' | 'isentinel/package-json' | 'isentinel/package-json/root' | 'isentinel/perfectionist/setup' | 'isentinel/perfectionist' | 'isentinel/perfectionist/jsx' | 'isentinel/pnpm/setup' | 'isentinel/pnpm/package-json' | 'isentinel/pnpm/pnpm-workspace-yaml' | 'isentinel/promise' | 'isentinel/react/setup' | 'isentinel/react/setup/naming' | 'isentinel/react/setup/testing-library' | 'isentinel/react/rules' | 'isentinel/react/type-aware-rules' | 'isentinel/roblox/setup' | 'isentinel/roblox/parser' | 'isentinel/roblox/type-aware-parser' | 'isentinel/roblox' | 'isentinel/roblox/rules-type-aware' | 'isentinel/roblox/format-lua/setup' | 'isentinel/roblox/format-lua' | 'isentinel/small-rules/setup' | 'isentinel/small-rules' | 'isentinel/sonarjs' | 'isentinel/spelling/setup' | 'isentinel/spelling' | 'isentinel/stylistic/setup' | 'isentinel/stylistic' | 'isentinel/test/jest/setup' | 'isentinel/test/jest/rules' | 'isentinel/test/jest/type-tests' | 'isentinel/test/vitest/setup' | 'isentinel/test/vitest/rules' | 'isentinel/test/vitest/type-tests' | 'isentinel/toml/setup' | 'isentinel/toml/rules' | 'isentinel/typescript/setup' | 'isentinel/typescript/parser' | 'isentinel/typescript/type-aware-parser' | 'isentinel/typescript/rules' | 'isentinel/typescript/rules-type-aware' | 'isentinel/typescript/erasable-syntax-only' | 'isentinel/unicorn/setup' | 'isentinel/unicorn/rules' | 'isentinel/unicorn/root' | 'isentinel/yaml/setup' | 'isentinel/yaml/rules';
|
|
27189
|
+
type ConfigNames = 'isentinel/eslint/comments' | 'isentinel/eslint/comments/src' | 'isentinel/e18e/rules' | 'isentinel/eslint-plugin/setup' | 'isentinel/eslint-plugin/rules' | 'isentinel/flawless/setup' | 'isentinel/flawless/rules' | 'isentinel/flawless/markdown-code' | 'isentinel/flawless/rules-type-aware' | 'isentinel/gitignore' | 'isentinel/ignores' | 'isentinel/imports/rules' | 'isentinel/imports/game' | 'isentinel/javascript/setup' | 'isentinel/javascript/rules' | 'isentinel/jsdoc/setup' | 'isentinel/jsdoc' | 'isentinel/jsonc/setup' | 'isentinel/jsonc/rules' | 'isentinel/jsonc/tsconfig' | 'isentinel/markdown/setup' | 'isentinel/markdown/processor' | 'isentinel/markdown/parser' | 'isentinel/markdown/disables' | 'isentinel/naming/setup' | 'isentinel/naming/ts/rules-type-aware' | 'isentinel/naming/tsx/rules-type-aware' | 'isentinel/node/rules' | 'isentinel/oxfmt/setup' | 'isentinel/oxfmt/javascript' | 'isentinel/oxfmt/typescript' | 'isentinel/oxfmt/css' | 'isentinel/oxfmt/scss' | 'isentinel/oxfmt/less' | 'isentinel/oxfmt/html' | 'isentinel/oxfmt/markdown' | 'isentinel/oxfmt/graphql' | 'isentinel/oxfmt/json' | 'isentinel/oxfmt/yaml' | 'isentinel/package-json/setup' | 'isentinel/package-json' | 'isentinel/package-json/root' | 'isentinel/perfectionist/setup' | 'isentinel/perfectionist' | 'isentinel/perfectionist/jsx' | 'isentinel/pnpm/setup' | 'isentinel/pnpm/package-json' | 'isentinel/pnpm/pnpm-workspace-yaml' | 'isentinel/project-structure/setup' | 'isentinel/project-structure/rules' | 'isentinel/promise' | 'isentinel/react/setup' | 'isentinel/react/setup/naming' | 'isentinel/react/setup/testing-library' | 'isentinel/react/rules' | 'isentinel/react/type-aware-rules' | 'isentinel/roblox/setup' | 'isentinel/roblox/parser' | 'isentinel/roblox/type-aware-parser' | 'isentinel/roblox' | 'isentinel/roblox/rules-type-aware' | 'isentinel/roblox/format-lua/setup' | 'isentinel/roblox/format-lua' | 'isentinel/small-rules/setup' | 'isentinel/small-rules' | 'isentinel/sonarjs' | 'isentinel/spelling/setup' | 'isentinel/spelling' | 'isentinel/stylistic/setup' | 'isentinel/stylistic' | 'isentinel/test/jest/setup' | 'isentinel/test/jest/rules' | 'isentinel/test/jest/type-tests' | 'isentinel/test/vitest/setup' | 'isentinel/test/vitest/rules' | 'isentinel/test/vitest/type-tests' | 'isentinel/toml/setup' | 'isentinel/toml/rules' | 'isentinel/typescript/setup' | 'isentinel/typescript/parser' | 'isentinel/typescript/type-aware-parser' | 'isentinel/typescript/rules' | 'isentinel/typescript/rules-type-aware' | 'isentinel/typescript/erasable-syntax-only' | 'isentinel/unicorn/setup' | 'isentinel/unicorn/rules' | 'isentinel/unicorn/root' | 'isentinel/yaml/setup' | 'isentinel/yaml/rules';
|
|
27162
27190
|
//#endregion
|
|
27163
27191
|
//#region src/utils.d.ts
|
|
27164
27192
|
type ExtractRuleOptions<T> = T extends Linter.RuleEntry<infer U> ? U : never;
|
|
@@ -27496,6 +27524,37 @@ interface NamingConfig extends OptionsOverridesTypeAware {
|
|
|
27496
27524
|
*/
|
|
27497
27525
|
selectorsTsx?: Array<NamingSelector>;
|
|
27498
27526
|
}
|
|
27527
|
+
interface ProjectStructureConfig extends OptionsOverrides {
|
|
27528
|
+
/**
|
|
27529
|
+
* The files each linted source file has to sit next to, as
|
|
27530
|
+
* `enforceExistence` templates. Takes the plugin's name placeholders
|
|
27531
|
+
* (`{nodeName}`, `{NodeName}`, `{node-name}`, `{node_name}`,
|
|
27532
|
+
* `{NODE_NAME}`) plus `{ext}` for the extension of the file that matched.
|
|
27533
|
+
* A file already matching a template is exempt from it.
|
|
27534
|
+
*
|
|
27535
|
+
* @default ["{node-name}.spec.{ext}"]
|
|
27536
|
+
*/
|
|
27537
|
+
enforceExistence?: Array<string> | string;
|
|
27538
|
+
/**
|
|
27539
|
+
* Files exempt from the check.
|
|
27540
|
+
*
|
|
27541
|
+
* @default [...GLOB_TESTS, GLOB_DTS, ...GLOB_BUILD_CONFIGS]
|
|
27542
|
+
*/
|
|
27543
|
+
ignores?: Array<string>;
|
|
27544
|
+
/**
|
|
27545
|
+
* The folder the enforced paths resolve against, and where the plugin
|
|
27546
|
+
* writes `projectStructure.cache.json` when it reports.
|
|
27547
|
+
*
|
|
27548
|
+
* @default process.cwd()
|
|
27549
|
+
*/
|
|
27550
|
+
projectRoot?: string;
|
|
27551
|
+
/**
|
|
27552
|
+
* Restricts the check to one subtree of `projectRoot`, as a relative path.
|
|
27553
|
+
*
|
|
27554
|
+
* @default undefined - the whole of `projectRoot`
|
|
27555
|
+
*/
|
|
27556
|
+
structureRoot?: string;
|
|
27557
|
+
}
|
|
27499
27558
|
interface OptionsTypeScriptParserOptions {
|
|
27500
27559
|
/**
|
|
27501
27560
|
* Glob patterns for files that should be type aware.
|
|
@@ -27844,6 +27903,14 @@ interface OptionsConfig extends OptionsComponentExtensions, OptionsProjectType {
|
|
|
27844
27903
|
* @see https://github.com/antfu/pnpm-workspace-utils
|
|
27845
27904
|
*/
|
|
27846
27905
|
pnpm?: boolean | OptionsPnpm;
|
|
27906
|
+
/**
|
|
27907
|
+
* Require every source file to have a co-located test file, via
|
|
27908
|
+
* [eslint-plugin-project-structure](https://github.com/Igorkowalski94/eslint-plugin-project-structure).
|
|
27909
|
+
*
|
|
27910
|
+
* @default false
|
|
27911
|
+
* @requires eslint-plugin-project-structure
|
|
27912
|
+
*/
|
|
27913
|
+
projectStructure?: boolean | ProjectStructureConfig;
|
|
27847
27914
|
/**
|
|
27848
27915
|
* Enable react rules.
|
|
27849
27916
|
*
|
|
@@ -28282,6 +28349,9 @@ declare function perfectionist(config?: OptionsProjectType & PerfectionistConfig
|
|
|
28282
28349
|
//#region src/eslint/configs/pnpm.d.ts
|
|
28283
28350
|
declare function pnpm(options: OptionsPnpm & Required<OptionsIsInEditor>): Promise<Array<TypedFlatConfigItem>>;
|
|
28284
28351
|
//#endregion
|
|
28352
|
+
//#region src/eslint/configs/project-structure.d.ts
|
|
28353
|
+
declare function projectStructure({ enforceExistence, files, ignores, overrides, projectRoot, structureRoot }?: ProjectStructureConfig): Promise<Array<TypedFlatConfigItem>>;
|
|
28354
|
+
//#endregion
|
|
28285
28355
|
//#region src/eslint/configs/promise.d.ts
|
|
28286
28356
|
declare function promise(): Array<TypedFlatConfigItem>;
|
|
28287
28357
|
//#endregion
|
|
@@ -28388,4 +28458,4 @@ declare function unicorn({ complementIgnores, nameReplacements, roblox, root: cu
|
|
|
28388
28458
|
//#region src/eslint/configs/yaml.d.ts
|
|
28389
28459
|
declare function yaml({ files, overrides, stylistic }?: OptionsFiles & OptionsOverrides & OptionsStylistic): Promise<Array<TypedFlatConfigItem>>;
|
|
28390
28460
|
//#endregion
|
|
28391
|
-
export { type Awaitable, type ConfigNames, type ConfigSettings, type FlatConfigComposer, GLOB_ALL_JSON, GLOB_ALL_SRC, GLOB_BIN, GLOB_BUILD_CONFIGS, GLOB_CSS, GLOB_DTS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LINTABLE_EXTENSIONS, GLOB_LUA, GLOB_MARKDOWN, GLOB_MARKDOWN_BLOCKS, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_MISE, GLOB_PACKAGE_JSON, GLOB_PACKAGE_JSON_ROOT, GLOB_POSTCSS, GLOB_ROOT, GLOB_ROOT_SRC, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_SRC_EXTENSIONS, GLOB_STYLE, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSCONFIG, GLOB_TSX, GLOB_TYPE_TESTS, GLOB_XML, GLOB_YAML, GitignoreOptions, type JsdocOptions, MARKDOWN_PROCESSOR_NAME, type NamedFlatConfigItem, type NamedOptionsConfig, type NamingConfig, type NamingSelector, type OptionsComponentExtensions, type OptionsConfig, type OptionsE18e, type OptionsFiles, type OptionsFilesTypeAware, type OptionsFormatters, type OptionsHasRoblox, type OptionsHasTypeScript, type OptionsIsInEditor, type OptionsJest, type OptionsOverrides, type OptionsOverridesTypeAware, type OptionsPnpm, type OptionsProjectType, type OptionsStylistic, type OptionsTestFramework, type OptionsTypeScriptErasableOnly, type OptionsTypeScriptParserOptions, type OptionsTypeScriptWithTypes, type OptionsTypescript, type OptionsUnicorn, type OptionsVitest, type OxfmtOptions, type PerfectionistConfig, type PrettierOptions, ROBLOX_ALLOWED_WORDS, type ReactConfig, type ReactSettings, type Rules, type SpellCheckConfig, type StylisticConfig, StylisticConfigDefaults, type TypedFlatConfigItem, comments, isentinel as default, isentinel, defaultPluginRenaming, disables, e18e, eslintPlugin, flawless, gitignore, ignores$1 as ignores, imports, isAgentAutofixDisabled, isInAgentSession, isInEditorEnvironment, isInGitHooksOrLintStaged, javascript, jsdoc, jsonc, loadSmallRulesPlugin, markdown, naming, node, oxfmt, packageJson, perfectionist, pnpm, promise, react, roblox$1 as roblox, smallRules, sonarjs, sortCspell, sortGithubAction, sortMiseToml, sortPnpmWorkspace, sortRojoProject, sortTsconfig, spelling, stylistic$1 as stylistic, test, toml, typescript, unicorn, yaml };
|
|
28461
|
+
export { type Awaitable, type ConfigNames, type ConfigSettings, type FlatConfigComposer, GLOB_ALL_JSON, GLOB_ALL_SRC, GLOB_BIN, GLOB_BUILD_CONFIGS, GLOB_CSS, GLOB_DTS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LINTABLE_EXTENSIONS, GLOB_LUA, GLOB_MARKDOWN, GLOB_MARKDOWN_BLOCKS, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_MISE, GLOB_PACKAGE_JSON, GLOB_PACKAGE_JSON_ROOT, GLOB_POSTCSS, GLOB_ROOT, GLOB_ROOT_SRC, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_SRC_EXTENSIONS, GLOB_STYLE, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSCONFIG, GLOB_TSX, GLOB_TYPE_TESTS, GLOB_XML, GLOB_YAML, GitignoreOptions, type JsdocOptions, MARKDOWN_PROCESSOR_NAME, type NamedFlatConfigItem, type NamedOptionsConfig, type NamingConfig, type NamingSelector, type OptionsComponentExtensions, type OptionsConfig, type OptionsE18e, type OptionsFiles, type OptionsFilesTypeAware, type OptionsFormatters, type OptionsHasRoblox, type OptionsHasTypeScript, type OptionsIsInEditor, type OptionsJest, type OptionsOverrides, type OptionsOverridesTypeAware, type OptionsPnpm, type OptionsProjectType, type OptionsStylistic, type OptionsTestFramework, type OptionsTypeScriptErasableOnly, type OptionsTypeScriptParserOptions, type OptionsTypeScriptWithTypes, type OptionsTypescript, type OptionsUnicorn, type OptionsVitest, type OxfmtOptions, type PerfectionistConfig, type PrettierOptions, type ProjectStructureConfig, ROBLOX_ALLOWED_WORDS, type ReactConfig, type ReactSettings, type Rules, type SpellCheckConfig, type StylisticConfig, StylisticConfigDefaults, type TypedFlatConfigItem, comments, isentinel as default, isentinel, defaultPluginRenaming, disables, e18e, eslintPlugin, flawless, gitignore, ignores$1 as ignores, imports, isAgentAutofixDisabled, isInAgentSession, isInEditorEnvironment, isInGitHooksOrLintStaged, javascript, jsdoc, jsonc, loadSmallRulesPlugin, markdown, naming, node, oxfmt, packageJson, perfectionist, pnpm, projectStructure, promise, react, roblox$1 as roblox, smallRules, sonarjs, sortCspell, sortGithubAction, sortMiseToml, sortPnpmWorkspace, sortRojoProject, sortTsconfig, spelling, stylistic$1 as stylistic, test, toml, typescript, unicorn, yaml };
|
package/dist/index.mjs
CHANGED
|
@@ -1576,8 +1576,10 @@ function disables({ root, workspaceRoot }) {
|
|
|
1576
1576
|
rules: {
|
|
1577
1577
|
"antfu/no-top-level-await": "off",
|
|
1578
1578
|
"no-console": "off",
|
|
1579
|
+
"roblox/no-null": "off",
|
|
1579
1580
|
"small-rules/require-async-suffix": "off",
|
|
1580
|
-
"ts/explicit-function-return-type": "off"
|
|
1581
|
+
"ts/explicit-function-return-type": "off",
|
|
1582
|
+
"unicorn/no-null": "off"
|
|
1581
1583
|
}
|
|
1582
1584
|
},
|
|
1583
1585
|
{
|
|
@@ -1640,7 +1642,8 @@ function disables({ root, workspaceRoot }) {
|
|
|
1640
1642
|
"import/no-default-export": "off",
|
|
1641
1643
|
"small-rules/require-async-suffix": "off",
|
|
1642
1644
|
"sonar/file-name-differ-from-class": "off",
|
|
1643
|
-
"unicorn/filename-case": "off"
|
|
1645
|
+
"unicorn/filename-case": "off",
|
|
1646
|
+
"unicorn/no-null": "off"
|
|
1644
1647
|
}
|
|
1645
1648
|
},
|
|
1646
1649
|
{
|
|
@@ -1886,7 +1889,7 @@ async function flawless(options = {}, prettierOptions = {}) {
|
|
|
1886
1889
|
];
|
|
1887
1890
|
}
|
|
1888
1891
|
//#endregion
|
|
1889
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@eslint/compat/2.1.0/
|
|
1892
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@eslint/compat/2.1.0/90f1da88f603538864cab10657b202d55290237a3b641df9ac72b842a3be07f2/node_modules/@eslint/compat/dist/esm/index.js
|
|
1890
1893
|
/**
|
|
1891
1894
|
* @fileoverview Ignore file utilities for the compat package.
|
|
1892
1895
|
* @author Nicholas C. Zakas
|
|
@@ -1915,7 +1918,7 @@ function convertIgnorePatternToMinimatch(pattern) {
|
|
|
1915
1918
|
}
|
|
1916
1919
|
var init_esm$1 = __esmMin((() => {}));
|
|
1917
1920
|
//#endregion
|
|
1918
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/
|
|
1921
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/0a594adbd94ca75e2950b1104992894d49bc93f4f2bc935ad192d7104e4c271e/node_modules/eslint-config-flat-gitignore/dist/index.mjs
|
|
1919
1922
|
var dist_exports = /* @__PURE__ */ __exportAll$2({ default: () => ignore });
|
|
1920
1923
|
function toArray(array) {
|
|
1921
1924
|
array = array ?? [];
|
|
@@ -3947,6 +3950,68 @@ async function detectCatalogUsage() {
|
|
|
3947
3950
|
return yaml.includes("catalog:") || yaml.includes("catalogs:");
|
|
3948
3951
|
}
|
|
3949
3952
|
//#endregion
|
|
3953
|
+
//#region src/eslint/configs/project-structure.ts
|
|
3954
|
+
init_globs();
|
|
3955
|
+
/** Stands for the extension of the file a rule matched. */
|
|
3956
|
+
const EXTENSION_TOKEN = "{ext}";
|
|
3957
|
+
const DEFAULT_ENFORCE_EXISTENCE = [`{node-name}.spec.${EXTENSION_TOKEN}`];
|
|
3958
|
+
/** Reusable-rule id for "a folder of any name". */
|
|
3959
|
+
const ANY_FOLDER = "isentinelAnyFolder";
|
|
3960
|
+
async function projectStructure({ enforceExistence = DEFAULT_ENFORCE_EXISTENCE, files = [GLOB_SRC], ignores = [
|
|
3961
|
+
...GLOB_TESTS,
|
|
3962
|
+
GLOB_DTS,
|
|
3963
|
+
...GLOB_BUILD_CONFIGS
|
|
3964
|
+
], overrides = {}, projectRoot = process.cwd(), structureRoot } = {}) {
|
|
3965
|
+
await ensurePackages(["eslint-plugin-project-structure"]);
|
|
3966
|
+
const { projectStructurePlugin } = await import("eslint-plugin-project-structure");
|
|
3967
|
+
const children = buildChildren(typeof enforceExistence === "string" ? [enforceExistence] : enforceExistence);
|
|
3968
|
+
return [{
|
|
3969
|
+
name: "isentinel/project-structure/setup",
|
|
3970
|
+
plugins: { "project-structure": projectStructurePlugin }
|
|
3971
|
+
}, {
|
|
3972
|
+
name: "isentinel/project-structure/rules",
|
|
3973
|
+
files,
|
|
3974
|
+
ignores,
|
|
3975
|
+
rules: {
|
|
3976
|
+
"project-structure/folder-structure": ["error", {
|
|
3977
|
+
longPathsInfo: false,
|
|
3978
|
+
projectRoot,
|
|
3979
|
+
rules: { [ANY_FOLDER]: {
|
|
3980
|
+
name: "*",
|
|
3981
|
+
children
|
|
3982
|
+
} },
|
|
3983
|
+
structure: children,
|
|
3984
|
+
...structureRoot === void 0 ? {} : { structureRoot }
|
|
3985
|
+
}],
|
|
3986
|
+
...overrides
|
|
3987
|
+
}
|
|
3988
|
+
}];
|
|
3989
|
+
}
|
|
3990
|
+
/**
|
|
3991
|
+
* The rules matching the files inside one folder, in the order
|
|
3992
|
+
* `folder-structure` tries them - first match wins.
|
|
3993
|
+
*
|
|
3994
|
+
* Every entry is permissive: `structure` is required by the rule and an
|
|
3995
|
+
* unmatched node is an error, so anything less would turn the co-location
|
|
3996
|
+
* check into whole-tree naming enforcement.
|
|
3997
|
+
*
|
|
3998
|
+
* @param templates - The `enforceExistence` templates, before substitution.
|
|
3999
|
+
* @returns The child rules, ending in the recursive folder rule.
|
|
4000
|
+
*/
|
|
4001
|
+
function buildChildren(templates) {
|
|
4002
|
+
const children = templates.map((template) => {
|
|
4003
|
+
return { name: (template.split("/").pop() ?? template).replaceAll(/\{[^{}]*\}/g, "*") };
|
|
4004
|
+
});
|
|
4005
|
+
for (const extension of GLOB_SRC_EXTENSIONS) children.push({
|
|
4006
|
+
name: `*.${extension}`,
|
|
4007
|
+
enforceExistence: templates.map((template) => {
|
|
4008
|
+
return template.replaceAll(EXTENSION_TOKEN, () => extension);
|
|
4009
|
+
})
|
|
4010
|
+
});
|
|
4011
|
+
children.push({ ruleId: ANY_FOLDER });
|
|
4012
|
+
return children;
|
|
4013
|
+
}
|
|
4014
|
+
//#endregion
|
|
3950
4015
|
//#region src/rules/promise.ts
|
|
3951
4016
|
/**
|
|
3952
4017
|
* Promise rules shared between the ESLint and oxlint factories.
|
|
@@ -6154,7 +6219,7 @@ async function unicorn({ complementIgnores, nameReplacements, roblox = true, roo
|
|
|
6154
6219
|
];
|
|
6155
6220
|
}
|
|
6156
6221
|
//#endregion
|
|
6157
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/
|
|
6222
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/a00fc88a04d0f2081267792f61f05ad4ceff0f52e1ff41acbbc866518b4fd9c1/node_modules/eslint-plugin-yml/lib/chunk-CfYAbeIz.mjs
|
|
6158
6223
|
var __defProp$1, __exportAll$1;
|
|
6159
6224
|
var init_chunk_CfYAbeIz = __esmMin((() => {
|
|
6160
6225
|
__defProp$1 = Object.defineProperty;
|
|
@@ -9337,7 +9402,7 @@ var init_lib$1 = __esmMin((() => {
|
|
|
9337
9402
|
({ ...meta_exports$1 });
|
|
9338
9403
|
}));
|
|
9339
9404
|
//#endregion
|
|
9340
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/
|
|
9405
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/a00fc88a04d0f2081267792f61f05ad4ceff0f52e1ff41acbbc866518b4fd9c1/node_modules/eslint-plugin-yml/lib/index.mjs
|
|
9341
9406
|
var lib_exports = /* @__PURE__ */ __exportAll$2({
|
|
9342
9407
|
configs: () => configs,
|
|
9343
9408
|
default: () => src_default,
|
|
@@ -15344,6 +15409,7 @@ const typeAwarePrefixes = /* @__PURE__ */ new Set([
|
|
|
15344
15409
|
"package-json",
|
|
15345
15410
|
"perfectionist",
|
|
15346
15411
|
"pnpm",
|
|
15412
|
+
"project-structure",
|
|
15347
15413
|
"promise",
|
|
15348
15414
|
"react",
|
|
15349
15415
|
"react-jsx",
|
|
@@ -19919,7 +19985,7 @@ const flatConfigProps = [
|
|
|
19919
19985
|
"settings"
|
|
19920
19986
|
];
|
|
19921
19987
|
async function isentinel(options, ...userConfigs) {
|
|
19922
|
-
const { autoRenamePlugins = true, componentExts: componentExtensions = [], e18e: enableE18e = true, eslintPlugin: enableEslintPlugin = false, formatters, gitignore: enableGitignore = true, jsdoc: enableJsdoc = true, jsonc: enableJsonc = true, jsx: enableJsx = true, markdown: enableMarkdown = true, oxlint: enableOxlint = false, pnpm: enableCatalogs = findUpSync("pnpm-workspace.yaml") !== void 0, react: enableReact = false, root: customRootGlobs, spellCheck: enableSpellCheck, toml: enableToml = true, yaml: enableYaml = true } = options;
|
|
19988
|
+
const { autoRenamePlugins = true, componentExts: componentExtensions = [], e18e: enableE18e = true, eslintPlugin: enableEslintPlugin = false, formatters, gitignore: enableGitignore = true, jsdoc: enableJsdoc = true, jsonc: enableJsonc = true, jsx: enableJsx = true, markdown: enableMarkdown = true, oxlint: enableOxlint = false, pnpm: enableCatalogs = findUpSync("pnpm-workspace.yaml") !== void 0, projectStructure: enableProjectStructure = false, react: enableReact = false, root: customRootGlobs, spellCheck: enableSpellCheck, toml: enableToml = true, yaml: enableYaml = true } = options;
|
|
19923
19989
|
const rootGlobs = mergeGlobs(GLOB_ROOT, customRootGlobs);
|
|
19924
19990
|
const enableRoblox = options.roblox !== false;
|
|
19925
19991
|
const reactOptions = resolveSubOptions(options, "react");
|
|
@@ -20042,6 +20108,7 @@ async function isentinel(options, ...userConfigs) {
|
|
|
20042
20108
|
...testOptions
|
|
20043
20109
|
}));
|
|
20044
20110
|
}
|
|
20111
|
+
if (enableProjectStructure !== false) configs.push(projectStructure(resolveSubOptions(options, "projectStructure")));
|
|
20045
20112
|
if (enableReact !== false) configs.push(react({
|
|
20046
20113
|
...resolveSubOptions(options, "react"),
|
|
20047
20114
|
...getOverrides(options, "react"),
|
|
@@ -20169,4 +20236,4 @@ async function isentinel(options, ...userConfigs) {
|
|
|
20169
20236
|
return composer;
|
|
20170
20237
|
}
|
|
20171
20238
|
//#endregion
|
|
20172
|
-
export { GLOB_ALL_JSON, GLOB_ALL_SRC, GLOB_BIN, GLOB_BUILD_CONFIGS, GLOB_CSS, GLOB_DTS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LINTABLE_EXTENSIONS, GLOB_LUA, GLOB_MARKDOWN, GLOB_MARKDOWN_BLOCKS, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_MISE, GLOB_PACKAGE_JSON, GLOB_PACKAGE_JSON_ROOT, GLOB_POSTCSS, GLOB_ROOT, GLOB_ROOT_SRC, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_SRC_EXTENSIONS, GLOB_STYLE, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSCONFIG, GLOB_TSX, GLOB_TYPE_TESTS, GLOB_XML, GLOB_YAML, MARKDOWN_PROCESSOR_NAME, ROBLOX_ALLOWED_WORDS, StylisticConfigDefaults, comments, isentinel as default, isentinel, defaultPluginRenaming, disables, e18e, eslintPlugin, flawless, gitignore, ignores, imports, isAgentAutofixDisabled, isInAgentSession, isInEditorEnvironment, isInGitHooksOrLintStaged, javascript, jsdoc, jsonc, loadSmallRulesPlugin, markdown, naming, node, oxfmt, packageJson, perfectionist, pnpm, promise, react, roblox, smallRules, sonarjs, sortCspell, sortGithubAction, sortMiseToml, sortPnpmWorkspace, sortRojoProject, sortTsconfig, spelling, stylistic, test, toml, typescript, unicorn, yaml };
|
|
20239
|
+
export { GLOB_ALL_JSON, GLOB_ALL_SRC, GLOB_BIN, GLOB_BUILD_CONFIGS, GLOB_CSS, GLOB_DTS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LINTABLE_EXTENSIONS, GLOB_LUA, GLOB_MARKDOWN, GLOB_MARKDOWN_BLOCKS, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_MISE, GLOB_PACKAGE_JSON, GLOB_PACKAGE_JSON_ROOT, GLOB_POSTCSS, GLOB_ROOT, GLOB_ROOT_SRC, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_SRC_EXTENSIONS, GLOB_STYLE, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSCONFIG, GLOB_TSX, GLOB_TYPE_TESTS, GLOB_XML, GLOB_YAML, MARKDOWN_PROCESSOR_NAME, ROBLOX_ALLOWED_WORDS, StylisticConfigDefaults, comments, isentinel as default, isentinel, defaultPluginRenaming, disables, e18e, eslintPlugin, flawless, gitignore, ignores, imports, isAgentAutofixDisabled, isInAgentSession, isInEditorEnvironment, isInGitHooksOrLintStaged, javascript, jsdoc, jsonc, loadSmallRulesPlugin, markdown, naming, node, oxfmt, packageJson, perfectionist, pnpm, projectStructure, promise, react, roblox, smallRules, sonarjs, sortCspell, sortGithubAction, sortMiseToml, sortPnpmWorkspace, sortRojoProject, sortTsconfig, spelling, stylistic, test, toml, typescript, unicorn, yaml };
|
package/dist/lint-cli.mjs
CHANGED
|
@@ -38,7 +38,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
38
38
|
}) : target, mod));
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region package.json
|
|
41
|
-
var version = "6.0.0-beta.
|
|
41
|
+
var version = "6.0.0-beta.43";
|
|
42
42
|
//#endregion
|
|
43
43
|
//#region src/lint-cli/lib/cli/types.ts
|
|
44
44
|
/**
|
|
@@ -1104,17 +1104,22 @@ const PACKAGE_RESOLUTION = {
|
|
|
1104
1104
|
*/
|
|
1105
1105
|
function applyHashBust(run, bust, hash) {
|
|
1106
1106
|
if (hash === void 0) return {
|
|
1107
|
-
|
|
1107
|
+
cleared: [],
|
|
1108
1108
|
firstRun: false
|
|
1109
1109
|
};
|
|
1110
1110
|
const swap = swapState(statePath(run.cwd, bust.name, run.key), hash);
|
|
1111
1111
|
if (swap !== "changed") return {
|
|
1112
|
-
|
|
1112
|
+
cleared: [],
|
|
1113
1113
|
firstRun: swap === "first"
|
|
1114
1114
|
};
|
|
1115
|
-
|
|
1115
|
+
const cleared = [];
|
|
1116
|
+
for (const base of bust.caches) {
|
|
1117
|
+
const cacheFilePath = path.resolve(run.cwd, cacheFileFor(base, run.key));
|
|
1118
|
+
fs.rmSync(cacheFilePath, { force: true });
|
|
1119
|
+
cleared.push(cacheFilePath);
|
|
1120
|
+
}
|
|
1116
1121
|
return {
|
|
1117
|
-
|
|
1122
|
+
cleared,
|
|
1118
1123
|
firstRun: false
|
|
1119
1124
|
};
|
|
1120
1125
|
}
|
|
@@ -4854,6 +4859,17 @@ function buildGateValue(resolution, options) {
|
|
|
4854
4859
|
//#region src/lint-cli/lib/typescript/affected.ts
|
|
4855
4860
|
const warned = /* @__PURE__ */ new Set();
|
|
4856
4861
|
/**
|
|
4862
|
+
* State-file base name for the builder's incremental state, shared by the
|
|
4863
|
+
* per-project path and the prefix {@link hasBuilderState} scans for.
|
|
4864
|
+
*/
|
|
4865
|
+
const BUILD_INFO_STATE = "tsbuildinfo";
|
|
4866
|
+
/**
|
|
4867
|
+
* State-file base name for the gate paired with each buildinfo. Deliberately
|
|
4868
|
+
* not a `tsbuildinfo-` suffix, so anything enumerating a variant's buildinfo
|
|
4869
|
+
* files does not pick a gate up as one (see {@link gateStatePath}).
|
|
4870
|
+
*/
|
|
4871
|
+
const GATE_STATE = "tsgate";
|
|
4872
|
+
/**
|
|
4857
4873
|
* Compute the set of files whose type-aware lint results may have changed since
|
|
4858
4874
|
* the previous run, using TypeScript's builder API. The builder does a native
|
|
4859
4875
|
* shape-hash BFS: it recomputes each dependent's emitted-`.d.ts` shape hash and
|
|
@@ -4911,6 +4927,44 @@ function computeAffectedFiles({ key, cwd }, mode) {
|
|
|
4911
4927
|
}
|
|
4912
4928
|
}
|
|
4913
4929
|
/**
|
|
4930
|
+
* Whether a previous run left builder state for this mode and config variant.
|
|
4931
|
+
*
|
|
4932
|
+
* The one thing a builder pass does that nothing else can is establish this
|
|
4933
|
+
* state. Its affected set is disposable — a caller with an empty cache re-lints
|
|
4934
|
+
* regardless — but a run that skips the builder while no state exists only
|
|
4935
|
+
* defers the cost onto the next run, which then reports `firstRun` and throws
|
|
4936
|
+
* its affected set away. A file edited in between would be re-linted on its own
|
|
4937
|
+
* mtime while its importers kept stale type-aware cache entries, which no later
|
|
4938
|
+
* run revisits. Callers that skip the builder as an optimisation ask this
|
|
4939
|
+
* first.
|
|
4940
|
+
*
|
|
4941
|
+
* Any one project's state is enough: {@link computeAffectedFiles} reports
|
|
4942
|
+
* `firstRun` only when no project at all had state, and a newly added project
|
|
4943
|
+
* contributes its whole file set rather than an empty one.
|
|
4944
|
+
*
|
|
4945
|
+
* @param run - The run context.
|
|
4946
|
+
* @param mode - The active ESLint type-aware mode (never `"off"` here).
|
|
4947
|
+
* @returns True when at least one buildinfo for this mode and variant exists.
|
|
4948
|
+
*/
|
|
4949
|
+
function hasBuilderState({ key, cwd }, mode) {
|
|
4950
|
+
const prefix = `${path.basename(statePath(cwd, BUILD_INFO_STATE, modeSuffix(mode), key))}-`;
|
|
4951
|
+
try {
|
|
4952
|
+
return fs.readdirSync(stateDirectory(cwd)).some((name) => name.startsWith(prefix) && !name.endsWith(".tmp"));
|
|
4953
|
+
} catch {
|
|
4954
|
+
return false;
|
|
4955
|
+
}
|
|
4956
|
+
}
|
|
4957
|
+
/**
|
|
4958
|
+
* The state-file segment discriminating the type-aware mode a builder ran
|
|
4959
|
+
* under. Two modes resolve different programs, so their state cannot be shared.
|
|
4960
|
+
*
|
|
4961
|
+
* @param mode - The active ESLint type-aware mode (never `"off"` here).
|
|
4962
|
+
* @returns The file-name segment for that mode.
|
|
4963
|
+
*/
|
|
4964
|
+
function modeSuffix(mode) {
|
|
4965
|
+
return mode === "only" ? "typeaware" : "full";
|
|
4966
|
+
}
|
|
4967
|
+
/**
|
|
4914
4968
|
* Resolve the builder incremental-state (`.tsbuildinfo`) file for a mode and
|
|
4915
4969
|
* config variant.
|
|
4916
4970
|
*
|
|
@@ -4934,7 +4988,7 @@ function computeAffectedFiles({ key, cwd }, mode) {
|
|
|
4934
4988
|
* @returns The absolute path to the mode's buildinfo file.
|
|
4935
4989
|
*/
|
|
4936
4990
|
function builderStatePath(cwd, mode, key, projectId) {
|
|
4937
|
-
return statePath(cwd,
|
|
4991
|
+
return statePath(cwd, BUILD_INFO_STATE, modeSuffix(mode), key, projectId);
|
|
4938
4992
|
}
|
|
4939
4993
|
/**
|
|
4940
4994
|
* Resolve the gate state paired with one {@link builderStatePath} buildinfo:
|
|
@@ -4959,7 +5013,7 @@ function builderStatePath(cwd, mode, key, projectId) {
|
|
|
4959
5013
|
* @returns The absolute path to the gate state file.
|
|
4960
5014
|
*/
|
|
4961
5015
|
function gateStatePath(cwd, mode, key, projectId) {
|
|
4962
|
-
return statePath(cwd,
|
|
5016
|
+
return statePath(cwd, GATE_STATE, modeSuffix(mode), key, projectId);
|
|
4963
5017
|
}
|
|
4964
5018
|
/**
|
|
4965
5019
|
* Emit a warning at most once per distinct message. Keyed by message rather
|
|
@@ -5291,15 +5345,17 @@ function sizePasses(descriptors, run, inputs) {
|
|
|
5291
5345
|
* @returns The number of dirty files.
|
|
5292
5346
|
*/
|
|
5293
5347
|
function mutatingDirtyCount(descriptor, cacheLocation, targetFiles, { clearedCaches, run }) {
|
|
5294
|
-
|
|
5348
|
+
const buildsProgram = descriptor.invalidation !== "none";
|
|
5349
|
+
const mode = descriptor.invalidation === "only" ? "only" : void 0;
|
|
5350
|
+
if (clearedCaches.has(cacheLocation) && (!buildsProgram || hasBuilderState(run, mode))) return targetFiles.length;
|
|
5295
5351
|
const cache = openCache(cacheLocation, run.ci);
|
|
5296
5352
|
const dirty = new Set((cache?.getUpdatedFiles(targetFiles) ?? targetFiles).map((file) => normalizePath(file)));
|
|
5297
|
-
if (
|
|
5353
|
+
if (buildsProgram) {
|
|
5298
5354
|
const outcome = applyTypeAwareInvalidation(run, {
|
|
5299
5355
|
alreadyDirty: dirty,
|
|
5300
5356
|
cache,
|
|
5301
5357
|
cacheLocation,
|
|
5302
|
-
mode
|
|
5358
|
+
mode,
|
|
5303
5359
|
targetFiles
|
|
5304
5360
|
});
|
|
5305
5361
|
if (outcome.busted) return targetFiles.length;
|
|
@@ -5423,9 +5479,13 @@ function plan(options, run) {
|
|
|
5423
5479
|
const canMutateCaches = mutate && options.cache;
|
|
5424
5480
|
const hasTypeAwarePass = descriptors.some((descriptor) => descriptor.invalidation !== "none");
|
|
5425
5481
|
const configHash = options.cache ? computeConfigHash(cwd, files.configFiles) : void 0;
|
|
5426
|
-
|
|
5427
|
-
if (canMutateCaches
|
|
5428
|
-
|
|
5482
|
+
const cleared = [];
|
|
5483
|
+
if (canMutateCaches) {
|
|
5484
|
+
cleared.push(...applyHashBust(run, CONFIG_DRIFT, configHash).cleared);
|
|
5485
|
+
if (hasTypeAwarePass) cleared.push(...applyHashBust(run, PACKAGE_RESOLUTION, computePackageJsonHash(cwd)).cleared);
|
|
5486
|
+
cleared.push(...sweepStaleCaches(cwd, newestBustMtime));
|
|
5487
|
+
}
|
|
5488
|
+
const clearedCaches = new Set(cleared);
|
|
5429
5489
|
const sizingFiles = withoutIgnored(files, resolveIgnoredFiles(run, configHash, files.lintable));
|
|
5430
5490
|
const inputs = {
|
|
5431
5491
|
clearedCaches,
|
package/dist/oxlint.d.mts
CHANGED
|
@@ -7787,6 +7787,21 @@ interface RuleOptions {
|
|
|
7787
7787
|
* @see https://eslint.org/docs/latest/rules/preserve-caught-error
|
|
7788
7788
|
*/
|
|
7789
7789
|
'preserve-caught-error'?: Linter.RuleEntry<PreserveCaughtError>;
|
|
7790
|
+
/**
|
|
7791
|
+
* Enforce advanced naming rules and prohibit the use of given selectors in a given file. Have full control over what your file can contain and the naming conventions it must follow.
|
|
7792
|
+
* @see https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bfile%E2%80%91composition#root
|
|
7793
|
+
*/
|
|
7794
|
+
'project-structure/file-composition'?: Linter.RuleEntry<ProjectStructureFileComposition>;
|
|
7795
|
+
/**
|
|
7796
|
+
* Enforce rules on folder structure to keep your repository consistent, orderly and well thought out.
|
|
7797
|
+
* @see https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bfolder%E2%80%91structure#root
|
|
7798
|
+
*/
|
|
7799
|
+
'project-structure/folder-structure'?: Linter.RuleEntry<ProjectStructureFolderStructure>;
|
|
7800
|
+
/**
|
|
7801
|
+
* A key principle of a healthy project is to prevent the creation of a massive dependency tree, where removing or editing one feature triggers a chain reaction that impacts the entire project. Create independent modules to keep your project scalable and easy to maintain. Get rid of dependencies between modules and create truly independent functionalities.
|
|
7802
|
+
* @see https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bindependent%E2%80%91modules#root
|
|
7803
|
+
*/
|
|
7804
|
+
'project-structure/independent-modules'?: Linter.RuleEntry<ProjectStructureIndependentModules>;
|
|
7790
7805
|
/**
|
|
7791
7806
|
* Require returning inside each `then()` to create readable and reusable Promise chains.
|
|
7792
7807
|
* @see https://github.com/eslint-community/eslint-plugin-promise/blob/main/docs/rules/always-return.md
|
|
@@ -20595,6 +20610,18 @@ type PreserveCaughtError = [] | [{
|
|
|
20595
20610
|
argumentPosition: number;
|
|
20596
20611
|
})[];
|
|
20597
20612
|
}];
|
|
20613
|
+
// ----- project-structure/file-composition -----
|
|
20614
|
+
type ProjectStructureFileComposition = [] | [{
|
|
20615
|
+
[k: string]: unknown | undefined;
|
|
20616
|
+
}];
|
|
20617
|
+
// ----- project-structure/folder-structure -----
|
|
20618
|
+
type ProjectStructureFolderStructure = [] | [{
|
|
20619
|
+
[k: string]: unknown | undefined;
|
|
20620
|
+
}];
|
|
20621
|
+
// ----- project-structure/independent-modules -----
|
|
20622
|
+
type ProjectStructureIndependentModules = [] | [{
|
|
20623
|
+
[k: string]: unknown | undefined;
|
|
20624
|
+
}];
|
|
20598
20625
|
// ----- promise/always-return -----
|
|
20599
20626
|
type PromiseAlwaysReturn = [] | [{
|
|
20600
20627
|
ignoreLastCallback?: boolean;
|
|
@@ -24764,6 +24791,37 @@ interface NamingConfig extends OptionsOverridesTypeAware {
|
|
|
24764
24791
|
*/
|
|
24765
24792
|
selectorsTsx?: Array<NamingSelector>;
|
|
24766
24793
|
}
|
|
24794
|
+
interface ProjectStructureConfig extends OptionsOverrides {
|
|
24795
|
+
/**
|
|
24796
|
+
* The files each linted source file has to sit next to, as
|
|
24797
|
+
* `enforceExistence` templates. Takes the plugin's name placeholders
|
|
24798
|
+
* (`{nodeName}`, `{NodeName}`, `{node-name}`, `{node_name}`,
|
|
24799
|
+
* `{NODE_NAME}`) plus `{ext}` for the extension of the file that matched.
|
|
24800
|
+
* A file already matching a template is exempt from it.
|
|
24801
|
+
*
|
|
24802
|
+
* @default ["{node-name}.spec.{ext}"]
|
|
24803
|
+
*/
|
|
24804
|
+
enforceExistence?: Array<string> | string;
|
|
24805
|
+
/**
|
|
24806
|
+
* Files exempt from the check.
|
|
24807
|
+
*
|
|
24808
|
+
* @default [...GLOB_TESTS, GLOB_DTS, ...GLOB_BUILD_CONFIGS]
|
|
24809
|
+
*/
|
|
24810
|
+
ignores?: Array<string>;
|
|
24811
|
+
/**
|
|
24812
|
+
* The folder the enforced paths resolve against, and where the plugin
|
|
24813
|
+
* writes `projectStructure.cache.json` when it reports.
|
|
24814
|
+
*
|
|
24815
|
+
* @default process.cwd()
|
|
24816
|
+
*/
|
|
24817
|
+
projectRoot?: string;
|
|
24818
|
+
/**
|
|
24819
|
+
* Restricts the check to one subtree of `projectRoot`, as a relative path.
|
|
24820
|
+
*
|
|
24821
|
+
* @default undefined - the whole of `projectRoot`
|
|
24822
|
+
*/
|
|
24823
|
+
structureRoot?: string;
|
|
24824
|
+
}
|
|
24767
24825
|
interface OptionsTypeScriptParserOptions {
|
|
24768
24826
|
/**
|
|
24769
24827
|
* Glob patterns for files that should be type aware.
|
|
@@ -25112,6 +25170,14 @@ interface OptionsConfig extends OptionsComponentExtensions, OptionsProjectType {
|
|
|
25112
25170
|
* @see https://github.com/antfu/pnpm-workspace-utils
|
|
25113
25171
|
*/
|
|
25114
25172
|
pnpm?: boolean | OptionsPnpm;
|
|
25173
|
+
/**
|
|
25174
|
+
* Require every source file to have a co-located test file, via
|
|
25175
|
+
* [eslint-plugin-project-structure](https://github.com/Igorkowalski94/eslint-plugin-project-structure).
|
|
25176
|
+
*
|
|
25177
|
+
* @default false
|
|
25178
|
+
* @requires eslint-plugin-project-structure
|
|
25179
|
+
*/
|
|
25180
|
+
projectStructure?: boolean | ProjectStructureConfig;
|
|
25115
25181
|
/**
|
|
25116
25182
|
* Enable react rules.
|
|
25117
25183
|
*
|
|
@@ -33239,7 +33305,7 @@ type TypedOxlintConfigItem = Omit<OxlintOverride$1, "rules"> & {
|
|
|
33239
33305
|
* Oxlint can only lint JS/TS files, so the JSON, YAML, TOML, Markdown and
|
|
33240
33306
|
* pnpm-related options are omitted, along with ESLint-only options.
|
|
33241
33307
|
*/
|
|
33242
|
-
type OxlintOptionsConfig = Omit<OptionsConfig, "autoRenamePlugins" | "flawless" | "jsonc" | "markdown" | "namedConfigs" | "naming" | "oxlint" | "pnpm" | "toml" | "yaml">;
|
|
33308
|
+
type OxlintOptionsConfig = Omit<OptionsConfig, "autoRenamePlugins" | "flawless" | "jsonc" | "markdown" | "namedConfigs" | "naming" | "oxlint" | "pnpm" | "projectStructure" | "toml" | "yaml">;
|
|
33243
33309
|
/**
|
|
33244
33310
|
* Options accepted by the oxlint factory function.
|
|
33245
33311
|
*
|
package/dist/oxlint.mjs
CHANGED
|
@@ -3237,6 +3237,7 @@ const enabledPresetRuleNames = /* @__PURE__ */ new Set([
|
|
|
3237
3237
|
"prefer-rest-params",
|
|
3238
3238
|
"prefer-spread",
|
|
3239
3239
|
"prefer-template",
|
|
3240
|
+
"project-structure/folder-structure",
|
|
3240
3241
|
"promise/always-return",
|
|
3241
3242
|
"promise/catch-or-return",
|
|
3242
3243
|
"promise/no-multiple-resolved",
|
|
@@ -6742,8 +6743,10 @@ function oxlintDisables({ configDirectory, root, workspaceRoot }) {
|
|
|
6742
6743
|
rules: {
|
|
6743
6744
|
"antfu/no-top-level-await": "off",
|
|
6744
6745
|
"no-console": "off",
|
|
6746
|
+
"roblox/no-null": "off",
|
|
6745
6747
|
"small-rules/require-async-suffix": "off",
|
|
6746
|
-
"ts/explicit-function-return-type": "off"
|
|
6748
|
+
"ts/explicit-function-return-type": "off",
|
|
6749
|
+
"unicorn/no-null": "off"
|
|
6747
6750
|
}
|
|
6748
6751
|
}),
|
|
6749
6752
|
...createOxlintConfigs({
|
|
@@ -6811,7 +6814,8 @@ function oxlintDisables({ configDirectory, root, workspaceRoot }) {
|
|
|
6811
6814
|
"import/no-default-export": "off",
|
|
6812
6815
|
"small-rules/require-async-suffix": "off",
|
|
6813
6816
|
"sonar/file-name-differ-from-class": "off",
|
|
6814
|
-
"unicorn/filename-case": "off"
|
|
6817
|
+
"unicorn/filename-case": "off",
|
|
6818
|
+
"unicorn/no-null": "off"
|
|
6815
6819
|
}
|
|
6816
6820
|
}),
|
|
6817
6821
|
...createOxlintConfigs({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isentinel/eslint-config",
|
|
3
|
-
"version": "6.0.0-beta.
|
|
3
|
+
"version": "6.0.0-beta.43",
|
|
4
4
|
"description": "iSentinel's ESLint config",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint-config",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"yargs": "18.0.0"
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
|
-
"@antfu/ni": "30.
|
|
112
|
+
"@antfu/ni": "30.5.0",
|
|
113
113
|
"@eslint-react/shared": "5.17.3",
|
|
114
114
|
"@eslint/config-inspector": "3.1.0",
|
|
115
115
|
"@isentinel/tsconfig": "1.2.0",
|
|
@@ -122,12 +122,13 @@
|
|
|
122
122
|
"@types/yargs": "17.0.35",
|
|
123
123
|
"@vitest/eslint-plugin": "1.6.26",
|
|
124
124
|
"bumpp": "12.0.0",
|
|
125
|
-
"eslint": "10.
|
|
125
|
+
"eslint": "10.8.1",
|
|
126
126
|
"eslint-plugin-erasable-syntax-only": "0.4.2",
|
|
127
127
|
"eslint-plugin-eslint-plugin": "7.5.0",
|
|
128
128
|
"eslint-plugin-jest": "29.16.0",
|
|
129
129
|
"eslint-plugin-jest-extended": "3.0.1",
|
|
130
130
|
"eslint-plugin-n": "18.2.2",
|
|
131
|
+
"eslint-plugin-project-structure": "3.14.3",
|
|
131
132
|
"eslint-plugin-react-jsx": "5.17.3",
|
|
132
133
|
"eslint-plugin-react-naming-convention": "5.17.3",
|
|
133
134
|
"eslint-plugin-react-x": "5.17.3",
|
|
@@ -144,7 +145,7 @@
|
|
|
144
145
|
"typescript": "6.0.3",
|
|
145
146
|
"unplugin-unused": "0.5.7",
|
|
146
147
|
"vitest": "4.1.10",
|
|
147
|
-
"@isentinel/eslint-config": "6.0.0-beta.
|
|
148
|
+
"@isentinel/eslint-config": "6.0.0-beta.43"
|
|
148
149
|
},
|
|
149
150
|
"peerDependencies": {
|
|
150
151
|
"@vitest/eslint-plugin": "^1.6.4",
|
|
@@ -153,6 +154,7 @@
|
|
|
153
154
|
"eslint-plugin-jest": "^29.15.0",
|
|
154
155
|
"eslint-plugin-jest-extended": "^3.0.0",
|
|
155
156
|
"eslint-plugin-n": "^17.0.0 || ^18.0.0",
|
|
157
|
+
"eslint-plugin-project-structure": "^3.14.0",
|
|
156
158
|
"eslint-plugin-react-jsx": "^5.10.0",
|
|
157
159
|
"eslint-plugin-react-naming-convention": "^5.10.0",
|
|
158
160
|
"eslint-plugin-react-x": "^5.10.0",
|
|
@@ -176,6 +178,9 @@
|
|
|
176
178
|
"eslint-plugin-n": {
|
|
177
179
|
"optional": true
|
|
178
180
|
},
|
|
181
|
+
"eslint-plugin-project-structure": {
|
|
182
|
+
"optional": true
|
|
183
|
+
},
|
|
179
184
|
"eslint-plugin-react-jsx": {
|
|
180
185
|
"optional": true
|
|
181
186
|
},
|