@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.
- package/dist/26.js +26163 -0
- package/dist/630.js +1269 -0
- package/dist/630.js.LICENSE.txt +7 -0
- package/dist/build-utils/build/chunks/assetsModules.d.ts +7 -1
- package/dist/build-utils/build/loader/probeLoader.d.ts +7 -2
- package/dist/build-utils/build/utils/parseBundle.d.ts +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1725 -7
- package/dist/inner-plugins/constants.d.ts +1 -1
- package/dist/inner-plugins/plugins/base.d.ts +2 -2
- package/dist/logger.d.ts +2 -2
- package/dist/probe-loader.js +2 -0
- package/dist/proxy-loader.d.ts +1 -0
- package/dist/proxy-loader.js +48 -0
- package/dist/rslib-runtime.js +28 -0
- package/dist/rspack-plugin/constants.d.ts +1 -1
- package/dist/rules/rules/ecma-version-check/htmlParserStub.d.ts +3 -0
- package/dist/rules/rules/ecma-version-check/types.d.ts +13 -2
- package/dist/sdk/server/apis/base.d.ts +1 -1
- package/dist/sdk/server/socket/api.d.ts +1 -1
- package/dist/sdk/utils/date.d.ts +1 -0
- package/dist/types/loader.d.ts +1 -1
- package/package.json +20 -113
- package/dist/build-utils/build/chunks/assetsModules.js +0 -9
- package/dist/build-utils/build/chunks/index.js +0 -3
- package/dist/build-utils/build/chunks/rspack/transform.js +0 -44
- package/dist/build-utils/build/envinfo.js +0 -60
- package/dist/build-utils/build/file/cache.js +0 -24
- package/dist/build-utils/build/file/index.js +0 -5
- package/dist/build-utils/build/file/sharding.js +0 -38
- package/dist/build-utils/build/index.js +0 -12
- package/dist/build-utils/build/json.js +0 -67
- package/dist/build-utils/build/loader/index.js +0 -3
- package/dist/build-utils/build/loader/probeLoader.js +0 -44
- package/dist/build-utils/build/loader/probeLoaderPlugin.js +0 -32
- package/dist/build-utils/build/module-graph/index.js +0 -2
- package/dist/build-utils/build/module-graph/parser.js +0 -13
- package/dist/build-utils/build/module-graph/rspack/transform.js +0 -111
- package/dist/build-utils/build/module-graph/utils.js +0 -60
- package/dist/build-utils/build/process.js +0 -18
- package/dist/build-utils/build/server.js +0 -107
- package/dist/build-utils/build/utils/index.js +0 -4
- package/dist/build-utils/build/utils/loader.js +0 -267
- package/dist/build-utils/build/utils/parseBundle.js +0 -238
- package/dist/build-utils/build/utils/plugin.js +0 -21
- package/dist/build-utils/index.js +0 -13
- package/dist/collection.d.ts +0 -1
- package/dist/collection.js +0 -2
- package/dist/common/file.js +0 -8
- package/dist/common/global-config.js +0 -33
- package/dist/common/index.d.ts +0 -4
- package/dist/common/index.js +0 -6
- package/dist/common-browser.d.ts +0 -1
- package/dist/common-browser.js +0 -2
- package/dist/error/error.js +0 -143
- package/dist/error/index.js +0 -3
- package/dist/error/transform.js +0 -138
- package/dist/error/utils.js +0 -23
- package/dist/graph/index.d.ts +0 -1
- package/dist/graph/index.js +0 -2
- package/dist/inner-plugins/constants.js +0 -19
- package/dist/inner-plugins/index.js +0 -3
- package/dist/inner-plugins/loaders/proxy.js +0 -65
- package/dist/inner-plugins/plugins/base.js +0 -20
- package/dist/inner-plugins/plugins/bundle.js +0 -63
- package/dist/inner-plugins/plugins/ensureModulesChunkGraph.js +0 -74
- package/dist/inner-plugins/plugins/errors.js +0 -65
- package/dist/inner-plugins/plugins/index.js +0 -11
- package/dist/inner-plugins/plugins/loader.js +0 -108
- package/dist/inner-plugins/plugins/plugins.js +0 -40
- package/dist/inner-plugins/plugins/progress.js +0 -35
- package/dist/inner-plugins/plugins/resolver.js +0 -57
- package/dist/inner-plugins/plugins/rspack.js +0 -99
- package/dist/inner-plugins/plugins/rules.js +0 -64
- package/dist/inner-plugins/plugins/sourcemapTool.js +0 -230
- package/dist/inner-plugins/plugins/summary.js +0 -92
- package/dist/inner-plugins/utils/circleDetect.js +0 -16
- package/dist/inner-plugins/utils/config.js +0 -141
- package/dist/inner-plugins/utils/index.js +0 -8
- package/dist/inner-plugins/utils/loader.js +0 -134
- package/dist/inner-plugins/utils/normalize-config.js +0 -77
- package/dist/inner-plugins/utils/openBrowser.js +0 -55
- package/dist/inner-plugins/utils/plugin-common.js +0 -94
- package/dist/inner-plugins/utils/plugin.js +0 -70
- package/dist/inner-plugins/utils/sdk.js +0 -19
- package/dist/logger.js +0 -51
- package/dist/rspack-plugin/constants.js +0 -23
- package/dist/rspack-plugin/index.js +0 -3
- package/dist/rspack-plugin/multiple.js +0 -39
- package/dist/rspack-plugin/plugin.js +0 -133
- package/dist/rule-utils/document/document.js +0 -46
- package/dist/rule-utils/document/index.js +0 -4
- package/dist/rule-utils/document/server.js +0 -13
- package/dist/rule-utils/document/types.js +0 -1
- package/dist/rule-utils/index.js +0 -3
- package/dist/rule-utils/parser/asserts.js +0 -105
- package/dist/rule-utils/parser/index.js +0 -5
- package/dist/rule-utils/parser/parser.js +0 -24
- package/dist/rule-utils/parser/types.js +0 -8
- package/dist/rule-utils/parser/utils.js +0 -106
- package/dist/rules/index.js +0 -4
- package/dist/rules/linter.js +0 -36
- package/dist/rules/rule.js +0 -101
- package/dist/rules/rules/cjs-require/index.js +0 -50
- package/dist/rules/rules/cjs-require/types.js +0 -1
- package/dist/rules/rules/cross-chunks-package/index.js +0 -41
- package/dist/rules/rules/cross-chunks-package/types.js +0 -1
- package/dist/rules/rules/cross-chunks-package/utils.js +0 -7
- package/dist/rules/rules/default-import-check/index.js +0 -83
- package/dist/rules/rules/default-import-check/types.js +0 -1
- package/dist/rules/rules/default-import-check/utils.js +0 -52
- package/dist/rules/rules/duplicate-package/index.js +0 -39
- package/dist/rules/rules/duplicate-package/types.js +0 -24
- package/dist/rules/rules/duplicate-package/utils.js +0 -38
- package/dist/rules/rules/ecma-version-check/index.js +0 -53
- package/dist/rules/rules/ecma-version-check/types.js +0 -1
- package/dist/rules/rules/ecma-version-check/utils.js +0 -6
- package/dist/rules/rules/esm-resolved-to-cjs/index.js +0 -193
- package/dist/rules/rules/esm-resolved-to-cjs/types.js +0 -1
- package/dist/rules/rules/index.js +0 -22
- package/dist/rules/rules/loader-performance-optimization/index.js +0 -86
- package/dist/rules/rules/loader-performance-optimization/types.js +0 -1
- package/dist/rules/rules/loader-performance-optimization/utils.js +0 -10
- package/dist/rules/rules/module-mixed-chunks/index.js +0 -52
- package/dist/rules/rules/module-mixed-chunks/types.js +0 -1
- package/dist/rules/rules/side-effects-only-imports/index.js +0 -81
- package/dist/rules/rules/side-effects-only-imports/types.js +0 -1
- package/dist/rules/utils.js +0 -10
- package/dist/sdk/index.js +0 -3
- package/dist/sdk/multiple/controller.js +0 -42
- package/dist/sdk/multiple/index.js +0 -3
- package/dist/sdk/multiple/primary.js +0 -64
- package/dist/sdk/multiple/server.js +0 -14
- package/dist/sdk/sdk/core.js +0 -163
- package/dist/sdk/sdk/index.js +0 -435
- package/dist/sdk/sdk/types.js +0 -1
- package/dist/sdk/server/apis/alerts.js +0 -30
- package/dist/sdk/server/apis/base.js +0 -22
- package/dist/sdk/server/apis/bundle-diff.js +0 -51
- package/dist/sdk/server/apis/data.js +0 -44
- package/dist/sdk/server/apis/fs.js +0 -28
- package/dist/sdk/server/apis/graph.js +0 -116
- package/dist/sdk/server/apis/index.js +0 -11
- package/dist/sdk/server/apis/loader.js +0 -120
- package/dist/sdk/server/apis/plugin.js +0 -39
- package/dist/sdk/server/apis/project.js +0 -59
- package/dist/sdk/server/apis/renderer.js +0 -33
- package/dist/sdk/server/apis/resolver.js +0 -38
- package/dist/sdk/server/client.js +0 -8
- package/dist/sdk/server/fakeServer.js +0 -12
- package/dist/sdk/server/index.js +0 -292
- package/dist/sdk/server/json-body.js +0 -150
- package/dist/sdk/server/router.js +0 -83
- package/dist/sdk/server/security.js +0 -47
- package/dist/sdk/server/socket/api.js +0 -22
- package/dist/sdk/server/socket/index.js +0 -166
- package/dist/sdk/server/utils.js +0 -19
- package/dist/sdk/utils/base.js +0 -22
- package/dist/sdk/utils/constant.js +0 -4
- package/dist/sdk/utils/index.js +0 -4
- package/dist/sdk/utils/openBrowser.js +0 -53
- package/dist/sdk/utils/upload.js +0 -6
- package/dist/sdk.js +0 -2
- package/dist/types/index.js +0 -4
- package/dist/types/loader.js +0 -1
- package/dist/types/plugin.js +0 -1
- package/dist/types/rules.js +0 -1
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Loader } from "../build-utils/index.js";
|
|
3
|
-
import { InternalBundlePlugin, InternalErrorReporterPlugin, InternalLoaderPlugin, InternalPluginsPlugin, InternalResolverPlugin, InternalRulesPlugin, InternalSummaryPlugin, ensureModulesChunksGraphFn, handleBriefModeReport, normalizeRspackUserOptions, processCompilerConfig, setSDK } from "../inner-plugins/index.js";
|
|
4
|
-
import { RsdoctorSDK, findRoot } from "../sdk.js";
|
|
5
|
-
import { Constants, Manifest, SDK } from "@rsdoctor/shared/types";
|
|
6
|
-
import path from "path";
|
|
7
|
-
import { pkg, pluginTapName, pluginTapPostOptions } from "./constants.js";
|
|
8
|
-
import { ModuleGraph } from "../graph/index.js";
|
|
9
|
-
import { Loader as index_js_Loader } from "../common/index.js";
|
|
10
|
-
import { logger, time, timeEnd } from "../logger.js";
|
|
11
|
-
import { getRspackNativePlugin } from "../inner-plugins/plugins/rspack.js";
|
|
12
|
-
let hasGreeted = false;
|
|
13
|
-
class RsdoctorRspackPlugin {
|
|
14
|
-
apply(compiler) {
|
|
15
|
-
time('RsdoctorRspackPlugin.apply');
|
|
16
|
-
try {
|
|
17
|
-
if (!hasGreeted && !compiler.isChild()) {
|
|
18
|
-
hasGreeted = true;
|
|
19
|
-
logger.greet(`
|
|
20
|
-
\nRsdoctor v${pkg.version}\n`);
|
|
21
|
-
}
|
|
22
|
-
if (!this._bootstrapTask) this._bootstrapTask = this.sdk.bootstrap();
|
|
23
|
-
if (compiler.options.name) this.sdk.setName(compiler.options.name);
|
|
24
|
-
setSDK(this.sdk);
|
|
25
|
-
compiler.hooks.afterPlugins.tap(pluginTapPostOptions, this.afterPlugins.bind(this, compiler));
|
|
26
|
-
compiler.hooks.done.tapPromise({
|
|
27
|
-
...pluginTapPostOptions,
|
|
28
|
-
stage: pluginTapPostOptions.stage + 100
|
|
29
|
-
}, this.done.bind(this, compiler));
|
|
30
|
-
new InternalSummaryPlugin(this).apply(compiler);
|
|
31
|
-
if (this.options.features.loader) {
|
|
32
|
-
new Loader.ProbeLoaderPlugin().apply(compiler);
|
|
33
|
-
this.sdk.addClientRoutes([
|
|
34
|
-
Manifest.RsdoctorManifestClientRoutes.Loaders
|
|
35
|
-
]);
|
|
36
|
-
if (!index_js_Loader.isVue(compiler)) new InternalLoaderPlugin(this).apply(compiler);
|
|
37
|
-
}
|
|
38
|
-
if (this.options.features.plugins) new InternalPluginsPlugin(this).apply(compiler);
|
|
39
|
-
if (this.options.features.bundle) new InternalBundlePlugin(this).apply(compiler);
|
|
40
|
-
if (this.options.features.resolver) new InternalResolverPlugin(this).apply(compiler);
|
|
41
|
-
new InternalRulesPlugin(this).apply(compiler);
|
|
42
|
-
new InternalErrorReporterPlugin(this).apply(compiler);
|
|
43
|
-
const RsdoctorRspackNativePlugin = getRspackNativePlugin(compiler);
|
|
44
|
-
logger.debug('[RspackNativePlugin] Enabled');
|
|
45
|
-
new RsdoctorRspackNativePlugin({
|
|
46
|
-
moduleGraphFeatures: true,
|
|
47
|
-
chunkGraphFeatures: true,
|
|
48
|
-
sourceMapFeatures: {
|
|
49
|
-
cheap: false,
|
|
50
|
-
module: false
|
|
51
|
-
}
|
|
52
|
-
}).apply(compiler);
|
|
53
|
-
} finally{
|
|
54
|
-
timeEnd('RsdoctorRspackPlugin.apply');
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
ensureModulesChunksGraphApplied(compiler) {
|
|
58
|
-
ensureModulesChunksGraphFn(compiler, this);
|
|
59
|
-
}
|
|
60
|
-
getRspackConfig(compiler) {
|
|
61
|
-
time('RsdoctorRspackPlugin.getRspackConfig');
|
|
62
|
-
try {
|
|
63
|
-
if (compiler.isChild()) return;
|
|
64
|
-
const configuration = processCompilerConfig(compiler.options);
|
|
65
|
-
const rspackVersion = compiler.webpack?.rspackVersion || compiler.webpack?.version;
|
|
66
|
-
this.sdk.reportConfiguration({
|
|
67
|
-
name: 'rspack',
|
|
68
|
-
version: rspackVersion || 'unknown',
|
|
69
|
-
config: configuration,
|
|
70
|
-
root: findRoot() || ''
|
|
71
|
-
});
|
|
72
|
-
} finally{
|
|
73
|
-
timeEnd('RsdoctorRspackPlugin.getRspackConfig');
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
constructor(options){
|
|
77
|
-
this.name = pluginTapName;
|
|
78
|
-
this.browserIsOpened = false;
|
|
79
|
-
this.afterPlugins = (compiler)=>{
|
|
80
|
-
time('RsdoctorRspackPlugin.afterPlugins');
|
|
81
|
-
try {
|
|
82
|
-
this.getRspackConfig(compiler);
|
|
83
|
-
} finally{
|
|
84
|
-
timeEnd('RsdoctorRspackPlugin.afterPlugins');
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
this.done = async (compiler)=>{
|
|
88
|
-
time('RsdoctorRspackPlugin.done');
|
|
89
|
-
try {
|
|
90
|
-
logger.debug('[RsdoctorRspackPlugin] bootstrap(start) in done()');
|
|
91
|
-
await this.sdk.bootstrap();
|
|
92
|
-
logger.debug('[RsdoctorRspackPlugin] bootstrap(end) in done()');
|
|
93
|
-
this.sdk.addClientRoutes([
|
|
94
|
-
Manifest.RsdoctorManifestClientRoutes.Overall
|
|
95
|
-
]);
|
|
96
|
-
if (this.outsideInstance && 'parent' in this.sdk) this.sdk.parent.master.setOutputDir(path.resolve(this.options.output.reportDir || compiler.outputPath, this.options.output.mode === SDK.IMode[SDK.IMode.brief] ? '' : `./${Constants.RsdoctorOutputFolder}`));
|
|
97
|
-
this.sdk.setOutputDir(path.resolve(this.options.output.reportDir || compiler.outputPath, this.options.output.mode === SDK.IMode[SDK.IMode.brief] ? '' : `./${Constants.RsdoctorOutputFolder}`));
|
|
98
|
-
await this.sdk.writeStore();
|
|
99
|
-
if (!this.options.disableClientServer) if (this.options.output.mode === SDK.IMode[SDK.IMode.brief]) await handleBriefModeReport(this.sdk, this.options, this.options.disableClientServer);
|
|
100
|
-
else await this.sdk.server.openClientPage('homepage');
|
|
101
|
-
if (this.options.disableClientServer || this.options.output.mode === SDK.IMode[SDK.IMode.brief] && Array.isArray(this.options.output.options?.type) && 1 === this.options.output.options.type.length && 'json' === this.options.output.options.type[0]) await this.sdk.dispose();
|
|
102
|
-
} finally{
|
|
103
|
-
timeEnd('RsdoctorRspackPlugin.done');
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
this.options = normalizeRspackUserOptions(Object.assign(options || {}, {
|
|
107
|
-
supports: {
|
|
108
|
-
...options?.supports
|
|
109
|
-
}
|
|
110
|
-
}));
|
|
111
|
-
const { port, server, output, innerClientPath, printLog, sdkInstance } = this.options;
|
|
112
|
-
this.sdk = this.options.sdkInstance ?? new RsdoctorSDK({
|
|
113
|
-
port,
|
|
114
|
-
name: pluginTapName,
|
|
115
|
-
root: process.cwd(),
|
|
116
|
-
type: output.reportCodeType,
|
|
117
|
-
config: {
|
|
118
|
-
innerClientPath,
|
|
119
|
-
printLog,
|
|
120
|
-
server,
|
|
121
|
-
mode: output.mode ? output.mode : void 0,
|
|
122
|
-
brief: output.mode === SDK.IMode[SDK.IMode.brief] ? output.options || void 0 : void 0,
|
|
123
|
-
features: {
|
|
124
|
-
treeShaking: this.options.features.treeShaking
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
this.outsideInstance = Boolean(sdkInstance);
|
|
129
|
-
this.modulesGraph = new ModuleGraph();
|
|
130
|
-
this.isRsdoctorPlugin = true;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
export { RsdoctorRspackPlugin };
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Lodash } from "../../common/index.js";
|
|
3
|
-
import { LinesAndColumns } from "lines-and-columns";
|
|
4
|
-
class Document {
|
|
5
|
-
createFinder() {
|
|
6
|
-
const find = new LinesAndColumns(this._text);
|
|
7
|
-
this.positionAt = (offset)=>{
|
|
8
|
-
if (offset >= this._text.length) offset = this._text.length - 1;
|
|
9
|
-
if (offset < 0) offset = 0;
|
|
10
|
-
const result = find.locationForIndex(offset);
|
|
11
|
-
if (!result) return;
|
|
12
|
-
return {
|
|
13
|
-
line: result.line + 1,
|
|
14
|
-
column: result.column
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
this.offsetAt = (position)=>find.indexForLocation({
|
|
18
|
-
line: position.line - 1,
|
|
19
|
-
column: position.column
|
|
20
|
-
}) ?? void 0;
|
|
21
|
-
}
|
|
22
|
-
getText(range) {
|
|
23
|
-
if (!range) return this._text;
|
|
24
|
-
const start = 'number' == typeof range.start ? range.start : this.offsetAt(range.start);
|
|
25
|
-
const end = 'number' == typeof range.end ? range.end : this.offsetAt(range.end);
|
|
26
|
-
if (Lodash.isUndefined(start)) throw new Error(`Location ${JSON.stringify(start)} is illegal`);
|
|
27
|
-
if (Lodash.isUndefined(end)) throw new Error(`Location ${JSON.stringify(end)} is illegal`);
|
|
28
|
-
return this._text.slice(start, end);
|
|
29
|
-
}
|
|
30
|
-
edit(data) {
|
|
31
|
-
let { _text: content } = this;
|
|
32
|
-
const startOffset = Lodash.isNumber(data.start) ? data.start : this.offsetAt(data.start);
|
|
33
|
-
const endOffset = Lodash.isNumber(data.end) ? data.end : this.offsetAt(data.end);
|
|
34
|
-
if (Lodash.isUndefined(startOffset) || Lodash.isUndefined(endOffset)) return;
|
|
35
|
-
const startTxt = content.substring(0, startOffset);
|
|
36
|
-
const endTxt = content.substring(endOffset, content.length);
|
|
37
|
-
content = startTxt + data.newText + endTxt;
|
|
38
|
-
return content;
|
|
39
|
-
}
|
|
40
|
-
constructor(content){
|
|
41
|
-
this._text = '';
|
|
42
|
-
this._text = content;
|
|
43
|
-
this.createFinder();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
export { Document };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Document } from "./document.js";
|
|
3
|
-
const store = new Map();
|
|
4
|
-
function getDocument(content) {
|
|
5
|
-
if (store.has(content)) return store.get(content);
|
|
6
|
-
const doc = new Document(content);
|
|
7
|
-
store.set(content, doc);
|
|
8
|
-
return doc;
|
|
9
|
-
}
|
|
10
|
-
function clearDocument() {
|
|
11
|
-
store.clear();
|
|
12
|
-
}
|
|
13
|
-
export { clearDocument, getDocument };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
package/dist/rule-utils/index.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Lodash } from "../../common/index.js";
|
|
3
|
-
function isSyntaxNode(node) {
|
|
4
|
-
return Lodash.isObject(node) && 'type' in node;
|
|
5
|
-
}
|
|
6
|
-
function assertCreator(type) {
|
|
7
|
-
return (node)=>isSyntaxNode(node) && node.type === type;
|
|
8
|
-
}
|
|
9
|
-
const asserts = {
|
|
10
|
-
isProgram: assertCreator('Program'),
|
|
11
|
-
isEmptyStatement: assertCreator('EmptyStatement'),
|
|
12
|
-
isBlockStatement: assertCreator('BlockStatement'),
|
|
13
|
-
isStaticBlock: assertCreator('StaticBlock'),
|
|
14
|
-
isExpressionStatement: assertCreator('ExpressionStatement'),
|
|
15
|
-
isIfStatement: assertCreator('IfStatement'),
|
|
16
|
-
isLabeledStatement: assertCreator('LabeledStatement'),
|
|
17
|
-
isBreakStatement: assertCreator('BreakStatement'),
|
|
18
|
-
isContinueStatement: assertCreator('ContinueStatement'),
|
|
19
|
-
isWithStatement: assertCreator('WithStatement'),
|
|
20
|
-
isSwitchStatement: assertCreator('SwitchStatement'),
|
|
21
|
-
isReturnStatement: assertCreator('ReturnStatement'),
|
|
22
|
-
isThrowStatement: assertCreator('ThrowStatement'),
|
|
23
|
-
isTryStatement: assertCreator('TryStatement'),
|
|
24
|
-
isWhileStatement: assertCreator('WhileStatement'),
|
|
25
|
-
isDoWhileStatement: assertCreator('DoWhileStatement'),
|
|
26
|
-
isForStatement: assertCreator('ForStatement'),
|
|
27
|
-
isForInStatement: assertCreator('ForInStatement'),
|
|
28
|
-
isForOfStatement: assertCreator('ForOfStatement'),
|
|
29
|
-
isDebuggerStatement: assertCreator('DebuggerStatement'),
|
|
30
|
-
isFunctionDeclaration: assertCreator('FunctionDeclaration'),
|
|
31
|
-
isVariableDeclaration: assertCreator('VariableDeclaration'),
|
|
32
|
-
isVariableDeclarator: assertCreator('VariableDeclarator'),
|
|
33
|
-
isChainExpression: assertCreator('ChainExpression'),
|
|
34
|
-
isThisExpression: assertCreator('ThisExpression'),
|
|
35
|
-
isArrayExpression: assertCreator('ArrayExpression'),
|
|
36
|
-
isObjectExpression: assertCreator('ObjectExpression'),
|
|
37
|
-
isPrivateIdentifier: assertCreator('PrivateIdentifier'),
|
|
38
|
-
isProperty: assertCreator('Property'),
|
|
39
|
-
isPropertyDefinition: assertCreator('PropertyDefinition'),
|
|
40
|
-
isFunctionExpression: assertCreator('FunctionExpression'),
|
|
41
|
-
isSequenceExpression: assertCreator('SequenceExpression'),
|
|
42
|
-
isUnaryExpression: assertCreator('UnaryExpression'),
|
|
43
|
-
isBinaryExpression: assertCreator('BinaryExpression'),
|
|
44
|
-
isAssignmentExpression: assertCreator('AssignmentExpression'),
|
|
45
|
-
isUpdateExpression: assertCreator('UpdateExpression'),
|
|
46
|
-
isLogicalExpression: assertCreator('LogicalExpression'),
|
|
47
|
-
isConditionalExpression: assertCreator('ConditionalExpression'),
|
|
48
|
-
isNewExpression: assertCreator('NewExpression'),
|
|
49
|
-
isSwitchCase: assertCreator('SwitchCase'),
|
|
50
|
-
isCatchClause: assertCreator('CatchClause'),
|
|
51
|
-
isIdentifier: assertCreator('Identifier'),
|
|
52
|
-
isLiteral: assertCreator('Literal'),
|
|
53
|
-
isSuper: assertCreator('Super'),
|
|
54
|
-
isSpreadElement: assertCreator('SpreadElement'),
|
|
55
|
-
isArrowFunctionExpression: assertCreator('ArrowFunctionExpression'),
|
|
56
|
-
isYieldExpression: assertCreator('YieldExpression'),
|
|
57
|
-
isTemplateLiteral: assertCreator('TemplateLiteral'),
|
|
58
|
-
isTaggedTemplateExpression: assertCreator('TaggedTemplateExpression'),
|
|
59
|
-
isTemplateElement: assertCreator('TemplateElement'),
|
|
60
|
-
isObjectPattern: assertCreator('ObjectPattern'),
|
|
61
|
-
isArrayPattern: assertCreator('ArrayPattern'),
|
|
62
|
-
isRestElement: assertCreator('RestElement'),
|
|
63
|
-
isAssignmentPattern: assertCreator('AssignmentPattern'),
|
|
64
|
-
isClassBody: assertCreator('ClassBody'),
|
|
65
|
-
isClassDeclaration: assertCreator('ClassDeclaration'),
|
|
66
|
-
isClassExpression: assertCreator('ClassExpression'),
|
|
67
|
-
isMetaProperty: assertCreator('MetaProperty'),
|
|
68
|
-
isImportDeclaration: assertCreator('ImportDeclaration'),
|
|
69
|
-
isImportSpecifier: assertCreator('ImportSpecifier'),
|
|
70
|
-
isImportExpression: assertCreator('ImportExpression'),
|
|
71
|
-
isImportDefaultSpecifier: assertCreator('ImportDefaultSpecifier'),
|
|
72
|
-
isImportNamespaceSpecifier: assertCreator('ImportNamespaceSpecifier'),
|
|
73
|
-
isExportNamedDeclaration: assertCreator('ExportNamedDeclaration'),
|
|
74
|
-
isExportSpecifier: assertCreator('ExportSpecifier'),
|
|
75
|
-
isExportDefaultDeclaration: assertCreator('ExportDefaultDeclaration'),
|
|
76
|
-
isExportAllDeclaration: assertCreator('ExportAllDeclaration'),
|
|
77
|
-
isAwaitExpression: assertCreator('AwaitExpression'),
|
|
78
|
-
isMethodDefinition: assertCreator('MethodDefinition'),
|
|
79
|
-
isMemberExpression: assertCreator('MemberExpression'),
|
|
80
|
-
isComment (node) {
|
|
81
|
-
return isSyntaxNode(node) && ('Line' === node.type || 'Block' === node.type);
|
|
82
|
-
},
|
|
83
|
-
isDirective (node) {
|
|
84
|
-
return asserts.isExpressionStatement(node) && 'directive' in node;
|
|
85
|
-
},
|
|
86
|
-
isSimpleCallExpression (node) {
|
|
87
|
-
return isSyntaxNode(node) && 'CallExpression' === node.type;
|
|
88
|
-
},
|
|
89
|
-
isAssignmentProperty (node) {
|
|
90
|
-
return asserts.isProperty(node) && 'init' === node.kind;
|
|
91
|
-
},
|
|
92
|
-
isSimpleLiteral (node) {
|
|
93
|
-
return asserts.isLiteral(node) && !asserts.isRegExpLiteral(node) && !asserts.isBigIntLiteral(node);
|
|
94
|
-
},
|
|
95
|
-
isRegExpLiteral (node) {
|
|
96
|
-
return asserts.isLiteral(node) && 'regex' in node;
|
|
97
|
-
},
|
|
98
|
-
isBigIntLiteral (node) {
|
|
99
|
-
return asserts.isLiteral(node) && 'bigint' in node;
|
|
100
|
-
},
|
|
101
|
-
isExportStatement (node) {
|
|
102
|
-
return asserts.isExportAllDeclaration(node) || asserts.isExportDefaultDeclaration(node) || asserts.isExportNamedDeclaration(node);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
export { asserts };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Parser } from "acorn";
|
|
3
|
-
import { importAttributes } from "acorn-import-attributes";
|
|
4
|
-
import * as __rspack_external_acorn_walk_1e4235a7 from "acorn-walk";
|
|
5
|
-
import { asserts } from "./asserts.js";
|
|
6
|
-
import * as __rspack_external__utils_js_a9c81ddd from "./utils.js";
|
|
7
|
-
const acornParserInternal = Parser.extend(importAttributes);
|
|
8
|
-
let acornParserExport = Parser.extend(importAttributes);
|
|
9
|
-
const parser = {
|
|
10
|
-
walk: __rspack_external_acorn_walk_1e4235a7,
|
|
11
|
-
parse: (input, options)=>acornParserExport.parse(input, options),
|
|
12
|
-
parseExpressionAt: (input, pos, options)=>acornParserExport.parseExpressionAt(input, pos, options),
|
|
13
|
-
extend (...args) {
|
|
14
|
-
acornParserExport = acornParserExport.extend(...args);
|
|
15
|
-
return acornParserExport;
|
|
16
|
-
},
|
|
17
|
-
asserts: asserts,
|
|
18
|
-
utils: __rspack_external__utils_js_a9c81ddd,
|
|
19
|
-
internal: {
|
|
20
|
-
parse: (input, options)=>acornParserInternal.parse(input, options),
|
|
21
|
-
parseExpressionAt: (input, pos, options)=>acornParserInternal.parseExpressionAt(input, pos, options)
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
export { parser };
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { parse } from "acorn";
|
|
3
|
-
import { ECMAVersion } from "./types.js";
|
|
4
|
-
import { asserts } from "./asserts.js";
|
|
5
|
-
function isSameSemantics(node1, node2) {
|
|
6
|
-
if (node1.type !== node2.type) return false;
|
|
7
|
-
switch(node1.type){
|
|
8
|
-
case 'CallExpression':
|
|
9
|
-
{
|
|
10
|
-
const next = node2;
|
|
11
|
-
return node1.arguments.length === next.arguments.length && Boolean(node1.optional) === Boolean(next.optional) && isSameSemantics(node1.callee, next.callee) && node1.arguments.every((node, i)=>isSameSemantics(node, next.arguments[i]));
|
|
12
|
-
}
|
|
13
|
-
case 'MemberExpression':
|
|
14
|
-
{
|
|
15
|
-
const next = node2;
|
|
16
|
-
return node1.computed === next.computed && Boolean(node1.optional) === Boolean(next.optional) && isSameSemantics(node1.object, next.object) && isSameSemantics(node1.property, next.property);
|
|
17
|
-
}
|
|
18
|
-
case 'Identifier':
|
|
19
|
-
return node1.name === node2.name;
|
|
20
|
-
case 'Literal':
|
|
21
|
-
if (asserts.isSimpleLiteral(node1) && asserts.isSimpleLiteral(node2)) return node1.value === node2.value;
|
|
22
|
-
return node1.raw === node2.raw;
|
|
23
|
-
case 'ObjectExpression':
|
|
24
|
-
{
|
|
25
|
-
const next = node2;
|
|
26
|
-
return node1.properties.length === next.properties.length && node1.properties.every((prop, i)=>isSameSemantics(prop, next.properties[i]));
|
|
27
|
-
}
|
|
28
|
-
case 'Property':
|
|
29
|
-
{
|
|
30
|
-
const next = node2;
|
|
31
|
-
return node1.computed === next.computed && node1.kind === next.kind && node1.method === next.method && isSameSemantics(node1.key, next.key) && isSameSemantics(node1.value, next.value);
|
|
32
|
-
}
|
|
33
|
-
default:
|
|
34
|
-
throw new Error(`Unknown node type: ${node1.type}`);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function getDefaultImports(node) {
|
|
38
|
-
return node.body.filter((statement)=>{
|
|
39
|
-
if ('ImportDeclaration' !== statement.type) return false;
|
|
40
|
-
const specifier = statement?.specifiers?.[0];
|
|
41
|
-
if (specifier?.type === 'ImportDefaultSpecifier') return true;
|
|
42
|
-
return false;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
function getIdentifierInPattern(name, node) {
|
|
46
|
-
if (asserts.isIdentifier(node) && node.name === name) return node;
|
|
47
|
-
if (asserts.isObjectPattern(node)) for (const prop of node.properties){
|
|
48
|
-
if (asserts.isAssignmentProperty(prop)) return getIdentifierInPattern(name, prop.value);
|
|
49
|
-
if (asserts.isRestElement(prop)) return getIdentifierInPattern(name, prop);
|
|
50
|
-
}
|
|
51
|
-
if (asserts.isArrayPattern(node)) {
|
|
52
|
-
for (const el of node.elements)if (el) {
|
|
53
|
-
const result = getIdentifierInPattern(name, el);
|
|
54
|
-
if (result) return result;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (asserts.isRestElement(node)) return getIdentifierInPattern(name, node.argument);
|
|
58
|
-
if (asserts.isAssignmentPattern(node)) return getIdentifierInPattern(name, node.left);
|
|
59
|
-
}
|
|
60
|
-
function getIdentifierInDeclaration(name, node) {
|
|
61
|
-
function getId(node) {
|
|
62
|
-
return asserts.isIdentifier(node.id) && node.id.name === name ? node.id : void 0;
|
|
63
|
-
}
|
|
64
|
-
if (asserts.isFunctionDeclaration(node)) return getId(node);
|
|
65
|
-
if (asserts.isClassDeclaration(node)) return getId(node);
|
|
66
|
-
if (asserts.isVariableDeclaration(node)) return node.declarations.find((item)=>getIdentifierInPattern(name, item.id))?.id;
|
|
67
|
-
}
|
|
68
|
-
function getIdentifierInImport(name, node) {
|
|
69
|
-
if (asserts.isImportDeclaration(node)) {
|
|
70
|
-
for (const specifier of node.specifiers ?? [])if (specifier.local.name === name) return specifier.local;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
function getIdentifierInExport(name, node) {
|
|
74
|
-
if (asserts.isExportNamedDeclaration(node)) {
|
|
75
|
-
if (node.declaration) return getIdentifierInDeclaration(name, node.declaration);
|
|
76
|
-
for (const specifier of node.specifiers ?? [])if (specifier.exported.name === name) return specifier.exported;
|
|
77
|
-
}
|
|
78
|
-
if (asserts.isExportAllDeclaration(node) && node.exported) {
|
|
79
|
-
if (node.exported.name === name) return node.exported;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
function canParse(code, ecmaVersion) {
|
|
83
|
-
try {
|
|
84
|
-
parse(code, {
|
|
85
|
-
ecmaVersion,
|
|
86
|
-
sourceType: 'number' == typeof ecmaVersion && ecmaVersion <= 5 ? "script" : 'module'
|
|
87
|
-
});
|
|
88
|
-
return true;
|
|
89
|
-
} catch {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function isES5(code) {
|
|
94
|
-
return canParse(code, 5);
|
|
95
|
-
}
|
|
96
|
-
function isES6(code) {
|
|
97
|
-
return canParse(code, 6);
|
|
98
|
-
}
|
|
99
|
-
function detectECMAVersion(code) {
|
|
100
|
-
if (isES6(code)) {
|
|
101
|
-
if (isES5(code)) return ECMAVersion.ES5;
|
|
102
|
-
return ECMAVersion.ES6;
|
|
103
|
-
}
|
|
104
|
-
return ECMAVersion.ES7P;
|
|
105
|
-
}
|
|
106
|
-
export { canParse, detectECMAVersion, getDefaultImports, getIdentifierInDeclaration, getIdentifierInExport, getIdentifierInImport, getIdentifierInPattern, isES5, isES6, isSameSemantics };
|
package/dist/rules/index.js
DELETED
package/dist/rules/linter.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Linter } from "@rsdoctor/shared/types";
|
|
3
|
-
import { Rule } from "./rule.js";
|
|
4
|
-
import { rules as index_js_rules } from "./rules/index.js";
|
|
5
|
-
import { toSeverity } from "./utils.js";
|
|
6
|
-
class linter_Linter {
|
|
7
|
-
getRules(ruleMap, extendRules, filterLevel) {
|
|
8
|
-
const outside = extendRules.map((item)=>Rule.from(item));
|
|
9
|
-
const rules = index_js_rules.map((item)=>new Rule(item)).concat(outside);
|
|
10
|
-
rules.forEach((rule)=>{
|
|
11
|
-
const config = ruleMap[rule.title];
|
|
12
|
-
if (null != config) rule.setOption(config);
|
|
13
|
-
});
|
|
14
|
-
return rules.filter((rule)=>rule.match(filterLevel));
|
|
15
|
-
}
|
|
16
|
-
async validate(context) {
|
|
17
|
-
const lintResult = {
|
|
18
|
-
errors: [],
|
|
19
|
-
replace: []
|
|
20
|
-
};
|
|
21
|
-
await Promise.all(this.rules.map(async (rule)=>{
|
|
22
|
-
const result = await rule.validate(context);
|
|
23
|
-
lintResult.errors.push(...result.errors);
|
|
24
|
-
lintResult.replace.push(...result.replace);
|
|
25
|
-
}));
|
|
26
|
-
return lintResult;
|
|
27
|
-
}
|
|
28
|
-
async afterValidate(context) {
|
|
29
|
-
await Promise.all(this.rules.map((rule)=>rule.afterValidate(context)));
|
|
30
|
-
}
|
|
31
|
-
constructor({ rules, extends: extendRules, level } = {}){
|
|
32
|
-
this.rules = [];
|
|
33
|
-
this.rules = this.getRules(rules ?? {}, extendRules ?? [], toSeverity(level ?? 'Error', Linter.Severity.Error));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export { Linter as LinterType, linter_Linter as Linter };
|
package/dist/rules/rule.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Linter, Rule } from "@rsdoctor/shared/types";
|
|
3
|
-
import { Lodash } from "../common/index.js";
|
|
4
|
-
import { noop, toSeverity } from "./utils.js";
|
|
5
|
-
class rule_Rule {
|
|
6
|
-
static from(data) {
|
|
7
|
-
return new rule_Rule({
|
|
8
|
-
check: data.check,
|
|
9
|
-
onCheckEnd: data.onCheckEnd,
|
|
10
|
-
meta: {
|
|
11
|
-
...data.meta,
|
|
12
|
-
code: Rule.RuleMessageCodeEnumerated.Extend,
|
|
13
|
-
severity: toSeverity(data.meta.severity, Linter.Severity.Warn)
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
get code() {
|
|
18
|
-
return this.meta.code;
|
|
19
|
-
}
|
|
20
|
-
get title() {
|
|
21
|
-
return this.meta.title;
|
|
22
|
-
}
|
|
23
|
-
get severity() {
|
|
24
|
-
return this._severity;
|
|
25
|
-
}
|
|
26
|
-
get config() {
|
|
27
|
-
return this._config;
|
|
28
|
-
}
|
|
29
|
-
get category() {
|
|
30
|
-
return this.meta.category;
|
|
31
|
-
}
|
|
32
|
-
setOption(opt) {
|
|
33
|
-
let severity;
|
|
34
|
-
let config;
|
|
35
|
-
if (Array.isArray(opt)) {
|
|
36
|
-
severity = toSeverity(opt[0], this.meta.severity);
|
|
37
|
-
config = opt[1];
|
|
38
|
-
} else {
|
|
39
|
-
severity = toSeverity(opt, this.meta.severity);
|
|
40
|
-
config = void 0;
|
|
41
|
-
}
|
|
42
|
-
this._severity = severity;
|
|
43
|
-
this._config = Lodash.isPlainObject(config) ? {
|
|
44
|
-
...this.meta.defaultConfig,
|
|
45
|
-
...config
|
|
46
|
-
} : config || this.meta.defaultConfig;
|
|
47
|
-
}
|
|
48
|
-
match(level) {
|
|
49
|
-
if (level === Linter.Severity.Ignore || this.severity === Linter.Severity.Ignore) return false;
|
|
50
|
-
if (level === Linter.Severity.Error) return this.severity === Linter.Severity.Error || this.severity === Linter.Severity.Warn;
|
|
51
|
-
if (level === Linter.Severity.Warn) return this.severity === Linter.Severity.Warn;
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
async validate(context) {
|
|
55
|
-
const errors = [];
|
|
56
|
-
const replace = [];
|
|
57
|
-
const report = (data, remove)=>{
|
|
58
|
-
if (remove) replace.push(remove);
|
|
59
|
-
const severity = data.severity ? toSeverity(data.severity, this.severity) : this.severity;
|
|
60
|
-
const error = {
|
|
61
|
-
...data,
|
|
62
|
-
code: this.code,
|
|
63
|
-
severity,
|
|
64
|
-
category: this.category,
|
|
65
|
-
title: this.title.toUpperCase()
|
|
66
|
-
};
|
|
67
|
-
if (severity !== Linter.Severity.Ignore) errors.push(error);
|
|
68
|
-
};
|
|
69
|
-
await this.check({
|
|
70
|
-
...context,
|
|
71
|
-
ruleConfig: this.config,
|
|
72
|
-
report
|
|
73
|
-
});
|
|
74
|
-
return {
|
|
75
|
-
errors,
|
|
76
|
-
replace
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
async afterValidate({ hooks, validateResult, data }) {
|
|
80
|
-
if (this.onCheckEnd === noop) return;
|
|
81
|
-
await this.onCheckEnd({
|
|
82
|
-
data: {
|
|
83
|
-
...data,
|
|
84
|
-
ruleConfig: this.config
|
|
85
|
-
},
|
|
86
|
-
hooks,
|
|
87
|
-
validateResult
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
constructor(data){
|
|
91
|
-
this.check = data.check;
|
|
92
|
-
this.meta = data.meta;
|
|
93
|
-
this.onCheckEnd = 'function' == typeof data.onCheckEnd ? data.onCheckEnd : noop;
|
|
94
|
-
this._severity = this.meta.severity;
|
|
95
|
-
this._config = this.meta.defaultConfig;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function defineRule(ruleCreator) {
|
|
99
|
-
return ruleCreator();
|
|
100
|
-
}
|
|
101
|
-
export { defineRule, rule_Rule as Rule };
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
import { Linter } from "@rsdoctor/shared/types";
|
|
3
|
-
import { defineRule } from "../../rule.js";
|
|
4
|
-
const title = 'cjs-require';
|
|
5
|
-
const CJS_REQUIRE_TYPE = 'cjs require';
|
|
6
|
-
const NODE_MODULES_PATH_REGEXP = /[/\\]node_modules[/\\]/;
|
|
7
|
-
function isNodeModulesPath(modulePath) {
|
|
8
|
-
return NODE_MODULES_PATH_REGEXP.test(modulePath);
|
|
9
|
-
}
|
|
10
|
-
const rule = defineRule(()=>({
|
|
11
|
-
meta: {
|
|
12
|
-
code: 'E1008',
|
|
13
|
-
title: title,
|
|
14
|
-
category: 'bundle',
|
|
15
|
-
severity: Linter.Severity.Warn,
|
|
16
|
-
defaultConfig: {
|
|
17
|
-
ignore: []
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
check ({ moduleGraph, report, ruleConfig }) {
|
|
21
|
-
const dependencies = moduleGraph.getDependencies();
|
|
22
|
-
for (const dep of dependencies){
|
|
23
|
-
if (dep.typeString !== CJS_REQUIRE_TYPE) continue;
|
|
24
|
-
const issuerPath = dep.module.path;
|
|
25
|
-
if (isNodeModulesPath(issuerPath)) continue;
|
|
26
|
-
const requiredModule = dep.dependency;
|
|
27
|
-
if (ruleConfig.ignore.some((pattern)=>issuerPath.includes(pattern) || requiredModule.path.includes(pattern))) continue;
|
|
28
|
-
const detail = {
|
|
29
|
-
type: title,
|
|
30
|
-
issuerModule: {
|
|
31
|
-
id: dep.module.id,
|
|
32
|
-
path: dep.module.path,
|
|
33
|
-
identifier: dep.module.identifier
|
|
34
|
-
},
|
|
35
|
-
requiredModule: {
|
|
36
|
-
id: requiredModule.id,
|
|
37
|
-
path: requiredModule.path,
|
|
38
|
-
identifier: requiredModule.identifier
|
|
39
|
-
},
|
|
40
|
-
request: dep.request
|
|
41
|
-
};
|
|
42
|
-
const message = `"${issuerPath}" uses \`require('${dep.request}')\` (CJS require) which prevents tree-shaking of the entire module "${requiredModule.path}". Consider using \`require('${dep.request}').property\` or ESM \`import\` instead.`;
|
|
43
|
-
report({
|
|
44
|
-
message,
|
|
45
|
-
detail
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}));
|
|
50
|
-
export { rule };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "node:module";
|