@rslint/core 0.6.5 → 0.7.1

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/dist/index.js CHANGED
@@ -1,10 +1,15 @@
1
1
  import node_path from "node:path";
2
- import { readFile, writeFile } from "node:fs/promises";
2
+ import { lstat, readFile, stat as promises_stat, writeFile } from "node:fs/promises";
3
+ import fs_0, * as __rspack_external_fs from "fs";
4
+ import path_0, { basename, dirname, normalize as external_path_normalize, posix, relative as external_path_relative, resolve as external_path_resolve, sep } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { createRequire } from "module";
7
+ import picomatch from "picomatch";
8
+ import node_fs from "node:fs";
3
9
  import { NodeRslintService } from "./internal.js";
4
- import { loadConfigFile, normalizeConfig } from "./config-loader.js";
5
- import { findJSConfigUp, glob } from "./cli.js";
10
+ import { ConfigModuleHost, normalizeConfig } from "./519.js";
6
11
  import { RSLintService } from "./service.js";
7
- const typescript_base = {
12
+ const base = {
8
13
  files: [
9
14
  '**/*.ts',
10
15
  '**/*.tsx',
@@ -16,7 +21,7 @@ const typescript_base = {
16
21
  ]
17
22
  };
18
23
  const recommended = {
19
- ...typescript_base,
24
+ ...base,
20
25
  languageOptions: {
21
26
  parserOptions: {
22
27
  projectService: true
@@ -50,6 +55,7 @@ const recommended = {
50
55
  'no-delete-var': 'error',
51
56
  'no-dupe-else-if': 'error',
52
57
  'no-empty-character-class': 'error',
58
+ 'no-empty-static-block': 'error',
53
59
  'no-ex-assign': 'error',
54
60
  'no-extra-boolean-cast': 'error',
55
61
  'no-fallthrough': 'error',
@@ -66,6 +72,9 @@ const recommended = {
66
72
  'no-unexpected-multiline': 'error',
67
73
  'no-unsafe-finally': 'error',
68
74
  'no-unsafe-optional-chaining': 'error',
75
+ 'no-unused-labels': 'error',
76
+ 'no-unused-private-class-members': 'error',
77
+ 'no-unassigned-vars': 'error',
69
78
  'no-useless-backreference': 'error',
70
79
  'no-useless-catch': 'error',
71
80
  'no-useless-escape': 'error',
@@ -130,6 +139,7 @@ const javascript_recommended = {
130
139
  'no-dupe-class-members': 'error',
131
140
  'no-dupe-else-if': 'error',
132
141
  'no-empty-character-class': 'error',
142
+ 'no-empty-static-block': 'error',
133
143
  'no-ex-assign': 'error',
134
144
  'no-extra-boolean-cast': 'error',
135
145
  'no-fallthrough': 'error',
@@ -139,10 +149,12 @@ const javascript_recommended = {
139
149
  'no-invalid-regexp': 'error',
140
150
  'no-irregular-whitespace': 'error',
141
151
  'no-misleading-character-class': 'error',
152
+ 'no-new-native-nonconstructor': 'error',
142
153
  'no-nonoctal-decimal-escape': 'error',
143
154
  'no-obj-calls': 'error',
144
155
  'no-octal': 'error',
145
156
  'no-prototype-builtins': 'error',
157
+ 'no-redeclare': 'error',
146
158
  'no-regex-spaces': 'error',
147
159
  'no-self-assign': 'error',
148
160
  'no-setter-return': 'error',
@@ -154,6 +166,9 @@ const javascript_recommended = {
154
166
  'no-unsafe-finally': 'error',
155
167
  'no-unsafe-negation': 'error',
156
168
  'no-unsafe-optional-chaining': 'error',
169
+ 'no-unused-labels': 'error',
170
+ 'no-unused-private-class-members': 'error',
171
+ 'no-unassigned-vars': 'error',
157
172
  'no-useless-backreference': 'error',
158
173
  'no-useless-catch': 'error',
159
174
  'no-useless-escape': 'error',
@@ -190,6 +205,7 @@ const react_recommended = {
190
205
  'react'
191
206
  ],
192
207
  rules: {
208
+ 'react/display-name': 'error',
193
209
  'react/jsx-key': 'error',
194
210
  'react/jsx-no-comment-textnodes': 'error',
195
211
  'react/jsx-no-duplicate-props': 'error',
@@ -225,7 +241,11 @@ const import_recommended = {
225
241
  plugins: [
226
242
  'eslint-plugin-import'
227
243
  ],
228
- rules: {}
244
+ rules: {
245
+ 'import/namespace': 'error',
246
+ 'import/default': 'error',
247
+ 'import/no-duplicates': 'warn'
248
+ }
229
249
  };
230
250
  const promise_recommended = {
231
251
  plugins: [
@@ -236,8 +256,12 @@ const promise_recommended = {
236
256
  'promise/no-return-wrap': 'error',
237
257
  'promise/param-names': 'error',
238
258
  'promise/catch-or-return': 'error',
259
+ 'promise/no-nesting': 'warn',
239
260
  'promise/no-promise-in-callback': 'warn',
261
+ 'promise/no-callback-in-promise': 'warn',
240
262
  'promise/avoid-new': 'off',
263
+ 'promise/no-new-statics': 'error',
264
+ 'promise/no-return-in-finally': 'warn',
241
265
  'promise/valid-params': 'warn'
242
266
  }
243
267
  };
@@ -256,6 +280,7 @@ const jest_recommended = {
256
280
  'jest/no-export': 'error',
257
281
  'jest/no-focused-tests': 'error',
258
282
  'jest/no-identical-title': 'error',
283
+ 'jest/no-interpolation-in-snapshots': 'error',
259
284
  'jest/no-jasmine-globals': 'error',
260
285
  'jest/no-mocks-import': 'error',
261
286
  'jest/no-standalone-expect': 'error',
@@ -281,7 +306,15 @@ const unicorn_recommended = {
281
306
  ],
282
307
  rules: {
283
308
  'unicorn/filename-case': 'error',
284
- 'unicorn/no-static-only-class': 'error'
309
+ 'unicorn/new-for-builtins': 'error',
310
+ 'unicorn/no-instanceof-builtins': 'error',
311
+ 'unicorn/no-static-only-class': 'error',
312
+ 'unicorn/no-thenable': 'error',
313
+ 'unicorn/no-useless-switch-case': 'error',
314
+ 'unicorn/prefer-array-flat-map': 'error',
315
+ 'unicorn/prefer-number-properties': 'error',
316
+ 'unicorn/require-array-join-separator': 'error',
317
+ 'unicorn/require-number-to-fixed-digits-argument': 'error'
285
318
  }
286
319
  };
287
320
  const jsx_a11y_recommended = {
@@ -453,7 +486,7 @@ const jsx_a11y_recommended = {
453
486
  };
454
487
  const ts = {
455
488
  configs: {
456
- base: typescript_base,
489
+ base: base,
457
490
  recommended: recommended
458
491
  }
459
492
  };
@@ -498,6 +531,971 @@ const jsxA11yPlugin = {
498
531
  recommended: jsx_a11y_recommended
499
532
  }
500
533
  };
534
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
535
+ function cleanPath(path) {
536
+ let normalized = external_path_normalize(path);
537
+ if (normalized.length > 1 && normalized[normalized.length - 1] === sep) normalized = normalized.substring(0, normalized.length - 1);
538
+ return normalized;
539
+ }
540
+ const SLASHES_REGEX = /[\\/]/g;
541
+ function convertSlashes(path, separator) {
542
+ return path.replace(SLASHES_REGEX, separator);
543
+ }
544
+ const WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i;
545
+ function isRootDirectory(path) {
546
+ return "/" === path || WINDOWS_ROOT_DIR_REGEX.test(path);
547
+ }
548
+ function normalizePath(path, options) {
549
+ const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
550
+ const pathNeedsCleaning = "win32" === process.platform && path.includes("/") || path.startsWith(".");
551
+ if (resolvePaths) path = external_path_resolve(path);
552
+ if (normalizePath$1 || pathNeedsCleaning) path = cleanPath(path);
553
+ if ("." === path) return "";
554
+ const needsSeperator = path[path.length - 1] !== pathSeparator;
555
+ return convertSlashes(needsSeperator ? path + pathSeparator : path, pathSeparator);
556
+ }
557
+ function joinPathWithBasePath(filename, directoryPath) {
558
+ return directoryPath + filename;
559
+ }
560
+ function joinPathWithRelativePath(root, options) {
561
+ return function(filename, directoryPath) {
562
+ const sameRoot = directoryPath.startsWith(root);
563
+ if (sameRoot) return directoryPath.slice(root.length) + filename;
564
+ return convertSlashes(external_path_relative(root, directoryPath), options.pathSeparator) + options.pathSeparator + filename;
565
+ };
566
+ }
567
+ function joinPath(filename) {
568
+ return filename;
569
+ }
570
+ function joinDirectoryPath(filename, directoryPath, separator) {
571
+ return directoryPath + filename + separator;
572
+ }
573
+ function build$7(root, options) {
574
+ const { relativePaths, includeBasePath } = options;
575
+ return relativePaths && root ? joinPathWithRelativePath(root, options) : includeBasePath ? joinPathWithBasePath : joinPath;
576
+ }
577
+ function pushDirectoryWithRelativePath(root) {
578
+ return function(directoryPath, paths) {
579
+ paths.push(directoryPath.substring(root.length) || ".");
580
+ };
581
+ }
582
+ function pushDirectoryFilterWithRelativePath(root) {
583
+ return function(directoryPath, paths, filters) {
584
+ const relativePath = directoryPath.substring(root.length) || ".";
585
+ if (filters.every((filter)=>filter(relativePath, true))) paths.push(relativePath);
586
+ };
587
+ }
588
+ const pushDirectory = (directoryPath, paths)=>{
589
+ paths.push(directoryPath || ".");
590
+ };
591
+ const pushDirectoryFilter = (directoryPath, paths, filters)=>{
592
+ const path = directoryPath || ".";
593
+ if (filters.every((filter)=>filter(path, true))) paths.push(path);
594
+ };
595
+ const empty$2 = ()=>{};
596
+ function build$6(root, options) {
597
+ const { includeDirs, filters, relativePaths } = options;
598
+ if (!includeDirs) return empty$2;
599
+ if (relativePaths) return filters && filters.length ? pushDirectoryFilterWithRelativePath(root) : pushDirectoryWithRelativePath(root);
600
+ return filters && filters.length ? pushDirectoryFilter : pushDirectory;
601
+ }
602
+ const pushFileFilterAndCount = (filename, _paths, counts, filters)=>{
603
+ if (filters.every((filter)=>filter(filename, false))) counts.files++;
604
+ };
605
+ const pushFileFilter = (filename, paths, _counts, filters)=>{
606
+ if (filters.every((filter)=>filter(filename, false))) paths.push(filename);
607
+ };
608
+ const pushFileCount = (_filename, _paths, counts, _filters)=>{
609
+ counts.files++;
610
+ };
611
+ const pushFile = (filename, paths)=>{
612
+ paths.push(filename);
613
+ };
614
+ const empty$1 = ()=>{};
615
+ function build$5(options) {
616
+ const { excludeFiles, filters, onlyCounts } = options;
617
+ if (excludeFiles) return empty$1;
618
+ if (filters && filters.length) return onlyCounts ? pushFileFilterAndCount : pushFileFilter;
619
+ if (onlyCounts) return pushFileCount;
620
+ return pushFile;
621
+ }
622
+ const getArray = (paths)=>paths;
623
+ const getArrayGroup = ()=>[
624
+ ""
625
+ ].slice(0, 0);
626
+ function build$4(options) {
627
+ return options.group ? getArrayGroup : getArray;
628
+ }
629
+ const groupFiles = (groups, directory, files)=>{
630
+ groups.push({
631
+ directory,
632
+ files,
633
+ dir: directory
634
+ });
635
+ };
636
+ const empty = ()=>{};
637
+ function build$3(options) {
638
+ return options.group ? groupFiles : empty;
639
+ }
640
+ const resolveSymlinksAsync = function(path, state, callback$1) {
641
+ const { queue, fs, options: { suppressErrors } } = state;
642
+ queue.enqueue();
643
+ fs.realpath(path, (error, resolvedPath)=>{
644
+ if (error) return queue.dequeue(suppressErrors ? null : error, state);
645
+ fs.stat(resolvedPath, (error$1, stat)=>{
646
+ if (error$1) return queue.dequeue(suppressErrors ? null : error$1, state);
647
+ if (stat.isDirectory() && isRecursive(path, resolvedPath, state)) return queue.dequeue(null, state);
648
+ callback$1(stat, resolvedPath);
649
+ queue.dequeue(null, state);
650
+ });
651
+ });
652
+ };
653
+ const resolveSymlinks = function(path, state, callback$1) {
654
+ const { queue, fs, options: { suppressErrors } } = state;
655
+ queue.enqueue();
656
+ try {
657
+ const resolvedPath = fs.realpathSync(path);
658
+ const stat = fs.statSync(resolvedPath);
659
+ if (stat.isDirectory() && isRecursive(path, resolvedPath, state)) return;
660
+ callback$1(stat, resolvedPath);
661
+ } catch (e) {
662
+ if (!suppressErrors) throw e;
663
+ }
664
+ };
665
+ function build$2(options, isSynchronous) {
666
+ if (!options.resolveSymlinks || options.excludeSymlinks) return null;
667
+ return isSynchronous ? resolveSymlinks : resolveSymlinksAsync;
668
+ }
669
+ function isRecursive(path, resolved, state) {
670
+ if (state.options.useRealPaths) return isRecursiveUsingRealPaths(resolved, state);
671
+ let parent = dirname(path);
672
+ let depth = 1;
673
+ while(parent !== state.root && depth < 2){
674
+ const resolvedPath = state.symlinks.get(parent);
675
+ const isSameRoot = !!resolvedPath && (resolvedPath === resolved || resolvedPath.startsWith(resolved) || resolved.startsWith(resolvedPath));
676
+ if (isSameRoot) depth++;
677
+ else parent = dirname(parent);
678
+ }
679
+ state.symlinks.set(path, resolved);
680
+ return depth > 1;
681
+ }
682
+ function isRecursiveUsingRealPaths(resolved, state) {
683
+ return state.visited.includes(resolved + state.options.pathSeparator);
684
+ }
685
+ const onlyCountsSync = (state)=>state.counts;
686
+ const groupsSync = (state)=>state.groups;
687
+ const defaultSync = (state)=>state.paths;
688
+ const limitFilesSync = (state)=>state.paths.slice(0, state.options.maxFiles);
689
+ const onlyCountsAsync = (state, error, callback$1)=>{
690
+ report(error, callback$1, state.counts, state.options.suppressErrors);
691
+ return null;
692
+ };
693
+ const defaultAsync = (state, error, callback$1)=>{
694
+ report(error, callback$1, state.paths, state.options.suppressErrors);
695
+ return null;
696
+ };
697
+ const limitFilesAsync = (state, error, callback$1)=>{
698
+ report(error, callback$1, state.paths.slice(0, state.options.maxFiles), state.options.suppressErrors);
699
+ return null;
700
+ };
701
+ const groupsAsync = (state, error, callback$1)=>{
702
+ report(error, callback$1, state.groups, state.options.suppressErrors);
703
+ return null;
704
+ };
705
+ function report(error, callback$1, output, suppressErrors) {
706
+ callback$1(error && !suppressErrors ? error : null, output);
707
+ }
708
+ function build$1(options, isSynchronous) {
709
+ const { onlyCounts, group, maxFiles } = options;
710
+ if (onlyCounts) return isSynchronous ? onlyCountsSync : onlyCountsAsync;
711
+ if (group) return isSynchronous ? groupsSync : groupsAsync;
712
+ if (maxFiles) return isSynchronous ? limitFilesSync : limitFilesAsync;
713
+ return isSynchronous ? defaultSync : defaultAsync;
714
+ }
715
+ const readdirOpts = {
716
+ withFileTypes: true
717
+ };
718
+ const walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1)=>{
719
+ state.queue.enqueue();
720
+ if (currentDepth < 0) return state.queue.dequeue(null, state);
721
+ const { fs } = state;
722
+ state.visited.push(crawlPath);
723
+ state.counts.directories++;
724
+ fs.readdir(crawlPath || ".", readdirOpts, (error, entries = [])=>{
725
+ callback$1(entries, directoryPath, currentDepth);
726
+ state.queue.dequeue(state.options.suppressErrors ? null : error, state);
727
+ });
728
+ };
729
+ const walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1)=>{
730
+ const { fs } = state;
731
+ if (currentDepth < 0) return;
732
+ state.visited.push(crawlPath);
733
+ state.counts.directories++;
734
+ let entries = [];
735
+ try {
736
+ entries = fs.readdirSync(crawlPath || ".", readdirOpts);
737
+ } catch (e) {
738
+ if (!state.options.suppressErrors) throw e;
739
+ }
740
+ callback$1(entries, directoryPath, currentDepth);
741
+ };
742
+ function dist_build(isSynchronous) {
743
+ return isSynchronous ? walkSync : walkAsync;
744
+ }
745
+ var Queue = class {
746
+ count = 0;
747
+ constructor(onQueueEmpty){
748
+ this.onQueueEmpty = onQueueEmpty;
749
+ }
750
+ enqueue() {
751
+ this.count++;
752
+ return this.count;
753
+ }
754
+ dequeue(error, output) {
755
+ if (this.onQueueEmpty && (--this.count <= 0 || error)) {
756
+ this.onQueueEmpty(error, output);
757
+ if (error) {
758
+ output.controller.abort();
759
+ this.onQueueEmpty = void 0;
760
+ }
761
+ }
762
+ }
763
+ };
764
+ var Counter = class {
765
+ _files = 0;
766
+ _directories = 0;
767
+ set files(num) {
768
+ this._files = num;
769
+ }
770
+ get files() {
771
+ return this._files;
772
+ }
773
+ set directories(num) {
774
+ this._directories = num;
775
+ }
776
+ get directories() {
777
+ return this._directories;
778
+ }
779
+ get dirs() {
780
+ return this._directories;
781
+ }
782
+ };
783
+ var Aborter = class {
784
+ aborted = false;
785
+ abort() {
786
+ this.aborted = true;
787
+ }
788
+ };
789
+ var Walker = class {
790
+ root;
791
+ isSynchronous;
792
+ state;
793
+ joinPath;
794
+ pushDirectory;
795
+ pushFile;
796
+ getArray;
797
+ groupFiles;
798
+ resolveSymlink;
799
+ walkDirectory;
800
+ callbackInvoker;
801
+ constructor(root, options, callback$1){
802
+ this.isSynchronous = !callback$1;
803
+ this.callbackInvoker = build$1(options, this.isSynchronous);
804
+ this.root = normalizePath(root, options);
805
+ this.state = {
806
+ root: isRootDirectory(this.root) ? this.root : this.root.slice(0, -1),
807
+ paths: [
808
+ ""
809
+ ].slice(0, 0),
810
+ groups: [],
811
+ counts: new Counter(),
812
+ options,
813
+ queue: new Queue((error, state)=>this.callbackInvoker(state, error, callback$1)),
814
+ symlinks: /* @__PURE__ */ new Map(),
815
+ visited: [
816
+ ""
817
+ ].slice(0, 0),
818
+ controller: new Aborter(),
819
+ fs: options.fs || __rspack_external_fs
820
+ };
821
+ this.joinPath = build$7(this.root, options);
822
+ this.pushDirectory = build$6(this.root, options);
823
+ this.pushFile = build$5(options);
824
+ this.getArray = build$4(options);
825
+ this.groupFiles = build$3(options);
826
+ this.resolveSymlink = build$2(options, this.isSynchronous);
827
+ this.walkDirectory = dist_build(this.isSynchronous);
828
+ }
829
+ start() {
830
+ this.pushDirectory(this.root, this.state.paths, this.state.options.filters);
831
+ this.walkDirectory(this.state, this.root, this.root, this.state.options.maxDepth, this.walk);
832
+ return this.isSynchronous ? this.callbackInvoker(this.state, null) : null;
833
+ }
834
+ walk = (entries, directoryPath, depth)=>{
835
+ const { paths, options: { filters, resolveSymlinks: resolveSymlinks$1, excludeSymlinks, exclude, maxFiles, signal, useRealPaths, pathSeparator }, controller } = this.state;
836
+ if (controller.aborted || signal && signal.aborted || maxFiles && paths.length > maxFiles) return;
837
+ const files = this.getArray(this.state.paths);
838
+ for(let i = 0; i < entries.length; ++i){
839
+ const entry = entries[i];
840
+ if (entry.isFile() || entry.isSymbolicLink() && !resolveSymlinks$1 && !excludeSymlinks) {
841
+ const filename = this.joinPath(entry.name, directoryPath);
842
+ this.pushFile(filename, files, this.state.counts, filters);
843
+ } else if (entry.isDirectory()) {
844
+ let path = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator);
845
+ if (exclude && exclude(entry.name, path)) continue;
846
+ this.pushDirectory(path, paths, filters);
847
+ this.walkDirectory(this.state, path, path, depth - 1, this.walk);
848
+ } else if (this.resolveSymlink && entry.isSymbolicLink()) {
849
+ let path = joinPathWithBasePath(entry.name, directoryPath);
850
+ this.resolveSymlink(path, this.state, (stat, resolvedPath)=>{
851
+ if (stat.isDirectory()) {
852
+ resolvedPath = normalizePath(resolvedPath, this.state.options);
853
+ if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path + pathSeparator)) return;
854
+ this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path + pathSeparator, depth - 1, this.walk);
855
+ } else {
856
+ resolvedPath = useRealPaths ? resolvedPath : path;
857
+ const filename = basename(resolvedPath);
858
+ const directoryPath$1 = normalizePath(dirname(resolvedPath), this.state.options);
859
+ resolvedPath = this.joinPath(filename, directoryPath$1);
860
+ this.pushFile(resolvedPath, files, this.state.counts, filters);
861
+ }
862
+ });
863
+ }
864
+ }
865
+ this.groupFiles(this.state.groups, directoryPath, files);
866
+ };
867
+ };
868
+ function promise(root, options) {
869
+ return new Promise((resolve$1, reject)=>{
870
+ callback(root, options, (err, output)=>{
871
+ if (err) return reject(err);
872
+ resolve$1(output);
873
+ });
874
+ });
875
+ }
876
+ function callback(root, options, callback$1) {
877
+ let walker = new Walker(root, options, callback$1);
878
+ walker.start();
879
+ }
880
+ function sync(root, options) {
881
+ const walker = new Walker(root, options);
882
+ return walker.start();
883
+ }
884
+ var APIBuilder = class {
885
+ constructor(root, options){
886
+ this.root = root;
887
+ this.options = options;
888
+ }
889
+ withPromise() {
890
+ return promise(this.root, this.options);
891
+ }
892
+ withCallback(cb) {
893
+ callback(this.root, this.options, cb);
894
+ }
895
+ sync() {
896
+ return sync(this.root, this.options);
897
+ }
898
+ };
899
+ let pm = null;
900
+ try {
901
+ __require.resolve("picomatch");
902
+ pm = __require("picomatch");
903
+ } catch {}
904
+ var Builder = class {
905
+ globCache = {};
906
+ options = {
907
+ maxDepth: 1 / 0,
908
+ suppressErrors: true,
909
+ pathSeparator: sep,
910
+ filters: []
911
+ };
912
+ globFunction;
913
+ constructor(options){
914
+ this.options = {
915
+ ...this.options,
916
+ ...options
917
+ };
918
+ this.globFunction = this.options.globFunction;
919
+ }
920
+ group() {
921
+ this.options.group = true;
922
+ return this;
923
+ }
924
+ withPathSeparator(separator) {
925
+ this.options.pathSeparator = separator;
926
+ return this;
927
+ }
928
+ withBasePath() {
929
+ this.options.includeBasePath = true;
930
+ return this;
931
+ }
932
+ withRelativePaths() {
933
+ this.options.relativePaths = true;
934
+ return this;
935
+ }
936
+ withDirs() {
937
+ this.options.includeDirs = true;
938
+ return this;
939
+ }
940
+ withMaxDepth(depth) {
941
+ this.options.maxDepth = depth;
942
+ return this;
943
+ }
944
+ withMaxFiles(limit) {
945
+ this.options.maxFiles = limit;
946
+ return this;
947
+ }
948
+ withFullPaths() {
949
+ this.options.resolvePaths = true;
950
+ this.options.includeBasePath = true;
951
+ return this;
952
+ }
953
+ withErrors() {
954
+ this.options.suppressErrors = false;
955
+ return this;
956
+ }
957
+ withSymlinks({ resolvePaths = true } = {}) {
958
+ this.options.resolveSymlinks = true;
959
+ this.options.useRealPaths = resolvePaths;
960
+ return this.withFullPaths();
961
+ }
962
+ withAbortSignal(signal) {
963
+ this.options.signal = signal;
964
+ return this;
965
+ }
966
+ normalize() {
967
+ this.options.normalizePath = true;
968
+ return this;
969
+ }
970
+ filter(predicate) {
971
+ this.options.filters.push(predicate);
972
+ return this;
973
+ }
974
+ onlyDirs() {
975
+ this.options.excludeFiles = true;
976
+ this.options.includeDirs = true;
977
+ return this;
978
+ }
979
+ exclude(predicate) {
980
+ this.options.exclude = predicate;
981
+ return this;
982
+ }
983
+ onlyCounts() {
984
+ this.options.onlyCounts = true;
985
+ return this;
986
+ }
987
+ crawl(root) {
988
+ return new APIBuilder(root || ".", this.options);
989
+ }
990
+ withGlobFunction(fn) {
991
+ this.globFunction = fn;
992
+ return this;
993
+ }
994
+ crawlWithOptions(root, options) {
995
+ this.options = {
996
+ ...this.options,
997
+ ...options
998
+ };
999
+ return new APIBuilder(root || ".", this.options);
1000
+ }
1001
+ glob(...patterns) {
1002
+ if (this.globFunction) return this.globWithOptions(patterns);
1003
+ return this.globWithOptions(patterns, {
1004
+ dot: true
1005
+ });
1006
+ }
1007
+ globWithOptions(patterns, ...options) {
1008
+ const globFn = this.globFunction || pm;
1009
+ if (!globFn) throw new Error("Please specify a glob function to use glob matching.");
1010
+ var isMatch = this.globCache[patterns.join("\0")];
1011
+ if (!isMatch) {
1012
+ isMatch = globFn(patterns, ...options);
1013
+ this.globCache[patterns.join("\0")] = isMatch;
1014
+ }
1015
+ this.options.filters.push((path)=>isMatch(path));
1016
+ return this;
1017
+ }
1018
+ };
1019
+ const isReadonlyArray = Array.isArray;
1020
+ const isWin = "win32" === process.platform;
1021
+ const ONLY_PARENT_DIRECTORIES = /^(\/?\.\.)+$/;
1022
+ function getPartialMatcher(patterns, options = {}) {
1023
+ const patternsCount = patterns.length;
1024
+ const patternsParts = Array(patternsCount);
1025
+ const matchers = Array(patternsCount);
1026
+ const globstarEnabled = !options.noglobstar;
1027
+ for(let i = 0; i < patternsCount; i++){
1028
+ const parts = splitPattern(patterns[i]);
1029
+ patternsParts[i] = parts;
1030
+ const partsCount = parts.length;
1031
+ const partMatchers = Array(partsCount);
1032
+ for(let j = 0; j < partsCount; j++)partMatchers[j] = picomatch(parts[j], options);
1033
+ matchers[i] = partMatchers;
1034
+ }
1035
+ return (input)=>{
1036
+ const inputParts = input.split("/");
1037
+ if (".." === inputParts[0] && ONLY_PARENT_DIRECTORIES.test(input)) return true;
1038
+ for(let i = 0; i < patterns.length; i++){
1039
+ const patternParts = patternsParts[i];
1040
+ const matcher = matchers[i];
1041
+ const inputPatternCount = inputParts.length;
1042
+ const minParts = Math.min(inputPatternCount, patternParts.length);
1043
+ let j = 0;
1044
+ while(j < minParts){
1045
+ const part = patternParts[j];
1046
+ if (part.includes("/")) return true;
1047
+ const match = matcher[j](inputParts[j]);
1048
+ if (!match) break;
1049
+ if (globstarEnabled && "**" === part) return true;
1050
+ j++;
1051
+ }
1052
+ if (j === inputPatternCount) return true;
1053
+ }
1054
+ return false;
1055
+ };
1056
+ }
1057
+ const WIN32_ROOT_DIR = /^[A-Z]:\/$/i;
1058
+ const isRoot = isWin ? (p)=>WIN32_ROOT_DIR.test(p) : (p)=>"/" === p;
1059
+ function buildFormat(cwd, root, absolute) {
1060
+ if (cwd === root || root.startsWith(`${cwd}/`)) {
1061
+ if (absolute) {
1062
+ const start = isRoot(cwd) ? cwd.length : cwd.length + 1;
1063
+ return (p, isDir)=>p.slice(start, isDir ? -1 : void 0) || ".";
1064
+ }
1065
+ const prefix = root.slice(cwd.length + 1);
1066
+ if (prefix) return (p, isDir)=>{
1067
+ if ("." === p) return prefix;
1068
+ const result = `${prefix}/${p}`;
1069
+ return isDir ? result.slice(0, -1) : result;
1070
+ };
1071
+ return (p, isDir)=>isDir && "." !== p ? p.slice(0, -1) : p;
1072
+ }
1073
+ if (absolute) return (p)=>posix.relative(cwd, p) || ".";
1074
+ return (p)=>posix.relative(cwd, `${root}/${p}`) || ".";
1075
+ }
1076
+ function buildRelative(cwd, root) {
1077
+ if (root.startsWith(`${cwd}/`)) {
1078
+ const prefix = root.slice(cwd.length + 1);
1079
+ return (p)=>`${prefix}/${p}`;
1080
+ }
1081
+ return (p)=>{
1082
+ const result = posix.relative(cwd, `${root}/${p}`);
1083
+ if (p.endsWith("/") && "" !== result) return `${result}/`;
1084
+ return result || ".";
1085
+ };
1086
+ }
1087
+ const splitPatternOptions = {
1088
+ parts: true
1089
+ };
1090
+ function splitPattern(path$1) {
1091
+ var _result$parts;
1092
+ const result = picomatch.scan(path$1, splitPatternOptions);
1093
+ return (null == (_result$parts = result.parts) ? void 0 : _result$parts.length) ? result.parts : [
1094
+ path$1
1095
+ ];
1096
+ }
1097
+ const ESCAPED_WIN32_BACKSLASHES = /\\(?![()[\]{}!+@])/g;
1098
+ function convertPosixPathToPattern(path$1) {
1099
+ return escapePosixPath(path$1);
1100
+ }
1101
+ function convertWin32PathToPattern(path$1) {
1102
+ return escapeWin32Path(path$1).replace(ESCAPED_WIN32_BACKSLASHES, "/");
1103
+ }
1104
+ const convertPathToPattern = isWin ? convertWin32PathToPattern : convertPosixPathToPattern;
1105
+ const POSIX_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}*?|]|^!|[!+@](?=\()|\\(?![()[\]{}!*+?@|]))/g;
1106
+ const WIN32_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}]|^!|[!+@](?=\())/g;
1107
+ const escapePosixPath = (path$1)=>path$1.replace(POSIX_UNESCAPED_GLOB_SYMBOLS, "\\$&");
1108
+ const escapeWin32Path = (path$1)=>path$1.replace(WIN32_UNESCAPED_GLOB_SYMBOLS, "\\$&");
1109
+ const escapePath = isWin ? escapeWin32Path : escapePosixPath;
1110
+ function isDynamicPattern(pattern, options) {
1111
+ if ((null == options ? void 0 : options.caseSensitiveMatch) === false) return true;
1112
+ const scan = picomatch.scan(pattern);
1113
+ return scan.isGlob || scan.negated;
1114
+ }
1115
+ function log(...tasks) {
1116
+ console.log(`[tinyglobby ${/* @__PURE__ */ new Date().toLocaleTimeString("es")}]`, ...tasks);
1117
+ }
1118
+ const PARENT_DIRECTORY = /^(\/?\.\.)+/;
1119
+ const ESCAPING_BACKSLASHES = /\\(?=[()[\]{}!*+?@|])/g;
1120
+ const BACKSLASHES = /\\/g;
1121
+ function normalizePattern(pattern, expandDirectories, cwd, props, isIgnore) {
1122
+ let result = pattern;
1123
+ if (pattern.endsWith("/")) result = pattern.slice(0, -1);
1124
+ if (!result.endsWith("*") && expandDirectories) result += "/**";
1125
+ const escapedCwd = escapePath(cwd);
1126
+ result = path_0.isAbsolute(result.replace(ESCAPING_BACKSLASHES, "")) ? posix.relative(escapedCwd, result) : posix.normalize(result);
1127
+ const parentDirectoryMatch = PARENT_DIRECTORY.exec(result);
1128
+ const parts = splitPattern(result);
1129
+ if (null == parentDirectoryMatch ? void 0 : parentDirectoryMatch[0]) {
1130
+ const n = (parentDirectoryMatch[0].length + 1) / 3;
1131
+ let i = 0;
1132
+ const cwdParts = escapedCwd.split("/");
1133
+ while(i < n && parts[i + n] === cwdParts[cwdParts.length + i - n]){
1134
+ result = result.slice(0, (n - i - 1) * 3) + result.slice((n - i) * 3 + parts[i + n].length + 1) || ".";
1135
+ i++;
1136
+ }
1137
+ const potentialRoot = posix.join(cwd, parentDirectoryMatch[0].slice(3 * i));
1138
+ if (!potentialRoot.startsWith(".") && props.root.length > potentialRoot.length) {
1139
+ props.root = potentialRoot;
1140
+ props.depthOffset = -n + i;
1141
+ }
1142
+ }
1143
+ if (!isIgnore && props.depthOffset >= 0) {
1144
+ null != props.commonPath || (props.commonPath = parts);
1145
+ const newCommonPath = [];
1146
+ const length = Math.min(props.commonPath.length, parts.length);
1147
+ for(let i = 0; i < length; i++){
1148
+ const part = parts[i];
1149
+ if ("**" === part && !parts[i + 1]) {
1150
+ newCommonPath.pop();
1151
+ break;
1152
+ }
1153
+ if (part !== props.commonPath[i] || isDynamicPattern(part) || i === parts.length - 1) break;
1154
+ newCommonPath.push(part);
1155
+ }
1156
+ props.depthOffset = newCommonPath.length;
1157
+ props.commonPath = newCommonPath;
1158
+ props.root = newCommonPath.length > 0 ? posix.join(cwd, ...newCommonPath) : cwd;
1159
+ }
1160
+ return result;
1161
+ }
1162
+ function processPatterns({ patterns = [
1163
+ "**/*"
1164
+ ], ignore = [], expandDirectories = true }, cwd, props) {
1165
+ if ("string" == typeof patterns) patterns = [
1166
+ patterns
1167
+ ];
1168
+ if ("string" == typeof ignore) ignore = [
1169
+ ignore
1170
+ ];
1171
+ const matchPatterns = [];
1172
+ const ignorePatterns = [];
1173
+ for (const pattern of ignore)if (pattern) {
1174
+ if ("!" !== pattern[0] || "(" === pattern[1]) ignorePatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, true));
1175
+ }
1176
+ for (const pattern of patterns)if (pattern) {
1177
+ if ("!" !== pattern[0] || "(" === pattern[1]) matchPatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, false));
1178
+ else if ("!" !== pattern[1] || "(" === pattern[2]) ignorePatterns.push(normalizePattern(pattern.slice(1), expandDirectories, cwd, props, true));
1179
+ }
1180
+ return {
1181
+ match: matchPatterns,
1182
+ ignore: ignorePatterns
1183
+ };
1184
+ }
1185
+ function formatPaths(paths, relative) {
1186
+ for(let i = paths.length - 1; i >= 0; i--){
1187
+ const path$1 = paths[i];
1188
+ paths[i] = relative(path$1);
1189
+ }
1190
+ return paths;
1191
+ }
1192
+ function normalizeCwd(cwd) {
1193
+ if (!cwd) return process.cwd().replace(BACKSLASHES, "/");
1194
+ if (cwd instanceof URL) return fileURLToPath(cwd).replace(BACKSLASHES, "/");
1195
+ return path_0.resolve(cwd).replace(BACKSLASHES, "/");
1196
+ }
1197
+ function getCrawler(patterns, inputOptions = {}) {
1198
+ const options = process.env.TINYGLOBBY_DEBUG ? {
1199
+ ...inputOptions,
1200
+ debug: true
1201
+ } : inputOptions;
1202
+ const cwd = normalizeCwd(options.cwd);
1203
+ if (options.debug) log("globbing with:", {
1204
+ patterns,
1205
+ options,
1206
+ cwd
1207
+ });
1208
+ if (Array.isArray(patterns) && 0 === patterns.length) return [
1209
+ {
1210
+ sync: ()=>[],
1211
+ withPromise: async ()=>[]
1212
+ },
1213
+ false
1214
+ ];
1215
+ const props = {
1216
+ root: cwd,
1217
+ commonPath: null,
1218
+ depthOffset: 0
1219
+ };
1220
+ const processed = processPatterns({
1221
+ ...options,
1222
+ patterns
1223
+ }, cwd, props);
1224
+ if (options.debug) log("internal processing patterns:", processed);
1225
+ const matchOptions = {
1226
+ dot: options.dot,
1227
+ nobrace: false === options.braceExpansion,
1228
+ nocase: false === options.caseSensitiveMatch,
1229
+ noextglob: false === options.extglob,
1230
+ noglobstar: false === options.globstar,
1231
+ posix: true
1232
+ };
1233
+ const matcher = picomatch(processed.match, {
1234
+ ...matchOptions,
1235
+ ignore: processed.ignore
1236
+ });
1237
+ const ignore = picomatch(processed.ignore, matchOptions);
1238
+ const partialMatcher = getPartialMatcher(processed.match, matchOptions);
1239
+ const format = buildFormat(cwd, props.root, options.absolute);
1240
+ const formatExclude = options.absolute ? format : buildFormat(cwd, props.root, true);
1241
+ const fdirOptions = {
1242
+ filters: [
1243
+ options.debug ? (p, isDirectory)=>{
1244
+ const path$1 = format(p, isDirectory);
1245
+ const matches = matcher(path$1);
1246
+ if (matches) log(`matched ${path$1}`);
1247
+ return matches;
1248
+ } : (p, isDirectory)=>matcher(format(p, isDirectory))
1249
+ ],
1250
+ exclude: options.debug ? (_, p)=>{
1251
+ const relativePath = formatExclude(p, true);
1252
+ const skipped = "." !== relativePath && !partialMatcher(relativePath) || ignore(relativePath);
1253
+ skipped ? log(`skipped ${p}`) : log(`crawling ${p}`);
1254
+ return skipped;
1255
+ } : (_, p)=>{
1256
+ const relativePath = formatExclude(p, true);
1257
+ return "." !== relativePath && !partialMatcher(relativePath) || ignore(relativePath);
1258
+ },
1259
+ fs: options.fs ? {
1260
+ readdir: options.fs.readdir || fs_0.readdir,
1261
+ readdirSync: options.fs.readdirSync || fs_0.readdirSync,
1262
+ realpath: options.fs.realpath || fs_0.realpath,
1263
+ realpathSync: options.fs.realpathSync || fs_0.realpathSync,
1264
+ stat: options.fs.stat || fs_0.stat,
1265
+ statSync: options.fs.statSync || fs_0.statSync
1266
+ } : void 0,
1267
+ pathSeparator: "/",
1268
+ relativePaths: true,
1269
+ resolveSymlinks: true,
1270
+ signal: options.signal
1271
+ };
1272
+ if (void 0 !== options.deep) fdirOptions.maxDepth = Math.round(options.deep - props.depthOffset);
1273
+ if (options.absolute) {
1274
+ fdirOptions.relativePaths = false;
1275
+ fdirOptions.resolvePaths = true;
1276
+ fdirOptions.includeBasePath = true;
1277
+ }
1278
+ if (false === options.followSymbolicLinks) {
1279
+ fdirOptions.resolveSymlinks = false;
1280
+ fdirOptions.excludeSymlinks = true;
1281
+ }
1282
+ if (options.onlyDirectories) {
1283
+ fdirOptions.excludeFiles = true;
1284
+ fdirOptions.includeDirs = true;
1285
+ } else if (false === options.onlyFiles) fdirOptions.includeDirs = true;
1286
+ props.root = props.root.replace(BACKSLASHES, "");
1287
+ const root = props.root;
1288
+ if (options.debug) log("internal properties:", props);
1289
+ const relative = cwd !== root && !options.absolute && buildRelative(cwd, props.root);
1290
+ return [
1291
+ new Builder(fdirOptions).crawl(root),
1292
+ relative
1293
+ ];
1294
+ }
1295
+ async function glob(patternsOrOptions, options) {
1296
+ if (patternsOrOptions && (null == options ? void 0 : options.patterns)) throw new Error("Cannot pass patterns as both an argument and an option");
1297
+ const isModern = isReadonlyArray(patternsOrOptions) || "string" == typeof patternsOrOptions;
1298
+ const opts = isModern ? options : patternsOrOptions;
1299
+ const patterns = isModern ? patternsOrOptions : patternsOrOptions.patterns;
1300
+ const [crawler, relative] = getCrawler(patterns, opts);
1301
+ if (!relative) return crawler.withPromise();
1302
+ return formatPaths(await crawler.withPromise(), relative);
1303
+ }
1304
+ function createPathIdentity(paths, caseSensitive) {
1305
+ const normalize = (filePath)=>{
1306
+ let normalized = paths.normalize(filePath);
1307
+ const root = paths.parse(normalized).root;
1308
+ while(normalized.length > root.length && normalized.endsWith(paths.sep))normalized = normalized.slice(0, -1);
1309
+ return normalized;
1310
+ };
1311
+ const key = (filePath)=>{
1312
+ const normalized = normalize(filePath);
1313
+ return caseSensitive ? normalized : normalized.toLowerCase();
1314
+ };
1315
+ return {
1316
+ paths,
1317
+ key,
1318
+ normalize,
1319
+ equals: (left, right)=>key(left) === key(right),
1320
+ isSameOrChild: (parent, child)=>{
1321
+ const parentKey = key(parent);
1322
+ const childKey = key(child);
1323
+ if (parentKey === childKey) return true;
1324
+ const prefix = parentKey.endsWith(paths.sep) ? parentKey : `${parentKey}${paths.sep}`;
1325
+ return childKey.startsWith(prefix);
1326
+ },
1327
+ compare: (left, right)=>key(left).localeCompare(key(right)) || normalize(left).localeCompare(normalize(right))
1328
+ };
1329
+ }
1330
+ const nativePathIdentity = createPathIdentity(node_path, true);
1331
+ async function realpathNative(filePath) {
1332
+ const resolvedPath = await new Promise((resolve, reject)=>{
1333
+ node_fs.realpath.native(filePath, (error, resolvedPath)=>{
1334
+ if (error) reject(error);
1335
+ else resolve(resolvedPath);
1336
+ });
1337
+ });
1338
+ return resolvedPath;
1339
+ }
1340
+ class RunPathResolver {
1341
+ #resolved = new Map();
1342
+ async resolve(filePath) {
1343
+ const resolved = await this.#resolveState(filePath);
1344
+ return resolved;
1345
+ }
1346
+ async #resolveState(filePath) {
1347
+ const lexicalPath = nativePathIdentity.normalize(filePath);
1348
+ const lexicalKey = nativePathIdentity.key(lexicalPath);
1349
+ let pending = this.#resolved.get(lexicalKey);
1350
+ if (!pending) {
1351
+ pending = (async ()=>{
1352
+ let canonicalPath = lexicalPath;
1353
+ let physicallyResolved = false;
1354
+ try {
1355
+ canonicalPath = nativePathIdentity.normalize(await realpathNative(lexicalPath));
1356
+ physicallyResolved = true;
1357
+ } catch {}
1358
+ return {
1359
+ lexicalPath,
1360
+ lexicalKey,
1361
+ canonicalPath,
1362
+ canonicalKey: nativePathIdentity.key(canonicalPath),
1363
+ physicallyResolved
1364
+ };
1365
+ })();
1366
+ this.#resolved.set(lexicalKey, pending);
1367
+ }
1368
+ const resolved = await pending;
1369
+ return resolved;
1370
+ }
1371
+ async resolveWithAncestorFallback(filePath) {
1372
+ const exact = await this.#resolveState(filePath);
1373
+ if (exact.physicallyResolved) return exact;
1374
+ const suffix = [];
1375
+ let current = exact.lexicalPath;
1376
+ while(true){
1377
+ const parent = node_path.dirname(current);
1378
+ if (nativePathIdentity.equals(parent, current)) return exact;
1379
+ suffix.unshift(node_path.basename(current));
1380
+ const resolvedParent = await this.#resolveState(parent);
1381
+ if (resolvedParent.physicallyResolved) {
1382
+ const canonicalPath = nativePathIdentity.normalize(node_path.resolve(resolvedParent.canonicalPath, ...suffix));
1383
+ return {
1384
+ lexicalPath: exact.lexicalPath,
1385
+ lexicalKey: exact.lexicalKey,
1386
+ canonicalPath,
1387
+ canonicalKey: nativePathIdentity.key(canonicalPath)
1388
+ };
1389
+ }
1390
+ current = parent;
1391
+ }
1392
+ }
1393
+ async resolveAll(filePaths, concurrency = 32) {
1394
+ const results = new Array(filePaths.length);
1395
+ let next = 0;
1396
+ const worker = async ()=>{
1397
+ while(true){
1398
+ const index = next++;
1399
+ if (index >= filePaths.length) return;
1400
+ results[index] = await this.resolve(filePaths[index]);
1401
+ }
1402
+ };
1403
+ const workerCount = Math.min(filePaths.length, Math.max(1, Math.floor(concurrency)));
1404
+ await Promise.all(Array.from({
1405
+ length: workerCount
1406
+ }, worker));
1407
+ return results;
1408
+ }
1409
+ }
1410
+ function isRecord(value) {
1411
+ return null !== value && 'object' == typeof value && !Array.isArray(value);
1412
+ }
1413
+ function isPluginHostFactoryModule(value) {
1414
+ return isRecord(value) && 'function' == typeof value.createPluginLintHost;
1415
+ }
1416
+ function isPluginLintHost(value) {
1417
+ return isRecord(value) && 'function' == typeof value.lint && 'function' == typeof value.shutdown;
1418
+ }
1419
+ let pluginHostFactoryPromise;
1420
+ async function loadPluginHostFactory() {
1421
+ pluginHostFactoryPromise ??= (async ()=>{
1422
+ const pluginEntry = '@rslint/core/eslint-plugin';
1423
+ const module = await import(pluginEntry);
1424
+ if (!isPluginHostFactoryModule(module)) throw new Error('rslint ESLint-plugin entry does not export createPluginLintHost');
1425
+ return module.createPluginLintHost;
1426
+ })();
1427
+ const factory = await pluginHostFactoryPromise;
1428
+ return factory;
1429
+ }
1430
+ class PluginHostLifecycle {
1431
+ #pendingBuilds = new Set();
1432
+ #staged = new Set();
1433
+ #active = new Set();
1434
+ #shutdowns = new WeakMap();
1435
+ async trackBuild(build) {
1436
+ this.#pendingBuilds.add(build);
1437
+ build.then(()=>this.#pendingBuilds.delete(build), ()=>this.#pendingBuilds.delete(build));
1438
+ const result = await build;
1439
+ return result;
1440
+ }
1441
+ stage(host) {
1442
+ this.#staged.add(host);
1443
+ }
1444
+ publish(host) {
1445
+ this.#staged.delete(host);
1446
+ this.#active.add(host);
1447
+ }
1448
+ async shutdown(host) {
1449
+ this.#staged.delete(host);
1450
+ this.#active.delete(host);
1451
+ let shutdown = this.#shutdowns.get(host);
1452
+ if (!shutdown) {
1453
+ shutdown = host.shutdown();
1454
+ this.#shutdowns.set(host, shutdown);
1455
+ }
1456
+ await shutdown;
1457
+ }
1458
+ async shutdownAll() {
1459
+ while(this.#pendingBuilds.size > 0)await Promise.allSettled([
1460
+ ...this.#pendingBuilds
1461
+ ]);
1462
+ const shutdowns = [];
1463
+ for (const host of new Set([
1464
+ ...this.#staged,
1465
+ ...this.#active
1466
+ ]))shutdowns.push(this.shutdown(host));
1467
+ await Promise.allSettled(shutdowns);
1468
+ }
1469
+ }
1470
+ async function stageNativeConfigActivation(configHost, request, getPluginHostFactory, onLog, isClosing, lifecycle) {
1471
+ let pluginHost = null;
1472
+ try {
1473
+ const activation = await configHost.activateConfigs(request, void 0, async (candidate)=>{
1474
+ if (0 === candidate.pluginConfigs.length) return;
1475
+ if (isClosing()) throw new Error('rslint service is closing');
1476
+ const createPluginLintHost = await getPluginHostFactory();
1477
+ if (isClosing()) throw new Error('rslint service is closing');
1478
+ const build = (async ()=>{
1479
+ const host = await createPluginLintHost(candidate.pluginConfigs, onLog);
1480
+ lifecycle?.stage(host);
1481
+ return host;
1482
+ })();
1483
+ pluginHost = await (lifecycle?.trackBuild(build) ?? build);
1484
+ if (isClosing()) throw new Error('rslint service is closing');
1485
+ });
1486
+ if (isClosing()) throw new Error('rslint service is closing');
1487
+ return {
1488
+ activation,
1489
+ pluginHost
1490
+ };
1491
+ } catch (error) {
1492
+ try {
1493
+ const createdHost = pluginHost;
1494
+ if (isPluginLintHost(createdHost)) await (lifecycle?.shutdown(createdHost) ?? createdHost.shutdown());
1495
+ } catch {}
1496
+ throw error;
1497
+ }
1498
+ }
501
1499
  function _to_primitive(input, hint) {
502
1500
  if ("object" !== _type_of(input) || null === input) return input;
503
1501
  var prim = input[Symbol.toPrimitive];
@@ -516,6 +1514,105 @@ function _type_of(obj) {
516
1514
  return obj && "u" > typeof Symbol && obj.constructor === Symbol ? "symbol" : typeof obj;
517
1515
  }
518
1516
  let _computedKey;
1517
+ function rslint_isRecord(value) {
1518
+ return null !== value && 'object' == typeof value && !Array.isArray(value);
1519
+ }
1520
+ function globPatternRole(pattern) {
1521
+ if ('!' !== pattern[0] || '(' === pattern[1]) return 'match';
1522
+ if ('!' !== pattern[1] || '(' === pattern[2]) return 'ignore';
1523
+ return 'skip';
1524
+ }
1525
+ const DEFAULT_LINT_GLOB_IGNORES = [
1526
+ '**/node_modules/**',
1527
+ '**/.git/**'
1528
+ ];
1529
+ function staticGlobRoot(pattern, cwd) {
1530
+ const absolutePattern = node_path.resolve(cwd, pattern);
1531
+ const root = node_path.parse(absolutePattern).root;
1532
+ const segments = absolutePattern.slice(root.length).split(node_path.sep);
1533
+ let current = root;
1534
+ for (const segment of segments){
1535
+ if (!segment || isDynamicPattern(segment)) break;
1536
+ current = node_path.join(current, segment);
1537
+ }
1538
+ return current || cwd;
1539
+ }
1540
+ function deduplicateScanDirectories(directories) {
1541
+ const byIdentity = new Map();
1542
+ for (const directory of directories){
1543
+ const normalized = node_path.normalize(directory);
1544
+ const key = nativePathIdentity.key(normalized);
1545
+ if (!byIdentity.has(key)) byIdentity.set(key, normalized);
1546
+ }
1547
+ return [
1548
+ ...byIdentity.values()
1549
+ ].sort(nativePathIdentity.compare);
1550
+ }
1551
+ function normalizeGlobPatternForCwd(pattern, cwd) {
1552
+ let normalized = pattern;
1553
+ if (normalized.endsWith('/') || normalized.endsWith('\\')) normalized = normalized.slice(0, -1);
1554
+ if (node_path.isAbsolute(normalized)) normalized = node_path.relative(cwd, normalized);
1555
+ normalized = normalized.split(node_path.sep).join('/');
1556
+ return node_path.posix.normalize(normalized);
1557
+ }
1558
+ function matchesExcludedLiteral(filePath, patterns, cwd) {
1559
+ const candidate = node_path.relative(cwd, filePath).split(node_path.sep).join('/');
1560
+ for (const rawPattern of patterns){
1561
+ let pattern = rawPattern;
1562
+ if (pattern.startsWith('!')) {
1563
+ if ('(' === pattern[1]) continue;
1564
+ if ('!' === pattern[1] && '(' !== pattern[2]) continue;
1565
+ pattern = pattern.slice(1);
1566
+ }
1567
+ pattern = normalizeGlobPatternForCwd(pattern, cwd);
1568
+ const expandedPatterns = pattern.endsWith('*') ? [
1569
+ pattern
1570
+ ] : [
1571
+ pattern,
1572
+ `${pattern}/**`
1573
+ ];
1574
+ if (picomatch(expandedPatterns, {
1575
+ dot: true,
1576
+ nocase: false
1577
+ })(candidate)) return true;
1578
+ }
1579
+ return false;
1580
+ }
1581
+ async function classifyLintPatterns(patterns, cwd) {
1582
+ const literalFilePatterns = [];
1583
+ const literalDirectorySymlinks = [];
1584
+ const scanDirectories = new Set();
1585
+ const excludedLiteralPatterns = [
1586
+ ...DEFAULT_LINT_GLOB_IGNORES,
1587
+ ...patterns.filter((pattern)=>'ignore' === globPatternRole(pattern))
1588
+ ];
1589
+ for (const pattern of patterns){
1590
+ if ('match' !== globPatternRole(pattern)) continue;
1591
+ if (isDynamicPattern(pattern)) {
1592
+ const scanRoot = staticGlobRoot(pattern, cwd);
1593
+ try {
1594
+ if ((await promises_stat(scanRoot)).isDirectory()) scanDirectories.add(scanRoot);
1595
+ } catch {}
1596
+ continue;
1597
+ }
1598
+ const absolute = node_path.resolve(cwd, pattern);
1599
+ try {
1600
+ const info = await promises_stat(absolute);
1601
+ if (info.isDirectory()) {
1602
+ scanDirectories.add(absolute);
1603
+ if ((await lstat(absolute)).isSymbolicLink()) literalDirectorySymlinks.push(absolute);
1604
+ } else if (info.isFile()) {
1605
+ const absolutePattern = node_path.resolve(cwd, pattern);
1606
+ if (!matchesExcludedLiteral(absolutePattern, excludedLiteralPatterns, cwd)) literalFilePatterns.push(absolutePattern);
1607
+ }
1608
+ } catch {}
1609
+ }
1610
+ return {
1611
+ literalFilePatterns,
1612
+ literalDirectorySymlinks,
1613
+ scanDirectories: deduplicateScanDirectories(scanDirectories)
1614
+ };
1615
+ }
519
1616
  _computedKey = _to_property_key(Symbol.asyncDispose);
520
1617
  class Rslint {
521
1618
  #service;
@@ -524,6 +1621,10 @@ class Rslint {
524
1621
  #overrideConfigFile;
525
1622
  #fix;
526
1623
  #virtualFiles;
1624
+ #pluginHosts = new PluginHostLifecycle();
1625
+ #normalizedOverrideConfig;
1626
+ #closeRequested = false;
1627
+ #closePromise;
527
1628
  constructor(options = {}){
528
1629
  this.#cwd = options.cwd ? node_path.resolve(options.cwd) : process.cwd();
529
1630
  this.#overrideConfig = options.overrideConfig;
@@ -534,65 +1635,132 @@ class Rslint {
534
1635
  }
535
1636
  async lintText(code, options = {}) {
536
1637
  const filePath = node_path.resolve(this.#cwd, options.filePath ?? '__text__.ts');
537
- const { config, configDirectory } = await this.#resolveConfig(node_path.dirname(filePath));
538
- const response = await this.#service.lint({
539
- config,
540
- configDirectory,
541
- workingDirectory: this.#cwd,
542
- files: [
1638
+ const pathResolver = new RunPathResolver();
1639
+ const resolvedFile = await pathResolver.resolveWithAncestorFallback(filePath);
1640
+ const overrideConfig = this.#getNormalizedOverrideConfig() ?? [];
1641
+ const usesNativeDiscovery = true !== this.#overrideConfigFile;
1642
+ const discoverySession = usesNativeDiscovery ? this.#createNativeConfigDiscoverySession() : null;
1643
+ try {
1644
+ const response = await this.#service.lint({
1645
+ config: usesNativeDiscovery ? void 0 : overrideConfig,
1646
+ configDiscovery: usesNativeDiscovery ? {
1647
+ explicitConfigPath: 'string' == typeof this.#overrideConfigFile ? node_path.resolve(this.#cwd, this.#overrideConfigFile) : void 0,
1648
+ explicitFiles: [
1649
+ true
1650
+ ],
1651
+ overrideConfig
1652
+ } : void 0,
1653
+ configDirectory: usesNativeDiscovery ? void 0 : this.#cwd,
1654
+ workingDirectory: this.#cwd,
1655
+ files: [
1656
+ filePath
1657
+ ],
1658
+ canonicalFiles: [
1659
+ resolvedFile.canonicalPath
1660
+ ],
1661
+ fileContents: {
1662
+ ...this.#resolveOverlay(),
1663
+ [filePath]: code
1664
+ },
1665
+ fix: this.#fix
1666
+ }, discoverySession?.handlers ?? {});
1667
+ const results = this.#toLintResults(response, this.#cwd, [
543
1668
  filePath
544
- ],
545
- fileContents: {
546
- ...this.#resolveOverlay(),
1669
+ ], {
547
1670
  [filePath]: code
548
- },
549
- fix: this.#fix
550
- });
551
- const results = this.#toLintResults(response, configDirectory, [
552
- filePath
553
- ], {
554
- [filePath]: code
555
- });
556
- const primary = results.filter((r)=>r.filePath === filePath);
557
- if (null == options.filePath) {
558
- for (const r of primary)if (r.filePath === filePath) r.filePath = '<text>';
1671
+ });
1672
+ const primary = results.filter((r)=>nativePathIdentity.equals(r.filePath, filePath));
1673
+ if (null == options.filePath) {
1674
+ for (const r of primary)if (nativePathIdentity.equals(r.filePath, filePath)) r.filePath = '<text>';
1675
+ }
1676
+ return primary;
1677
+ } finally{
1678
+ await discoverySession?.shutdown();
559
1679
  }
560
- return primary;
561
1680
  }
562
1681
  async lintFiles(patterns) {
563
1682
  const globs = Array.isArray(patterns) ? patterns : [
564
1683
  patterns
565
1684
  ];
566
- const matched = await glob(globs, {
1685
+ const { literalFilePatterns, literalDirectorySymlinks, scanDirectories } = await classifyLintPatterns(globs, this.#cwd);
1686
+ const globOptions = {
567
1687
  cwd: this.#cwd,
568
1688
  absolute: true,
569
- onlyFiles: true
1689
+ onlyFiles: true,
1690
+ dot: true,
1691
+ ignore: DEFAULT_LINT_GLOB_IGNORES
1692
+ };
1693
+ const matched = await glob(globs, {
1694
+ ...globOptions,
1695
+ followSymbolicLinks: false
570
1696
  });
571
- const files = matched.map((f)=>node_path.normalize(f));
572
- if (0 === files.length) return [];
573
- const { config, configDirectory } = await this.#resolveConfig(this.#cwd);
574
- const response = await this.#service.lint({
575
- config,
576
- configDirectory,
577
- workingDirectory: this.#cwd,
578
- files,
579
- fileContents: this.#resolveOverlay(),
580
- fix: this.#fix
1697
+ const directorySymlinkMatches = 0 === literalDirectorySymlinks.length ? [] : await glob([
1698
+ ...literalDirectorySymlinks.map((directory)=>`${convertPathToPattern(directory)}/**/*`),
1699
+ ...globs.filter((pattern)=>pattern.startsWith('!'))
1700
+ ], {
1701
+ ...globOptions,
1702
+ followSymbolicLinks: false
581
1703
  });
582
- const contents = {};
583
- const bomFiles = new Set();
584
- for (const d of response.diagnostics ?? []){
585
- const abs = node_path.isAbsolute(d.filePath) ? node_path.normalize(d.filePath) : node_path.resolve(configDirectory, d.filePath);
586
- if (!(abs in contents)) try {
587
- const raw = await readFile(abs, 'utf8');
588
- if (0xfeff === raw.charCodeAt(0)) {
589
- bomFiles.add(abs);
590
- contents[abs] = raw.slice(1);
591
- } else contents[abs] = raw;
592
- } catch {}
1704
+ const literalMatches = literalFilePatterns;
1705
+ const filesByIdentity = new Map();
1706
+ for (const file of [
1707
+ ...matched,
1708
+ ...directorySymlinkMatches
1709
+ ]){
1710
+ const normalized = node_path.normalize(file);
1711
+ const key = nativePathIdentity.key(normalized);
1712
+ if (!filesByIdentity.has(key)) filesByIdentity.set(key, {
1713
+ filePath: normalized,
1714
+ explicit: false
1715
+ });
1716
+ }
1717
+ for (const file of literalMatches){
1718
+ const normalized = node_path.normalize(file);
1719
+ const key = nativePathIdentity.key(normalized);
1720
+ filesByIdentity.set(key, {
1721
+ filePath: normalized,
1722
+ explicit: true
1723
+ });
1724
+ }
1725
+ const lexicalFiles = [
1726
+ ...filesByIdentity.values()
1727
+ ];
1728
+ if (0 === lexicalFiles.length) return [];
1729
+ const pathResolver = new RunPathResolver();
1730
+ const resolvedPaths = await pathResolver.resolveAll(lexicalFiles.map(({ filePath })=>filePath));
1731
+ const plannedFiles = resolvedPaths.map((resolved, index)=>({
1732
+ ...resolved,
1733
+ explicit: lexicalFiles[index].explicit
1734
+ }));
1735
+ const selectedFiles = [
1736
+ ...plannedFiles
1737
+ ].sort((left, right)=>nativePathIdentity.compare(left.lexicalPath, right.lexicalPath));
1738
+ const overrideConfig = this.#getNormalizedOverrideConfig() ?? [];
1739
+ const usesNativeDiscovery = true !== this.#overrideConfigFile;
1740
+ const discoverySession = usesNativeDiscovery ? this.#createNativeConfigDiscoverySession() : null;
1741
+ try {
1742
+ const files = selectedFiles.map((file)=>file.lexicalPath);
1743
+ const response = await this.#service.lint({
1744
+ config: usesNativeDiscovery ? void 0 : overrideConfig,
1745
+ configDiscovery: usesNativeDiscovery ? {
1746
+ explicitConfigPath: 'string' == typeof this.#overrideConfigFile ? node_path.resolve(this.#cwd, this.#overrideConfigFile) : void 0,
1747
+ directories: scanDirectories,
1748
+ explicitFiles: selectedFiles.map((file)=>file.explicit),
1749
+ overrideConfig
1750
+ } : void 0,
1751
+ configDirectory: usesNativeDiscovery ? void 0 : this.#cwd,
1752
+ workingDirectory: this.#cwd,
1753
+ files,
1754
+ canonicalFiles: selectedFiles.map((file)=>file.canonicalPath),
1755
+ fileContents: this.#resolveOverlay(),
1756
+ fix: this.#fix
1757
+ }, discoverySession?.handlers ?? {});
1758
+ const { contents, bomFiles } = await this.#readDiagnosticContents(response, this.#cwd);
1759
+ const linted = response.lintedFiles ? response.lintedFiles.map((file)=>node_path.isAbsolute(file) ? node_path.normalize(file) : node_path.resolve(this.#cwd, file)) : files;
1760
+ return this.#toLintResults(response, this.#cwd, linted, contents, bomFiles).sort((a, b)=>nativePathIdentity.compare(a.filePath, b.filePath));
1761
+ } finally{
1762
+ await discoverySession?.shutdown();
593
1763
  }
594
- const linted = response.lintedFiles ? response.lintedFiles.map((f)=>node_path.isAbsolute(f) ? node_path.normalize(f) : node_path.resolve(configDirectory, f)) : files;
595
- return this.#toLintResults(response, configDirectory, linted, contents, bomFiles);
596
1764
  }
597
1765
  static async outputFixes(results) {
598
1766
  await Promise.all(results.map(async (r)=>{
@@ -600,7 +1768,17 @@ class Rslint {
600
1768
  }));
601
1769
  }
602
1770
  async close() {
603
- await this.#service.close();
1771
+ this.#closePromise ??= this.#closeResources();
1772
+ await this.#closePromise;
1773
+ }
1774
+ async #closeResources() {
1775
+ this.#closeRequested = true;
1776
+ await this.#pluginHosts.shutdownAll();
1777
+ try {
1778
+ await this.#service.close();
1779
+ } finally{
1780
+ await this.#pluginHosts.shutdownAll();
1781
+ }
604
1782
  }
605
1783
  async [_computedKey]() {
606
1784
  await this.close();
@@ -611,52 +1789,109 @@ class Rslint {
611
1789
  for (const [p, content] of Object.entries(this.#virtualFiles))resolved[node_path.resolve(this.#cwd, p)] = content;
612
1790
  return resolved;
613
1791
  }
614
- async #resolveConfig(fromDir) {
615
- let base = [];
616
- let configDirectory = this.#cwd;
617
- if (true === this.#overrideConfigFile) ;
618
- else if ('string' == typeof this.#overrideConfigFile) {
619
- const configPath = node_path.resolve(this.#cwd, this.#overrideConfigFile);
620
- base = normalizeConfig(await loadConfigFile(configPath));
621
- configDirectory = node_path.dirname(configPath);
622
- } else {
623
- const configPath = findJSConfigUp(fromDir);
624
- if (configPath) {
625
- base = normalizeConfig(await loadConfigFile(configPath));
626
- configDirectory = node_path.dirname(configPath);
627
- }
1792
+ #createNativeConfigDiscoverySession() {
1793
+ const configHost = new ConfigModuleHost();
1794
+ const transactions = new Set();
1795
+ let pluginSession = null;
1796
+ const shutdown = async ()=>{
1797
+ if (pluginSession) await this.#pluginHosts.shutdown(pluginSession.host);
1798
+ pluginSession = null;
1799
+ for (const transactionId of transactions)configHost.deleteSession(transactionId);
1800
+ transactions.clear();
1801
+ };
1802
+ return {
1803
+ handlers: {
1804
+ loadConfigs: async (request)=>{
1805
+ const response = await configHost.loadConfigs(request);
1806
+ transactions.add(request.transactionId);
1807
+ return response;
1808
+ },
1809
+ activateConfigs: async (request)=>{
1810
+ const { activation, pluginHost } = await stageNativeConfigActivation(configHost, request, loadPluginHostFactory, (record)=>{
1811
+ process.stderr.write(`[rslint:plugin] ${record.text}\n`);
1812
+ }, ()=>this.#closeRequested, this.#pluginHosts);
1813
+ if (pluginHost) {
1814
+ if (this.#closeRequested) {
1815
+ await this.#pluginHosts.shutdown(pluginHost);
1816
+ throw new Error('rslint service is closing');
1817
+ }
1818
+ this.#pluginHosts.publish(pluginHost);
1819
+ pluginSession = {
1820
+ host: pluginHost
1821
+ };
1822
+ }
1823
+ return activation;
1824
+ },
1825
+ pluginLint: async (request)=>{
1826
+ if (!pluginSession) throw new Error('rslint API: pluginLint requested without an activated plugin host');
1827
+ return pluginSession.host.lint(request);
1828
+ }
1829
+ },
1830
+ shutdown
1831
+ };
1832
+ }
1833
+ #getNormalizedOverrideConfig() {
1834
+ if (null == this.#overrideConfig) return null;
1835
+ if (this.#normalizedOverrideConfig) return this.#normalizedOverrideConfig;
1836
+ const override = Array.isArray(this.#overrideConfig) ? this.#overrideConfig : [
1837
+ this.#overrideConfig
1838
+ ];
1839
+ for (const [index, entry] of override.entries()){
1840
+ if (null == entry || 'object' != typeof entry || Array.isArray(entry)) continue;
1841
+ const plugins = rslint_isRecord(entry) ? entry.plugins : void 0;
1842
+ if (null !== plugins && 'object' == typeof plugins && !Array.isArray(plugins)) throw new Error(`[rslint] overrideConfig entry at index ${index} uses object-form "plugins". Community ESLint plugins in overrideConfig are not supported because the plugin worker cannot re-import an in-memory plugin object. Move the plugin declaration to rslint.config.js (or .mjs/.cjs/.ts/.mts/.cts), or use array-form built-in plugins.`);
628
1843
  }
629
- if (null != this.#overrideConfig) {
630
- const override = Array.isArray(this.#overrideConfig) ? this.#overrideConfig : [
631
- this.#overrideConfig
632
- ];
633
- base = [
634
- ...base,
635
- ...normalizeConfig(override)
636
- ];
1844
+ this.#normalizedOverrideConfig = normalizeConfig(override);
1845
+ return this.#normalizedOverrideConfig;
1846
+ }
1847
+ async #readDiagnosticContents(response, configDirectory) {
1848
+ const contents = {};
1849
+ const bomFiles = new Set();
1850
+ for (const d of response.diagnostics ?? []){
1851
+ const abs = node_path.isAbsolute(d.filePath) ? node_path.normalize(d.filePath) : node_path.resolve(configDirectory, d.filePath);
1852
+ if (!(abs in contents)) try {
1853
+ const raw = await readFile(abs, 'utf8');
1854
+ if (0xfeff === raw.charCodeAt(0)) {
1855
+ bomFiles.add(nativePathIdentity.key(abs));
1856
+ contents[abs] = raw.slice(1);
1857
+ } else contents[abs] = raw;
1858
+ } catch {}
637
1859
  }
638
1860
  return {
639
- config: base,
640
- configDirectory
1861
+ contents,
1862
+ bomFiles
641
1863
  };
642
1864
  }
643
1865
  #toLintResults(response, configDirectory, files, contents, bomFiles) {
644
1866
  const toAbs = (p)=>node_path.isAbsolute(p) ? node_path.normalize(p) : node_path.resolve(configDirectory, p);
1867
+ const contentByPath = new Map();
1868
+ for (const [filePath, source] of Object.entries(contents ?? {}))contentByPath.set(nativePathIdentity.key(filePath), source);
645
1869
  const byFile = new Map();
646
- for (const f of files)byFile.set(node_path.normalize(f), []);
1870
+ for (const file of files){
1871
+ const filePath = node_path.normalize(file);
1872
+ const key = nativePathIdentity.key(filePath);
1873
+ if (!byFile.has(key)) byFile.set(key, {
1874
+ filePath,
1875
+ messages: []
1876
+ });
1877
+ }
647
1878
  for (const d of response.diagnostics ?? []){
648
1879
  const abs = toAbs(d.filePath);
649
- let messages = byFile.get(abs);
650
- if (!messages) {
651
- messages = [];
652
- byFile.set(abs, messages);
1880
+ const key = nativePathIdentity.key(abs);
1881
+ let bucket = byFile.get(key);
1882
+ if (!bucket) {
1883
+ bucket = {
1884
+ filePath: abs,
1885
+ messages: []
1886
+ };
1887
+ byFile.set(key, bucket);
653
1888
  }
654
- messages.push(toLintMessage(d, contents?.[abs]));
1889
+ bucket.messages.push(toLintMessage(d, contentByPath.get(key)));
655
1890
  }
656
- const outputByAbs = new Map();
657
- for (const [rel, fixed] of Object.entries(response.output ?? {}))outputByAbs.set(toAbs(rel), fixed);
1891
+ const outputByPath = new Map();
1892
+ for (const [rel, fixed] of Object.entries(response.output ?? {}))outputByPath.set(nativePathIdentity.key(toAbs(rel)), fixed);
658
1893
  const results = [];
659
- for (const [filePath, messages] of byFile){
1894
+ for (const [key, { filePath, messages }] of byFile){
660
1895
  let errorCount = 0;
661
1896
  let warningCount = 0;
662
1897
  let fixableErrorCount = 0;
@@ -676,8 +1911,8 @@ class Rslint {
676
1911
  fixableErrorCount,
677
1912
  fixableWarningCount
678
1913
  };
679
- const output = outputByAbs.get(filePath);
680
- if (void 0 !== output) result.output = bomFiles?.has(filePath) ? '\uFEFF' + output : output;
1914
+ const output = outputByPath.get(key);
1915
+ if (void 0 !== output) result.output = bomFiles?.has(key) ? '\uFEFF' + output : output;
681
1916
  results.push(result);
682
1917
  }
683
1918
  return results;
@@ -750,6 +1985,6 @@ function mergeFixes(fixes, sourceText) {
750
1985
  text
751
1986
  };
752
1987
  }
753
- export { defineConfig, globalIgnores } from "./config-loader.js";
1988
+ export { defineConfig, globalIgnores } from "./519.js";
754
1989
  export { runCLI } from "./cli.js";
755
1990
  export { Rslint, importPlugin, jestPlugin, js, jsxA11yPlugin, promisePlugin, reactHooksPlugin, reactPlugin, ts, unicornPlugin };