@rsdoctor/core 2.0.0-alpha.1 → 2.0.0-alpha.2

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.
Files changed (167) hide show
  1. package/dist/26.js +26163 -0
  2. package/dist/630.js +1269 -0
  3. package/dist/630.js.LICENSE.txt +7 -0
  4. package/dist/build-utils/build/chunks/assetsModules.d.ts +7 -1
  5. package/dist/build-utils/build/loader/probeLoader.d.ts +7 -2
  6. package/dist/build-utils/build/utils/parseBundle.d.ts +1 -1
  7. package/dist/index.d.ts +5 -5
  8. package/dist/index.js +1725 -7
  9. package/dist/inner-plugins/constants.d.ts +1 -1
  10. package/dist/inner-plugins/plugins/base.d.ts +2 -2
  11. package/dist/logger.d.ts +2 -2
  12. package/dist/probe-loader.js +2 -0
  13. package/dist/proxy-loader.d.ts +1 -0
  14. package/dist/proxy-loader.js +48 -0
  15. package/dist/rslib-runtime.js +28 -0
  16. package/dist/rspack-plugin/constants.d.ts +1 -1
  17. package/dist/rules/rules/ecma-version-check/htmlParserStub.d.ts +3 -0
  18. package/dist/rules/rules/ecma-version-check/types.d.ts +13 -2
  19. package/dist/sdk/server/apis/base.d.ts +1 -1
  20. package/dist/sdk/server/socket/api.d.ts +1 -1
  21. package/dist/sdk/utils/date.d.ts +1 -0
  22. package/dist/types/loader.d.ts +1 -1
  23. package/package.json +20 -113
  24. package/dist/build-utils/build/chunks/assetsModules.js +0 -9
  25. package/dist/build-utils/build/chunks/index.js +0 -3
  26. package/dist/build-utils/build/chunks/rspack/transform.js +0 -44
  27. package/dist/build-utils/build/envinfo.js +0 -60
  28. package/dist/build-utils/build/file/cache.js +0 -24
  29. package/dist/build-utils/build/file/index.js +0 -5
  30. package/dist/build-utils/build/file/sharding.js +0 -38
  31. package/dist/build-utils/build/index.js +0 -12
  32. package/dist/build-utils/build/json.js +0 -67
  33. package/dist/build-utils/build/loader/index.js +0 -3
  34. package/dist/build-utils/build/loader/probeLoader.js +0 -44
  35. package/dist/build-utils/build/loader/probeLoaderPlugin.js +0 -32
  36. package/dist/build-utils/build/module-graph/index.js +0 -2
  37. package/dist/build-utils/build/module-graph/parser.js +0 -13
  38. package/dist/build-utils/build/module-graph/rspack/transform.js +0 -111
  39. package/dist/build-utils/build/module-graph/utils.js +0 -60
  40. package/dist/build-utils/build/process.js +0 -18
  41. package/dist/build-utils/build/server.js +0 -107
  42. package/dist/build-utils/build/utils/index.js +0 -4
  43. package/dist/build-utils/build/utils/loader.js +0 -267
  44. package/dist/build-utils/build/utils/parseBundle.js +0 -238
  45. package/dist/build-utils/build/utils/plugin.js +0 -21
  46. package/dist/build-utils/index.js +0 -13
  47. package/dist/collection.d.ts +0 -1
  48. package/dist/collection.js +0 -2
  49. package/dist/common/file.js +0 -8
  50. package/dist/common/global-config.js +0 -33
  51. package/dist/common/index.d.ts +0 -4
  52. package/dist/common/index.js +0 -6
  53. package/dist/common-browser.d.ts +0 -1
  54. package/dist/common-browser.js +0 -2
  55. package/dist/error/error.js +0 -143
  56. package/dist/error/index.js +0 -3
  57. package/dist/error/transform.js +0 -138
  58. package/dist/error/utils.js +0 -23
  59. package/dist/graph/index.d.ts +0 -1
  60. package/dist/graph/index.js +0 -2
  61. package/dist/inner-plugins/constants.js +0 -19
  62. package/dist/inner-plugins/index.js +0 -3
  63. package/dist/inner-plugins/loaders/proxy.js +0 -65
  64. package/dist/inner-plugins/plugins/base.js +0 -20
  65. package/dist/inner-plugins/plugins/bundle.js +0 -63
  66. package/dist/inner-plugins/plugins/ensureModulesChunkGraph.js +0 -74
  67. package/dist/inner-plugins/plugins/errors.js +0 -65
  68. package/dist/inner-plugins/plugins/index.js +0 -11
  69. package/dist/inner-plugins/plugins/loader.js +0 -108
  70. package/dist/inner-plugins/plugins/plugins.js +0 -40
  71. package/dist/inner-plugins/plugins/progress.js +0 -35
  72. package/dist/inner-plugins/plugins/resolver.js +0 -57
  73. package/dist/inner-plugins/plugins/rspack.js +0 -99
  74. package/dist/inner-plugins/plugins/rules.js +0 -64
  75. package/dist/inner-plugins/plugins/sourcemapTool.js +0 -230
  76. package/dist/inner-plugins/plugins/summary.js +0 -92
  77. package/dist/inner-plugins/utils/circleDetect.js +0 -16
  78. package/dist/inner-plugins/utils/config.js +0 -141
  79. package/dist/inner-plugins/utils/index.js +0 -8
  80. package/dist/inner-plugins/utils/loader.js +0 -134
  81. package/dist/inner-plugins/utils/normalize-config.js +0 -77
  82. package/dist/inner-plugins/utils/openBrowser.js +0 -55
  83. package/dist/inner-plugins/utils/plugin-common.js +0 -94
  84. package/dist/inner-plugins/utils/plugin.js +0 -70
  85. package/dist/inner-plugins/utils/sdk.js +0 -19
  86. package/dist/logger.js +0 -51
  87. package/dist/rspack-plugin/constants.js +0 -23
  88. package/dist/rspack-plugin/index.js +0 -3
  89. package/dist/rspack-plugin/multiple.js +0 -39
  90. package/dist/rspack-plugin/plugin.js +0 -133
  91. package/dist/rule-utils/document/document.js +0 -46
  92. package/dist/rule-utils/document/index.js +0 -4
  93. package/dist/rule-utils/document/server.js +0 -13
  94. package/dist/rule-utils/document/types.js +0 -1
  95. package/dist/rule-utils/index.js +0 -3
  96. package/dist/rule-utils/parser/asserts.js +0 -105
  97. package/dist/rule-utils/parser/index.js +0 -5
  98. package/dist/rule-utils/parser/parser.js +0 -24
  99. package/dist/rule-utils/parser/types.js +0 -8
  100. package/dist/rule-utils/parser/utils.js +0 -106
  101. package/dist/rules/index.js +0 -4
  102. package/dist/rules/linter.js +0 -36
  103. package/dist/rules/rule.js +0 -101
  104. package/dist/rules/rules/cjs-require/index.js +0 -50
  105. package/dist/rules/rules/cjs-require/types.js +0 -1
  106. package/dist/rules/rules/cross-chunks-package/index.js +0 -41
  107. package/dist/rules/rules/cross-chunks-package/types.js +0 -1
  108. package/dist/rules/rules/cross-chunks-package/utils.js +0 -7
  109. package/dist/rules/rules/default-import-check/index.js +0 -83
  110. package/dist/rules/rules/default-import-check/types.js +0 -1
  111. package/dist/rules/rules/default-import-check/utils.js +0 -52
  112. package/dist/rules/rules/duplicate-package/index.js +0 -39
  113. package/dist/rules/rules/duplicate-package/types.js +0 -24
  114. package/dist/rules/rules/duplicate-package/utils.js +0 -38
  115. package/dist/rules/rules/ecma-version-check/index.js +0 -53
  116. package/dist/rules/rules/ecma-version-check/types.js +0 -1
  117. package/dist/rules/rules/ecma-version-check/utils.js +0 -6
  118. package/dist/rules/rules/esm-resolved-to-cjs/index.js +0 -193
  119. package/dist/rules/rules/esm-resolved-to-cjs/types.js +0 -1
  120. package/dist/rules/rules/index.js +0 -22
  121. package/dist/rules/rules/loader-performance-optimization/index.js +0 -86
  122. package/dist/rules/rules/loader-performance-optimization/types.js +0 -1
  123. package/dist/rules/rules/loader-performance-optimization/utils.js +0 -10
  124. package/dist/rules/rules/module-mixed-chunks/index.js +0 -52
  125. package/dist/rules/rules/module-mixed-chunks/types.js +0 -1
  126. package/dist/rules/rules/side-effects-only-imports/index.js +0 -81
  127. package/dist/rules/rules/side-effects-only-imports/types.js +0 -1
  128. package/dist/rules/utils.js +0 -10
  129. package/dist/sdk/index.js +0 -3
  130. package/dist/sdk/multiple/controller.js +0 -42
  131. package/dist/sdk/multiple/index.js +0 -3
  132. package/dist/sdk/multiple/primary.js +0 -64
  133. package/dist/sdk/multiple/server.js +0 -14
  134. package/dist/sdk/sdk/core.js +0 -163
  135. package/dist/sdk/sdk/index.js +0 -435
  136. package/dist/sdk/sdk/types.js +0 -1
  137. package/dist/sdk/server/apis/alerts.js +0 -30
  138. package/dist/sdk/server/apis/base.js +0 -22
  139. package/dist/sdk/server/apis/bundle-diff.js +0 -51
  140. package/dist/sdk/server/apis/data.js +0 -44
  141. package/dist/sdk/server/apis/fs.js +0 -28
  142. package/dist/sdk/server/apis/graph.js +0 -116
  143. package/dist/sdk/server/apis/index.js +0 -11
  144. package/dist/sdk/server/apis/loader.js +0 -120
  145. package/dist/sdk/server/apis/plugin.js +0 -39
  146. package/dist/sdk/server/apis/project.js +0 -59
  147. package/dist/sdk/server/apis/renderer.js +0 -33
  148. package/dist/sdk/server/apis/resolver.js +0 -38
  149. package/dist/sdk/server/client.js +0 -8
  150. package/dist/sdk/server/fakeServer.js +0 -12
  151. package/dist/sdk/server/index.js +0 -292
  152. package/dist/sdk/server/json-body.js +0 -150
  153. package/dist/sdk/server/router.js +0 -83
  154. package/dist/sdk/server/security.js +0 -47
  155. package/dist/sdk/server/socket/api.js +0 -22
  156. package/dist/sdk/server/socket/index.js +0 -166
  157. package/dist/sdk/server/utils.js +0 -19
  158. package/dist/sdk/utils/base.js +0 -22
  159. package/dist/sdk/utils/constant.js +0 -4
  160. package/dist/sdk/utils/index.js +0 -4
  161. package/dist/sdk/utils/openBrowser.js +0 -53
  162. package/dist/sdk/utils/upload.js +0 -6
  163. package/dist/sdk.js +0 -2
  164. package/dist/types/index.js +0 -4
  165. package/dist/types/loader.js +0 -1
  166. package/dist/types/plugin.js +0 -1
  167. package/dist/types/rules.js +0 -1
@@ -1,41 +0,0 @@
1
- import "node:module";
2
- import { Linter } from "@rsdoctor/shared/types";
3
- import { defineRule } from "../../rule.js";
4
- import { getErrorMsgForDupPckChunks } from "./utils.js";
5
- import { uniq } from "../../../collection.js";
6
- const title = 'cross-chunks-package';
7
- const rule = defineRule(()=>({
8
- meta: {
9
- code: 'E1002',
10
- title: title,
11
- category: 'bundle',
12
- severity: Linter.Severity.Warn,
13
- defaultConfig: {
14
- ignore: []
15
- }
16
- },
17
- check ({ packageGraph, report }) {
18
- const packages = packageGraph.getPackages().filter((pkg)=>(pkg.duplicates?.length ?? 0) > 0);
19
- for (const pkg of packages){
20
- const duplicates = pkg.duplicates;
21
- const detail = {
22
- type: title,
23
- chunks: duplicates,
24
- package: {
25
- name: pkg.name,
26
- id: pkg.id,
27
- size: pkg.getSize(),
28
- version: pkg.version
29
- }
30
- };
31
- const chunks = [];
32
- duplicates.forEach((dup)=>chunks.push(...dup.chunks.map((ck)=>ck.name)));
33
- const message = getErrorMsgForDupPckChunks(uniq(chunks), pkg.name);
34
- report({
35
- message,
36
- detail
37
- });
38
- }
39
- }
40
- }));
41
- export { rule };
@@ -1 +0,0 @@
1
- import "node:module";
@@ -1,7 +0,0 @@
1
- import "node:module";
2
- function getErrorMsgForDupPckChunks(chunks, pkgName) {
3
- let message = `The same package ${pkgName} was bundled into different chunks:\n`;
4
- for (const chunkName of chunks)message += ` ${chunkName}\n`;
5
- return message.slice(0, -1);
6
- }
7
- export { getErrorMsgForDupPckChunks };
@@ -1,83 +0,0 @@
1
- import "node:module";
2
- import { builtinModules } from "module";
3
- import { Linter } from "@rsdoctor/shared/types";
4
- import { getDocument, parser } from "../../../rule-utils/index.js";
5
- import { getDefaultImportByRequest, getFixData, getSourceRangeFromTransformedOffset, hasSameLeftInAssignStatement } from "./utils.js";
6
- import { defineRule } from "../../rule.js";
7
- const title = 'default-import-check';
8
- const rule = defineRule(()=>{
9
- const parserOpt = {
10
- ecmaVersion: 6
11
- };
12
- const exportsDefault = parser.internal.parseExpressionAt('exports.default', 0, parserOpt);
13
- const moduleExportsDefault = parser.internal.parseExpressionAt('module.exports.default', 0, parserOpt);
14
- return {
15
- meta: {
16
- code: 'E1005',
17
- title: title,
18
- category: 'compile',
19
- severity: Linter.Severity.Warn,
20
- defaultConfig: {
21
- ignore: []
22
- }
23
- },
24
- check ({ moduleGraph, report, ruleConfig }) {
25
- const dependencyWithNode = moduleGraph.getDependencies().filter((dep)=>'dynamic' === dep.meta.exportsType).filter((dep)=>!dep.module.path.includes('node_modules')).filter((dep)=>!ruleConfig.ignore.includes(dep.request) && !builtinModules.includes(dep.request)).filter((dep)=>dep.dependency.meta.hasSetEsModuleStatement).filter((dep)=>dep.dependency.getProgram()).filter((dep)=>!hasSameLeftInAssignStatement(dep.dependency.getProgram(), [
26
- exportsDefault,
27
- moduleExportsDefault
28
- ])).map((dependency)=>{
29
- const { module, request } = dependency;
30
- const node = module.getProgram() && getDefaultImportByRequest(module.getProgram(), request);
31
- return node ? {
32
- dependency,
33
- node
34
- } : {};
35
- }).filter((dep)=>dep?.dependency);
36
- for (const { dependency, node } of dependencyWithNode){
37
- if (!dependency) continue;
38
- const document = getSourceRangeFromTransformedOffset(dependency.module, node);
39
- if (!document) continue;
40
- const message = 'Do not to use the default import when you import a cjs module.';
41
- const canFix = !document.isTransformed && !document.path.includes('node_modules');
42
- if (canFix) {
43
- const fixData = getFixData(dependency.module, node, document.range);
44
- const detail = {
45
- type: 'code-change',
46
- file: {
47
- path: document.path,
48
- actual: document.content,
49
- line: document.range.start.line,
50
- expected: getDocument(document.content).edit(fixData)
51
- }
52
- };
53
- report({
54
- message,
55
- document,
56
- detail,
57
- suggestions: {
58
- description: 'Use namespace import instead.',
59
- fixData
60
- }
61
- });
62
- } else {
63
- const detail = {
64
- type: 'code-view',
65
- file: {
66
- path: document.path,
67
- content: document.content,
68
- ranges: [
69
- node.loc
70
- ]
71
- }
72
- };
73
- report({
74
- message,
75
- document,
76
- detail
77
- });
78
- }
79
- }
80
- }
81
- };
82
- });
83
- export { rule };
@@ -1 +0,0 @@
1
- import "node:module";
@@ -1,52 +0,0 @@
1
- import "node:module";
2
- import { getDocument, parser } from "../../../rule-utils/index.js";
3
- import { Lodash } from "../../../common/index.js";
4
- function getDefaultImportByRequest(node, request) {
5
- return parser.utils.getDefaultImports(node).find((decl)=>decl.source.value === request);
6
- }
7
- function hasSameLeftInAssignStatement(node, compare) {
8
- return node.body.filter(parser.asserts.isExpressionStatement).map((node)=>node.expression).filter(parser.asserts.isAssignmentExpression).map((node)=>node.left).find((node)=>compare.some((item)=>parser.utils.isSameSemantics(node, item)));
9
- }
10
- function importDeclarationToString(node) {
11
- const defaultSpecifier = node.specifiers[0];
12
- const rawRequest = (node.source.raw ?? '').trim();
13
- return `import * as ${defaultSpecifier.local.name} from ${rawRequest}`;
14
- }
15
- function getFixData(module, node, originalRange) {
16
- const { source, transformed } = module.getSource();
17
- const document = getDocument(source);
18
- const newImportText = importDeclarationToString(node);
19
- const oldText = transformed.substring(node.start, node.end);
20
- const hasLastSemi = ';' === oldText[oldText.length - 1];
21
- return {
22
- start: document.offsetAt(originalRange.start),
23
- end: document.offsetAt(originalRange.end),
24
- newText: hasLastSemi ? `${newImportText};` : newImportText
25
- };
26
- }
27
- function getSourceRangeFromTransformedOffset(module, node) {
28
- const source = module.getSource();
29
- const sourceMap = module.getSourceMap();
30
- const transformedStart = node.loc.start;
31
- const transformedEnd = node.loc.end;
32
- if (!transformedStart || !transformedEnd) return;
33
- const transformedReport = {
34
- path: module.path,
35
- content: source.transformed,
36
- isTransformed: true,
37
- range: {
38
- start: transformedStart,
39
- end: transformedEnd
40
- }
41
- };
42
- if (!sourceMap) return transformedReport;
43
- const sourceRange = module.getSourceRange(node.loc);
44
- if (Lodash.isUndefined(sourceRange?.start.line) || Lodash.isUndefined(sourceRange?.start.column) || Lodash.isUndefined(sourceRange?.end?.line) || Lodash.isUndefined(sourceRange?.end?.column)) return transformedReport;
45
- return {
46
- path: module.path,
47
- isTransformed: false,
48
- content: source.source,
49
- range: sourceRange
50
- };
51
- }
52
- export { getDefaultImportByRequest, getFixData, getSourceRangeFromTransformedOffset, hasSameLeftInAssignStatement, importDeclarationToString };
@@ -1,39 +0,0 @@
1
- import "node:module";
2
- import { Linter } from "@rsdoctor/shared/types";
3
- import { diff, gt } from "semver";
4
- import { getErrorDetail, getErrorMsg } from "./utils.js";
5
- import { defineRule } from "../../rule.js";
6
- import * as __rspack_external__types_js_b06c0ce5 from "./types.js";
7
- const title = 'duplicate-package';
8
- const { CheckVersionMap: CheckVersionMap } = __rspack_external__types_js_b06c0ce5;
9
- const rule = defineRule(()=>({
10
- meta: {
11
- code: 'E1001',
12
- title: title,
13
- category: 'bundle',
14
- severity: Linter.Severity.Warn,
15
- defaultConfig: {
16
- checkVersion: 'major',
17
- ignore: []
18
- }
19
- },
20
- check ({ packageGraph, report, root, ruleConfig }) {
21
- const checkVersion = CheckVersionMap[ruleConfig.checkVersion];
22
- const packages = packageGraph.getDuplicatePackages().filter((pkg)=>!ruleConfig.ignore.includes(pkg[0].name)).map((pkgs)=>pkgs.filter((current)=>{
23
- const check = pkgs.reduce((ans, pkg)=>ans | CheckVersionMap[diff(current.version, pkg.version) ?? 'null'], 0);
24
- return check <= checkVersion;
25
- }).sort((_packA, _packB)=>gt(_packA.version, _packB.version) ? 1 : -1)).filter((pkgs)=>pkgs.length > 1 && pkgs.filter((pkg)=>pkg.getSize().parsedSize > 0).length > 1);
26
- for (const pkg of packages){
27
- const message = getErrorMsg(pkg, root);
28
- const detail = {
29
- type: 'package-relation',
30
- packages: pkg.map((item)=>getErrorDetail(item, packageGraph))
31
- };
32
- report({
33
- message,
34
- detail
35
- });
36
- }
37
- }
38
- }));
39
- export { rule };
@@ -1,24 +0,0 @@
1
- import "node:module";
2
- var types_CheckVersion = /*#__PURE__*/ function(CheckVersion) {
3
- CheckVersion[CheckVersion["null"] = 0] = "null";
4
- CheckVersion[CheckVersion["prerelease"] = 1] = "prerelease";
5
- CheckVersion[CheckVersion["prepatch"] = 16] = "prepatch";
6
- CheckVersion[CheckVersion["patch"] = 256] = "patch";
7
- CheckVersion[CheckVersion["preminor"] = 4096] = "preminor";
8
- CheckVersion[CheckVersion["minor"] = 65536] = "minor";
9
- CheckVersion[CheckVersion["premajor"] = 1048576] = "premajor";
10
- CheckVersion[CheckVersion["major"] = 16777216] = "major";
11
- return CheckVersion;
12
- }({});
13
- var types_CheckVersionMap = /*#__PURE__*/ function(CheckVersionMap) {
14
- CheckVersionMap[CheckVersionMap["null"] = 0] = "null";
15
- CheckVersionMap[CheckVersionMap["prerelease"] = 1] = "prerelease";
16
- CheckVersionMap[CheckVersionMap["prepatch"] = 17] = "prepatch";
17
- CheckVersionMap[CheckVersionMap["patch"] = 273] = "patch";
18
- CheckVersionMap[CheckVersionMap["preminor"] = 4369] = "preminor";
19
- CheckVersionMap[CheckVersionMap["minor"] = 69905] = "minor";
20
- CheckVersionMap[CheckVersionMap["premajor"] = 1118481] = "premajor";
21
- CheckVersionMap[CheckVersionMap["major"] = 17895697] = "major";
22
- return CheckVersionMap;
23
- }({});
24
- export { types_CheckVersion as CheckVersion, types_CheckVersionMap as CheckVersionMap };
@@ -1,38 +0,0 @@
1
- import "node:module";
2
- import path from "path";
3
- import { filesize } from "filesize";
4
- function getErrorMsg(packages, root) {
5
- const pkgName = packages[0].name;
6
- let message = `Multiple packages of ${pkgName} found:\n`;
7
- for (const pkg of packages)message += ` ${pkg.version} ${filesize(pkg.getSize().parsedSize)} ${path.relative(root, pkg.root)}\n`;
8
- return message.slice(0, -1);
9
- }
10
- function getErrorDetail(pkg, pkgGraph) {
11
- function getImported(pkg, ans) {
12
- const dependencies = pkgGraph.getDependenciesFromPackage(pkg);
13
- for (const dep of dependencies)if (dep.refDependency) {
14
- if (!ans.some((dep)=>dep.dependency === pkg)) {
15
- if (!dep.package) return ans.concat(dep);
16
- return getImported(dep.package, ans.concat(dep));
17
- }
18
- }
19
- return ans;
20
- }
21
- const packageImportLinks = getImported(pkg, []);
22
- return {
23
- target: {
24
- name: pkg.name,
25
- version: pkg.version,
26
- root: pkg.root
27
- },
28
- targetSize: {
29
- sourceSize: pkg.getSize().sourceSize,
30
- parsedSize: pkg.getSize().parsedSize
31
- },
32
- dependencies: packageImportLinks.map((item)=>({
33
- dependencyId: item.refDependency.id,
34
- group: item.package ? `${item.package.name}@${item.package.version}` : void 0
35
- }))
36
- };
37
- }
38
- export { getErrorDetail, getErrorMsg };
@@ -1,53 +0,0 @@
1
- import "node:module";
2
- import path from "path";
3
- import { CheckSyntax } from "@rsbuild/plugin-check-syntax";
4
- import { loadConfig } from "browserslist-load-config";
5
- import { defineRule } from "../../rule.js";
6
- import { Linter } from "@rsdoctor/shared/types";
7
- const title = 'ecma-version-check';
8
- const rule = defineRule(()=>({
9
- meta: {
10
- code: 'E1004',
11
- title: title,
12
- category: 'bundle',
13
- severity: Linter.Severity.Warn,
14
- defaultConfig: {
15
- ecmaVersion: void 0,
16
- targets: []
17
- }
18
- },
19
- async check ({ chunkGraph, report, ruleConfig, root, configs }) {
20
- for (const asset of chunkGraph.getAssets()){
21
- if ('.js' !== path.extname(asset.path) && '.bundle' !== path.extname(asset.path)) continue;
22
- const browserslistConfig = loadConfig({
23
- path: root,
24
- env: 'production'
25
- });
26
- const { exclude, excludeOutput, targets, ecmaVersion } = ruleConfig;
27
- const finalTargets = targets || browserslistConfig || [];
28
- if (!finalTargets.length && !ecmaVersion) return;
29
- const buildConfig = configs[0]?.config;
30
- const context = buildConfig?.context || root;
31
- const checkSyntax = new CheckSyntax({
32
- exclude,
33
- excludeOutput,
34
- ecmaVersion,
35
- rootPath: context,
36
- targets: finalTargets
37
- });
38
- const outputDir = buildConfig?.output?.path || path.resolve(root, 'dist');
39
- const assetPath = path.resolve(outputDir, asset.path);
40
- await checkSyntax.check(assetPath, asset.content);
41
- checkSyntax.errors.forEach((err)=>{
42
- report({
43
- message: `Found syntax that does not match "ecmaVersion <= ${checkSyntax.ecmaVersion}"`,
44
- detail: {
45
- error: err,
46
- type: 'link'
47
- }
48
- });
49
- });
50
- }
51
- }
52
- }));
53
- export { rule };
@@ -1 +0,0 @@
1
- import "node:module";
@@ -1,6 +0,0 @@
1
- import "node:module";
2
- function getVersionNumber(ECMAString) {
3
- const version = ECMAString.match(/\d/);
4
- return version?.length ? Number(version[0]) : void 0;
5
- }
6
- export { getVersionNumber };
@@ -1,193 +0,0 @@
1
- import "node:module";
2
- import fs from "fs";
3
- import path from "path";
4
- import { Linter, SDK } from "@rsdoctor/shared/types";
5
- import { defineRule } from "../../rule.js";
6
- const title = 'esm-resolved-to-cjs';
7
- function normalizePathForCompare(filePath) {
8
- const queryIndex = filePath.indexOf('?');
9
- const hashIndex = filePath.indexOf('#');
10
- const splitIndex = [
11
- queryIndex,
12
- hashIndex
13
- ].filter((index)=>index >= 0).reduce((min, index)=>Math.min(min, index), 1 / 0);
14
- const cleanPath = splitIndex === 1 / 0 ? filePath : filePath.slice(0, splitIndex);
15
- return path.normalize(cleanPath);
16
- }
17
- function isDefinitelyEsmFile(filePath) {
18
- return '.mjs' === path.extname(normalizePathForCompare(filePath));
19
- }
20
- function isDeclaredEsmEntry(filePath, esmEntries, toRealPath) {
21
- const realPath = toRealPath(filePath);
22
- return esmEntries.some((esmEntry)=>realPath === toRealPath(esmEntry));
23
- }
24
- function isRecord(value) {
25
- return null !== value && 'object' == typeof value && !Array.isArray(value);
26
- }
27
- function substituteExportPattern(target, wildcard) {
28
- return target.replace(/\*/g, wildcard);
29
- }
30
- function toPackagePath(pkgRoot, target, wildcard) {
31
- return path.resolve(pkgRoot, substituteExportPattern(target, wildcard));
32
- }
33
- function collectStringTargets(value, wildcard) {
34
- if ('string' == typeof value) return [
35
- substituteExportPattern(value, wildcard)
36
- ];
37
- if (Array.isArray(value)) return value.flatMap((item)=>collectStringTargets(item, wildcard));
38
- if (!isRecord(value)) return [];
39
- return Object.values(value).flatMap((child)=>collectStringTargets(child, wildcard));
40
- }
41
- function collectEsmTargets(exportEntry, pkgRoot, wildcard) {
42
- const entries = new Set();
43
- const addTargets = (value)=>{
44
- for (const target of collectStringTargets(value, wildcard))entries.add(toPackagePath(pkgRoot, target, ''));
45
- };
46
- const visit = (value)=>{
47
- if ('string' == typeof value || Array.isArray(value)) return void addTargets(value);
48
- if (!isRecord(value)) return;
49
- addTargets(value['import']);
50
- addTargets(value['module']);
51
- for (const child of Object.values(value))if (isRecord(child) || Array.isArray(child)) visit(child);
52
- };
53
- visit(exportEntry);
54
- return entries;
55
- }
56
- function hasSubpathExportKeys(exports) {
57
- return Object.keys(exports).some((key)=>'.' === key || key.startsWith('./'));
58
- }
59
- function matchPatternExportKey(patternKey, exportKey) {
60
- const wildcardIndex = patternKey.indexOf('*');
61
- if (wildcardIndex < 0) return null;
62
- const prefix = patternKey.slice(0, wildcardIndex);
63
- const suffix = patternKey.slice(wildcardIndex + 1);
64
- if (!exportKey.startsWith(prefix) || !exportKey.endsWith(suffix)) return null;
65
- return exportKey.slice(prefix.length, exportKey.length - suffix.length);
66
- }
67
- function resolveExportEntry(exports, exportKey) {
68
- if (Object.prototype.hasOwnProperty.call(exports, exportKey)) return {
69
- value: exports[exportKey],
70
- wildcard: ''
71
- };
72
- for (const [key, value] of Object.entries(exports)){
73
- const wildcard = matchPatternExportKey(key, exportKey);
74
- if (null !== wildcard) return {
75
- value,
76
- wildcard
77
- };
78
- }
79
- return null;
80
- }
81
- function resolveExportEntryForKey(exportsField, exportKey) {
82
- if (!isRecord(exportsField)) return null;
83
- if (!hasSubpathExportKeys(exportsField)) return '.' === exportKey ? {
84
- value: exportsField,
85
- wildcard: ''
86
- } : null;
87
- return resolveExportEntry(exportsField, exportKey);
88
- }
89
- function extractEsmEntries(pkgJson, pkgRoot, exportKey) {
90
- const { exports: exportsField, module: moduleField } = pkgJson;
91
- const resolvedExport = resolveExportEntryForKey(exportsField, exportKey);
92
- const entries = resolvedExport ? collectEsmTargets(resolvedExport.value, pkgRoot, resolvedExport.wildcard) : new Set();
93
- if ('.' === exportKey && 'string' == typeof moduleField) entries.add(path.resolve(pkgRoot, moduleField));
94
- return entries;
95
- }
96
- function getExportKeyFromRequest(packageName, request) {
97
- if (request === packageName) return '.';
98
- if (request.startsWith(`${packageName}/`)) return `.${request.slice(packageName.length)}`;
99
- return null;
100
- }
101
- const rule = defineRule(()=>({
102
- meta: {
103
- code: 'E1009',
104
- title: title,
105
- category: 'bundle',
106
- severity: Linter.Severity.Warn,
107
- defaultConfig: {
108
- ignore: []
109
- }
110
- },
111
- check ({ moduleGraph, packageGraph, report, ruleConfig }) {
112
- const pkgJsonCache = new Map();
113
- const realPathCache = new Map();
114
- const readPkgJson = (pkgRoot)=>{
115
- if (pkgJsonCache.has(pkgRoot)) return pkgJsonCache.get(pkgRoot);
116
- try {
117
- const raw = fs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf-8');
118
- const parsed = JSON.parse(raw);
119
- pkgJsonCache.set(pkgRoot, parsed);
120
- return parsed;
121
- } catch {
122
- pkgJsonCache.set(pkgRoot, null);
123
- return null;
124
- }
125
- };
126
- const toRealPath = (filePath)=>{
127
- const normalized = normalizePathForCompare(filePath);
128
- if (realPathCache.has(normalized)) return realPathCache.get(normalized);
129
- try {
130
- const realPath = 'function' == typeof fs.realpathSync.native ? fs.realpathSync.native(normalized) : fs.realpathSync(normalized);
131
- const normalizedRealPath = path.normalize(realPath);
132
- realPathCache.set(normalized, normalizedRealPath);
133
- return normalizedRealPath;
134
- } catch {
135
- realPathCache.set(normalized, normalized);
136
- return normalized;
137
- }
138
- };
139
- const groups = new Map();
140
- const inNodeModules = /[/\\]node_modules[/\\]/;
141
- for (const dep of moduleGraph.getDependencies()){
142
- if (dep.kind !== SDK.DependencyKind.ImportStatement || inNodeModules.test(dep.module.path) || !inNodeModules.test(dep.dependency.path) || dep.dependency.meta.strictHarmonyModule || ruleConfig.ignore.some((p)=>dep.request.includes(p))) continue;
143
- const pkg = packageGraph.getPackageByModule(dep.dependency);
144
- if (!pkg?.root) continue;
145
- const pkgJson = readPkgJson(pkg.root);
146
- if (ruleConfig.ignore.some((p)=>pkg.name.includes(p)) || !pkgJson) continue;
147
- const exportKey = getExportKeyFromRequest(pkg.name, dep.request);
148
- if (!exportKey) continue;
149
- const esmEntries = extractEsmEntries(pkgJson, pkg.root, exportKey);
150
- if (0 === esmEntries.size) continue;
151
- const esmEntryList = Array.from(esmEntries);
152
- const resolvedModuleRealPath = toRealPath(dep.dependency.path);
153
- if (isDefinitelyEsmFile(resolvedModuleRealPath)) continue;
154
- if (isDeclaredEsmEntry(resolvedModuleRealPath, esmEntryList, toRealPath)) continue;
155
- const groupKey = `${pkg.name}::${resolvedModuleRealPath}`;
156
- const issuer = {
157
- id: dep.module.id,
158
- path: dep.module.path,
159
- request: dep.request
160
- };
161
- if (groups.has(groupKey)) groups.get(groupKey).issuers.push(issuer);
162
- else groups.set(groupKey, {
163
- packageName: pkg.name,
164
- packageVersion: pkg.version,
165
- esmEntry: esmEntryList[0],
166
- resolvedModule: {
167
- id: dep.dependency.id,
168
- path: dep.dependency.path,
169
- identifier: dep.dependency.identifier
170
- },
171
- issuers: [
172
- issuer
173
- ]
174
- });
175
- }
176
- for (const group of groups.values()){
177
- const detail = {
178
- type: title,
179
- packageName: group.packageName,
180
- packageVersion: group.packageVersion,
181
- esmEntry: group.esmEntry,
182
- resolvedModule: group.resolvedModule,
183
- issuers: group.issuers
184
- };
185
- const message = `"${group.packageName}" declares an ESM entry ("${group.esmEntry}") but was resolved to CJS by ${group.issuers.length} ESM import(s). Check your bundler's \`resolve.mainFields\` or \`resolve.conditionNames\` config.`;
186
- report({
187
- message,
188
- detail
189
- });
190
- }
191
- }
192
- }));
193
- export { rule };
@@ -1 +0,0 @@
1
- import "node:module";
@@ -1,22 +0,0 @@
1
- import "node:module";
2
- import { rule } from "./duplicate-package/index.js";
3
- import { rule as index_js_rule } from "./default-import-check/index.js";
4
- import { rule as external_loader_performance_optimization_index_js_rule } from "./loader-performance-optimization/index.js";
5
- import { rule as external_ecma_version_check_index_js_rule } from "./ecma-version-check/index.js";
6
- import { rule as external_cross_chunks_package_index_js_rule } from "./cross-chunks-package/index.js";
7
- import { rule as external_module_mixed_chunks_index_js_rule } from "./module-mixed-chunks/index.js";
8
- import { rule as external_side_effects_only_imports_index_js_rule } from "./side-effects-only-imports/index.js";
9
- import { rule as external_cjs_require_index_js_rule } from "./cjs-require/index.js";
10
- import { rule as external_esm_resolved_to_cjs_index_js_rule } from "./esm-resolved-to-cjs/index.js";
11
- const rules = [
12
- rule,
13
- index_js_rule,
14
- external_loader_performance_optimization_index_js_rule,
15
- external_ecma_version_check_index_js_rule,
16
- external_cross_chunks_package_index_js_rule,
17
- external_module_mixed_chunks_index_js_rule,
18
- external_side_effects_only_imports_index_js_rule,
19
- external_cjs_require_index_js_rule,
20
- external_esm_resolved_to_cjs_index_js_rule
21
- ];
22
- export { rules };
@@ -1,86 +0,0 @@
1
- import "node:module";
2
- import { Linter } from "@rsdoctor/shared/types";
3
- import { Loader, Time } from "../../../common/index.js";
4
- import { defineRule } from "../../rule.js";
5
- import { match } from "./utils.js";
6
- const title = 'loader-performance-optimization';
7
- const rule = defineRule(()=>({
8
- meta: {
9
- code: 'E1003',
10
- title: title,
11
- category: 'compile',
12
- severity: Linter.Severity.Warn,
13
- defaultConfig: {
14
- ignore: [],
15
- threshold: 5000,
16
- extensions: [
17
- 'js',
18
- 'css',
19
- 'jpg',
20
- 'jpeg',
21
- 'png',
22
- 'gif',
23
- 'webp',
24
- 'svg'
25
- ]
26
- }
27
- },
28
- check ({ loader, configs, root, ruleConfig, report }) {
29
- const { extensions, ignore = [], threshold = 5000 } = ruleConfig;
30
- if (!extensions || extensions?.length === 0) return;
31
- if (0 === loader.length) return;
32
- const { config } = configs.find((e)=>'rspack' === e.name) || {
33
- config: void 0
34
- };
35
- if (!config) return;
36
- const cwd = config.context || root;
37
- const nodeModulesPathRegexp = /\/node_modules\//;
38
- const resultMap = new Map();
39
- const loaders = loader.flatMap((el)=>el.loaders);
40
- for (const item of loader){
41
- const { path, ext } = item.resource;
42
- if (match(ext, extensions)) {
43
- if (nodeModulesPathRegexp.test(path) || !path.startsWith(cwd)) item.loaders.forEach((el)=>{
44
- if (match(el.loader, ignore)) return;
45
- const costs = Loader.getLoaderCosts(el, loaders);
46
- const v = {
47
- ...el,
48
- __resource__: item.resource,
49
- __costs__: costs
50
- };
51
- if (resultMap.has(el.loader)) resultMap.get(el.loader).push(v);
52
- else resultMap.set(el.loader, [
53
- v
54
- ]);
55
- });
56
- }
57
- }
58
- const sum = (arr)=>{
59
- const v1 = arr.reduce((t, c)=>t + c.__costs__, 0);
60
- const v2 = Math.max.apply(null, arr.map((e)=>e.endAt)) - Math.min.apply(arr.map((e)=>e.startAt));
61
- if (v2 >= v1 || v2 === -1 / 0) return v1;
62
- return v2;
63
- };
64
- for (const [loaderName, v] of resultMap.entries()){
65
- const nodeModulesFiles = v.filter((e)=>nodeModulesPathRegexp.test(e.__resource__.path));
66
- const nodeModulesFilesCosts = sum(nodeModulesFiles);
67
- const outofCwdFiles = v.filter((e)=>!e.__resource__.path.startsWith(cwd));
68
- const outofCwdFilesCosts = sum(outofCwdFiles);
69
- const msg = [
70
- nodeModulesFilesCosts >= threshold && `${nodeModulesFiles.length} node_modules files (costs: ${Time.formatCosts(nodeModulesFilesCosts)})`,
71
- outofCwdFilesCosts >= threshold && `${outofCwdFiles.length} outside project files (costs: ${Time.formatCosts(outofCwdFilesCosts)})`
72
- ].filter(Boolean).join(' and ');
73
- if (msg) {
74
- const message = `${loaderName} has processed ${msg}.`;
75
- report({
76
- message,
77
- detail: {
78
- description: message,
79
- type: 'link'
80
- }
81
- });
82
- }
83
- }
84
- }
85
- }));
86
- export { rule };